blob: 224d9e9a0ee228f97712e8a78deaa32be0256ffc [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//===----------------------------------------------------------------------===//
John McCall83024632010-08-25 22:03:47 +000013#include "clang/Sema/SemaInternal.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"
Jordan Rose4938f272013-02-09 10:09:43 +000017#include "clang/Basic/CharInfo.h"
Douglas Gregor07f43572012-01-29 18:15:03 +000018#include "clang/Lex/HeaderSearch.h"
Douglas Gregorf329c7c2009-10-30 16:50:04 +000019#include "clang/Lex/MacroInfo.h"
20#include "clang/Lex/Preprocessor.h"
Chandler Carruth3a022472012-12-04 09:13:33 +000021#include "clang/Sema/CodeCompleteConsumer.h"
Chandler Carruth3a022472012-12-04 09:13:33 +000022#include "clang/Sema/Lookup.h"
23#include "clang/Sema/Overload.h"
24#include "clang/Sema/Scope.h"
25#include "clang/Sema/ScopeInfo.h"
Douglas Gregor1154e272010-09-16 16:06:31 +000026#include "llvm/ADT/DenseSet.h"
Benjamin Kramere0513cb2012-01-30 16:17:39 +000027#include "llvm/ADT/SmallBitVector.h"
Douglas Gregor3545ff42009-09-21 16:56:56 +000028#include "llvm/ADT/SmallPtrSet.h"
Benjamin Kramer49038022012-02-04 13:45:25 +000029#include "llvm/ADT/SmallString.h"
Douglas Gregore6688e62009-09-28 03:51:44 +000030#include "llvm/ADT/StringExtras.h"
Douglas Gregor9d2ddb22010-04-06 19:22:33 +000031#include "llvm/ADT/StringSwitch.h"
Douglas Gregor67c692c2010-08-26 15:07:07 +000032#include "llvm/ADT/Twine.h"
Douglas Gregor3545ff42009-09-21 16:56:56 +000033#include <list>
34#include <map>
35#include <vector>
Douglas Gregor2436e712009-09-17 21:32:03 +000036
37using namespace clang;
John McCallaab3e412010-08-25 08:40:02 +000038using namespace sema;
Douglas Gregor2436e712009-09-17 21:32:03 +000039
Douglas Gregor3545ff42009-09-21 16:56:56 +000040namespace {
41 /// \brief A container of code-completion results.
42 class ResultBuilder {
43 public:
44 /// \brief The type of a name-lookup filter, which can be provided to the
45 /// name-lookup routines to specify which declarations should be included in
46 /// the result set (when it returns true) and which declarations should be
47 /// filtered out (returns false).
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +000048 typedef bool (ResultBuilder::*LookupFilter)(const NamedDecl *) const;
Douglas Gregor3545ff42009-09-21 16:56:56 +000049
John McCall276321a2010-08-25 06:19:51 +000050 typedef CodeCompletionResult Result;
Douglas Gregor3545ff42009-09-21 16:56:56 +000051
52 private:
53 /// \brief The actual results we have found.
54 std::vector<Result> Results;
55
56 /// \brief A record of all of the declarations we have found and placed
57 /// into the result set, used to ensure that no declaration ever gets into
58 /// the result set twice.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +000059 llvm::SmallPtrSet<const Decl*, 16> AllDeclsFound;
Douglas Gregor3545ff42009-09-21 16:56:56 +000060
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +000061 typedef std::pair<const NamedDecl *, unsigned> DeclIndexPair;
Douglas Gregor05e7ca32009-12-06 20:23:50 +000062
63 /// \brief An entry in the shadow map, which is optimized to store
64 /// a single (declaration, index) mapping (the common case) but
65 /// can also store a list of (declaration, index) mappings.
66 class ShadowMapEntry {
Chris Lattner0e62c1c2011-07-23 10:55:15 +000067 typedef SmallVector<DeclIndexPair, 4> DeclIndexPairVector;
Douglas Gregor05e7ca32009-12-06 20:23:50 +000068
69 /// \brief Contains either the solitary NamedDecl * or a vector
70 /// of (declaration, index) pairs.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +000071 llvm::PointerUnion<const NamedDecl *, DeclIndexPairVector*> DeclOrVector;
Douglas Gregor05e7ca32009-12-06 20:23:50 +000072
73 /// \brief When the entry contains a single declaration, this is
74 /// the index associated with that entry.
75 unsigned SingleDeclIndex;
76
77 public:
78 ShadowMapEntry() : DeclOrVector(), SingleDeclIndex(0) { }
79
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +000080 void Add(const NamedDecl *ND, unsigned Index) {
Douglas Gregor05e7ca32009-12-06 20:23:50 +000081 if (DeclOrVector.isNull()) {
82 // 0 - > 1 elements: just set the single element information.
83 DeclOrVector = ND;
84 SingleDeclIndex = Index;
85 return;
86 }
87
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +000088 if (const NamedDecl *PrevND =
89 DeclOrVector.dyn_cast<const NamedDecl *>()) {
Douglas Gregor05e7ca32009-12-06 20:23:50 +000090 // 1 -> 2 elements: create the vector of results and push in the
91 // existing declaration.
92 DeclIndexPairVector *Vec = new DeclIndexPairVector;
93 Vec->push_back(DeclIndexPair(PrevND, SingleDeclIndex));
94 DeclOrVector = Vec;
95 }
96
97 // Add the new element to the end of the vector.
98 DeclOrVector.get<DeclIndexPairVector*>()->push_back(
99 DeclIndexPair(ND, Index));
100 }
101
102 void Destroy() {
103 if (DeclIndexPairVector *Vec
104 = DeclOrVector.dyn_cast<DeclIndexPairVector *>()) {
105 delete Vec;
Craig Topperc3ec1492014-05-26 06:22:03 +0000106 DeclOrVector = ((NamedDecl *)nullptr);
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000107 }
108 }
109
110 // Iteration.
111 class iterator;
112 iterator begin() const;
113 iterator end() const;
114 };
115
Douglas Gregor3545ff42009-09-21 16:56:56 +0000116 /// \brief A mapping from declaration names to the declarations that have
117 /// this name within a particular scope and their index within the list of
118 /// results.
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000119 typedef llvm::DenseMap<DeclarationName, ShadowMapEntry> ShadowMap;
Douglas Gregor3545ff42009-09-21 16:56:56 +0000120
121 /// \brief The semantic analysis object for which results are being
122 /// produced.
123 Sema &SemaRef;
Douglas Gregorb278aaf2011-02-01 19:23:04 +0000124
125 /// \brief The allocator used to allocate new code-completion strings.
Douglas Gregorbcbf46c2011-02-01 22:57:45 +0000126 CodeCompletionAllocator &Allocator;
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +0000127
128 CodeCompletionTUInfo &CCTUInfo;
Douglas Gregor3545ff42009-09-21 16:56:56 +0000129
130 /// \brief If non-NULL, a filter function used to remove any code-completion
131 /// results that are not desirable.
132 LookupFilter Filter;
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000133
134 /// \brief Whether we should allow declarations as
135 /// nested-name-specifiers that would otherwise be filtered out.
136 bool AllowNestedNameSpecifiers;
137
Douglas Gregor7aa6b222010-05-30 01:49:25 +0000138 /// \brief If set, the type that we would prefer our resulting value
139 /// declarations to have.
140 ///
141 /// Closely matching the preferred type gives a boost to a result's
142 /// priority.
143 CanQualType PreferredType;
144
Douglas Gregor3545ff42009-09-21 16:56:56 +0000145 /// \brief A list of shadow maps, which is used to model name hiding at
146 /// different levels of, e.g., the inheritance hierarchy.
147 std::list<ShadowMap> ShadowMaps;
148
Douglas Gregor9be0ed42010-08-26 16:36:48 +0000149 /// \brief If we're potentially referring to a C++ member function, the set
150 /// of qualifiers applied to the object type.
151 Qualifiers ObjectTypeQualifiers;
152
153 /// \brief Whether the \p ObjectTypeQualifiers field is active.
154 bool HasObjectTypeQualifiers;
155
Douglas Gregorc2cb2e22010-08-27 15:29:55 +0000156 /// \brief The selector that we prefer.
157 Selector PreferredSelector;
158
Douglas Gregor05fcf842010-11-02 20:36:02 +0000159 /// \brief The completion context in which we are gathering results.
Douglas Gregor50832e02010-09-20 22:39:41 +0000160 CodeCompletionContext CompletionContext;
161
James Dennett596e4752012-06-14 03:11:41 +0000162 /// \brief If we are in an instance method definition, the \@implementation
Douglas Gregor05fcf842010-11-02 20:36:02 +0000163 /// object.
164 ObjCImplementationDecl *ObjCImplementation;
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000165
Douglas Gregor50832e02010-09-20 22:39:41 +0000166 void AdjustResultPriorityForDecl(Result &R);
Douglas Gregor95887f92010-07-08 23:20:03 +0000167
Douglas Gregor0212fd72010-09-21 16:06:22 +0000168 void MaybeAddConstructorResults(Result R);
169
Douglas Gregor3545ff42009-09-21 16:56:56 +0000170 public:
Douglas Gregorbcbf46c2011-02-01 22:57:45 +0000171 explicit ResultBuilder(Sema &SemaRef, CodeCompletionAllocator &Allocator,
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +0000172 CodeCompletionTUInfo &CCTUInfo,
Douglas Gregor0ac41382010-09-23 23:01:17 +0000173 const CodeCompletionContext &CompletionContext,
Craig Topperc3ec1492014-05-26 06:22:03 +0000174 LookupFilter Filter = nullptr)
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +0000175 : SemaRef(SemaRef), Allocator(Allocator), CCTUInfo(CCTUInfo),
176 Filter(Filter),
Douglas Gregorb278aaf2011-02-01 19:23:04 +0000177 AllowNestedNameSpecifiers(false), HasObjectTypeQualifiers(false),
Douglas Gregor05fcf842010-11-02 20:36:02 +0000178 CompletionContext(CompletionContext),
Craig Topperc3ec1492014-05-26 06:22:03 +0000179 ObjCImplementation(nullptr)
Douglas Gregor05fcf842010-11-02 20:36:02 +0000180 {
181 // If this is an Objective-C instance method definition, dig out the
182 // corresponding implementation.
183 switch (CompletionContext.getKind()) {
184 case CodeCompletionContext::CCC_Expression:
185 case CodeCompletionContext::CCC_ObjCMessageReceiver:
186 case CodeCompletionContext::CCC_ParenthesizedExpression:
187 case CodeCompletionContext::CCC_Statement:
188 case CodeCompletionContext::CCC_Recovery:
189 if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl())
190 if (Method->isInstanceMethod())
191 if (ObjCInterfaceDecl *Interface = Method->getClassInterface())
192 ObjCImplementation = Interface->getImplementation();
193 break;
194
195 default:
196 break;
197 }
198 }
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000199
200 /// \brief Determine the priority for a reference to the given declaration.
201 unsigned getBasePriority(const NamedDecl *D);
202
Douglas Gregorf64acca2010-05-25 21:41:55 +0000203 /// \brief Whether we should include code patterns in the completion
204 /// results.
205 bool includeCodePatterns() const {
206 return SemaRef.CodeCompleter &&
Douglas Gregorac322ec2010-08-27 21:18:54 +0000207 SemaRef.CodeCompleter->includeCodePatterns();
Douglas Gregorf64acca2010-05-25 21:41:55 +0000208 }
209
Douglas Gregor3545ff42009-09-21 16:56:56 +0000210 /// \brief Set the filter used for code-completion results.
211 void setFilter(LookupFilter Filter) {
212 this->Filter = Filter;
213 }
Craig Topperc3ec1492014-05-26 06:22:03 +0000214
215 Result *data() { return Results.empty()? nullptr : &Results.front(); }
Douglas Gregor3545ff42009-09-21 16:56:56 +0000216 unsigned size() const { return Results.size(); }
217 bool empty() const { return Results.empty(); }
218
Douglas Gregor7aa6b222010-05-30 01:49:25 +0000219 /// \brief Specify the preferred type.
220 void setPreferredType(QualType T) {
221 PreferredType = SemaRef.Context.getCanonicalType(T);
222 }
223
Douglas Gregor9be0ed42010-08-26 16:36:48 +0000224 /// \brief Set the cv-qualifiers on the object type, for us in filtering
225 /// calls to member functions.
226 ///
227 /// When there are qualifiers in this set, they will be used to filter
228 /// out member functions that aren't available (because there will be a
229 /// cv-qualifier mismatch) or prefer functions with an exact qualifier
230 /// match.
231 void setObjectTypeQualifiers(Qualifiers Quals) {
232 ObjectTypeQualifiers = Quals;
233 HasObjectTypeQualifiers = true;
234 }
235
Douglas Gregorc2cb2e22010-08-27 15:29:55 +0000236 /// \brief Set the preferred selector.
237 ///
238 /// When an Objective-C method declaration result is added, and that
239 /// method's selector matches this preferred selector, we give that method
240 /// a slight priority boost.
241 void setPreferredSelector(Selector Sel) {
242 PreferredSelector = Sel;
243 }
Douglas Gregor05fcf842010-11-02 20:36:02 +0000244
Douglas Gregor50832e02010-09-20 22:39:41 +0000245 /// \brief Retrieve the code-completion context for which results are
246 /// being collected.
247 const CodeCompletionContext &getCompletionContext() const {
248 return CompletionContext;
249 }
250
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000251 /// \brief Specify whether nested-name-specifiers are allowed.
252 void allowNestedNameSpecifiers(bool Allow = true) {
253 AllowNestedNameSpecifiers = Allow;
254 }
255
Douglas Gregor74661272010-09-21 00:03:25 +0000256 /// \brief Return the semantic analysis object for which we are collecting
257 /// code completion results.
258 Sema &getSema() const { return SemaRef; }
259
Douglas Gregorb278aaf2011-02-01 19:23:04 +0000260 /// \brief Retrieve the allocator used to allocate code completion strings.
Douglas Gregorbcbf46c2011-02-01 22:57:45 +0000261 CodeCompletionAllocator &getAllocator() const { return Allocator; }
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +0000262
263 CodeCompletionTUInfo &getCodeCompletionTUInfo() const { return CCTUInfo; }
Douglas Gregorb278aaf2011-02-01 19:23:04 +0000264
Douglas Gregor7c208612010-01-14 00:20:49 +0000265 /// \brief Determine whether the given declaration is at all interesting
266 /// as a code-completion result.
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000267 ///
268 /// \param ND the declaration that we are inspecting.
269 ///
270 /// \param AsNestedNameSpecifier will be set true if this declaration is
271 /// only interesting when it is a nested-name-specifier.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000272 bool isInterestingDecl(const NamedDecl *ND,
273 bool &AsNestedNameSpecifier) const;
Douglas Gregore0717ab2010-01-14 00:41:07 +0000274
275 /// \brief Check whether the result is hidden by the Hiding declaration.
276 ///
277 /// \returns true if the result is hidden and cannot be found, false if
278 /// the hidden result could still be found. When false, \p R may be
279 /// modified to describe how the result can be found (e.g., via extra
280 /// qualification).
281 bool CheckHiddenResult(Result &R, DeclContext *CurContext,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000282 const NamedDecl *Hiding);
Douglas Gregore0717ab2010-01-14 00:41:07 +0000283
Douglas Gregor3545ff42009-09-21 16:56:56 +0000284 /// \brief Add a new result to this result set (if it isn't already in one
285 /// of the shadow maps), or replace an existing result (for, e.g., a
286 /// redeclaration).
Douglas Gregor2af2f672009-09-21 20:12:40 +0000287 ///
Douglas Gregord8c61782012-02-15 15:34:24 +0000288 /// \param R the result to add (if it is unique).
Douglas Gregor2af2f672009-09-21 20:12:40 +0000289 ///
Douglas Gregord8c61782012-02-15 15:34:24 +0000290 /// \param CurContext the context in which this result will be named.
Craig Topperc3ec1492014-05-26 06:22:03 +0000291 void MaybeAddResult(Result R, DeclContext *CurContext = nullptr);
292
Douglas Gregorc580c522010-01-14 01:09:38 +0000293 /// \brief Add a new result to this result set, where we already know
Yaron Keren8fbe43982014-11-14 18:33:42 +0000294 /// the hiding declaration (if any).
Douglas Gregorc580c522010-01-14 01:09:38 +0000295 ///
296 /// \param R the result to add (if it is unique).
297 ///
298 /// \param CurContext the context in which this result will be named.
299 ///
300 /// \param Hiding the declaration that hides the result.
Douglas Gregor09bbc652010-01-14 15:47:35 +0000301 ///
302 /// \param InBaseClass whether the result was found in a base
303 /// class of the searched context.
304 void AddResult(Result R, DeclContext *CurContext, NamedDecl *Hiding,
305 bool InBaseClass);
Douglas Gregorc580c522010-01-14 01:09:38 +0000306
Douglas Gregor78a21012010-01-14 16:01:26 +0000307 /// \brief Add a new non-declaration result to this result set.
308 void AddResult(Result R);
309
Douglas Gregor3545ff42009-09-21 16:56:56 +0000310 /// \brief Enter into a new scope.
311 void EnterNewScope();
312
313 /// \brief Exit from the current scope.
314 void ExitScope();
315
Douglas Gregorbaf69612009-11-18 04:19:12 +0000316 /// \brief Ignore this declaration, if it is seen again.
Dmitri Gribenko6cfb1532013-02-14 13:53:30 +0000317 void Ignore(const Decl *D) { AllDeclsFound.insert(D->getCanonicalDecl()); }
Douglas Gregorbaf69612009-11-18 04:19:12 +0000318
Douglas Gregor3545ff42009-09-21 16:56:56 +0000319 /// \name Name lookup predicates
320 ///
321 /// These predicates can be passed to the name lookup functions to filter the
322 /// results of name lookup. All of the predicates have the same type, so that
323 ///
324 //@{
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000325 bool IsOrdinaryName(const NamedDecl *ND) const;
326 bool IsOrdinaryNonTypeName(const NamedDecl *ND) const;
327 bool IsIntegralConstantValue(const NamedDecl *ND) const;
328 bool IsOrdinaryNonValueName(const NamedDecl *ND) const;
329 bool IsNestedNameSpecifier(const NamedDecl *ND) const;
330 bool IsEnum(const NamedDecl *ND) const;
331 bool IsClassOrStruct(const NamedDecl *ND) const;
332 bool IsUnion(const NamedDecl *ND) const;
333 bool IsNamespace(const NamedDecl *ND) const;
334 bool IsNamespaceOrAlias(const NamedDecl *ND) const;
335 bool IsType(const NamedDecl *ND) const;
336 bool IsMember(const NamedDecl *ND) const;
337 bool IsObjCIvar(const NamedDecl *ND) const;
338 bool IsObjCMessageReceiver(const NamedDecl *ND) const;
339 bool IsObjCMessageReceiverOrLambdaCapture(const NamedDecl *ND) const;
340 bool IsObjCCollection(const NamedDecl *ND) const;
341 bool IsImpossibleToSatisfy(const NamedDecl *ND) const;
Douglas Gregor3545ff42009-09-21 16:56:56 +0000342 //@}
343 };
Alexander Kornienkoab9db512015-06-22 23:07:51 +0000344}
Douglas Gregor3545ff42009-09-21 16:56:56 +0000345
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000346class ResultBuilder::ShadowMapEntry::iterator {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000347 llvm::PointerUnion<const NamedDecl *, const DeclIndexPair *> DeclOrIterator;
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000348 unsigned SingleDeclIndex;
349
350public:
351 typedef DeclIndexPair value_type;
352 typedef value_type reference;
353 typedef std::ptrdiff_t difference_type;
354 typedef std::input_iterator_tag iterator_category;
355
356 class pointer {
357 DeclIndexPair Value;
358
359 public:
360 pointer(const DeclIndexPair &Value) : Value(Value) { }
361
362 const DeclIndexPair *operator->() const {
363 return &Value;
364 }
365 };
Craig Topperc3ec1492014-05-26 06:22:03 +0000366
367 iterator() : DeclOrIterator((NamedDecl *)nullptr), SingleDeclIndex(0) {}
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000368
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000369 iterator(const NamedDecl *SingleDecl, unsigned Index)
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000370 : DeclOrIterator(SingleDecl), SingleDeclIndex(Index) { }
371
372 iterator(const DeclIndexPair *Iterator)
373 : DeclOrIterator(Iterator), SingleDeclIndex(0) { }
374
375 iterator &operator++() {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000376 if (DeclOrIterator.is<const NamedDecl *>()) {
Craig Topperc3ec1492014-05-26 06:22:03 +0000377 DeclOrIterator = (NamedDecl *)nullptr;
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000378 SingleDeclIndex = 0;
379 return *this;
380 }
381
382 const DeclIndexPair *I = DeclOrIterator.get<const DeclIndexPair*>();
383 ++I;
384 DeclOrIterator = I;
385 return *this;
386 }
387
Chris Lattner9795b392010-09-04 18:12:20 +0000388 /*iterator operator++(int) {
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000389 iterator tmp(*this);
390 ++(*this);
391 return tmp;
Chris Lattner9795b392010-09-04 18:12:20 +0000392 }*/
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000393
394 reference operator*() const {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000395 if (const NamedDecl *ND = DeclOrIterator.dyn_cast<const NamedDecl *>())
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000396 return reference(ND, SingleDeclIndex);
397
Douglas Gregor94bb5e82009-12-06 21:27:58 +0000398 return *DeclOrIterator.get<const DeclIndexPair*>();
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000399 }
400
401 pointer operator->() const {
402 return pointer(**this);
403 }
404
405 friend bool operator==(const iterator &X, const iterator &Y) {
Douglas Gregor94bb5e82009-12-06 21:27:58 +0000406 return X.DeclOrIterator.getOpaqueValue()
407 == Y.DeclOrIterator.getOpaqueValue() &&
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000408 X.SingleDeclIndex == Y.SingleDeclIndex;
409 }
410
411 friend bool operator!=(const iterator &X, const iterator &Y) {
Douglas Gregor94bb5e82009-12-06 21:27:58 +0000412 return !(X == Y);
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000413 }
414};
415
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000416ResultBuilder::ShadowMapEntry::iterator
417ResultBuilder::ShadowMapEntry::begin() const {
418 if (DeclOrVector.isNull())
419 return iterator();
420
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000421 if (const NamedDecl *ND = DeclOrVector.dyn_cast<const NamedDecl *>())
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000422 return iterator(ND, SingleDeclIndex);
423
424 return iterator(DeclOrVector.get<DeclIndexPairVector *>()->begin());
425}
426
427ResultBuilder::ShadowMapEntry::iterator
428ResultBuilder::ShadowMapEntry::end() const {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000429 if (DeclOrVector.is<const NamedDecl *>() || DeclOrVector.isNull())
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000430 return iterator();
431
432 return iterator(DeclOrVector.get<DeclIndexPairVector *>()->end());
433}
434
Douglas Gregor2af2f672009-09-21 20:12:40 +0000435/// \brief Compute the qualification required to get from the current context
436/// (\p CurContext) to the target context (\p TargetContext).
437///
438/// \param Context the AST context in which the qualification will be used.
439///
440/// \param CurContext the context where an entity is being named, which is
441/// typically based on the current scope.
442///
443/// \param TargetContext the context in which the named entity actually
444/// resides.
445///
446/// \returns a nested name specifier that refers into the target context, or
447/// NULL if no qualification is needed.
448static NestedNameSpecifier *
449getRequiredQualification(ASTContext &Context,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000450 const DeclContext *CurContext,
451 const DeclContext *TargetContext) {
452 SmallVector<const DeclContext *, 4> TargetParents;
Douglas Gregor2af2f672009-09-21 20:12:40 +0000453
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000454 for (const DeclContext *CommonAncestor = TargetContext;
Douglas Gregor2af2f672009-09-21 20:12:40 +0000455 CommonAncestor && !CommonAncestor->Encloses(CurContext);
456 CommonAncestor = CommonAncestor->getLookupParent()) {
457 if (CommonAncestor->isTransparentContext() ||
458 CommonAncestor->isFunctionOrMethod())
459 continue;
460
461 TargetParents.push_back(CommonAncestor);
462 }
Craig Topperc3ec1492014-05-26 06:22:03 +0000463
464 NestedNameSpecifier *Result = nullptr;
Douglas Gregor2af2f672009-09-21 20:12:40 +0000465 while (!TargetParents.empty()) {
Robert Wilhelm25284cc2013-08-23 16:11:15 +0000466 const DeclContext *Parent = TargetParents.pop_back_val();
467
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000468 if (const NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Parent)) {
Douglas Gregor68762e72010-08-23 21:17:50 +0000469 if (!Namespace->getIdentifier())
470 continue;
471
Douglas Gregor2af2f672009-09-21 20:12:40 +0000472 Result = NestedNameSpecifier::Create(Context, Result, Namespace);
Douglas Gregor68762e72010-08-23 21:17:50 +0000473 }
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000474 else if (const TagDecl *TD = dyn_cast<TagDecl>(Parent))
Douglas Gregor2af2f672009-09-21 20:12:40 +0000475 Result = NestedNameSpecifier::Create(Context, Result,
476 false,
477 Context.getTypeDeclType(TD).getTypePtr());
Douglas Gregor9eb77012009-11-07 00:00:49 +0000478 }
Douglas Gregor2af2f672009-09-21 20:12:40 +0000479 return Result;
480}
481
Alp Toker034bbd52014-06-30 01:33:53 +0000482/// Determine whether \p Id is a name reserved for the implementation (C99
483/// 7.1.3, C++ [lib.global.names]).
Argyrios Kyrtzidis5d8006d2016-07-01 01:17:02 +0000484static bool isReservedName(const IdentifierInfo *Id,
485 bool doubleUnderscoreOnly = false) {
Alp Toker034bbd52014-06-30 01:33:53 +0000486 if (Id->getLength() < 2)
487 return false;
488 const char *Name = Id->getNameStart();
489 return Name[0] == '_' &&
Argyrios Kyrtzidis5d8006d2016-07-01 01:17:02 +0000490 (Name[1] == '_' || (Name[1] >= 'A' && Name[1] <= 'Z' &&
491 !doubleUnderscoreOnly));
492}
493
494// Some declarations have reserved names that we don't want to ever show.
495// Filter out names reserved for the implementation if they come from a
496// system header.
497static bool shouldIgnoreDueToReservedName(const NamedDecl *ND, Sema &SemaRef) {
498 const IdentifierInfo *Id = ND->getIdentifier();
499 if (!Id)
500 return false;
501
502 // Ignore reserved names for compiler provided decls.
503 if (isReservedName(Id) && ND->getLocation().isInvalid())
504 return true;
505
506 // For system headers ignore only double-underscore names.
507 // This allows for system headers providing private symbols with a single
508 // underscore.
509 if (isReservedName(Id, /*doubleUnderscoreOnly=*/true) &&
510 SemaRef.SourceMgr.isInSystemHeader(
511 SemaRef.SourceMgr.getSpellingLoc(ND->getLocation())))
512 return true;
513
514 return false;
Alp Toker034bbd52014-06-30 01:33:53 +0000515}
516
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000517bool ResultBuilder::isInterestingDecl(const NamedDecl *ND,
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000518 bool &AsNestedNameSpecifier) const {
519 AsNestedNameSpecifier = false;
520
Richard Smithf2005d32015-12-29 23:34:32 +0000521 auto *Named = ND;
Douglas Gregor7c208612010-01-14 00:20:49 +0000522 ND = ND->getUnderlyingDecl();
Douglas Gregor58acf322009-10-09 22:16:47 +0000523
524 // Skip unnamed entities.
Douglas Gregor7c208612010-01-14 00:20:49 +0000525 if (!ND->getDeclName())
526 return false;
Douglas Gregor3545ff42009-09-21 16:56:56 +0000527
528 // Friend declarations and declarations introduced due to friends are never
529 // added as results.
Richard Smith6eece292015-01-15 02:27:20 +0000530 if (ND->getFriendObjectKind() == Decl::FOK_Undeclared)
Douglas Gregor7c208612010-01-14 00:20:49 +0000531 return false;
532
Douglas Gregor99fe2ad2009-12-11 17:31:05 +0000533 // Class template (partial) specializations are never added as results.
Douglas Gregor7c208612010-01-14 00:20:49 +0000534 if (isa<ClassTemplateSpecializationDecl>(ND) ||
535 isa<ClassTemplatePartialSpecializationDecl>(ND))
536 return false;
Douglas Gregor3545ff42009-09-21 16:56:56 +0000537
Douglas Gregor99fe2ad2009-12-11 17:31:05 +0000538 // Using declarations themselves are never added as results.
Douglas Gregor7c208612010-01-14 00:20:49 +0000539 if (isa<UsingDecl>(ND))
540 return false;
Argyrios Kyrtzidis5d8006d2016-07-01 01:17:02 +0000541
542 if (shouldIgnoreDueToReservedName(ND, SemaRef))
543 return false;
Douglas Gregor2927c0c2010-11-09 03:59:40 +0000544
Douglas Gregor59cab552010-08-16 23:05:20 +0000545 if (Filter == &ResultBuilder::IsNestedNameSpecifier ||
Richard Smithf2005d32015-12-29 23:34:32 +0000546 (isa<NamespaceDecl>(ND) &&
Douglas Gregor59cab552010-08-16 23:05:20 +0000547 Filter != &ResultBuilder::IsNamespace &&
Douglas Gregor0ac41382010-09-23 23:01:17 +0000548 Filter != &ResultBuilder::IsNamespaceOrAlias &&
Craig Topperc3ec1492014-05-26 06:22:03 +0000549 Filter != nullptr))
Douglas Gregor59cab552010-08-16 23:05:20 +0000550 AsNestedNameSpecifier = true;
551
Douglas Gregor3545ff42009-09-21 16:56:56 +0000552 // Filter out any unwanted results.
Richard Smithf2005d32015-12-29 23:34:32 +0000553 if (Filter && !(this->*Filter)(Named)) {
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000554 // Check whether it is interesting as a nested-name-specifier.
David Blaikiebbafb8a2012-03-11 07:00:24 +0000555 if (AllowNestedNameSpecifiers && SemaRef.getLangOpts().CPlusPlus &&
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000556 IsNestedNameSpecifier(ND) &&
557 (Filter != &ResultBuilder::IsMember ||
558 (isa<CXXRecordDecl>(ND) &&
559 cast<CXXRecordDecl>(ND)->isInjectedClassName()))) {
560 AsNestedNameSpecifier = true;
561 return true;
562 }
563
Douglas Gregor7c208612010-01-14 00:20:49 +0000564 return false;
Douglas Gregor59cab552010-08-16 23:05:20 +0000565 }
Douglas Gregor7c208612010-01-14 00:20:49 +0000566 // ... then it must be interesting!
567 return true;
568}
569
Douglas Gregore0717ab2010-01-14 00:41:07 +0000570bool ResultBuilder::CheckHiddenResult(Result &R, DeclContext *CurContext,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000571 const NamedDecl *Hiding) {
Douglas Gregore0717ab2010-01-14 00:41:07 +0000572 // In C, there is no way to refer to a hidden name.
573 // FIXME: This isn't true; we can find a tag name hidden by an ordinary
574 // name if we introduce the tag type.
David Blaikiebbafb8a2012-03-11 07:00:24 +0000575 if (!SemaRef.getLangOpts().CPlusPlus)
Douglas Gregore0717ab2010-01-14 00:41:07 +0000576 return true;
577
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000578 const DeclContext *HiddenCtx =
579 R.Declaration->getDeclContext()->getRedeclContext();
Douglas Gregore0717ab2010-01-14 00:41:07 +0000580
581 // There is no way to qualify a name declared in a function or method.
582 if (HiddenCtx->isFunctionOrMethod())
583 return true;
584
Sebastian Redl50c68252010-08-31 00:36:30 +0000585 if (HiddenCtx == Hiding->getDeclContext()->getRedeclContext())
Douglas Gregore0717ab2010-01-14 00:41:07 +0000586 return true;
587
588 // We can refer to the result with the appropriate qualification. Do it.
589 R.Hidden = true;
590 R.QualifierIsInformative = false;
591
592 if (!R.Qualifier)
593 R.Qualifier = getRequiredQualification(SemaRef.Context,
594 CurContext,
595 R.Declaration->getDeclContext());
596 return false;
597}
598
Douglas Gregor95887f92010-07-08 23:20:03 +0000599/// \brief A simplified classification of types used to determine whether two
600/// types are "similar enough" when adjusting priorities.
Douglas Gregor6e240332010-08-16 16:18:59 +0000601SimplifiedTypeClass clang::getSimplifiedTypeClass(CanQualType T) {
Douglas Gregor95887f92010-07-08 23:20:03 +0000602 switch (T->getTypeClass()) {
603 case Type::Builtin:
604 switch (cast<BuiltinType>(T)->getKind()) {
605 case BuiltinType::Void:
606 return STC_Void;
607
608 case BuiltinType::NullPtr:
609 return STC_Pointer;
610
611 case BuiltinType::Overload:
612 case BuiltinType::Dependent:
Douglas Gregor95887f92010-07-08 23:20:03 +0000613 return STC_Other;
614
615 case BuiltinType::ObjCId:
616 case BuiltinType::ObjCClass:
617 case BuiltinType::ObjCSel:
618 return STC_ObjectiveC;
619
620 default:
621 return STC_Arithmetic;
622 }
David Blaikie8a40f702012-01-17 06:56:22 +0000623
Douglas Gregor95887f92010-07-08 23:20:03 +0000624 case Type::Complex:
625 return STC_Arithmetic;
626
627 case Type::Pointer:
628 return STC_Pointer;
629
630 case Type::BlockPointer:
631 return STC_Block;
632
633 case Type::LValueReference:
634 case Type::RValueReference:
635 return getSimplifiedTypeClass(T->getAs<ReferenceType>()->getPointeeType());
636
637 case Type::ConstantArray:
638 case Type::IncompleteArray:
639 case Type::VariableArray:
640 case Type::DependentSizedArray:
641 return STC_Array;
642
643 case Type::DependentSizedExtVector:
644 case Type::Vector:
645 case Type::ExtVector:
646 return STC_Arithmetic;
647
648 case Type::FunctionProto:
649 case Type::FunctionNoProto:
650 return STC_Function;
651
652 case Type::Record:
653 return STC_Record;
654
655 case Type::Enum:
656 return STC_Arithmetic;
657
658 case Type::ObjCObject:
659 case Type::ObjCInterface:
660 case Type::ObjCObjectPointer:
661 return STC_ObjectiveC;
662
663 default:
664 return STC_Other;
665 }
666}
667
668/// \brief Get the type that a given expression will have if this declaration
669/// is used as an expression in its "typical" code-completion form.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000670QualType clang::getDeclUsageType(ASTContext &C, const NamedDecl *ND) {
Douglas Gregor95887f92010-07-08 23:20:03 +0000671 ND = cast<NamedDecl>(ND->getUnderlyingDecl());
672
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000673 if (const TypeDecl *Type = dyn_cast<TypeDecl>(ND))
Douglas Gregor95887f92010-07-08 23:20:03 +0000674 return C.getTypeDeclType(Type);
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000675 if (const ObjCInterfaceDecl *Iface = dyn_cast<ObjCInterfaceDecl>(ND))
Douglas Gregor95887f92010-07-08 23:20:03 +0000676 return C.getObjCInterfaceType(Iface);
677
678 QualType T;
Alp Tokera2794f92014-01-22 07:29:52 +0000679 if (const FunctionDecl *Function = ND->getAsFunction())
Douglas Gregor603d81b2010-07-13 08:18:22 +0000680 T = Function->getCallResultType();
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000681 else if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND))
Douglas Gregor603d81b2010-07-13 08:18:22 +0000682 T = Method->getSendResultType();
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000683 else if (const EnumConstantDecl *Enumerator = dyn_cast<EnumConstantDecl>(ND))
Douglas Gregor95887f92010-07-08 23:20:03 +0000684 T = C.getTypeDeclType(cast<EnumDecl>(Enumerator->getDeclContext()));
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000685 else if (const ObjCPropertyDecl *Property = dyn_cast<ObjCPropertyDecl>(ND))
Douglas Gregor95887f92010-07-08 23:20:03 +0000686 T = Property->getType();
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000687 else if (const ValueDecl *Value = dyn_cast<ValueDecl>(ND))
Douglas Gregor95887f92010-07-08 23:20:03 +0000688 T = Value->getType();
689 else
690 return QualType();
Douglas Gregoraf670a82011-04-14 20:33:34 +0000691
692 // Dig through references, function pointers, and block pointers to
693 // get down to the likely type of an expression when the entity is
694 // used.
695 do {
696 if (const ReferenceType *Ref = T->getAs<ReferenceType>()) {
697 T = Ref->getPointeeType();
698 continue;
699 }
700
701 if (const PointerType *Pointer = T->getAs<PointerType>()) {
702 if (Pointer->getPointeeType()->isFunctionType()) {
703 T = Pointer->getPointeeType();
704 continue;
705 }
706
707 break;
708 }
709
710 if (const BlockPointerType *Block = T->getAs<BlockPointerType>()) {
711 T = Block->getPointeeType();
712 continue;
713 }
714
715 if (const FunctionType *Function = T->getAs<FunctionType>()) {
Alp Toker314cc812014-01-25 16:55:45 +0000716 T = Function->getReturnType();
Douglas Gregoraf670a82011-04-14 20:33:34 +0000717 continue;
718 }
719
720 break;
721 } while (true);
722
723 return T;
Douglas Gregor95887f92010-07-08 23:20:03 +0000724}
725
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000726unsigned ResultBuilder::getBasePriority(const NamedDecl *ND) {
727 if (!ND)
728 return CCP_Unlikely;
729
730 // Context-based decisions.
Richard Smith541b38b2013-09-20 01:15:31 +0000731 const DeclContext *LexicalDC = ND->getLexicalDeclContext();
732 if (LexicalDC->isFunctionOrMethod()) {
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000733 // _cmd is relatively rare
734 if (const ImplicitParamDecl *ImplicitParam =
735 dyn_cast<ImplicitParamDecl>(ND))
736 if (ImplicitParam->getIdentifier() &&
737 ImplicitParam->getIdentifier()->isStr("_cmd"))
738 return CCP_ObjC_cmd;
739
740 return CCP_LocalDeclaration;
741 }
Richard Smith541b38b2013-09-20 01:15:31 +0000742
743 const DeclContext *DC = ND->getDeclContext()->getRedeclContext();
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000744 if (DC->isRecord() || isa<ObjCContainerDecl>(DC))
745 return CCP_MemberDeclaration;
746
747 // Content-based decisions.
748 if (isa<EnumConstantDecl>(ND))
749 return CCP_Constant;
750
Douglas Gregor52e0de42013-01-31 05:03:46 +0000751 // Use CCP_Type for type declarations unless we're in a statement, Objective-C
752 // message receiver, or parenthesized expression context. There, it's as
753 // likely that the user will want to write a type as other declarations.
754 if ((isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND)) &&
755 !(CompletionContext.getKind() == CodeCompletionContext::CCC_Statement ||
756 CompletionContext.getKind()
757 == CodeCompletionContext::CCC_ObjCMessageReceiver ||
758 CompletionContext.getKind()
759 == CodeCompletionContext::CCC_ParenthesizedExpression))
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000760 return CCP_Type;
761
762 return CCP_Declaration;
763}
764
Douglas Gregor50832e02010-09-20 22:39:41 +0000765void ResultBuilder::AdjustResultPriorityForDecl(Result &R) {
766 // If this is an Objective-C method declaration whose selector matches our
767 // preferred selector, give it a priority boost.
768 if (!PreferredSelector.isNull())
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000769 if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(R.Declaration))
Douglas Gregor50832e02010-09-20 22:39:41 +0000770 if (PreferredSelector == Method->getSelector())
771 R.Priority += CCD_SelectorMatch;
Douglas Gregor5fb901d2010-09-20 23:11:55 +0000772
Douglas Gregor50832e02010-09-20 22:39:41 +0000773 // If we have a preferred type, adjust the priority for results with exactly-
774 // matching or nearly-matching types.
775 if (!PreferredType.isNull()) {
776 QualType T = getDeclUsageType(SemaRef.Context, R.Declaration);
777 if (!T.isNull()) {
778 CanQualType TC = SemaRef.Context.getCanonicalType(T);
779 // Check for exactly-matching types (modulo qualifiers).
780 if (SemaRef.Context.hasSameUnqualifiedType(PreferredType, TC))
781 R.Priority /= CCF_ExactTypeMatch;
782 // Check for nearly-matching types, based on classification of each.
783 else if ((getSimplifiedTypeClass(PreferredType)
Douglas Gregor95887f92010-07-08 23:20:03 +0000784 == getSimplifiedTypeClass(TC)) &&
Douglas Gregor50832e02010-09-20 22:39:41 +0000785 !(PreferredType->isEnumeralType() && TC->isEnumeralType()))
786 R.Priority /= CCF_SimilarTypeMatch;
787 }
788 }
Douglas Gregor95887f92010-07-08 23:20:03 +0000789}
790
Douglas Gregor0212fd72010-09-21 16:06:22 +0000791void ResultBuilder::MaybeAddConstructorResults(Result R) {
David Blaikiebbafb8a2012-03-11 07:00:24 +0000792 if (!SemaRef.getLangOpts().CPlusPlus || !R.Declaration ||
Douglas Gregor0212fd72010-09-21 16:06:22 +0000793 !CompletionContext.wantConstructorResults())
794 return;
795
796 ASTContext &Context = SemaRef.Context;
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000797 const NamedDecl *D = R.Declaration;
Craig Topperc3ec1492014-05-26 06:22:03 +0000798 const CXXRecordDecl *Record = nullptr;
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000799 if (const ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(D))
Douglas Gregor0212fd72010-09-21 16:06:22 +0000800 Record = ClassTemplate->getTemplatedDecl();
801 else if ((Record = dyn_cast<CXXRecordDecl>(D))) {
802 // Skip specializations and partial specializations.
803 if (isa<ClassTemplateSpecializationDecl>(Record))
804 return;
805 } else {
806 // There are no constructors here.
807 return;
808 }
809
810 Record = Record->getDefinition();
811 if (!Record)
812 return;
813
814
815 QualType RecordTy = Context.getTypeDeclType(Record);
816 DeclarationName ConstructorName
817 = Context.DeclarationNames.getCXXConstructorName(
818 Context.getCanonicalType(RecordTy));
Richard Smithcf4bdde2015-02-21 02:45:19 +0000819 DeclContext::lookup_result Ctors = Record->lookup(ConstructorName);
820 for (DeclContext::lookup_iterator I = Ctors.begin(),
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000821 E = Ctors.end();
822 I != E; ++I) {
David Blaikieff7d47a2012-12-19 00:45:41 +0000823 R.Declaration = *I;
Douglas Gregor0212fd72010-09-21 16:06:22 +0000824 R.CursorKind = getCursorKindForDecl(R.Declaration);
825 Results.push_back(R);
826 }
827}
828
Douglas Gregor7c208612010-01-14 00:20:49 +0000829void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) {
830 assert(!ShadowMaps.empty() && "Must enter into a results scope");
831
832 if (R.Kind != Result::RK_Declaration) {
833 // For non-declaration results, just add the result.
834 Results.push_back(R);
835 return;
836 }
837
838 // Look through using declarations.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000839 if (const UsingShadowDecl *Using =
840 dyn_cast<UsingShadowDecl>(R.Declaration)) {
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000841 MaybeAddResult(Result(Using->getTargetDecl(),
842 getBasePriority(Using->getTargetDecl()),
843 R.Qualifier),
844 CurContext);
Douglas Gregor7c208612010-01-14 00:20:49 +0000845 return;
846 }
847
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000848 const Decl *CanonDecl = R.Declaration->getCanonicalDecl();
Douglas Gregor7c208612010-01-14 00:20:49 +0000849 unsigned IDNS = CanonDecl->getIdentifierNamespace();
850
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000851 bool AsNestedNameSpecifier = false;
852 if (!isInterestingDecl(R.Declaration, AsNestedNameSpecifier))
Douglas Gregor7c208612010-01-14 00:20:49 +0000853 return;
854
Douglas Gregor0212fd72010-09-21 16:06:22 +0000855 // C++ constructors are never found by name lookup.
856 if (isa<CXXConstructorDecl>(R.Declaration))
857 return;
858
Douglas Gregor3545ff42009-09-21 16:56:56 +0000859 ShadowMap &SMap = ShadowMaps.back();
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000860 ShadowMapEntry::iterator I, IEnd;
861 ShadowMap::iterator NamePos = SMap.find(R.Declaration->getDeclName());
862 if (NamePos != SMap.end()) {
863 I = NamePos->second.begin();
864 IEnd = NamePos->second.end();
865 }
866
867 for (; I != IEnd; ++I) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000868 const NamedDecl *ND = I->first;
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000869 unsigned Index = I->second;
Douglas Gregor3545ff42009-09-21 16:56:56 +0000870 if (ND->getCanonicalDecl() == CanonDecl) {
871 // This is a redeclaration. Always pick the newer declaration.
Douglas Gregor3545ff42009-09-21 16:56:56 +0000872 Results[Index].Declaration = R.Declaration;
873
Douglas Gregor3545ff42009-09-21 16:56:56 +0000874 // We're done.
875 return;
876 }
877 }
878
879 // This is a new declaration in this scope. However, check whether this
880 // declaration name is hidden by a similarly-named declaration in an outer
881 // scope.
882 std::list<ShadowMap>::iterator SM, SMEnd = ShadowMaps.end();
883 --SMEnd;
884 for (SM = ShadowMaps.begin(); SM != SMEnd; ++SM) {
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000885 ShadowMapEntry::iterator I, IEnd;
886 ShadowMap::iterator NamePos = SM->find(R.Declaration->getDeclName());
887 if (NamePos != SM->end()) {
888 I = NamePos->second.begin();
889 IEnd = NamePos->second.end();
890 }
891 for (; I != IEnd; ++I) {
Douglas Gregor3545ff42009-09-21 16:56:56 +0000892 // A tag declaration does not hide a non-tag declaration.
John McCalle87beb22010-04-23 18:46:30 +0000893 if (I->first->hasTagIdentifierNamespace() &&
Richard Smith541b38b2013-09-20 01:15:31 +0000894 (IDNS & (Decl::IDNS_Member | Decl::IDNS_Ordinary |
895 Decl::IDNS_LocalExtern | Decl::IDNS_ObjCProtocol)))
Douglas Gregor3545ff42009-09-21 16:56:56 +0000896 continue;
897
898 // Protocols are in distinct namespaces from everything else.
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000899 if (((I->first->getIdentifierNamespace() & Decl::IDNS_ObjCProtocol)
Douglas Gregor3545ff42009-09-21 16:56:56 +0000900 || (IDNS & Decl::IDNS_ObjCProtocol)) &&
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000901 I->first->getIdentifierNamespace() != IDNS)
Douglas Gregor3545ff42009-09-21 16:56:56 +0000902 continue;
903
904 // The newly-added result is hidden by an entry in the shadow map.
Douglas Gregore0717ab2010-01-14 00:41:07 +0000905 if (CheckHiddenResult(R, CurContext, I->first))
Douglas Gregor3545ff42009-09-21 16:56:56 +0000906 return;
Douglas Gregor3545ff42009-09-21 16:56:56 +0000907
908 break;
909 }
910 }
911
912 // Make sure that any given declaration only shows up in the result set once.
David Blaikie82e95a32014-11-19 07:49:47 +0000913 if (!AllDeclsFound.insert(CanonDecl).second)
Douglas Gregor3545ff42009-09-21 16:56:56 +0000914 return;
Douglas Gregorc2cb2e22010-08-27 15:29:55 +0000915
Douglas Gregore412a5a2009-09-23 22:26:46 +0000916 // If the filter is for nested-name-specifiers, then this result starts a
917 // nested-name-specifier.
Douglas Gregora2db7932010-05-26 22:00:08 +0000918 if (AsNestedNameSpecifier) {
Douglas Gregore412a5a2009-09-23 22:26:46 +0000919 R.StartsNestedNameSpecifier = true;
Douglas Gregora2db7932010-05-26 22:00:08 +0000920 R.Priority = CCP_NestedNameSpecifier;
Douglas Gregor50832e02010-09-20 22:39:41 +0000921 } else
922 AdjustResultPriorityForDecl(R);
Douglas Gregorc2cb2e22010-08-27 15:29:55 +0000923
Douglas Gregor5bf52692009-09-22 23:15:58 +0000924 // If this result is supposed to have an informative qualifier, add one.
Douglas Gregore412a5a2009-09-23 22:26:46 +0000925 if (R.QualifierIsInformative && !R.Qualifier &&
926 !R.StartsNestedNameSpecifier) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000927 const DeclContext *Ctx = R.Declaration->getDeclContext();
928 if (const NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Ctx))
Craig Topperc3ec1492014-05-26 06:22:03 +0000929 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, nullptr,
930 Namespace);
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000931 else if (const TagDecl *Tag = dyn_cast<TagDecl>(Ctx))
Craig Topperc3ec1492014-05-26 06:22:03 +0000932 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, nullptr,
933 false, SemaRef.Context.getTypeDeclType(Tag).getTypePtr());
Douglas Gregor5bf52692009-09-22 23:15:58 +0000934 else
935 R.QualifierIsInformative = false;
936 }
Douglas Gregore412a5a2009-09-23 22:26:46 +0000937
Douglas Gregor3545ff42009-09-21 16:56:56 +0000938 // Insert this result into the set of results and into the current shadow
939 // map.
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000940 SMap[R.Declaration->getDeclName()].Add(R.Declaration, Results.size());
Douglas Gregor3545ff42009-09-21 16:56:56 +0000941 Results.push_back(R);
Douglas Gregor0212fd72010-09-21 16:06:22 +0000942
943 if (!AsNestedNameSpecifier)
944 MaybeAddConstructorResults(R);
Douglas Gregor3545ff42009-09-21 16:56:56 +0000945}
946
Douglas Gregorc580c522010-01-14 01:09:38 +0000947void ResultBuilder::AddResult(Result R, DeclContext *CurContext,
Douglas Gregor09bbc652010-01-14 15:47:35 +0000948 NamedDecl *Hiding, bool InBaseClass = false) {
Douglas Gregor78a21012010-01-14 16:01:26 +0000949 if (R.Kind != Result::RK_Declaration) {
950 // For non-declaration results, just add the result.
951 Results.push_back(R);
952 return;
953 }
954
Douglas Gregorc580c522010-01-14 01:09:38 +0000955 // Look through using declarations.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000956 if (const UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(R.Declaration)) {
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000957 AddResult(Result(Using->getTargetDecl(),
958 getBasePriority(Using->getTargetDecl()),
959 R.Qualifier),
960 CurContext, Hiding);
Douglas Gregorc580c522010-01-14 01:09:38 +0000961 return;
962 }
963
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000964 bool AsNestedNameSpecifier = false;
965 if (!isInterestingDecl(R.Declaration, AsNestedNameSpecifier))
Douglas Gregorc580c522010-01-14 01:09:38 +0000966 return;
967
Douglas Gregor0212fd72010-09-21 16:06:22 +0000968 // C++ constructors are never found by name lookup.
969 if (isa<CXXConstructorDecl>(R.Declaration))
970 return;
971
Douglas Gregorc580c522010-01-14 01:09:38 +0000972 if (Hiding && CheckHiddenResult(R, CurContext, Hiding))
973 return;
Nick Lewyckyc3921482012-04-03 21:44:08 +0000974
Douglas Gregorc580c522010-01-14 01:09:38 +0000975 // Make sure that any given declaration only shows up in the result set once.
David Blaikie82e95a32014-11-19 07:49:47 +0000976 if (!AllDeclsFound.insert(R.Declaration->getCanonicalDecl()).second)
Douglas Gregorc580c522010-01-14 01:09:38 +0000977 return;
978
979 // If the filter is for nested-name-specifiers, then this result starts a
980 // nested-name-specifier.
Douglas Gregora2db7932010-05-26 22:00:08 +0000981 if (AsNestedNameSpecifier) {
Douglas Gregorc580c522010-01-14 01:09:38 +0000982 R.StartsNestedNameSpecifier = true;
Douglas Gregora2db7932010-05-26 22:00:08 +0000983 R.Priority = CCP_NestedNameSpecifier;
984 }
Douglas Gregor09bbc652010-01-14 15:47:35 +0000985 else if (Filter == &ResultBuilder::IsMember && !R.Qualifier && InBaseClass &&
986 isa<CXXRecordDecl>(R.Declaration->getDeclContext()
Sebastian Redl50c68252010-08-31 00:36:30 +0000987 ->getRedeclContext()))
Douglas Gregor09bbc652010-01-14 15:47:35 +0000988 R.QualifierIsInformative = true;
989
Douglas Gregorc580c522010-01-14 01:09:38 +0000990 // If this result is supposed to have an informative qualifier, add one.
991 if (R.QualifierIsInformative && !R.Qualifier &&
992 !R.StartsNestedNameSpecifier) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000993 const DeclContext *Ctx = R.Declaration->getDeclContext();
994 if (const NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Ctx))
Craig Topperc3ec1492014-05-26 06:22:03 +0000995 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, nullptr,
996 Namespace);
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000997 else if (const TagDecl *Tag = dyn_cast<TagDecl>(Ctx))
Craig Topperc3ec1492014-05-26 06:22:03 +0000998 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, nullptr, false,
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000999 SemaRef.Context.getTypeDeclType(Tag).getTypePtr());
Douglas Gregorc580c522010-01-14 01:09:38 +00001000 else
1001 R.QualifierIsInformative = false;
1002 }
1003
Douglas Gregora2db7932010-05-26 22:00:08 +00001004 // Adjust the priority if this result comes from a base class.
1005 if (InBaseClass)
1006 R.Priority += CCD_InBaseClass;
1007
Douglas Gregor50832e02010-09-20 22:39:41 +00001008 AdjustResultPriorityForDecl(R);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00001009
Douglas Gregor9be0ed42010-08-26 16:36:48 +00001010 if (HasObjectTypeQualifiers)
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001011 if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(R.Declaration))
Douglas Gregor9be0ed42010-08-26 16:36:48 +00001012 if (Method->isInstance()) {
1013 Qualifiers MethodQuals
1014 = Qualifiers::fromCVRMask(Method->getTypeQualifiers());
1015 if (ObjectTypeQualifiers == MethodQuals)
1016 R.Priority += CCD_ObjectQualifierMatch;
1017 else if (ObjectTypeQualifiers - MethodQuals) {
1018 // The method cannot be invoked, because doing so would drop
1019 // qualifiers.
1020 return;
1021 }
1022 }
1023
Douglas Gregorc580c522010-01-14 01:09:38 +00001024 // Insert this result into the set of results.
1025 Results.push_back(R);
Douglas Gregor0212fd72010-09-21 16:06:22 +00001026
1027 if (!AsNestedNameSpecifier)
1028 MaybeAddConstructorResults(R);
Douglas Gregorc580c522010-01-14 01:09:38 +00001029}
1030
Douglas Gregor78a21012010-01-14 16:01:26 +00001031void ResultBuilder::AddResult(Result R) {
1032 assert(R.Kind != Result::RK_Declaration &&
1033 "Declaration results need more context");
1034 Results.push_back(R);
1035}
1036
Douglas Gregor3545ff42009-09-21 16:56:56 +00001037/// \brief Enter into a new scope.
Benjamin Kramer3204b152015-05-29 19:42:19 +00001038void ResultBuilder::EnterNewScope() { ShadowMaps.emplace_back(); }
Douglas Gregor3545ff42009-09-21 16:56:56 +00001039
1040/// \brief Exit from the current scope.
1041void ResultBuilder::ExitScope() {
Douglas Gregor05e7ca32009-12-06 20:23:50 +00001042 for (ShadowMap::iterator E = ShadowMaps.back().begin(),
1043 EEnd = ShadowMaps.back().end();
1044 E != EEnd;
1045 ++E)
1046 E->second.Destroy();
1047
Douglas Gregor3545ff42009-09-21 16:56:56 +00001048 ShadowMaps.pop_back();
1049}
1050
Douglas Gregor9d64c5e2009-09-21 20:51:25 +00001051/// \brief Determines whether this given declaration will be found by
1052/// ordinary name lookup.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001053bool ResultBuilder::IsOrdinaryName(const NamedDecl *ND) const {
Douglas Gregor70febae2010-05-28 00:49:12 +00001054 ND = cast<NamedDecl>(ND->getUnderlyingDecl());
1055
Richard Smith541b38b2013-09-20 01:15:31 +00001056 // If name lookup finds a local extern declaration, then we are in a
1057 // context where it behaves like an ordinary name.
1058 unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_LocalExtern;
David Blaikiebbafb8a2012-03-11 07:00:24 +00001059 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregor9858ed52010-06-15 20:26:51 +00001060 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member;
David Blaikiebbafb8a2012-03-11 07:00:24 +00001061 else if (SemaRef.getLangOpts().ObjC1) {
Douglas Gregor05fcf842010-11-02 20:36:02 +00001062 if (isa<ObjCIvarDecl>(ND))
1063 return true;
Douglas Gregor05fcf842010-11-02 20:36:02 +00001064 }
1065
Douglas Gregor9d64c5e2009-09-21 20:51:25 +00001066 return ND->getIdentifierNamespace() & IDNS;
1067}
1068
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001069/// \brief Determines whether this given declaration will be found by
Douglas Gregor70febae2010-05-28 00:49:12 +00001070/// ordinary name lookup but is not a type name.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001071bool ResultBuilder::IsOrdinaryNonTypeName(const NamedDecl *ND) const {
Douglas Gregor70febae2010-05-28 00:49:12 +00001072 ND = cast<NamedDecl>(ND->getUnderlyingDecl());
1073 if (isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND))
1074 return false;
1075
Richard Smith541b38b2013-09-20 01:15:31 +00001076 unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_LocalExtern;
David Blaikiebbafb8a2012-03-11 07:00:24 +00001077 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregor9858ed52010-06-15 20:26:51 +00001078 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member;
David Blaikiebbafb8a2012-03-11 07:00:24 +00001079 else if (SemaRef.getLangOpts().ObjC1) {
Douglas Gregor05fcf842010-11-02 20:36:02 +00001080 if (isa<ObjCIvarDecl>(ND))
1081 return true;
Douglas Gregor05fcf842010-11-02 20:36:02 +00001082 }
1083
Douglas Gregor70febae2010-05-28 00:49:12 +00001084 return ND->getIdentifierNamespace() & IDNS;
1085}
1086
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001087bool ResultBuilder::IsIntegralConstantValue(const NamedDecl *ND) const {
Douglas Gregor85b50632010-07-28 21:50:18 +00001088 if (!IsOrdinaryNonTypeName(ND))
1089 return 0;
1090
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001091 if (const ValueDecl *VD = dyn_cast<ValueDecl>(ND->getUnderlyingDecl()))
Douglas Gregor85b50632010-07-28 21:50:18 +00001092 if (VD->getType()->isIntegralOrEnumerationType())
1093 return true;
1094
1095 return false;
1096}
1097
Douglas Gregor70febae2010-05-28 00:49:12 +00001098/// \brief Determines whether this given declaration will be found by
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001099/// ordinary name lookup.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001100bool ResultBuilder::IsOrdinaryNonValueName(const NamedDecl *ND) const {
Douglas Gregor70febae2010-05-28 00:49:12 +00001101 ND = cast<NamedDecl>(ND->getUnderlyingDecl());
1102
Richard Smith541b38b2013-09-20 01:15:31 +00001103 unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_LocalExtern;
David Blaikiebbafb8a2012-03-11 07:00:24 +00001104 if (SemaRef.getLangOpts().CPlusPlus)
John McCalle87beb22010-04-23 18:46:30 +00001105 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001106
1107 return (ND->getIdentifierNamespace() & IDNS) &&
Douglas Gregor70febae2010-05-28 00:49:12 +00001108 !isa<ValueDecl>(ND) && !isa<FunctionTemplateDecl>(ND) &&
1109 !isa<ObjCPropertyDecl>(ND);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001110}
1111
Douglas Gregor3545ff42009-09-21 16:56:56 +00001112/// \brief Determines whether the given declaration is suitable as the
1113/// start of a C++ nested-name-specifier, e.g., a class or namespace.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001114bool ResultBuilder::IsNestedNameSpecifier(const NamedDecl *ND) const {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001115 // Allow us to find class templates, too.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001116 if (const ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
Douglas Gregor3545ff42009-09-21 16:56:56 +00001117 ND = ClassTemplate->getTemplatedDecl();
1118
1119 return SemaRef.isAcceptableNestedNameSpecifier(ND);
1120}
1121
1122/// \brief Determines whether the given declaration is an enumeration.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001123bool ResultBuilder::IsEnum(const NamedDecl *ND) const {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001124 return isa<EnumDecl>(ND);
1125}
1126
1127/// \brief Determines whether the given declaration is a class or struct.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001128bool ResultBuilder::IsClassOrStruct(const NamedDecl *ND) const {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001129 // Allow us to find class templates, too.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001130 if (const ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
Douglas Gregor3545ff42009-09-21 16:56:56 +00001131 ND = ClassTemplate->getTemplatedDecl();
Joao Matosdc86f942012-08-31 18:45:21 +00001132
1133 // For purposes of this check, interfaces match too.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001134 if (const RecordDecl *RD = dyn_cast<RecordDecl>(ND))
Abramo Bagnara6150c882010-05-11 21:36:43 +00001135 return RD->getTagKind() == TTK_Class ||
Joao Matosdc86f942012-08-31 18:45:21 +00001136 RD->getTagKind() == TTK_Struct ||
1137 RD->getTagKind() == TTK_Interface;
Douglas Gregor3545ff42009-09-21 16:56:56 +00001138
1139 return false;
1140}
1141
1142/// \brief Determines whether the given declaration is a union.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001143bool ResultBuilder::IsUnion(const NamedDecl *ND) const {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001144 // Allow us to find class templates, too.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001145 if (const ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
Douglas Gregor3545ff42009-09-21 16:56:56 +00001146 ND = ClassTemplate->getTemplatedDecl();
1147
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001148 if (const RecordDecl *RD = dyn_cast<RecordDecl>(ND))
Abramo Bagnara6150c882010-05-11 21:36:43 +00001149 return RD->getTagKind() == TTK_Union;
Douglas Gregor3545ff42009-09-21 16:56:56 +00001150
1151 return false;
1152}
1153
1154/// \brief Determines whether the given declaration is a namespace.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001155bool ResultBuilder::IsNamespace(const NamedDecl *ND) const {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001156 return isa<NamespaceDecl>(ND);
1157}
1158
1159/// \brief Determines whether the given declaration is a namespace or
1160/// namespace alias.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001161bool ResultBuilder::IsNamespaceOrAlias(const NamedDecl *ND) const {
Richard Smithf2005d32015-12-29 23:34:32 +00001162 return isa<NamespaceDecl>(ND->getUnderlyingDecl());
Douglas Gregor3545ff42009-09-21 16:56:56 +00001163}
1164
Douglas Gregor99fe2ad2009-12-11 17:31:05 +00001165/// \brief Determines whether the given declaration is a type.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001166bool ResultBuilder::IsType(const NamedDecl *ND) const {
Richard Smithf2005d32015-12-29 23:34:32 +00001167 ND = ND->getUnderlyingDecl();
Douglas Gregor99fa2642010-08-24 01:06:58 +00001168 return isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND);
Douglas Gregor3545ff42009-09-21 16:56:56 +00001169}
1170
Douglas Gregor99fe2ad2009-12-11 17:31:05 +00001171/// \brief Determines which members of a class should be visible via
1172/// "." or "->". Only value declarations, nested name specifiers, and
1173/// using declarations thereof should show up.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001174bool ResultBuilder::IsMember(const NamedDecl *ND) const {
Richard Smithf2005d32015-12-29 23:34:32 +00001175 ND = ND->getUnderlyingDecl();
Douglas Gregor70788392009-12-11 18:14:22 +00001176 return isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND) ||
Richard Smithf2005d32015-12-29 23:34:32 +00001177 isa<ObjCPropertyDecl>(ND);
Douglas Gregore412a5a2009-09-23 22:26:46 +00001178}
1179
Douglas Gregora817a192010-05-27 23:06:34 +00001180static bool isObjCReceiverType(ASTContext &C, QualType T) {
1181 T = C.getCanonicalType(T);
1182 switch (T->getTypeClass()) {
1183 case Type::ObjCObject:
1184 case Type::ObjCInterface:
1185 case Type::ObjCObjectPointer:
1186 return true;
1187
1188 case Type::Builtin:
1189 switch (cast<BuiltinType>(T)->getKind()) {
1190 case BuiltinType::ObjCId:
1191 case BuiltinType::ObjCClass:
1192 case BuiltinType::ObjCSel:
1193 return true;
1194
1195 default:
1196 break;
1197 }
1198 return false;
1199
1200 default:
1201 break;
1202 }
1203
David Blaikiebbafb8a2012-03-11 07:00:24 +00001204 if (!C.getLangOpts().CPlusPlus)
Douglas Gregora817a192010-05-27 23:06:34 +00001205 return false;
1206
1207 // FIXME: We could perform more analysis here to determine whether a
1208 // particular class type has any conversions to Objective-C types. For now,
1209 // just accept all class types.
1210 return T->isDependentType() || T->isRecordType();
1211}
1212
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001213bool ResultBuilder::IsObjCMessageReceiver(const NamedDecl *ND) const {
Douglas Gregora817a192010-05-27 23:06:34 +00001214 QualType T = getDeclUsageType(SemaRef.Context, ND);
1215 if (T.isNull())
1216 return false;
1217
1218 T = SemaRef.Context.getBaseElementType(T);
1219 return isObjCReceiverType(SemaRef.Context, T);
1220}
1221
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001222bool ResultBuilder::IsObjCMessageReceiverOrLambdaCapture(const NamedDecl *ND) const {
Douglas Gregord8c61782012-02-15 15:34:24 +00001223 if (IsObjCMessageReceiver(ND))
1224 return true;
1225
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001226 const VarDecl *Var = dyn_cast<VarDecl>(ND);
Douglas Gregord8c61782012-02-15 15:34:24 +00001227 if (!Var)
1228 return false;
1229
1230 return Var->hasLocalStorage() && !Var->hasAttr<BlocksAttr>();
1231}
1232
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001233bool ResultBuilder::IsObjCCollection(const NamedDecl *ND) const {
David Blaikiebbafb8a2012-03-11 07:00:24 +00001234 if ((SemaRef.getLangOpts().CPlusPlus && !IsOrdinaryName(ND)) ||
1235 (!SemaRef.getLangOpts().CPlusPlus && !IsOrdinaryNonTypeName(ND)))
Douglas Gregor68762e72010-08-23 21:17:50 +00001236 return false;
1237
1238 QualType T = getDeclUsageType(SemaRef.Context, ND);
1239 if (T.isNull())
1240 return false;
1241
1242 T = SemaRef.Context.getBaseElementType(T);
1243 return T->isObjCObjectType() || T->isObjCObjectPointerType() ||
1244 T->isObjCIdType() ||
David Blaikiebbafb8a2012-03-11 07:00:24 +00001245 (SemaRef.getLangOpts().CPlusPlus && T->isRecordType());
Douglas Gregor68762e72010-08-23 21:17:50 +00001246}
Douglas Gregora817a192010-05-27 23:06:34 +00001247
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001248bool ResultBuilder::IsImpossibleToSatisfy(const NamedDecl *ND) const {
Douglas Gregor0ac41382010-09-23 23:01:17 +00001249 return false;
1250}
1251
James Dennettf1243872012-06-17 05:33:25 +00001252/// \brief Determines whether the given declaration is an Objective-C
Douglas Gregor2b8162b2010-01-14 16:08:12 +00001253/// instance variable.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001254bool ResultBuilder::IsObjCIvar(const NamedDecl *ND) const {
Douglas Gregor2b8162b2010-01-14 16:08:12 +00001255 return isa<ObjCIvarDecl>(ND);
1256}
1257
Douglas Gregorc580c522010-01-14 01:09:38 +00001258namespace {
1259 /// \brief Visible declaration consumer that adds a code-completion result
1260 /// for each visible declaration.
1261 class CodeCompletionDeclConsumer : public VisibleDeclConsumer {
1262 ResultBuilder &Results;
1263 DeclContext *CurContext;
1264
1265 public:
1266 CodeCompletionDeclConsumer(ResultBuilder &Results, DeclContext *CurContext)
1267 : Results(Results), CurContext(CurContext) { }
Craig Toppere14c0f82014-03-12 04:55:44 +00001268
1269 void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx,
1270 bool InBaseClass) override {
Erik Verbruggen2e657ff2011-10-06 07:27:49 +00001271 bool Accessible = true;
Douglas Gregor03ba1882011-11-03 16:51:37 +00001272 if (Ctx)
1273 Accessible = Results.getSema().IsSimplyAccessible(ND, Ctx);
Craig Topperc3ec1492014-05-26 06:22:03 +00001274
1275 ResultBuilder::Result Result(ND, Results.getBasePriority(ND), nullptr,
1276 false, Accessible);
Erik Verbruggen2e657ff2011-10-06 07:27:49 +00001277 Results.AddResult(Result, CurContext, Hiding, InBaseClass);
Douglas Gregorc580c522010-01-14 01:09:38 +00001278 }
1279 };
Alexander Kornienkoab9db512015-06-22 23:07:51 +00001280}
Douglas Gregorc580c522010-01-14 01:09:38 +00001281
Douglas Gregor3545ff42009-09-21 16:56:56 +00001282/// \brief Add type specifiers for the current language as keyword results.
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001283static void AddTypeSpecifierResults(const LangOptions &LangOpts,
Douglas Gregor3545ff42009-09-21 16:56:56 +00001284 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00001285 typedef CodeCompletionResult Result;
Douglas Gregora2db7932010-05-26 22:00:08 +00001286 Results.AddResult(Result("short", CCP_Type));
1287 Results.AddResult(Result("long", CCP_Type));
1288 Results.AddResult(Result("signed", CCP_Type));
1289 Results.AddResult(Result("unsigned", CCP_Type));
1290 Results.AddResult(Result("void", CCP_Type));
1291 Results.AddResult(Result("char", CCP_Type));
1292 Results.AddResult(Result("int", CCP_Type));
1293 Results.AddResult(Result("float", CCP_Type));
1294 Results.AddResult(Result("double", CCP_Type));
1295 Results.AddResult(Result("enum", CCP_Type));
1296 Results.AddResult(Result("struct", CCP_Type));
1297 Results.AddResult(Result("union", CCP_Type));
1298 Results.AddResult(Result("const", CCP_Type));
1299 Results.AddResult(Result("volatile", CCP_Type));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001300
Douglas Gregor3545ff42009-09-21 16:56:56 +00001301 if (LangOpts.C99) {
1302 // C99-specific
Douglas Gregora2db7932010-05-26 22:00:08 +00001303 Results.AddResult(Result("_Complex", CCP_Type));
1304 Results.AddResult(Result("_Imaginary", CCP_Type));
1305 Results.AddResult(Result("_Bool", CCP_Type));
1306 Results.AddResult(Result("restrict", CCP_Type));
Douglas Gregor3545ff42009-09-21 16:56:56 +00001307 }
1308
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00001309 CodeCompletionBuilder Builder(Results.getAllocator(),
1310 Results.getCodeCompletionTUInfo());
Douglas Gregor3545ff42009-09-21 16:56:56 +00001311 if (LangOpts.CPlusPlus) {
1312 // C++-specific
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00001313 Results.AddResult(Result("bool", CCP_Type +
1314 (LangOpts.ObjC1? CCD_bool_in_ObjC : 0)));
Douglas Gregora2db7932010-05-26 22:00:08 +00001315 Results.AddResult(Result("class", CCP_Type));
1316 Results.AddResult(Result("wchar_t", CCP_Type));
Douglas Gregor3545ff42009-09-21 16:56:56 +00001317
Douglas Gregorf4c33342010-05-28 00:22:41 +00001318 // typename qualified-id
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001319 Builder.AddTypedTextChunk("typename");
1320 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1321 Builder.AddPlaceholderChunk("qualifier");
1322 Builder.AddTextChunk("::");
1323 Builder.AddPlaceholderChunk("name");
1324 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf64acca2010-05-25 21:41:55 +00001325
Richard Smith2bf7fdb2013-01-02 11:42:31 +00001326 if (LangOpts.CPlusPlus11) {
Douglas Gregora2db7932010-05-26 22:00:08 +00001327 Results.AddResult(Result("auto", CCP_Type));
1328 Results.AddResult(Result("char16_t", CCP_Type));
1329 Results.AddResult(Result("char32_t", CCP_Type));
Douglas Gregorf4c33342010-05-28 00:22:41 +00001330
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001331 Builder.AddTypedTextChunk("decltype");
1332 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1333 Builder.AddPlaceholderChunk("expression");
1334 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1335 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor3545ff42009-09-21 16:56:56 +00001336 }
Alex Lorenz46eed9d2017-02-13 23:35:59 +00001337 } else
1338 Results.AddResult(Result("__auto_type", CCP_Type));
1339
Douglas Gregor3545ff42009-09-21 16:56:56 +00001340 // GNU extensions
1341 if (LangOpts.GNUMode) {
1342 // FIXME: Enable when we actually support decimal floating point.
Douglas Gregor78a21012010-01-14 16:01:26 +00001343 // Results.AddResult(Result("_Decimal32"));
1344 // Results.AddResult(Result("_Decimal64"));
1345 // Results.AddResult(Result("_Decimal128"));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001346
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001347 Builder.AddTypedTextChunk("typeof");
1348 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1349 Builder.AddPlaceholderChunk("expression");
1350 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00001351
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001352 Builder.AddTypedTextChunk("typeof");
1353 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1354 Builder.AddPlaceholderChunk("type");
1355 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1356 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor3545ff42009-09-21 16:56:56 +00001357 }
Douglas Gregor86b42682015-06-19 18:27:52 +00001358
1359 // Nullability
Douglas Gregoraea7afd2015-06-24 22:02:08 +00001360 Results.AddResult(Result("_Nonnull", CCP_Type));
1361 Results.AddResult(Result("_Null_unspecified", CCP_Type));
1362 Results.AddResult(Result("_Nullable", CCP_Type));
Douglas Gregor3545ff42009-09-21 16:56:56 +00001363}
1364
John McCallfaf5fb42010-08-26 23:41:50 +00001365static void AddStorageSpecifiers(Sema::ParserCompletionContext CCC,
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001366 const LangOptions &LangOpts,
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001367 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00001368 typedef CodeCompletionResult Result;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001369 // Note: we don't suggest either "auto" or "register", because both
1370 // are pointless as storage specifiers. Elsewhere, we suggest "auto"
1371 // in C++0x as a type specifier.
Douglas Gregor78a21012010-01-14 16:01:26 +00001372 Results.AddResult(Result("extern"));
1373 Results.AddResult(Result("static"));
Alex Lorenz8f4d3992017-02-13 23:19:40 +00001374
1375 if (LangOpts.CPlusPlus11) {
1376 CodeCompletionAllocator &Allocator = Results.getAllocator();
1377 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
1378
1379 // alignas
1380 Builder.AddTypedTextChunk("alignas");
1381 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1382 Builder.AddPlaceholderChunk("expression");
1383 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1384 Results.AddResult(Result(Builder.TakeString()));
1385
1386 Results.AddResult(Result("constexpr"));
1387 Results.AddResult(Result("thread_local"));
1388 }
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001389}
1390
John McCallfaf5fb42010-08-26 23:41:50 +00001391static void AddFunctionSpecifiers(Sema::ParserCompletionContext CCC,
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001392 const LangOptions &LangOpts,
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001393 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00001394 typedef CodeCompletionResult Result;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001395 switch (CCC) {
John McCallfaf5fb42010-08-26 23:41:50 +00001396 case Sema::PCC_Class:
1397 case Sema::PCC_MemberTemplate:
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001398 if (LangOpts.CPlusPlus) {
Douglas Gregor78a21012010-01-14 16:01:26 +00001399 Results.AddResult(Result("explicit"));
1400 Results.AddResult(Result("friend"));
1401 Results.AddResult(Result("mutable"));
1402 Results.AddResult(Result("virtual"));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001403 }
1404 // Fall through
1405
John McCallfaf5fb42010-08-26 23:41:50 +00001406 case Sema::PCC_ObjCInterface:
1407 case Sema::PCC_ObjCImplementation:
1408 case Sema::PCC_Namespace:
1409 case Sema::PCC_Template:
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001410 if (LangOpts.CPlusPlus || LangOpts.C99)
Douglas Gregor78a21012010-01-14 16:01:26 +00001411 Results.AddResult(Result("inline"));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001412 break;
1413
John McCallfaf5fb42010-08-26 23:41:50 +00001414 case Sema::PCC_ObjCInstanceVariableList:
1415 case Sema::PCC_Expression:
1416 case Sema::PCC_Statement:
1417 case Sema::PCC_ForInit:
1418 case Sema::PCC_Condition:
1419 case Sema::PCC_RecoveryInFunction:
1420 case Sema::PCC_Type:
Douglas Gregor5e35d592010-09-14 23:59:36 +00001421 case Sema::PCC_ParenthesizedExpression:
Douglas Gregor80039242011-02-15 20:33:25 +00001422 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001423 break;
1424 }
1425}
1426
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001427static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt);
1428static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt);
1429static void AddObjCVisibilityResults(const LangOptions &LangOpts,
Douglas Gregor48d46252010-01-13 21:54:15 +00001430 ResultBuilder &Results,
1431 bool NeedAt);
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001432static void AddObjCImplementationResults(const LangOptions &LangOpts,
Douglas Gregorf1934162010-01-13 21:24:21 +00001433 ResultBuilder &Results,
1434 bool NeedAt);
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001435static void AddObjCInterfaceResults(const LangOptions &LangOpts,
Douglas Gregorf1934162010-01-13 21:24:21 +00001436 ResultBuilder &Results,
1437 bool NeedAt);
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001438static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt);
Douglas Gregorf1934162010-01-13 21:24:21 +00001439
Douglas Gregorf4c33342010-05-28 00:22:41 +00001440static void AddTypedefResult(ResultBuilder &Results) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00001441 CodeCompletionBuilder Builder(Results.getAllocator(),
1442 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001443 Builder.AddTypedTextChunk("typedef");
1444 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1445 Builder.AddPlaceholderChunk("type");
1446 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1447 Builder.AddPlaceholderChunk("name");
1448 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00001449}
1450
John McCallfaf5fb42010-08-26 23:41:50 +00001451static bool WantTypesInContext(Sema::ParserCompletionContext CCC,
Douglas Gregor70febae2010-05-28 00:49:12 +00001452 const LangOptions &LangOpts) {
Douglas Gregor70febae2010-05-28 00:49:12 +00001453 switch (CCC) {
John McCallfaf5fb42010-08-26 23:41:50 +00001454 case Sema::PCC_Namespace:
1455 case Sema::PCC_Class:
1456 case Sema::PCC_ObjCInstanceVariableList:
1457 case Sema::PCC_Template:
1458 case Sema::PCC_MemberTemplate:
1459 case Sema::PCC_Statement:
1460 case Sema::PCC_RecoveryInFunction:
1461 case Sema::PCC_Type:
Douglas Gregor5e35d592010-09-14 23:59:36 +00001462 case Sema::PCC_ParenthesizedExpression:
Douglas Gregor80039242011-02-15 20:33:25 +00001463 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregor70febae2010-05-28 00:49:12 +00001464 return true;
1465
John McCallfaf5fb42010-08-26 23:41:50 +00001466 case Sema::PCC_Expression:
1467 case Sema::PCC_Condition:
Douglas Gregor5e35d592010-09-14 23:59:36 +00001468 return LangOpts.CPlusPlus;
1469
1470 case Sema::PCC_ObjCInterface:
1471 case Sema::PCC_ObjCImplementation:
Douglas Gregor70febae2010-05-28 00:49:12 +00001472 return false;
1473
John McCallfaf5fb42010-08-26 23:41:50 +00001474 case Sema::PCC_ForInit:
Douglas Gregor5e35d592010-09-14 23:59:36 +00001475 return LangOpts.CPlusPlus || LangOpts.ObjC1 || LangOpts.C99;
Douglas Gregor70febae2010-05-28 00:49:12 +00001476 }
David Blaikie8a40f702012-01-17 06:56:22 +00001477
1478 llvm_unreachable("Invalid ParserCompletionContext!");
Douglas Gregor70febae2010-05-28 00:49:12 +00001479}
1480
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00001481static PrintingPolicy getCompletionPrintingPolicy(const ASTContext &Context,
1482 const Preprocessor &PP) {
1483 PrintingPolicy Policy = Sema::getPrintingPolicy(Context, PP);
Douglas Gregore5c79d52011-10-18 21:20:17 +00001484 Policy.AnonymousTagLocations = false;
1485 Policy.SuppressStrongLifetime = true;
Douglas Gregor2e10cf92011-11-03 00:16:13 +00001486 Policy.SuppressUnwrittenScope = true;
Douglas Gregore5c79d52011-10-18 21:20:17 +00001487 return Policy;
1488}
1489
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00001490/// \brief Retrieve a printing policy suitable for code completion.
1491static PrintingPolicy getCompletionPrintingPolicy(Sema &S) {
1492 return getCompletionPrintingPolicy(S.Context, S.PP);
1493}
1494
Douglas Gregore5c79d52011-10-18 21:20:17 +00001495/// \brief Retrieve the string representation of the given type as a string
1496/// that has the appropriate lifetime for code completion.
1497///
1498/// This routine provides a fast path where we provide constant strings for
1499/// common type names.
1500static const char *GetCompletionTypeString(QualType T,
1501 ASTContext &Context,
1502 const PrintingPolicy &Policy,
1503 CodeCompletionAllocator &Allocator) {
1504 if (!T.getLocalQualifiers()) {
1505 // Built-in type names are constant strings.
1506 if (const BuiltinType *BT = dyn_cast<BuiltinType>(T))
Argyrios Kyrtzidisbbff3da2012-05-05 04:20:28 +00001507 return BT->getNameAsCString(Policy);
Douglas Gregore5c79d52011-10-18 21:20:17 +00001508
1509 // Anonymous tag types are constant strings.
1510 if (const TagType *TagT = dyn_cast<TagType>(T))
1511 if (TagDecl *Tag = TagT->getDecl())
John McCall5ea95772013-03-09 00:54:27 +00001512 if (!Tag->hasNameForLinkage()) {
Douglas Gregore5c79d52011-10-18 21:20:17 +00001513 switch (Tag->getTagKind()) {
1514 case TTK_Struct: return "struct <anonymous>";
Joao Matosdc86f942012-08-31 18:45:21 +00001515 case TTK_Interface: return "__interface <anonymous>";
1516 case TTK_Class: return "class <anonymous>";
Douglas Gregore5c79d52011-10-18 21:20:17 +00001517 case TTK_Union: return "union <anonymous>";
1518 case TTK_Enum: return "enum <anonymous>";
1519 }
1520 }
1521 }
1522
1523 // Slow path: format the type as a string.
1524 std::string Result;
1525 T.getAsStringInternal(Result, Policy);
1526 return Allocator.CopyString(Result);
1527}
1528
Douglas Gregord8c61782012-02-15 15:34:24 +00001529/// \brief Add a completion for "this", if we're in a member function.
1530static void addThisCompletion(Sema &S, ResultBuilder &Results) {
1531 QualType ThisTy = S.getCurrentThisType();
1532 if (ThisTy.isNull())
1533 return;
1534
1535 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00001536 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Douglas Gregord8c61782012-02-15 15:34:24 +00001537 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
1538 Builder.AddResultTypeChunk(GetCompletionTypeString(ThisTy,
1539 S.Context,
1540 Policy,
1541 Allocator));
1542 Builder.AddTypedTextChunk("this");
Joao Matosdc86f942012-08-31 18:45:21 +00001543 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
Douglas Gregord8c61782012-02-15 15:34:24 +00001544}
1545
Alex Lorenz8f4d3992017-02-13 23:19:40 +00001546static void AddStaticAssertResult(CodeCompletionBuilder &Builder,
1547 ResultBuilder &Results,
1548 const LangOptions &LangOpts) {
1549 if (!LangOpts.CPlusPlus11)
1550 return;
1551
1552 Builder.AddTypedTextChunk("static_assert");
1553 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1554 Builder.AddPlaceholderChunk("expression");
1555 Builder.AddChunk(CodeCompletionString::CK_Comma);
1556 Builder.AddPlaceholderChunk("message");
1557 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1558 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
1559}
1560
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001561/// \brief Add language constructs that show up for "ordinary" names.
John McCallfaf5fb42010-08-26 23:41:50 +00001562static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001563 Scope *S,
1564 Sema &SemaRef,
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001565 ResultBuilder &Results) {
Douglas Gregore5c79d52011-10-18 21:20:17 +00001566 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00001567 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001568
John McCall276321a2010-08-25 06:19:51 +00001569 typedef CodeCompletionResult Result;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001570 switch (CCC) {
John McCallfaf5fb42010-08-26 23:41:50 +00001571 case Sema::PCC_Namespace:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001572 if (SemaRef.getLangOpts().CPlusPlus) {
Douglas Gregorf4c33342010-05-28 00:22:41 +00001573 if (Results.includeCodePatterns()) {
1574 // namespace <identifier> { declarations }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001575 Builder.AddTypedTextChunk("namespace");
1576 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1577 Builder.AddPlaceholderChunk("identifier");
1578 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1579 Builder.AddPlaceholderChunk("declarations");
1580 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1581 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1582 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00001583 }
1584
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001585 // namespace identifier = identifier ;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001586 Builder.AddTypedTextChunk("namespace");
1587 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1588 Builder.AddPlaceholderChunk("name");
1589 Builder.AddChunk(CodeCompletionString::CK_Equal);
1590 Builder.AddPlaceholderChunk("namespace");
1591 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001592
1593 // Using directives
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001594 Builder.AddTypedTextChunk("using");
1595 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1596 Builder.AddTextChunk("namespace");
1597 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1598 Builder.AddPlaceholderChunk("identifier");
1599 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001600
1601 // asm(string-literal)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001602 Builder.AddTypedTextChunk("asm");
1603 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1604 Builder.AddPlaceholderChunk("string-literal");
1605 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1606 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001607
Douglas Gregorf4c33342010-05-28 00:22:41 +00001608 if (Results.includeCodePatterns()) {
1609 // Explicit template instantiation
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001610 Builder.AddTypedTextChunk("template");
1611 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1612 Builder.AddPlaceholderChunk("declaration");
1613 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00001614 }
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001615 }
Douglas Gregorf1934162010-01-13 21:24:21 +00001616
David Blaikiebbafb8a2012-03-11 07:00:24 +00001617 if (SemaRef.getLangOpts().ObjC1)
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001618 AddObjCTopLevelResults(Results, true);
Douglas Gregorf1934162010-01-13 21:24:21 +00001619
Douglas Gregorf4c33342010-05-28 00:22:41 +00001620 AddTypedefResult(Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001621 // Fall through
1622
John McCallfaf5fb42010-08-26 23:41:50 +00001623 case Sema::PCC_Class:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001624 if (SemaRef.getLangOpts().CPlusPlus) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001625 // Using declaration
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001626 Builder.AddTypedTextChunk("using");
1627 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1628 Builder.AddPlaceholderChunk("qualifier");
1629 Builder.AddTextChunk("::");
1630 Builder.AddPlaceholderChunk("name");
1631 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001632
Douglas Gregorf4c33342010-05-28 00:22:41 +00001633 // using typename qualifier::name (only in a dependent context)
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001634 if (SemaRef.CurContext->isDependentContext()) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001635 Builder.AddTypedTextChunk("using");
1636 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1637 Builder.AddTextChunk("typename");
1638 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1639 Builder.AddPlaceholderChunk("qualifier");
1640 Builder.AddTextChunk("::");
1641 Builder.AddPlaceholderChunk("name");
1642 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001643 }
1644
Alex Lorenz8f4d3992017-02-13 23:19:40 +00001645 AddStaticAssertResult(Builder, Results, SemaRef.getLangOpts());
1646
John McCallfaf5fb42010-08-26 23:41:50 +00001647 if (CCC == Sema::PCC_Class) {
Douglas Gregorf4c33342010-05-28 00:22:41 +00001648 AddTypedefResult(Results);
1649
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001650 // public:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001651 Builder.AddTypedTextChunk("public");
Douglas Gregor9489cdf2012-04-10 17:56:28 +00001652 if (Results.includeCodePatterns())
1653 Builder.AddChunk(CodeCompletionString::CK_Colon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001654 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001655
1656 // protected:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001657 Builder.AddTypedTextChunk("protected");
Douglas Gregor9489cdf2012-04-10 17:56:28 +00001658 if (Results.includeCodePatterns())
1659 Builder.AddChunk(CodeCompletionString::CK_Colon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001660 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001661
1662 // private:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001663 Builder.AddTypedTextChunk("private");
Douglas Gregor9489cdf2012-04-10 17:56:28 +00001664 if (Results.includeCodePatterns())
1665 Builder.AddChunk(CodeCompletionString::CK_Colon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001666 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001667 }
1668 }
1669 // Fall through
1670
John McCallfaf5fb42010-08-26 23:41:50 +00001671 case Sema::PCC_Template:
1672 case Sema::PCC_MemberTemplate:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001673 if (SemaRef.getLangOpts().CPlusPlus && Results.includeCodePatterns()) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001674 // template < parameters >
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001675 Builder.AddTypedTextChunk("template");
1676 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1677 Builder.AddPlaceholderChunk("parameters");
1678 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1679 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001680 }
1681
David Blaikiebbafb8a2012-03-11 07:00:24 +00001682 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
1683 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001684 break;
1685
John McCallfaf5fb42010-08-26 23:41:50 +00001686 case Sema::PCC_ObjCInterface:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001687 AddObjCInterfaceResults(SemaRef.getLangOpts(), Results, true);
1688 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
1689 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregorf1934162010-01-13 21:24:21 +00001690 break;
1691
John McCallfaf5fb42010-08-26 23:41:50 +00001692 case Sema::PCC_ObjCImplementation:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001693 AddObjCImplementationResults(SemaRef.getLangOpts(), Results, true);
1694 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
1695 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregorf1934162010-01-13 21:24:21 +00001696 break;
1697
John McCallfaf5fb42010-08-26 23:41:50 +00001698 case Sema::PCC_ObjCInstanceVariableList:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001699 AddObjCVisibilityResults(SemaRef.getLangOpts(), Results, true);
Douglas Gregor48d46252010-01-13 21:54:15 +00001700 break;
1701
John McCallfaf5fb42010-08-26 23:41:50 +00001702 case Sema::PCC_RecoveryInFunction:
1703 case Sema::PCC_Statement: {
Douglas Gregorf4c33342010-05-28 00:22:41 +00001704 AddTypedefResult(Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001705
David Blaikiebbafb8a2012-03-11 07:00:24 +00001706 if (SemaRef.getLangOpts().CPlusPlus && Results.includeCodePatterns() &&
1707 SemaRef.getLangOpts().CXXExceptions) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001708 Builder.AddTypedTextChunk("try");
1709 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1710 Builder.AddPlaceholderChunk("statements");
1711 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1712 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1713 Builder.AddTextChunk("catch");
1714 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1715 Builder.AddPlaceholderChunk("declaration");
1716 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1717 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1718 Builder.AddPlaceholderChunk("statements");
1719 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1720 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1721 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001722 }
David Blaikiebbafb8a2012-03-11 07:00:24 +00001723 if (SemaRef.getLangOpts().ObjC1)
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001724 AddObjCStatementResults(Results, true);
Douglas Gregorf1934162010-01-13 21:24:21 +00001725
Douglas Gregorf64acca2010-05-25 21:41:55 +00001726 if (Results.includeCodePatterns()) {
1727 // if (condition) { statements }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001728 Builder.AddTypedTextChunk("if");
1729 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00001730 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001731 Builder.AddPlaceholderChunk("condition");
Douglas Gregorf64acca2010-05-25 21:41:55 +00001732 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001733 Builder.AddPlaceholderChunk("expression");
1734 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1735 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1736 Builder.AddPlaceholderChunk("statements");
1737 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1738 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1739 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001740
Douglas Gregorf64acca2010-05-25 21:41:55 +00001741 // switch (condition) { }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001742 Builder.AddTypedTextChunk("switch");
1743 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00001744 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001745 Builder.AddPlaceholderChunk("condition");
Douglas Gregorf64acca2010-05-25 21:41:55 +00001746 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001747 Builder.AddPlaceholderChunk("expression");
1748 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1749 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1750 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1751 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1752 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf64acca2010-05-25 21:41:55 +00001753 }
1754
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001755 // Switch-specific statements.
John McCallaab3e412010-08-25 08:40:02 +00001756 if (!SemaRef.getCurFunction()->SwitchStack.empty()) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001757 // case expression:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001758 Builder.AddTypedTextChunk("case");
1759 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1760 Builder.AddPlaceholderChunk("expression");
1761 Builder.AddChunk(CodeCompletionString::CK_Colon);
1762 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001763
1764 // default:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001765 Builder.AddTypedTextChunk("default");
1766 Builder.AddChunk(CodeCompletionString::CK_Colon);
1767 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001768 }
1769
Douglas Gregorf64acca2010-05-25 21:41:55 +00001770 if (Results.includeCodePatterns()) {
1771 /// while (condition) { statements }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001772 Builder.AddTypedTextChunk("while");
1773 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00001774 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001775 Builder.AddPlaceholderChunk("condition");
Douglas Gregorf64acca2010-05-25 21:41:55 +00001776 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001777 Builder.AddPlaceholderChunk("expression");
1778 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1779 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1780 Builder.AddPlaceholderChunk("statements");
1781 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1782 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1783 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf64acca2010-05-25 21:41:55 +00001784
1785 // do { statements } while ( expression );
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001786 Builder.AddTypedTextChunk("do");
1787 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1788 Builder.AddPlaceholderChunk("statements");
1789 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1790 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1791 Builder.AddTextChunk("while");
1792 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1793 Builder.AddPlaceholderChunk("expression");
1794 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1795 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001796
Douglas Gregorf64acca2010-05-25 21:41:55 +00001797 // for ( for-init-statement ; condition ; expression ) { statements }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001798 Builder.AddTypedTextChunk("for");
1799 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00001800 if (SemaRef.getLangOpts().CPlusPlus || SemaRef.getLangOpts().C99)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001801 Builder.AddPlaceholderChunk("init-statement");
Douglas Gregorf64acca2010-05-25 21:41:55 +00001802 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001803 Builder.AddPlaceholderChunk("init-expression");
1804 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
1805 Builder.AddPlaceholderChunk("condition");
1806 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
1807 Builder.AddPlaceholderChunk("inc-expression");
1808 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1809 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1810 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1811 Builder.AddPlaceholderChunk("statements");
1812 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1813 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1814 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf64acca2010-05-25 21:41:55 +00001815 }
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001816
1817 if (S->getContinueParent()) {
1818 // continue ;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001819 Builder.AddTypedTextChunk("continue");
1820 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001821 }
1822
1823 if (S->getBreakParent()) {
1824 // break ;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001825 Builder.AddTypedTextChunk("break");
1826 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001827 }
1828
1829 // "return expression ;" or "return ;", depending on whether we
1830 // know the function is void or not.
1831 bool isVoid = false;
1832 if (FunctionDecl *Function = dyn_cast<FunctionDecl>(SemaRef.CurContext))
Alp Toker314cc812014-01-25 16:55:45 +00001833 isVoid = Function->getReturnType()->isVoidType();
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001834 else if (ObjCMethodDecl *Method
1835 = dyn_cast<ObjCMethodDecl>(SemaRef.CurContext))
Alp Toker314cc812014-01-25 16:55:45 +00001836 isVoid = Method->getReturnType()->isVoidType();
Douglas Gregor9a28e842010-03-01 23:15:13 +00001837 else if (SemaRef.getCurBlock() &&
1838 !SemaRef.getCurBlock()->ReturnType.isNull())
1839 isVoid = SemaRef.getCurBlock()->ReturnType->isVoidType();
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001840 Builder.AddTypedTextChunk("return");
Douglas Gregor44272ca2010-02-18 04:06:48 +00001841 if (!isVoid) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001842 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1843 Builder.AddPlaceholderChunk("expression");
Douglas Gregor44272ca2010-02-18 04:06:48 +00001844 }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001845 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001846
Douglas Gregorf4c33342010-05-28 00:22:41 +00001847 // goto identifier ;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001848 Builder.AddTypedTextChunk("goto");
1849 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1850 Builder.AddPlaceholderChunk("label");
1851 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001852
Douglas Gregorf4c33342010-05-28 00:22:41 +00001853 // Using directives
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001854 Builder.AddTypedTextChunk("using");
1855 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1856 Builder.AddTextChunk("namespace");
1857 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1858 Builder.AddPlaceholderChunk("identifier");
1859 Results.AddResult(Result(Builder.TakeString()));
Alex Lorenz8f4d3992017-02-13 23:19:40 +00001860
1861 AddStaticAssertResult(Builder, Results, SemaRef.getLangOpts());
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001862 }
1863
1864 // Fall through (for statement expressions).
John McCallfaf5fb42010-08-26 23:41:50 +00001865 case Sema::PCC_ForInit:
1866 case Sema::PCC_Condition:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001867 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001868 // Fall through: conditions and statements can have expressions.
Galina Kistanova33399112017-06-03 06:35:06 +00001869 LLVM_FALLTHROUGH;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001870
Douglas Gregor5e35d592010-09-14 23:59:36 +00001871 case Sema::PCC_ParenthesizedExpression:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001872 if (SemaRef.getLangOpts().ObjCAutoRefCount &&
John McCall31168b02011-06-15 23:02:42 +00001873 CCC == Sema::PCC_ParenthesizedExpression) {
1874 // (__bridge <type>)<expression>
1875 Builder.AddTypedTextChunk("__bridge");
1876 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1877 Builder.AddPlaceholderChunk("type");
1878 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1879 Builder.AddPlaceholderChunk("expression");
1880 Results.AddResult(Result(Builder.TakeString()));
1881
1882 // (__bridge_transfer <Objective-C type>)<expression>
1883 Builder.AddTypedTextChunk("__bridge_transfer");
1884 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1885 Builder.AddPlaceholderChunk("Objective-C type");
1886 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1887 Builder.AddPlaceholderChunk("expression");
1888 Results.AddResult(Result(Builder.TakeString()));
1889
1890 // (__bridge_retained <CF type>)<expression>
1891 Builder.AddTypedTextChunk("__bridge_retained");
1892 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1893 Builder.AddPlaceholderChunk("CF type");
1894 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1895 Builder.AddPlaceholderChunk("expression");
1896 Results.AddResult(Result(Builder.TakeString()));
1897 }
1898 // Fall through
Galina Kistanova33399112017-06-03 06:35:06 +00001899 LLVM_FALLTHROUGH;
John McCall31168b02011-06-15 23:02:42 +00001900
John McCallfaf5fb42010-08-26 23:41:50 +00001901 case Sema::PCC_Expression: {
David Blaikiebbafb8a2012-03-11 07:00:24 +00001902 if (SemaRef.getLangOpts().CPlusPlus) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001903 // 'this', if we're in a non-static member function.
Douglas Gregord8c61782012-02-15 15:34:24 +00001904 addThisCompletion(SemaRef, Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001905
Douglas Gregore5c79d52011-10-18 21:20:17 +00001906 // true
1907 Builder.AddResultTypeChunk("bool");
1908 Builder.AddTypedTextChunk("true");
1909 Results.AddResult(Result(Builder.TakeString()));
1910
1911 // false
1912 Builder.AddResultTypeChunk("bool");
1913 Builder.AddTypedTextChunk("false");
1914 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001915
David Blaikiebbafb8a2012-03-11 07:00:24 +00001916 if (SemaRef.getLangOpts().RTTI) {
Douglas Gregorc05f6572011-04-12 02:47:21 +00001917 // dynamic_cast < type-id > ( expression )
1918 Builder.AddTypedTextChunk("dynamic_cast");
1919 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1920 Builder.AddPlaceholderChunk("type");
1921 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1922 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1923 Builder.AddPlaceholderChunk("expression");
1924 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1925 Results.AddResult(Result(Builder.TakeString()));
1926 }
Douglas Gregorf4c33342010-05-28 00:22:41 +00001927
1928 // static_cast < type-id > ( expression )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001929 Builder.AddTypedTextChunk("static_cast");
1930 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1931 Builder.AddPlaceholderChunk("type");
1932 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1933 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1934 Builder.AddPlaceholderChunk("expression");
1935 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1936 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001937
Douglas Gregorf4c33342010-05-28 00:22:41 +00001938 // reinterpret_cast < type-id > ( expression )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001939 Builder.AddTypedTextChunk("reinterpret_cast");
1940 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1941 Builder.AddPlaceholderChunk("type");
1942 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1943 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1944 Builder.AddPlaceholderChunk("expression");
1945 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1946 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001947
Douglas Gregorf4c33342010-05-28 00:22:41 +00001948 // const_cast < type-id > ( expression )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001949 Builder.AddTypedTextChunk("const_cast");
1950 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1951 Builder.AddPlaceholderChunk("type");
1952 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1953 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1954 Builder.AddPlaceholderChunk("expression");
1955 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1956 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001957
David Blaikiebbafb8a2012-03-11 07:00:24 +00001958 if (SemaRef.getLangOpts().RTTI) {
Douglas Gregorc05f6572011-04-12 02:47:21 +00001959 // typeid ( expression-or-type )
Douglas Gregore5c79d52011-10-18 21:20:17 +00001960 Builder.AddResultTypeChunk("std::type_info");
Douglas Gregorc05f6572011-04-12 02:47:21 +00001961 Builder.AddTypedTextChunk("typeid");
1962 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1963 Builder.AddPlaceholderChunk("expression-or-type");
1964 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1965 Results.AddResult(Result(Builder.TakeString()));
1966 }
1967
Douglas Gregorf4c33342010-05-28 00:22:41 +00001968 // new T ( ... )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001969 Builder.AddTypedTextChunk("new");
1970 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1971 Builder.AddPlaceholderChunk("type");
1972 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1973 Builder.AddPlaceholderChunk("expressions");
1974 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1975 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001976
Douglas Gregorf4c33342010-05-28 00:22:41 +00001977 // new T [ ] ( ... )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001978 Builder.AddTypedTextChunk("new");
1979 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1980 Builder.AddPlaceholderChunk("type");
1981 Builder.AddChunk(CodeCompletionString::CK_LeftBracket);
1982 Builder.AddPlaceholderChunk("size");
1983 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
1984 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1985 Builder.AddPlaceholderChunk("expressions");
1986 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1987 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001988
Douglas Gregorf4c33342010-05-28 00:22:41 +00001989 // delete expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00001990 Builder.AddResultTypeChunk("void");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001991 Builder.AddTypedTextChunk("delete");
1992 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1993 Builder.AddPlaceholderChunk("expression");
1994 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001995
Douglas Gregorf4c33342010-05-28 00:22:41 +00001996 // delete [] expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00001997 Builder.AddResultTypeChunk("void");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001998 Builder.AddTypedTextChunk("delete");
1999 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2000 Builder.AddChunk(CodeCompletionString::CK_LeftBracket);
2001 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
2002 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2003 Builder.AddPlaceholderChunk("expression");
2004 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002005
David Blaikiebbafb8a2012-03-11 07:00:24 +00002006 if (SemaRef.getLangOpts().CXXExceptions) {
Douglas Gregorc05f6572011-04-12 02:47:21 +00002007 // throw expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00002008 Builder.AddResultTypeChunk("void");
Douglas Gregorc05f6572011-04-12 02:47:21 +00002009 Builder.AddTypedTextChunk("throw");
2010 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2011 Builder.AddPlaceholderChunk("expression");
2012 Results.AddResult(Result(Builder.TakeString()));
2013 }
Douglas Gregor4205fef2011-10-18 16:29:03 +00002014
Douglas Gregora2db7932010-05-26 22:00:08 +00002015 // FIXME: Rethrow?
Douglas Gregor4205fef2011-10-18 16:29:03 +00002016
Richard Smith2bf7fdb2013-01-02 11:42:31 +00002017 if (SemaRef.getLangOpts().CPlusPlus11) {
Douglas Gregor4205fef2011-10-18 16:29:03 +00002018 // nullptr
Douglas Gregore5c79d52011-10-18 21:20:17 +00002019 Builder.AddResultTypeChunk("std::nullptr_t");
Douglas Gregor4205fef2011-10-18 16:29:03 +00002020 Builder.AddTypedTextChunk("nullptr");
2021 Results.AddResult(Result(Builder.TakeString()));
2022
2023 // alignof
Douglas Gregore5c79d52011-10-18 21:20:17 +00002024 Builder.AddResultTypeChunk("size_t");
Douglas Gregor4205fef2011-10-18 16:29:03 +00002025 Builder.AddTypedTextChunk("alignof");
2026 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2027 Builder.AddPlaceholderChunk("type");
2028 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2029 Results.AddResult(Result(Builder.TakeString()));
2030
2031 // noexcept
Douglas Gregore5c79d52011-10-18 21:20:17 +00002032 Builder.AddResultTypeChunk("bool");
Douglas Gregor4205fef2011-10-18 16:29:03 +00002033 Builder.AddTypedTextChunk("noexcept");
2034 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2035 Builder.AddPlaceholderChunk("expression");
2036 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2037 Results.AddResult(Result(Builder.TakeString()));
2038
2039 // sizeof... expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00002040 Builder.AddResultTypeChunk("size_t");
Douglas Gregor4205fef2011-10-18 16:29:03 +00002041 Builder.AddTypedTextChunk("sizeof...");
2042 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2043 Builder.AddPlaceholderChunk("parameter-pack");
2044 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2045 Results.AddResult(Result(Builder.TakeString()));
2046 }
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002047 }
2048
David Blaikiebbafb8a2012-03-11 07:00:24 +00002049 if (SemaRef.getLangOpts().ObjC1) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002050 // Add "super", if we're in an Objective-C class with a superclass.
Ted Kremenek305a0a72010-05-31 21:43:10 +00002051 if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl()) {
2052 // The interface can be NULL.
2053 if (ObjCInterfaceDecl *ID = Method->getClassInterface())
Douglas Gregore5c79d52011-10-18 21:20:17 +00002054 if (ID->getSuperClass()) {
2055 std::string SuperType;
2056 SuperType = ID->getSuperClass()->getNameAsString();
2057 if (Method->isInstanceMethod())
2058 SuperType += " *";
2059
2060 Builder.AddResultTypeChunk(Allocator.CopyString(SuperType));
2061 Builder.AddTypedTextChunk("super");
2062 Results.AddResult(Result(Builder.TakeString()));
2063 }
Ted Kremenek305a0a72010-05-31 21:43:10 +00002064 }
2065
Douglas Gregorf98e6a22010-01-13 23:51:12 +00002066 AddObjCExpressionResults(Results, true);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002067 }
2068
Jordan Rose58d54722012-06-30 21:33:57 +00002069 if (SemaRef.getLangOpts().C11) {
2070 // _Alignof
2071 Builder.AddResultTypeChunk("size_t");
Richard Smith20e883e2015-04-29 23:20:19 +00002072 if (SemaRef.PP.isMacroDefined("alignof"))
Jordan Rose58d54722012-06-30 21:33:57 +00002073 Builder.AddTypedTextChunk("alignof");
2074 else
2075 Builder.AddTypedTextChunk("_Alignof");
2076 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2077 Builder.AddPlaceholderChunk("type");
2078 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2079 Results.AddResult(Result(Builder.TakeString()));
2080 }
2081
Douglas Gregorf4c33342010-05-28 00:22:41 +00002082 // sizeof expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00002083 Builder.AddResultTypeChunk("size_t");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002084 Builder.AddTypedTextChunk("sizeof");
2085 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2086 Builder.AddPlaceholderChunk("expression-or-type");
2087 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2088 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002089 break;
2090 }
Douglas Gregor99fa2642010-08-24 01:06:58 +00002091
John McCallfaf5fb42010-08-26 23:41:50 +00002092 case Sema::PCC_Type:
Douglas Gregor80039242011-02-15 20:33:25 +00002093 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregor99fa2642010-08-24 01:06:58 +00002094 break;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002095 }
2096
David Blaikiebbafb8a2012-03-11 07:00:24 +00002097 if (WantTypesInContext(CCC, SemaRef.getLangOpts()))
2098 AddTypeSpecifierResults(SemaRef.getLangOpts(), Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002099
David Blaikiebbafb8a2012-03-11 07:00:24 +00002100 if (SemaRef.getLangOpts().CPlusPlus && CCC != Sema::PCC_Type)
Douglas Gregor78a21012010-01-14 16:01:26 +00002101 Results.AddResult(Result("operator"));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002102}
2103
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002104/// \brief If the given declaration has an associated type, add it as a result
2105/// type chunk.
2106static void AddResultTypeChunk(ASTContext &Context,
Douglas Gregor75acd922011-09-27 23:30:47 +00002107 const PrintingPolicy &Policy,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002108 const NamedDecl *ND,
Douglas Gregorc3425b12015-07-07 06:20:19 +00002109 QualType BaseType,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002110 CodeCompletionBuilder &Result) {
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002111 if (!ND)
2112 return;
Douglas Gregor0212fd72010-09-21 16:06:22 +00002113
2114 // Skip constructors and conversion functions, which have their return types
2115 // built into their names.
2116 if (isa<CXXConstructorDecl>(ND) || isa<CXXConversionDecl>(ND))
2117 return;
2118
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002119 // Determine the type of the declaration (if it has a type).
Alp Tokera2794f92014-01-22 07:29:52 +00002120 QualType T;
2121 if (const FunctionDecl *Function = ND->getAsFunction())
Alp Toker314cc812014-01-25 16:55:45 +00002122 T = Function->getReturnType();
Douglas Gregorc3425b12015-07-07 06:20:19 +00002123 else if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND)) {
2124 if (!BaseType.isNull())
2125 T = Method->getSendResultType(BaseType);
2126 else
2127 T = Method->getReturnType();
2128 } else if (const EnumConstantDecl *Enumerator = dyn_cast<EnumConstantDecl>(ND))
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002129 T = Context.getTypeDeclType(cast<TypeDecl>(Enumerator->getDeclContext()));
2130 else if (isa<UnresolvedUsingValueDecl>(ND)) {
2131 /* Do nothing: ignore unresolved using declarations*/
Douglas Gregorc3425b12015-07-07 06:20:19 +00002132 } else if (const ObjCIvarDecl *Ivar = dyn_cast<ObjCIvarDecl>(ND)) {
2133 if (!BaseType.isNull())
2134 T = Ivar->getUsageType(BaseType);
2135 else
2136 T = Ivar->getType();
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002137 } else if (const ValueDecl *Value = dyn_cast<ValueDecl>(ND)) {
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002138 T = Value->getType();
Douglas Gregorc3425b12015-07-07 06:20:19 +00002139 } else if (const ObjCPropertyDecl *Property = dyn_cast<ObjCPropertyDecl>(ND)) {
2140 if (!BaseType.isNull())
2141 T = Property->getUsageType(BaseType);
2142 else
2143 T = Property->getType();
2144 }
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002145
2146 if (T.isNull() || Context.hasSameType(T, Context.DependentTy))
2147 return;
2148
Douglas Gregor75acd922011-09-27 23:30:47 +00002149 Result.AddResultTypeChunk(GetCompletionTypeString(T, Context, Policy,
Douglas Gregor304f9b02011-02-01 21:15:40 +00002150 Result.getAllocator()));
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002151}
2152
Richard Smith20e883e2015-04-29 23:20:19 +00002153static void MaybeAddSentinel(Preprocessor &PP,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002154 const NamedDecl *FunctionOrMethod,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002155 CodeCompletionBuilder &Result) {
Douglas Gregordbb71db2010-08-23 23:51:41 +00002156 if (SentinelAttr *Sentinel = FunctionOrMethod->getAttr<SentinelAttr>())
2157 if (Sentinel->getSentinel() == 0) {
Richard Smith20e883e2015-04-29 23:20:19 +00002158 if (PP.getLangOpts().ObjC1 && PP.isMacroDefined("nil"))
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002159 Result.AddTextChunk(", nil");
Richard Smith20e883e2015-04-29 23:20:19 +00002160 else if (PP.isMacroDefined("NULL"))
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002161 Result.AddTextChunk(", NULL");
Douglas Gregordbb71db2010-08-23 23:51:41 +00002162 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002163 Result.AddTextChunk(", (void*)0");
Douglas Gregordbb71db2010-08-23 23:51:41 +00002164 }
2165}
2166
Douglas Gregor86b42682015-06-19 18:27:52 +00002167static std::string formatObjCParamQualifiers(unsigned ObjCQuals,
2168 QualType &Type) {
Douglas Gregor8f08d742011-07-30 07:55:26 +00002169 std::string Result;
2170 if (ObjCQuals & Decl::OBJC_TQ_In)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002171 Result += "in ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002172 else if (ObjCQuals & Decl::OBJC_TQ_Inout)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002173 Result += "inout ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002174 else if (ObjCQuals & Decl::OBJC_TQ_Out)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002175 Result += "out ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002176 if (ObjCQuals & Decl::OBJC_TQ_Bycopy)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002177 Result += "bycopy ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002178 else if (ObjCQuals & Decl::OBJC_TQ_Byref)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002179 Result += "byref ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002180 if (ObjCQuals & Decl::OBJC_TQ_Oneway)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002181 Result += "oneway ";
Douglas Gregor86b42682015-06-19 18:27:52 +00002182 if (ObjCQuals & Decl::OBJC_TQ_CSNullability) {
2183 if (auto nullability = AttributedType::stripOuterNullability(Type)) {
2184 switch (*nullability) {
2185 case NullabilityKind::NonNull:
2186 Result += "nonnull ";
2187 break;
2188
2189 case NullabilityKind::Nullable:
2190 Result += "nullable ";
2191 break;
2192
2193 case NullabilityKind::Unspecified:
2194 Result += "null_unspecified ";
2195 break;
2196 }
2197 }
2198 }
Douglas Gregor8f08d742011-07-30 07:55:26 +00002199 return Result;
2200}
2201
Alex Lorenza1951202016-10-18 10:35:27 +00002202/// \brief Tries to find the most appropriate type location for an Objective-C
2203/// block placeholder.
2204///
2205/// This function ignores things like typedefs and qualifiers in order to
2206/// present the most relevant and accurate block placeholders in code completion
2207/// results.
2208static void findTypeLocationForBlockDecl(const TypeSourceInfo *TSInfo,
2209 FunctionTypeLoc &Block,
2210 FunctionProtoTypeLoc &BlockProto,
2211 bool SuppressBlock = false) {
2212 if (!TSInfo)
2213 return;
2214 TypeLoc TL = TSInfo->getTypeLoc().getUnqualifiedLoc();
2215 while (true) {
2216 // Look through typedefs.
2217 if (!SuppressBlock) {
2218 if (TypedefTypeLoc TypedefTL = TL.getAs<TypedefTypeLoc>()) {
2219 if (TypeSourceInfo *InnerTSInfo =
2220 TypedefTL.getTypedefNameDecl()->getTypeSourceInfo()) {
2221 TL = InnerTSInfo->getTypeLoc().getUnqualifiedLoc();
2222 continue;
2223 }
2224 }
2225
2226 // Look through qualified types
2227 if (QualifiedTypeLoc QualifiedTL = TL.getAs<QualifiedTypeLoc>()) {
2228 TL = QualifiedTL.getUnqualifiedLoc();
2229 continue;
2230 }
2231
2232 if (AttributedTypeLoc AttrTL = TL.getAs<AttributedTypeLoc>()) {
2233 TL = AttrTL.getModifiedLoc();
2234 continue;
2235 }
2236 }
2237
2238 // Try to get the function prototype behind the block pointer type,
2239 // then we're done.
2240 if (BlockPointerTypeLoc BlockPtr = TL.getAs<BlockPointerTypeLoc>()) {
2241 TL = BlockPtr.getPointeeLoc().IgnoreParens();
2242 Block = TL.getAs<FunctionTypeLoc>();
2243 BlockProto = TL.getAs<FunctionProtoTypeLoc>();
2244 }
2245 break;
2246 }
2247}
2248
Alex Lorenz920ae142016-10-18 10:38:58 +00002249static std::string
2250formatBlockPlaceholder(const PrintingPolicy &Policy, const NamedDecl *BlockDecl,
2251 FunctionTypeLoc &Block, FunctionProtoTypeLoc &BlockProto,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002252 bool SuppressBlockName = false,
Alex Lorenz920ae142016-10-18 10:38:58 +00002253 bool SuppressBlock = false,
2254 Optional<ArrayRef<QualType>> ObjCSubsts = None);
2255
Richard Smith20e883e2015-04-29 23:20:19 +00002256static std::string FormatFunctionParameter(const PrintingPolicy &Policy,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002257 const ParmVarDecl *Param,
Douglas Gregord793e7c2011-10-18 04:23:19 +00002258 bool SuppressName = false,
Douglas Gregorc3425b12015-07-07 06:20:19 +00002259 bool SuppressBlock = false,
2260 Optional<ArrayRef<QualType>> ObjCSubsts = None) {
Douglas Gregore90dd002010-08-24 16:15:59 +00002261 bool ObjCMethodParam = isa<ObjCMethodDecl>(Param->getDeclContext());
2262 if (Param->getType()->isDependentType() ||
2263 !Param->getType()->isBlockPointerType()) {
2264 // The argument for a dependent or non-block parameter is a placeholder
2265 // containing that parameter's type.
2266 std::string Result;
2267
Douglas Gregor981a0c42010-08-29 19:47:46 +00002268 if (Param->getIdentifier() && !ObjCMethodParam && !SuppressName)
Douglas Gregore90dd002010-08-24 16:15:59 +00002269 Result = Param->getIdentifier()->getName();
2270
Douglas Gregor86b42682015-06-19 18:27:52 +00002271 QualType Type = Param->getType();
Douglas Gregorc3425b12015-07-07 06:20:19 +00002272 if (ObjCSubsts)
2273 Type = Type.substObjCTypeArgs(Param->getASTContext(), *ObjCSubsts,
2274 ObjCSubstitutionContext::Parameter);
Douglas Gregore90dd002010-08-24 16:15:59 +00002275 if (ObjCMethodParam) {
Douglas Gregor86b42682015-06-19 18:27:52 +00002276 Result = "(" + formatObjCParamQualifiers(Param->getObjCDeclQualifier(),
2277 Type);
2278 Result += Type.getAsString(Policy) + ")";
Douglas Gregor981a0c42010-08-29 19:47:46 +00002279 if (Param->getIdentifier() && !SuppressName)
Douglas Gregore90dd002010-08-24 16:15:59 +00002280 Result += Param->getIdentifier()->getName();
Douglas Gregor86b42682015-06-19 18:27:52 +00002281 } else {
2282 Type.getAsStringInternal(Result, Policy);
Douglas Gregore90dd002010-08-24 16:15:59 +00002283 }
2284 return Result;
2285 }
Alex Lorenza1951202016-10-18 10:35:27 +00002286
Douglas Gregore90dd002010-08-24 16:15:59 +00002287 // The argument for a block pointer parameter is a block literal with
2288 // the appropriate type.
David Blaikie6adc78e2013-02-18 22:06:02 +00002289 FunctionTypeLoc Block;
2290 FunctionProtoTypeLoc BlockProto;
Alex Lorenza1951202016-10-18 10:35:27 +00002291 findTypeLocationForBlockDecl(Param->getTypeSourceInfo(), Block, BlockProto,
2292 SuppressBlock);
Alex Lorenz6bf4a582017-03-13 15:43:42 +00002293 // Try to retrieve the block type information from the property if this is a
2294 // parameter in a setter.
2295 if (!Block && ObjCMethodParam &&
2296 cast<ObjCMethodDecl>(Param->getDeclContext())->isPropertyAccessor()) {
2297 if (const auto *PD = cast<ObjCMethodDecl>(Param->getDeclContext())
2298 ->findPropertyDecl(/*CheckOverrides=*/false))
2299 findTypeLocationForBlockDecl(PD->getTypeSourceInfo(), Block, BlockProto,
2300 SuppressBlock);
2301 }
Douglas Gregore90dd002010-08-24 16:15:59 +00002302
2303 if (!Block) {
2304 // We were unable to find a FunctionProtoTypeLoc with parameter names
2305 // for the block; just use the parameter type as a placeholder.
2306 std::string Result;
Douglas Gregord793e7c2011-10-18 04:23:19 +00002307 if (!ObjCMethodParam && Param->getIdentifier())
2308 Result = Param->getIdentifier()->getName();
2309
Douglas Gregor86b42682015-06-19 18:27:52 +00002310 QualType Type = Param->getType().getUnqualifiedType();
Douglas Gregore90dd002010-08-24 16:15:59 +00002311
2312 if (ObjCMethodParam) {
Alex Lorenz01bcfc12016-11-23 16:28:34 +00002313 Result = Type.getAsString(Policy);
2314 std::string Quals =
2315 formatObjCParamQualifiers(Param->getObjCDeclQualifier(), Type);
2316 if (!Quals.empty())
2317 Result = "(" + Quals + " " + Result + ")";
2318 if (Result.back() != ')')
2319 Result += " ";
Douglas Gregore90dd002010-08-24 16:15:59 +00002320 if (Param->getIdentifier())
2321 Result += Param->getIdentifier()->getName();
Douglas Gregor86b42682015-06-19 18:27:52 +00002322 } else {
2323 Type.getAsStringInternal(Result, Policy);
Douglas Gregore90dd002010-08-24 16:15:59 +00002324 }
2325
2326 return Result;
2327 }
Alex Lorenz01bcfc12016-11-23 16:28:34 +00002328
Douglas Gregore90dd002010-08-24 16:15:59 +00002329 // We have the function prototype behind the block pointer type, as it was
2330 // written in the source.
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002331 return formatBlockPlaceholder(Policy, Param, Block, BlockProto,
2332 /*SuppressBlockName=*/false, SuppressBlock,
Alex Lorenz920ae142016-10-18 10:38:58 +00002333 ObjCSubsts);
2334}
2335
2336/// \brief Returns a placeholder string that corresponds to an Objective-C block
2337/// declaration.
2338///
2339/// \param BlockDecl A declaration with an Objective-C block type.
2340///
2341/// \param Block The most relevant type location for that block type.
2342///
2343/// \param SuppressBlockName Determines wether or not the name of the block
2344/// declaration is included in the resulting string.
2345static std::string
2346formatBlockPlaceholder(const PrintingPolicy &Policy, const NamedDecl *BlockDecl,
2347 FunctionTypeLoc &Block, FunctionProtoTypeLoc &BlockProto,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002348 bool SuppressBlockName, bool SuppressBlock,
Alex Lorenz920ae142016-10-18 10:38:58 +00002349 Optional<ArrayRef<QualType>> ObjCSubsts) {
Douglas Gregor67da50e2010-09-08 22:47:51 +00002350 std::string Result;
Alp Toker314cc812014-01-25 16:55:45 +00002351 QualType ResultType = Block.getTypePtr()->getReturnType();
Douglas Gregorc3425b12015-07-07 06:20:19 +00002352 if (ObjCSubsts)
Alex Lorenz920ae142016-10-18 10:38:58 +00002353 ResultType =
2354 ResultType.substObjCTypeArgs(BlockDecl->getASTContext(), *ObjCSubsts,
2355 ObjCSubstitutionContext::Result);
Douglas Gregord793e7c2011-10-18 04:23:19 +00002356 if (!ResultType->isVoidType() || SuppressBlock)
John McCall31168b02011-06-15 23:02:42 +00002357 ResultType.getAsStringInternal(Result, Policy);
Douglas Gregord793e7c2011-10-18 04:23:19 +00002358
2359 // Format the parameter list.
2360 std::string Params;
Alp Tokerb3fd5cf2014-01-21 00:32:38 +00002361 if (!BlockProto || Block.getNumParams() == 0) {
David Blaikie6adc78e2013-02-18 22:06:02 +00002362 if (BlockProto && BlockProto.getTypePtr()->isVariadic())
Douglas Gregord793e7c2011-10-18 04:23:19 +00002363 Params = "(...)";
Douglas Gregoraf25cfa2010-10-02 23:49:58 +00002364 else
Douglas Gregord793e7c2011-10-18 04:23:19 +00002365 Params = "(void)";
Douglas Gregor67da50e2010-09-08 22:47:51 +00002366 } else {
Douglas Gregord793e7c2011-10-18 04:23:19 +00002367 Params += "(";
Alp Tokerb3fd5cf2014-01-21 00:32:38 +00002368 for (unsigned I = 0, N = Block.getNumParams(); I != N; ++I) {
Douglas Gregor67da50e2010-09-08 22:47:51 +00002369 if (I)
Douglas Gregord793e7c2011-10-18 04:23:19 +00002370 Params += ", ";
Richard Smith20e883e2015-04-29 23:20:19 +00002371 Params += FormatFunctionParameter(Policy, Block.getParam(I),
Alp Tokerb3fd5cf2014-01-21 00:32:38 +00002372 /*SuppressName=*/false,
Alex Lorenz920ae142016-10-18 10:38:58 +00002373 /*SuppressBlock=*/true, ObjCSubsts);
Alp Tokerb3fd5cf2014-01-21 00:32:38 +00002374
David Blaikie6adc78e2013-02-18 22:06:02 +00002375 if (I == N - 1 && BlockProto.getTypePtr()->isVariadic())
Douglas Gregord793e7c2011-10-18 04:23:19 +00002376 Params += ", ...";
Douglas Gregor67da50e2010-09-08 22:47:51 +00002377 }
Douglas Gregord793e7c2011-10-18 04:23:19 +00002378 Params += ")";
Douglas Gregor400f5972010-08-31 05:13:43 +00002379 }
Alex Lorenz920ae142016-10-18 10:38:58 +00002380
Douglas Gregord793e7c2011-10-18 04:23:19 +00002381 if (SuppressBlock) {
2382 // Format as a parameter.
2383 Result = Result + " (^";
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002384 if (!SuppressBlockName && BlockDecl->getIdentifier())
Alex Lorenz920ae142016-10-18 10:38:58 +00002385 Result += BlockDecl->getIdentifier()->getName();
Douglas Gregord793e7c2011-10-18 04:23:19 +00002386 Result += ")";
2387 Result += Params;
2388 } else {
2389 // Format as a block literal argument.
2390 Result = '^' + Result;
2391 Result += Params;
Alex Lorenz920ae142016-10-18 10:38:58 +00002392
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002393 if (!SuppressBlockName && BlockDecl->getIdentifier())
Alex Lorenz920ae142016-10-18 10:38:58 +00002394 Result += BlockDecl->getIdentifier()->getName();
Douglas Gregord793e7c2011-10-18 04:23:19 +00002395 }
Alex Lorenz920ae142016-10-18 10:38:58 +00002396
Douglas Gregore90dd002010-08-24 16:15:59 +00002397 return Result;
2398}
2399
Douglas Gregor3545ff42009-09-21 16:56:56 +00002400/// \brief Add function parameter chunks to the given code completion string.
Richard Smith20e883e2015-04-29 23:20:19 +00002401static void AddFunctionParameterChunks(Preprocessor &PP,
Douglas Gregor75acd922011-09-27 23:30:47 +00002402 const PrintingPolicy &Policy,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002403 const FunctionDecl *Function,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002404 CodeCompletionBuilder &Result,
2405 unsigned Start = 0,
2406 bool InOptional = false) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002407 bool FirstParameter = true;
Douglas Gregor9eb77012009-11-07 00:00:49 +00002408
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002409 for (unsigned P = Start, N = Function->getNumParams(); P != N; ++P) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002410 const ParmVarDecl *Param = Function->getParamDecl(P);
Douglas Gregor3545ff42009-09-21 16:56:56 +00002411
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002412 if (Param->hasDefaultArg() && !InOptional) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002413 // When we see an optional default argument, put that argument and
2414 // the remaining default arguments into a new, optional string.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00002415 CodeCompletionBuilder Opt(Result.getAllocator(),
2416 Result.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002417 if (!FirstParameter)
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002418 Opt.AddChunk(CodeCompletionString::CK_Comma);
Richard Smith20e883e2015-04-29 23:20:19 +00002419 AddFunctionParameterChunks(PP, Policy, Function, Opt, P, true);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002420 Result.AddOptionalChunk(Opt.TakeString());
2421 break;
Douglas Gregor3545ff42009-09-21 16:56:56 +00002422 }
2423
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002424 if (FirstParameter)
2425 FirstParameter = false;
2426 else
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002427 Result.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002428
2429 InOptional = false;
Douglas Gregor3545ff42009-09-21 16:56:56 +00002430
2431 // Format the placeholder string.
Richard Smith20e883e2015-04-29 23:20:19 +00002432 std::string PlaceholderStr = FormatFunctionParameter(Policy, Param);
2433
Douglas Gregor400f5972010-08-31 05:13:43 +00002434 if (Function->isVariadic() && P == N - 1)
2435 PlaceholderStr += ", ...";
2436
Douglas Gregor3545ff42009-09-21 16:56:56 +00002437 // Add the placeholder string.
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002438 Result.AddPlaceholderChunk(
2439 Result.getAllocator().CopyString(PlaceholderStr));
Douglas Gregor3545ff42009-09-21 16:56:56 +00002440 }
Douglas Gregorba449032009-09-22 21:42:17 +00002441
2442 if (const FunctionProtoType *Proto
2443 = Function->getType()->getAs<FunctionProtoType>())
Douglas Gregordbb71db2010-08-23 23:51:41 +00002444 if (Proto->isVariadic()) {
Alp Toker9cacbab2014-01-20 20:26:09 +00002445 if (Proto->getNumParams() == 0)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002446 Result.AddPlaceholderChunk("...");
Douglas Gregordbb71db2010-08-23 23:51:41 +00002447
Richard Smith20e883e2015-04-29 23:20:19 +00002448 MaybeAddSentinel(PP, Function, Result);
Douglas Gregordbb71db2010-08-23 23:51:41 +00002449 }
Douglas Gregor3545ff42009-09-21 16:56:56 +00002450}
2451
2452/// \brief Add template parameter chunks to the given code completion string.
2453static void AddTemplateParameterChunks(ASTContext &Context,
Douglas Gregor75acd922011-09-27 23:30:47 +00002454 const PrintingPolicy &Policy,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002455 const TemplateDecl *Template,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002456 CodeCompletionBuilder &Result,
2457 unsigned MaxParameters = 0,
2458 unsigned Start = 0,
2459 bool InDefaultArg = false) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002460 bool FirstParameter = true;
Richard Smith6eece292015-01-15 02:27:20 +00002461
2462 // Prefer to take the template parameter names from the first declaration of
2463 // the template.
2464 Template = cast<TemplateDecl>(Template->getCanonicalDecl());
2465
Douglas Gregor3545ff42009-09-21 16:56:56 +00002466 TemplateParameterList *Params = Template->getTemplateParameters();
2467 TemplateParameterList::iterator PEnd = Params->end();
2468 if (MaxParameters)
2469 PEnd = Params->begin() + MaxParameters;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002470 for (TemplateParameterList::iterator P = Params->begin() + Start;
2471 P != PEnd; ++P) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002472 bool HasDefaultArg = false;
2473 std::string PlaceholderStr;
2474 if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*P)) {
2475 if (TTP->wasDeclaredWithTypename())
2476 PlaceholderStr = "typename";
2477 else
2478 PlaceholderStr = "class";
2479
2480 if (TTP->getIdentifier()) {
2481 PlaceholderStr += ' ';
2482 PlaceholderStr += TTP->getIdentifier()->getName();
2483 }
2484
2485 HasDefaultArg = TTP->hasDefaultArgument();
2486 } else if (NonTypeTemplateParmDecl *NTTP
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002487 = dyn_cast<NonTypeTemplateParmDecl>(*P)) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002488 if (NTTP->getIdentifier())
2489 PlaceholderStr = NTTP->getIdentifier()->getName();
John McCall31168b02011-06-15 23:02:42 +00002490 NTTP->getType().getAsStringInternal(PlaceholderStr, Policy);
Douglas Gregor3545ff42009-09-21 16:56:56 +00002491 HasDefaultArg = NTTP->hasDefaultArgument();
2492 } else {
2493 assert(isa<TemplateTemplateParmDecl>(*P));
2494 TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*P);
2495
2496 // Since putting the template argument list into the placeholder would
2497 // be very, very long, we just use an abbreviation.
2498 PlaceholderStr = "template<...> class";
2499 if (TTP->getIdentifier()) {
2500 PlaceholderStr += ' ';
2501 PlaceholderStr += TTP->getIdentifier()->getName();
2502 }
2503
2504 HasDefaultArg = TTP->hasDefaultArgument();
2505 }
2506
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002507 if (HasDefaultArg && !InDefaultArg) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002508 // When we see an optional default argument, put that argument and
2509 // the remaining default arguments into a new, optional string.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00002510 CodeCompletionBuilder Opt(Result.getAllocator(),
2511 Result.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002512 if (!FirstParameter)
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002513 Opt.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor75acd922011-09-27 23:30:47 +00002514 AddTemplateParameterChunks(Context, Policy, Template, Opt, MaxParameters,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002515 P - Params->begin(), true);
2516 Result.AddOptionalChunk(Opt.TakeString());
2517 break;
Douglas Gregor3545ff42009-09-21 16:56:56 +00002518 }
2519
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002520 InDefaultArg = false;
2521
Douglas Gregor3545ff42009-09-21 16:56:56 +00002522 if (FirstParameter)
2523 FirstParameter = false;
2524 else
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002525 Result.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor3545ff42009-09-21 16:56:56 +00002526
2527 // Add the placeholder string.
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002528 Result.AddPlaceholderChunk(
2529 Result.getAllocator().CopyString(PlaceholderStr));
Douglas Gregor3545ff42009-09-21 16:56:56 +00002530 }
2531}
2532
Douglas Gregorf2510672009-09-21 19:57:38 +00002533/// \brief Add a qualifier to the given code-completion string, if the
2534/// provided nested-name-specifier is non-NULL.
Douglas Gregor0f622362009-12-11 18:44:16 +00002535static void
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002536AddQualifierToCompletionString(CodeCompletionBuilder &Result,
Douglas Gregor0f622362009-12-11 18:44:16 +00002537 NestedNameSpecifier *Qualifier,
2538 bool QualifierIsInformative,
Douglas Gregor75acd922011-09-27 23:30:47 +00002539 ASTContext &Context,
2540 const PrintingPolicy &Policy) {
Douglas Gregorf2510672009-09-21 19:57:38 +00002541 if (!Qualifier)
2542 return;
2543
2544 std::string PrintedNNS;
2545 {
2546 llvm::raw_string_ostream OS(PrintedNNS);
Douglas Gregor75acd922011-09-27 23:30:47 +00002547 Qualifier->print(OS, Policy);
Douglas Gregorf2510672009-09-21 19:57:38 +00002548 }
Douglas Gregor5bf52692009-09-22 23:15:58 +00002549 if (QualifierIsInformative)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002550 Result.AddInformativeChunk(Result.getAllocator().CopyString(PrintedNNS));
Douglas Gregor5bf52692009-09-22 23:15:58 +00002551 else
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002552 Result.AddTextChunk(Result.getAllocator().CopyString(PrintedNNS));
Douglas Gregorf2510672009-09-21 19:57:38 +00002553}
2554
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002555static void
2556AddFunctionTypeQualsToCompletionString(CodeCompletionBuilder &Result,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002557 const FunctionDecl *Function) {
Douglas Gregor0f622362009-12-11 18:44:16 +00002558 const FunctionProtoType *Proto
2559 = Function->getType()->getAs<FunctionProtoType>();
2560 if (!Proto || !Proto->getTypeQuals())
2561 return;
2562
Douglas Gregor304f9b02011-02-01 21:15:40 +00002563 // FIXME: Add ref-qualifier!
2564
2565 // Handle single qualifiers without copying
2566 if (Proto->getTypeQuals() == Qualifiers::Const) {
2567 Result.AddInformativeChunk(" const");
2568 return;
2569 }
2570
2571 if (Proto->getTypeQuals() == Qualifiers::Volatile) {
2572 Result.AddInformativeChunk(" volatile");
2573 return;
2574 }
2575
2576 if (Proto->getTypeQuals() == Qualifiers::Restrict) {
2577 Result.AddInformativeChunk(" restrict");
2578 return;
2579 }
2580
2581 // Handle multiple qualifiers.
Douglas Gregor0f622362009-12-11 18:44:16 +00002582 std::string QualsStr;
David Blaikief5697e52012-08-10 00:55:35 +00002583 if (Proto->isConst())
Douglas Gregor0f622362009-12-11 18:44:16 +00002584 QualsStr += " const";
David Blaikief5697e52012-08-10 00:55:35 +00002585 if (Proto->isVolatile())
Douglas Gregor0f622362009-12-11 18:44:16 +00002586 QualsStr += " volatile";
David Blaikief5697e52012-08-10 00:55:35 +00002587 if (Proto->isRestrict())
Douglas Gregor0f622362009-12-11 18:44:16 +00002588 QualsStr += " restrict";
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002589 Result.AddInformativeChunk(Result.getAllocator().CopyString(QualsStr));
Douglas Gregor0f622362009-12-11 18:44:16 +00002590}
2591
Douglas Gregor0212fd72010-09-21 16:06:22 +00002592/// \brief Add the name of the given declaration
Douglas Gregor75acd922011-09-27 23:30:47 +00002593static void AddTypedNameChunk(ASTContext &Context, const PrintingPolicy &Policy,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002594 const NamedDecl *ND,
2595 CodeCompletionBuilder &Result) {
Douglas Gregor0212fd72010-09-21 16:06:22 +00002596 DeclarationName Name = ND->getDeclName();
2597 if (!Name)
2598 return;
2599
2600 switch (Name.getNameKind()) {
Douglas Gregor304f9b02011-02-01 21:15:40 +00002601 case DeclarationName::CXXOperatorName: {
Craig Topperc3ec1492014-05-26 06:22:03 +00002602 const char *OperatorName = nullptr;
Douglas Gregor304f9b02011-02-01 21:15:40 +00002603 switch (Name.getCXXOverloadedOperator()) {
2604 case OO_None:
2605 case OO_Conditional:
2606 case NUM_OVERLOADED_OPERATORS:
2607 OperatorName = "operator";
2608 break;
2609
2610#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
2611 case OO_##Name: OperatorName = "operator" Spelling; break;
2612#define OVERLOADED_OPERATOR_MULTI(Name,Spelling,Unary,Binary,MemberOnly)
2613#include "clang/Basic/OperatorKinds.def"
2614
2615 case OO_New: OperatorName = "operator new"; break;
2616 case OO_Delete: OperatorName = "operator delete"; break;
2617 case OO_Array_New: OperatorName = "operator new[]"; break;
2618 case OO_Array_Delete: OperatorName = "operator delete[]"; break;
2619 case OO_Call: OperatorName = "operator()"; break;
2620 case OO_Subscript: OperatorName = "operator[]"; break;
2621 }
2622 Result.AddTypedTextChunk(OperatorName);
2623 break;
2624 }
2625
Douglas Gregor0212fd72010-09-21 16:06:22 +00002626 case DeclarationName::Identifier:
2627 case DeclarationName::CXXConversionFunctionName:
Douglas Gregor0212fd72010-09-21 16:06:22 +00002628 case DeclarationName::CXXDestructorName:
2629 case DeclarationName::CXXLiteralOperatorName:
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002630 Result.AddTypedTextChunk(
2631 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor0212fd72010-09-21 16:06:22 +00002632 break;
2633
Richard Smith35845152017-02-07 01:37:30 +00002634 case DeclarationName::CXXDeductionGuideName:
Douglas Gregor0212fd72010-09-21 16:06:22 +00002635 case DeclarationName::CXXUsingDirective:
2636 case DeclarationName::ObjCZeroArgSelector:
2637 case DeclarationName::ObjCOneArgSelector:
2638 case DeclarationName::ObjCMultiArgSelector:
2639 break;
2640
2641 case DeclarationName::CXXConstructorName: {
Craig Topperc3ec1492014-05-26 06:22:03 +00002642 CXXRecordDecl *Record = nullptr;
Douglas Gregor0212fd72010-09-21 16:06:22 +00002643 QualType Ty = Name.getCXXNameType();
2644 if (const RecordType *RecordTy = Ty->getAs<RecordType>())
2645 Record = cast<CXXRecordDecl>(RecordTy->getDecl());
2646 else if (const InjectedClassNameType *InjectedTy
2647 = Ty->getAs<InjectedClassNameType>())
2648 Record = InjectedTy->getDecl();
2649 else {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002650 Result.AddTypedTextChunk(
2651 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor0212fd72010-09-21 16:06:22 +00002652 break;
2653 }
2654
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002655 Result.AddTypedTextChunk(
2656 Result.getAllocator().CopyString(Record->getNameAsString()));
Douglas Gregor0212fd72010-09-21 16:06:22 +00002657 if (ClassTemplateDecl *Template = Record->getDescribedClassTemplate()) {
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002658 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Douglas Gregor75acd922011-09-27 23:30:47 +00002659 AddTemplateParameterChunks(Context, Policy, Template, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002660 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregor0212fd72010-09-21 16:06:22 +00002661 }
2662 break;
2663 }
2664 }
2665}
2666
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002667CodeCompletionString *CodeCompletionResult::CreateCodeCompletionString(Sema &S,
Douglas Gregorc3425b12015-07-07 06:20:19 +00002668 const CodeCompletionContext &CCContext,
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00002669 CodeCompletionAllocator &Allocator,
Dmitri Gribenko3292d062012-07-02 17:35:10 +00002670 CodeCompletionTUInfo &CCTUInfo,
2671 bool IncludeBriefComments) {
Douglas Gregorc3425b12015-07-07 06:20:19 +00002672 return CreateCodeCompletionString(S.Context, S.PP, CCContext, Allocator,
2673 CCTUInfo, IncludeBriefComments);
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002674}
2675
Douglas Gregor3545ff42009-09-21 16:56:56 +00002676/// \brief If possible, create a new code completion string for the given
2677/// result.
2678///
2679/// \returns Either a new, heap-allocated code completion string describing
2680/// how to use this result, or NULL to indicate that the string or name of the
2681/// result is all that is needed.
2682CodeCompletionString *
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002683CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx,
2684 Preprocessor &PP,
Douglas Gregorc3425b12015-07-07 06:20:19 +00002685 const CodeCompletionContext &CCContext,
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00002686 CodeCompletionAllocator &Allocator,
Dmitri Gribenko3292d062012-07-02 17:35:10 +00002687 CodeCompletionTUInfo &CCTUInfo,
2688 bool IncludeBriefComments) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00002689 CodeCompletionBuilder Result(Allocator, CCTUInfo, Priority, Availability);
Douglas Gregor9eb77012009-11-07 00:00:49 +00002690
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002691 PrintingPolicy Policy = getCompletionPrintingPolicy(Ctx, PP);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002692 if (Kind == RK_Pattern) {
2693 Pattern->Priority = Priority;
2694 Pattern->Availability = Availability;
Douglas Gregor78254c82012-03-27 23:34:16 +00002695
2696 if (Declaration) {
2697 Result.addParentContext(Declaration->getDeclContext());
Douglas Gregor78254c82012-03-27 23:34:16 +00002698 Pattern->ParentName = Result.getParentName();
Fariborz Jahanian1fcf4922013-03-22 17:55:27 +00002699 // Provide code completion comment for self.GetterName where
2700 // GetterName is the getter method for a property with name
2701 // different from the property name (declared via a property
2702 // getter attribute.
2703 const NamedDecl *ND = Declaration;
2704 if (const ObjCMethodDecl *M = dyn_cast<ObjCMethodDecl>(ND))
2705 if (M->isPropertyAccessor())
2706 if (const ObjCPropertyDecl *PDecl = M->findPropertyDecl())
2707 if (PDecl->getGetterName() == M->getSelector() &&
Fariborz Jahanianbe8bc672013-03-23 01:10:45 +00002708 PDecl->getIdentifier() != M->getIdentifier()) {
2709 if (const RawComment *RC =
2710 Ctx.getRawCommentForAnyRedecl(M)) {
Fariborz Jahanian1fcf4922013-03-22 17:55:27 +00002711 Result.addBriefComment(RC->getBriefText(Ctx));
2712 Pattern->BriefComment = Result.getBriefComment();
2713 }
Fariborz Jahanianbe8bc672013-03-23 01:10:45 +00002714 else if (const RawComment *RC =
2715 Ctx.getRawCommentForAnyRedecl(PDecl)) {
2716 Result.addBriefComment(RC->getBriefText(Ctx));
2717 Pattern->BriefComment = Result.getBriefComment();
2718 }
2719 }
Douglas Gregor78254c82012-03-27 23:34:16 +00002720 }
2721
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002722 return Pattern;
2723 }
Douglas Gregorf09935f2009-12-01 05:55:20 +00002724
Douglas Gregorf09935f2009-12-01 05:55:20 +00002725 if (Kind == RK_Keyword) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002726 Result.AddTypedTextChunk(Keyword);
2727 return Result.TakeString();
Douglas Gregorf09935f2009-12-01 05:55:20 +00002728 }
Douglas Gregor3545ff42009-09-21 16:56:56 +00002729
Douglas Gregorf329c7c2009-10-30 16:50:04 +00002730 if (Kind == RK_Macro) {
Richard Smith20e883e2015-04-29 23:20:19 +00002731 const MacroInfo *MI = PP.getMacroInfo(Macro);
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002732 Result.AddTypedTextChunk(
2733 Result.getAllocator().CopyString(Macro->getName()));
Douglas Gregorf09935f2009-12-01 05:55:20 +00002734
Ben Langmuirc28ce3a2014-09-30 20:00:18 +00002735 if (!MI || !MI->isFunctionLike())
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002736 return Result.TakeString();
Douglas Gregorf329c7c2009-10-30 16:50:04 +00002737
2738 // Format a function-like macro with placeholders for the arguments.
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002739 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregor0c505312011-07-30 08:17:44 +00002740 MacroInfo::arg_iterator A = MI->arg_begin(), AEnd = MI->arg_end();
Douglas Gregor3aa55262012-01-21 00:43:38 +00002741
2742 // C99 variadic macros add __VA_ARGS__ at the end. Skip it.
2743 if (MI->isC99Varargs()) {
2744 --AEnd;
2745
2746 if (A == AEnd) {
2747 Result.AddPlaceholderChunk("...");
2748 }
Douglas Gregor0c505312011-07-30 08:17:44 +00002749 }
Douglas Gregor3aa55262012-01-21 00:43:38 +00002750
Douglas Gregor0c505312011-07-30 08:17:44 +00002751 for (MacroInfo::arg_iterator A = MI->arg_begin(); A != AEnd; ++A) {
Douglas Gregorf329c7c2009-10-30 16:50:04 +00002752 if (A != MI->arg_begin())
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002753 Result.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor3aa55262012-01-21 00:43:38 +00002754
2755 if (MI->isVariadic() && (A+1) == AEnd) {
Dylan Noblesmith2c1dd272012-02-05 02:13:05 +00002756 SmallString<32> Arg = (*A)->getName();
Douglas Gregor3aa55262012-01-21 00:43:38 +00002757 if (MI->isC99Varargs())
2758 Arg += ", ...";
2759 else
2760 Arg += "...";
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002761 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregor3aa55262012-01-21 00:43:38 +00002762 break;
Douglas Gregorf329c7c2009-10-30 16:50:04 +00002763 }
Douglas Gregor3aa55262012-01-21 00:43:38 +00002764
2765 // Non-variadic macros are simple.
2766 Result.AddPlaceholderChunk(
2767 Result.getAllocator().CopyString((*A)->getName()));
Douglas Gregor0c505312011-07-30 08:17:44 +00002768 }
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002769 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002770 return Result.TakeString();
Douglas Gregorf329c7c2009-10-30 16:50:04 +00002771 }
2772
Douglas Gregorf64acca2010-05-25 21:41:55 +00002773 assert(Kind == RK_Declaration && "Missed a result kind?");
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002774 const NamedDecl *ND = Declaration;
Douglas Gregor78254c82012-03-27 23:34:16 +00002775 Result.addParentContext(ND->getDeclContext());
Dmitri Gribenko3292d062012-07-02 17:35:10 +00002776
2777 if (IncludeBriefComments) {
2778 // Add documentation comment, if it exists.
Dmitri Gribenkoa43ec182012-08-11 00:51:43 +00002779 if (const RawComment *RC = Ctx.getRawCommentForAnyRedecl(ND)) {
Dmitri Gribenko3292d062012-07-02 17:35:10 +00002780 Result.addBriefComment(RC->getBriefText(Ctx));
Fariborz Jahanian15a0b552013-02-28 17:47:14 +00002781 }
2782 else if (const ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(ND))
2783 if (OMD->isPropertyAccessor())
2784 if (const ObjCPropertyDecl *PDecl = OMD->findPropertyDecl())
2785 if (const RawComment *RC = Ctx.getRawCommentForAnyRedecl(PDecl))
2786 Result.addBriefComment(RC->getBriefText(Ctx));
Dmitri Gribenko3292d062012-07-02 17:35:10 +00002787 }
2788
Douglas Gregor9eb77012009-11-07 00:00:49 +00002789 if (StartsNestedNameSpecifier) {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002790 Result.AddTypedTextChunk(
2791 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002792 Result.AddTextChunk("::");
2793 return Result.TakeString();
Douglas Gregor9eb77012009-11-07 00:00:49 +00002794 }
Erik Verbruggen98ea7f62011-10-14 15:31:08 +00002795
Aaron Ballmanbe22bcb2014-03-10 17:08:28 +00002796 for (const auto *I : ND->specific_attrs<AnnotateAttr>())
2797 Result.AddAnnotation(Result.getAllocator().CopyString(I->getAnnotation()));
Aaron Ballmanb97112e2014-03-08 22:19:01 +00002798
Douglas Gregorc3425b12015-07-07 06:20:19 +00002799 AddResultTypeChunk(Ctx, Policy, ND, CCContext.getBaseType(), Result);
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002800
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002801 if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(ND)) {
Douglas Gregor5bf52692009-09-22 23:15:58 +00002802 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002803 Ctx, Policy);
2804 AddTypedNameChunk(Ctx, Policy, ND, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002805 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Richard Smith20e883e2015-04-29 23:20:19 +00002806 AddFunctionParameterChunks(PP, Policy, Function, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002807 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor0f622362009-12-11 18:44:16 +00002808 AddFunctionTypeQualsToCompletionString(Result, Function);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002809 return Result.TakeString();
Douglas Gregor3545ff42009-09-21 16:56:56 +00002810 }
2811
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002812 if (const FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND)) {
Douglas Gregor5bf52692009-09-22 23:15:58 +00002813 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002814 Ctx, Policy);
Douglas Gregor3545ff42009-09-21 16:56:56 +00002815 FunctionDecl *Function = FunTmpl->getTemplatedDecl();
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002816 AddTypedNameChunk(Ctx, Policy, Function, Result);
Douglas Gregor0212fd72010-09-21 16:06:22 +00002817
Douglas Gregor3545ff42009-09-21 16:56:56 +00002818 // Figure out which template parameters are deduced (or have default
2819 // arguments).
Benjamin Kramere0513cb2012-01-30 16:17:39 +00002820 llvm::SmallBitVector Deduced;
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002821 Sema::MarkDeducedTemplateParameters(Ctx, FunTmpl, Deduced);
Douglas Gregor3545ff42009-09-21 16:56:56 +00002822 unsigned LastDeducibleArgument;
2823 for (LastDeducibleArgument = Deduced.size(); LastDeducibleArgument > 0;
2824 --LastDeducibleArgument) {
2825 if (!Deduced[LastDeducibleArgument - 1]) {
2826 // C++0x: Figure out if the template argument has a default. If so,
2827 // the user doesn't need to type this argument.
2828 // FIXME: We need to abstract template parameters better!
2829 bool HasDefaultArg = false;
2830 NamedDecl *Param = FunTmpl->getTemplateParameters()->getParam(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002831 LastDeducibleArgument - 1);
Douglas Gregor3545ff42009-09-21 16:56:56 +00002832 if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param))
2833 HasDefaultArg = TTP->hasDefaultArgument();
2834 else if (NonTypeTemplateParmDecl *NTTP
2835 = dyn_cast<NonTypeTemplateParmDecl>(Param))
2836 HasDefaultArg = NTTP->hasDefaultArgument();
2837 else {
2838 assert(isa<TemplateTemplateParmDecl>(Param));
2839 HasDefaultArg
Douglas Gregor9eb77012009-11-07 00:00:49 +00002840 = cast<TemplateTemplateParmDecl>(Param)->hasDefaultArgument();
Douglas Gregor3545ff42009-09-21 16:56:56 +00002841 }
2842
2843 if (!HasDefaultArg)
2844 break;
2845 }
2846 }
2847
2848 if (LastDeducibleArgument) {
2849 // Some of the function template arguments cannot be deduced from a
2850 // function call, so we introduce an explicit template argument list
2851 // containing all of the arguments up to the first deducible argument.
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002852 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002853 AddTemplateParameterChunks(Ctx, Policy, FunTmpl, Result,
Douglas Gregor3545ff42009-09-21 16:56:56 +00002854 LastDeducibleArgument);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002855 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregor3545ff42009-09-21 16:56:56 +00002856 }
2857
2858 // Add the function parameters
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 TemplateDecl *Template = dyn_cast<TemplateDecl>(ND)) {
Douglas Gregor5bf52692009-09-22 23:15:58 +00002867 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002868 Ctx, Policy);
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002869 Result.AddTypedTextChunk(
2870 Result.getAllocator().CopyString(Template->getNameAsString()));
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002871 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002872 AddTemplateParameterChunks(Ctx, Policy, Template, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002873 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002874 return Result.TakeString();
Douglas Gregor3545ff42009-09-21 16:56:56 +00002875 }
2876
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002877 if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND)) {
Douglas Gregord3c5d792009-11-17 16:44:22 +00002878 Selector Sel = Method->getSelector();
2879 if (Sel.isUnarySelector()) {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002880 Result.AddTypedTextChunk(Result.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00002881 Sel.getNameForSlot(0)));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002882 return Result.TakeString();
Douglas Gregord3c5d792009-11-17 16:44:22 +00002883 }
2884
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00002885 std::string SelName = Sel.getNameForSlot(0).str();
Douglas Gregor1b605f72009-11-19 01:08:35 +00002886 SelName += ':';
2887 if (StartParameter == 0)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002888 Result.AddTypedTextChunk(Result.getAllocator().CopyString(SelName));
Douglas Gregor1b605f72009-11-19 01:08:35 +00002889 else {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002890 Result.AddInformativeChunk(Result.getAllocator().CopyString(SelName));
Douglas Gregor1b605f72009-11-19 01:08:35 +00002891
2892 // If there is only one parameter, and we're past it, add an empty
2893 // typed-text chunk since there is nothing to type.
2894 if (Method->param_size() == 1)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002895 Result.AddTypedTextChunk("");
Douglas Gregor1b605f72009-11-19 01:08:35 +00002896 }
Douglas Gregord3c5d792009-11-17 16:44:22 +00002897 unsigned Idx = 0;
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002898 for (ObjCMethodDecl::param_const_iterator P = Method->param_begin(),
2899 PEnd = Method->param_end();
Douglas Gregord3c5d792009-11-17 16:44:22 +00002900 P != PEnd; (void)++P, ++Idx) {
2901 if (Idx > 0) {
Douglas Gregor1b605f72009-11-19 01:08:35 +00002902 std::string Keyword;
2903 if (Idx > StartParameter)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002904 Result.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregord3c5d792009-11-17 16:44:22 +00002905 if (IdentifierInfo *II = Sel.getIdentifierInfoForSlot(Idx))
Benjamin Kramer632500c2011-07-26 16:59:25 +00002906 Keyword += II->getName();
Douglas Gregord3c5d792009-11-17 16:44:22 +00002907 Keyword += ":";
Douglas Gregor95887f92010-07-08 23:20:03 +00002908 if (Idx < StartParameter || AllParametersAreInformative)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002909 Result.AddInformativeChunk(Result.getAllocator().CopyString(Keyword));
Douglas Gregor8e3e8742010-10-18 21:05:04 +00002910 else
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002911 Result.AddTypedTextChunk(Result.getAllocator().CopyString(Keyword));
Douglas Gregord3c5d792009-11-17 16:44:22 +00002912 }
Douglas Gregor1b605f72009-11-19 01:08:35 +00002913
2914 // If we're before the starting parameter, skip the placeholder.
2915 if (Idx < StartParameter)
2916 continue;
Douglas Gregord3c5d792009-11-17 16:44:22 +00002917
2918 std::string Arg;
Douglas Gregorc3425b12015-07-07 06:20:19 +00002919 QualType ParamType = (*P)->getType();
2920 Optional<ArrayRef<QualType>> ObjCSubsts;
2921 if (!CCContext.getBaseType().isNull())
2922 ObjCSubsts = CCContext.getBaseType()->getObjCSubstitutions(Method);
2923
2924 if (ParamType->isBlockPointerType() && !DeclaringEntity)
2925 Arg = FormatFunctionParameter(Policy, *P, true,
2926 /*SuppressBlock=*/false,
2927 ObjCSubsts);
Douglas Gregore90dd002010-08-24 16:15:59 +00002928 else {
Douglas Gregorc3425b12015-07-07 06:20:19 +00002929 if (ObjCSubsts)
2930 ParamType = ParamType.substObjCTypeArgs(Ctx, *ObjCSubsts,
2931 ObjCSubstitutionContext::Parameter);
Douglas Gregor86b42682015-06-19 18:27:52 +00002932 Arg = "(" + formatObjCParamQualifiers((*P)->getObjCDeclQualifier(),
Douglas Gregorc3425b12015-07-07 06:20:19 +00002933 ParamType);
2934 Arg += ParamType.getAsString(Policy) + ")";
Douglas Gregore90dd002010-08-24 16:15:59 +00002935 if (IdentifierInfo *II = (*P)->getIdentifier())
Douglas Gregor981a0c42010-08-29 19:47:46 +00002936 if (DeclaringEntity || AllParametersAreInformative)
Benjamin Kramer632500c2011-07-26 16:59:25 +00002937 Arg += II->getName();
Douglas Gregore90dd002010-08-24 16:15:59 +00002938 }
2939
Douglas Gregor400f5972010-08-31 05:13:43 +00002940 if (Method->isVariadic() && (P + 1) == PEnd)
2941 Arg += ", ...";
2942
Douglas Gregor95887f92010-07-08 23:20:03 +00002943 if (DeclaringEntity)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002944 Result.AddTextChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregor95887f92010-07-08 23:20:03 +00002945 else if (AllParametersAreInformative)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002946 Result.AddInformativeChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregorc8537c52009-11-19 07:41:15 +00002947 else
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002948 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregord3c5d792009-11-17 16:44:22 +00002949 }
2950
Douglas Gregor04c5f972009-12-23 00:21:46 +00002951 if (Method->isVariadic()) {
Douglas Gregor400f5972010-08-31 05:13:43 +00002952 if (Method->param_size() == 0) {
2953 if (DeclaringEntity)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002954 Result.AddTextChunk(", ...");
Douglas Gregor400f5972010-08-31 05:13:43 +00002955 else if (AllParametersAreInformative)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002956 Result.AddInformativeChunk(", ...");
Douglas Gregor400f5972010-08-31 05:13:43 +00002957 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002958 Result.AddPlaceholderChunk(", ...");
Douglas Gregor400f5972010-08-31 05:13:43 +00002959 }
Douglas Gregordbb71db2010-08-23 23:51:41 +00002960
Richard Smith20e883e2015-04-29 23:20:19 +00002961 MaybeAddSentinel(PP, Method, Result);
Douglas Gregor04c5f972009-12-23 00:21:46 +00002962 }
2963
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002964 return Result.TakeString();
Douglas Gregord3c5d792009-11-17 16:44:22 +00002965 }
2966
Douglas Gregorf09935f2009-12-01 05:55:20 +00002967 if (Qualifier)
Douglas Gregor5bf52692009-09-22 23:15:58 +00002968 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002969 Ctx, Policy);
Douglas Gregorf09935f2009-12-01 05:55:20 +00002970
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002971 Result.AddTypedTextChunk(
2972 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002973 return Result.TakeString();
Douglas Gregor3545ff42009-09-21 16:56:56 +00002974}
2975
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00002976/// \brief Add function overload parameter chunks to the given code completion
2977/// string.
2978static void AddOverloadParameterChunks(ASTContext &Context,
2979 const PrintingPolicy &Policy,
2980 const FunctionDecl *Function,
2981 const FunctionProtoType *Prototype,
2982 CodeCompletionBuilder &Result,
2983 unsigned CurrentArg,
2984 unsigned Start = 0,
2985 bool InOptional = false) {
2986 bool FirstParameter = true;
2987 unsigned NumParams = Function ? Function->getNumParams()
2988 : Prototype->getNumParams();
2989
2990 for (unsigned P = Start; P != NumParams; ++P) {
2991 if (Function && Function->getParamDecl(P)->hasDefaultArg() && !InOptional) {
2992 // When we see an optional default argument, put that argument and
2993 // the remaining default arguments into a new, optional string.
2994 CodeCompletionBuilder Opt(Result.getAllocator(),
2995 Result.getCodeCompletionTUInfo());
2996 if (!FirstParameter)
2997 Opt.AddChunk(CodeCompletionString::CK_Comma);
2998 // Optional sections are nested.
2999 AddOverloadParameterChunks(Context, Policy, Function, Prototype, Opt,
3000 CurrentArg, P, /*InOptional=*/true);
3001 Result.AddOptionalChunk(Opt.TakeString());
3002 return;
3003 }
3004
3005 if (FirstParameter)
3006 FirstParameter = false;
3007 else
3008 Result.AddChunk(CodeCompletionString::CK_Comma);
3009
3010 InOptional = false;
3011
3012 // Format the placeholder string.
3013 std::string Placeholder;
3014 if (Function)
Richard Smith20e883e2015-04-29 23:20:19 +00003015 Placeholder = FormatFunctionParameter(Policy, Function->getParamDecl(P));
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003016 else
3017 Placeholder = Prototype->getParamType(P).getAsString(Policy);
3018
3019 if (P == CurrentArg)
3020 Result.AddCurrentParameterChunk(
3021 Result.getAllocator().CopyString(Placeholder));
3022 else
3023 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Placeholder));
3024 }
3025
3026 if (Prototype && Prototype->isVariadic()) {
3027 CodeCompletionBuilder Opt(Result.getAllocator(),
3028 Result.getCodeCompletionTUInfo());
3029 if (!FirstParameter)
3030 Opt.AddChunk(CodeCompletionString::CK_Comma);
3031
3032 if (CurrentArg < NumParams)
3033 Opt.AddPlaceholderChunk("...");
3034 else
3035 Opt.AddCurrentParameterChunk("...");
3036
3037 Result.AddOptionalChunk(Opt.TakeString());
3038 }
3039}
3040
Douglas Gregorf0f51982009-09-23 00:34:09 +00003041CodeCompletionString *
3042CodeCompleteConsumer::OverloadCandidate::CreateSignatureString(
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003043 unsigned CurrentArg, Sema &S,
3044 CodeCompletionAllocator &Allocator,
3045 CodeCompletionTUInfo &CCTUInfo,
3046 bool IncludeBriefComments) const {
Douglas Gregor75acd922011-09-27 23:30:47 +00003047 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
John McCall31168b02011-06-15 23:02:42 +00003048
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003049 // FIXME: Set priority, availability appropriately.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003050 CodeCompletionBuilder Result(Allocator,CCTUInfo, 1, CXAvailability_Available);
Douglas Gregorf0f51982009-09-23 00:34:09 +00003051 FunctionDecl *FDecl = getFunction();
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003052 const FunctionProtoType *Proto
Douglas Gregorf0f51982009-09-23 00:34:09 +00003053 = dyn_cast<FunctionProtoType>(getFunctionType());
3054 if (!FDecl && !Proto) {
3055 // Function without a prototype. Just give the return type and a
3056 // highlighted ellipsis.
3057 const FunctionType *FT = getFunctionType();
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003058 Result.AddResultTypeChunk(Result.getAllocator().CopyString(
3059 FT->getReturnType().getAsString(Policy)));
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003060 Result.AddChunk(CodeCompletionString::CK_LeftParen);
3061 Result.AddChunk(CodeCompletionString::CK_CurrentParameter, "...");
3062 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003063 return Result.TakeString();
Douglas Gregorf0f51982009-09-23 00:34:09 +00003064 }
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003065
3066 if (FDecl) {
3067 if (IncludeBriefComments && CurrentArg < FDecl->getNumParams())
3068 if (auto RC = S.getASTContext().getRawCommentForAnyRedecl(
3069 FDecl->getParamDecl(CurrentArg)))
3070 Result.addBriefComment(RC->getBriefText(S.getASTContext()));
Douglas Gregorc3425b12015-07-07 06:20:19 +00003071 AddResultTypeChunk(S.Context, Policy, FDecl, QualType(), Result);
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003072 Result.AddTextChunk(
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003073 Result.getAllocator().CopyString(FDecl->getNameAsString()));
3074 } else {
3075 Result.AddResultTypeChunk(
3076 Result.getAllocator().CopyString(
Alp Toker314cc812014-01-25 16:55:45 +00003077 Proto->getReturnType().getAsString(Policy)));
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003078 }
Alp Toker314cc812014-01-25 16:55:45 +00003079
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003080 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003081 AddOverloadParameterChunks(S.getASTContext(), Policy, FDecl, Proto, Result,
3082 CurrentArg);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003083 Result.AddChunk(CodeCompletionString::CK_RightParen);
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003084
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003085 return Result.TakeString();
Douglas Gregorf0f51982009-09-23 00:34:09 +00003086}
3087
Chris Lattner0e62c1c2011-07-23 10:55:15 +00003088unsigned clang::getMacroUsagePriority(StringRef MacroName,
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00003089 const LangOptions &LangOpts,
Douglas Gregor6e240332010-08-16 16:18:59 +00003090 bool PreferredTypeIsPointer) {
3091 unsigned Priority = CCP_Macro;
3092
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00003093 // Treat the "nil", "Nil" and "NULL" macros as null pointer constants.
3094 if (MacroName.equals("nil") || MacroName.equals("NULL") ||
3095 MacroName.equals("Nil")) {
Douglas Gregor6e240332010-08-16 16:18:59 +00003096 Priority = CCP_Constant;
3097 if (PreferredTypeIsPointer)
3098 Priority = Priority / CCF_SimilarTypeMatch;
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00003099 }
3100 // Treat "YES", "NO", "true", and "false" as constants.
3101 else if (MacroName.equals("YES") || MacroName.equals("NO") ||
3102 MacroName.equals("true") || MacroName.equals("false"))
3103 Priority = CCP_Constant;
3104 // Treat "bool" as a type.
3105 else if (MacroName.equals("bool"))
3106 Priority = CCP_Type + (LangOpts.ObjC1? CCD_bool_in_ObjC : 0);
3107
Douglas Gregor6e240332010-08-16 16:18:59 +00003108
3109 return Priority;
3110}
3111
Dmitri Gribenkobdc80de2013-01-11 20:32:41 +00003112CXCursorKind clang::getCursorKindForDecl(const Decl *D) {
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003113 if (!D)
3114 return CXCursor_UnexposedDecl;
3115
3116 switch (D->getKind()) {
3117 case Decl::Enum: return CXCursor_EnumDecl;
3118 case Decl::EnumConstant: return CXCursor_EnumConstantDecl;
3119 case Decl::Field: return CXCursor_FieldDecl;
3120 case Decl::Function:
3121 return CXCursor_FunctionDecl;
3122 case Decl::ObjCCategory: return CXCursor_ObjCCategoryDecl;
3123 case Decl::ObjCCategoryImpl: return CXCursor_ObjCCategoryImplDecl;
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003124 case Decl::ObjCImplementation: return CXCursor_ObjCImplementationDecl;
Douglas Gregordeafd0b2011-12-27 22:43:10 +00003125
Argyrios Kyrtzidis3698cef2012-01-24 21:39:26 +00003126 case Decl::ObjCInterface: return CXCursor_ObjCInterfaceDecl;
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003127 case Decl::ObjCIvar: return CXCursor_ObjCIvarDecl;
3128 case Decl::ObjCMethod:
3129 return cast<ObjCMethodDecl>(D)->isInstanceMethod()
3130 ? CXCursor_ObjCInstanceMethodDecl : CXCursor_ObjCClassMethodDecl;
3131 case Decl::CXXMethod: return CXCursor_CXXMethod;
3132 case Decl::CXXConstructor: return CXCursor_Constructor;
3133 case Decl::CXXDestructor: return CXCursor_Destructor;
3134 case Decl::CXXConversion: return CXCursor_ConversionFunction;
3135 case Decl::ObjCProperty: return CXCursor_ObjCPropertyDecl;
Argyrios Kyrtzidis3698cef2012-01-24 21:39:26 +00003136 case Decl::ObjCProtocol: return CXCursor_ObjCProtocolDecl;
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003137 case Decl::ParmVar: return CXCursor_ParmDecl;
3138 case Decl::Typedef: return CXCursor_TypedefDecl;
Richard Smithdda56e42011-04-15 14:24:37 +00003139 case Decl::TypeAlias: return CXCursor_TypeAliasDecl;
Sergey Kalinichev8f3b1872015-11-15 13:48:32 +00003140 case Decl::TypeAliasTemplate: return CXCursor_TypeAliasTemplateDecl;
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003141 case Decl::Var: return CXCursor_VarDecl;
3142 case Decl::Namespace: return CXCursor_Namespace;
3143 case Decl::NamespaceAlias: return CXCursor_NamespaceAlias;
3144 case Decl::TemplateTypeParm: return CXCursor_TemplateTypeParameter;
3145 case Decl::NonTypeTemplateParm:return CXCursor_NonTypeTemplateParameter;
3146 case Decl::TemplateTemplateParm:return CXCursor_TemplateTemplateParameter;
3147 case Decl::FunctionTemplate: return CXCursor_FunctionTemplate;
3148 case Decl::ClassTemplate: return CXCursor_ClassTemplate;
Argyrios Kyrtzidis12afd702011-09-30 17:58:23 +00003149 case Decl::AccessSpec: return CXCursor_CXXAccessSpecifier;
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003150 case Decl::ClassTemplatePartialSpecialization:
3151 return CXCursor_ClassTemplatePartialSpecialization;
3152 case Decl::UsingDirective: return CXCursor_UsingDirective;
Olivier Goffart81978012016-06-09 16:15:55 +00003153 case Decl::StaticAssert: return CXCursor_StaticAssert;
Olivier Goffartd211c642016-11-04 06:29:27 +00003154 case Decl::Friend: return CXCursor_FriendDecl;
Douglas Gregor3e653b32012-04-30 23:41:16 +00003155 case Decl::TranslationUnit: return CXCursor_TranslationUnit;
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003156
3157 case Decl::Using:
3158 case Decl::UnresolvedUsingValue:
3159 case Decl::UnresolvedUsingTypename:
3160 return CXCursor_UsingDeclaration;
3161
Douglas Gregor4cd65962011-06-03 23:08:58 +00003162 case Decl::ObjCPropertyImpl:
3163 switch (cast<ObjCPropertyImplDecl>(D)->getPropertyImplementation()) {
3164 case ObjCPropertyImplDecl::Dynamic:
3165 return CXCursor_ObjCDynamicDecl;
3166
3167 case ObjCPropertyImplDecl::Synthesize:
3168 return CXCursor_ObjCSynthesizeDecl;
3169 }
Argyrios Kyrtzidis50e5b1d2012-10-05 00:22:24 +00003170
3171 case Decl::Import:
3172 return CXCursor_ModuleImportDecl;
Douglas Gregor85f3f952015-07-07 03:57:15 +00003173
3174 case Decl::ObjCTypeParam: return CXCursor_TemplateTypeParameter;
3175
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003176 default:
Dmitri Gribenkobdc80de2013-01-11 20:32:41 +00003177 if (const TagDecl *TD = dyn_cast<TagDecl>(D)) {
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003178 switch (TD->getTagKind()) {
Joao Matosdc86f942012-08-31 18:45:21 +00003179 case TTK_Interface: // fall through
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003180 case TTK_Struct: return CXCursor_StructDecl;
3181 case TTK_Class: return CXCursor_ClassDecl;
3182 case TTK_Union: return CXCursor_UnionDecl;
3183 case TTK_Enum: return CXCursor_EnumDecl;
3184 }
3185 }
3186 }
3187
3188 return CXCursor_UnexposedDecl;
3189}
3190
Douglas Gregor55b037b2010-07-08 20:55:51 +00003191static void AddMacroResults(Preprocessor &PP, ResultBuilder &Results,
Douglas Gregor8cb17462012-10-09 16:01:50 +00003192 bool IncludeUndefined,
Douglas Gregor55b037b2010-07-08 20:55:51 +00003193 bool TargetTypeIsPointer = false) {
John McCall276321a2010-08-25 06:19:51 +00003194 typedef CodeCompletionResult Result;
Douglas Gregor55b037b2010-07-08 20:55:51 +00003195
Douglas Gregorf329c7c2009-10-30 16:50:04 +00003196 Results.EnterNewScope();
Douglas Gregor8e3e8742010-10-18 21:05:04 +00003197
Douglas Gregor9eb77012009-11-07 00:00:49 +00003198 for (Preprocessor::macro_iterator M = PP.macro_begin(),
3199 MEnd = PP.macro_end();
Douglas Gregor55b037b2010-07-08 20:55:51 +00003200 M != MEnd; ++M) {
Richard Smith20e883e2015-04-29 23:20:19 +00003201 auto MD = PP.getMacroDefinition(M->first);
3202 if (IncludeUndefined || MD) {
3203 if (MacroInfo *MI = MD.getMacroInfo())
Argyrios Kyrtzidis9ef53ce2014-04-09 18:21:23 +00003204 if (MI->isUsedForHeaderGuard())
3205 continue;
3206
Douglas Gregor8cb17462012-10-09 16:01:50 +00003207 Results.AddResult(Result(M->first,
Douglas Gregor6e240332010-08-16 16:18:59 +00003208 getMacroUsagePriority(M->first->getName(),
David Blaikiebbafb8a2012-03-11 07:00:24 +00003209 PP.getLangOpts(),
Douglas Gregor6e240332010-08-16 16:18:59 +00003210 TargetTypeIsPointer)));
Argyrios Kyrtzidis9ef53ce2014-04-09 18:21:23 +00003211 }
Douglas Gregor55b037b2010-07-08 20:55:51 +00003212 }
Douglas Gregor8e3e8742010-10-18 21:05:04 +00003213
Douglas Gregorf329c7c2009-10-30 16:50:04 +00003214 Results.ExitScope();
Douglas Gregor8e3e8742010-10-18 21:05:04 +00003215
Douglas Gregorf329c7c2009-10-30 16:50:04 +00003216}
3217
Douglas Gregorce0e8562010-08-23 21:54:33 +00003218static void AddPrettyFunctionResults(const LangOptions &LangOpts,
3219 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00003220 typedef CodeCompletionResult Result;
Douglas Gregorce0e8562010-08-23 21:54:33 +00003221
3222 Results.EnterNewScope();
Douglas Gregor8e3e8742010-10-18 21:05:04 +00003223
Douglas Gregorce0e8562010-08-23 21:54:33 +00003224 Results.AddResult(Result("__PRETTY_FUNCTION__", CCP_Constant));
3225 Results.AddResult(Result("__FUNCTION__", CCP_Constant));
Richard Smith2bf7fdb2013-01-02 11:42:31 +00003226 if (LangOpts.C99 || LangOpts.CPlusPlus11)
Douglas Gregorce0e8562010-08-23 21:54:33 +00003227 Results.AddResult(Result("__func__", CCP_Constant));
3228 Results.ExitScope();
3229}
3230
Daniel Dunbar242ea9a2009-11-13 08:58:20 +00003231static void HandleCodeCompleteResults(Sema *S,
3232 CodeCompleteConsumer *CodeCompleter,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003233 CodeCompletionContext Context,
John McCall276321a2010-08-25 06:19:51 +00003234 CodeCompletionResult *Results,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003235 unsigned NumResults) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00003236 if (CodeCompleter)
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003237 CodeCompleter->ProcessCodeCompleteResults(*S, Context, Results, NumResults);
Douglas Gregor3545ff42009-09-21 16:56:56 +00003238}
3239
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003240static enum CodeCompletionContext::Kind mapCodeCompletionContext(Sema &S,
3241 Sema::ParserCompletionContext PCC) {
3242 switch (PCC) {
John McCallfaf5fb42010-08-26 23:41:50 +00003243 case Sema::PCC_Namespace:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003244 return CodeCompletionContext::CCC_TopLevel;
3245
John McCallfaf5fb42010-08-26 23:41:50 +00003246 case Sema::PCC_Class:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003247 return CodeCompletionContext::CCC_ClassStructUnion;
3248
John McCallfaf5fb42010-08-26 23:41:50 +00003249 case Sema::PCC_ObjCInterface:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003250 return CodeCompletionContext::CCC_ObjCInterface;
3251
John McCallfaf5fb42010-08-26 23:41:50 +00003252 case Sema::PCC_ObjCImplementation:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003253 return CodeCompletionContext::CCC_ObjCImplementation;
3254
John McCallfaf5fb42010-08-26 23:41:50 +00003255 case Sema::PCC_ObjCInstanceVariableList:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003256 return CodeCompletionContext::CCC_ObjCIvarList;
3257
John McCallfaf5fb42010-08-26 23:41:50 +00003258 case Sema::PCC_Template:
3259 case Sema::PCC_MemberTemplate:
Douglas Gregor0ac41382010-09-23 23:01:17 +00003260 if (S.CurContext->isFileContext())
3261 return CodeCompletionContext::CCC_TopLevel;
David Blaikie8a40f702012-01-17 06:56:22 +00003262 if (S.CurContext->isRecord())
Douglas Gregor0ac41382010-09-23 23:01:17 +00003263 return CodeCompletionContext::CCC_ClassStructUnion;
David Blaikie8a40f702012-01-17 06:56:22 +00003264 return CodeCompletionContext::CCC_Other;
Douglas Gregor0ac41382010-09-23 23:01:17 +00003265
John McCallfaf5fb42010-08-26 23:41:50 +00003266 case Sema::PCC_RecoveryInFunction:
Douglas Gregor0ac41382010-09-23 23:01:17 +00003267 return CodeCompletionContext::CCC_Recovery;
Douglas Gregorc769d6e2010-10-18 22:01:46 +00003268
John McCallfaf5fb42010-08-26 23:41:50 +00003269 case Sema::PCC_ForInit:
David Blaikiebbafb8a2012-03-11 07:00:24 +00003270 if (S.getLangOpts().CPlusPlus || S.getLangOpts().C99 ||
3271 S.getLangOpts().ObjC1)
Douglas Gregorc769d6e2010-10-18 22:01:46 +00003272 return CodeCompletionContext::CCC_ParenthesizedExpression;
3273 else
3274 return CodeCompletionContext::CCC_Expression;
3275
3276 case Sema::PCC_Expression:
John McCallfaf5fb42010-08-26 23:41:50 +00003277 case Sema::PCC_Condition:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003278 return CodeCompletionContext::CCC_Expression;
3279
John McCallfaf5fb42010-08-26 23:41:50 +00003280 case Sema::PCC_Statement:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003281 return CodeCompletionContext::CCC_Statement;
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003282
John McCallfaf5fb42010-08-26 23:41:50 +00003283 case Sema::PCC_Type:
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003284 return CodeCompletionContext::CCC_Type;
Douglas Gregor5e35d592010-09-14 23:59:36 +00003285
3286 case Sema::PCC_ParenthesizedExpression:
3287 return CodeCompletionContext::CCC_ParenthesizedExpression;
Douglas Gregor80039242011-02-15 20:33:25 +00003288
3289 case Sema::PCC_LocalDeclarationSpecifiers:
3290 return CodeCompletionContext::CCC_Type;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003291 }
David Blaikie8a40f702012-01-17 06:56:22 +00003292
3293 llvm_unreachable("Invalid ParserCompletionContext!");
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003294}
3295
Douglas Gregorac322ec2010-08-27 21:18:54 +00003296/// \brief If we're in a C++ virtual member function, add completion results
3297/// that invoke the functions we override, since it's common to invoke the
3298/// overridden function as well as adding new functionality.
3299///
3300/// \param S The semantic analysis object for which we are generating results.
3301///
3302/// \param InContext This context in which the nested-name-specifier preceding
3303/// the code-completion point
3304static void MaybeAddOverrideCalls(Sema &S, DeclContext *InContext,
3305 ResultBuilder &Results) {
3306 // Look through blocks.
3307 DeclContext *CurContext = S.CurContext;
3308 while (isa<BlockDecl>(CurContext))
3309 CurContext = CurContext->getParent();
3310
3311
3312 CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(CurContext);
3313 if (!Method || !Method->isVirtual())
3314 return;
3315
3316 // We need to have names for all of the parameters, if we're going to
3317 // generate a forwarding call.
David Majnemer59f77922016-06-24 04:05:48 +00003318 for (auto P : Method->parameters())
Aaron Ballman43b68be2014-03-07 17:50:17 +00003319 if (!P->getDeclName())
Douglas Gregorac322ec2010-08-27 21:18:54 +00003320 return;
Douglas Gregorac322ec2010-08-27 21:18:54 +00003321
Douglas Gregor75acd922011-09-27 23:30:47 +00003322 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
Douglas Gregorac322ec2010-08-27 21:18:54 +00003323 for (CXXMethodDecl::method_iterator M = Method->begin_overridden_methods(),
3324 MEnd = Method->end_overridden_methods();
3325 M != MEnd; ++M) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003326 CodeCompletionBuilder Builder(Results.getAllocator(),
3327 Results.getCodeCompletionTUInfo());
Dmitri Gribenko6cfb1532013-02-14 13:53:30 +00003328 const CXXMethodDecl *Overridden = *M;
Douglas Gregorac322ec2010-08-27 21:18:54 +00003329 if (Overridden->getCanonicalDecl() == Method->getCanonicalDecl())
3330 continue;
3331
3332 // If we need a nested-name-specifier, add one now.
3333 if (!InContext) {
3334 NestedNameSpecifier *NNS
3335 = getRequiredQualification(S.Context, CurContext,
3336 Overridden->getDeclContext());
3337 if (NNS) {
3338 std::string Str;
3339 llvm::raw_string_ostream OS(Str);
Douglas Gregor75acd922011-09-27 23:30:47 +00003340 NNS->print(OS, Policy);
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003341 Builder.AddTextChunk(Results.getAllocator().CopyString(OS.str()));
Douglas Gregorac322ec2010-08-27 21:18:54 +00003342 }
3343 } else if (!InContext->Equals(Overridden->getDeclContext()))
3344 continue;
3345
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003346 Builder.AddTypedTextChunk(Results.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003347 Overridden->getNameAsString()));
3348 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregorac322ec2010-08-27 21:18:54 +00003349 bool FirstParam = true;
David Majnemer59f77922016-06-24 04:05:48 +00003350 for (auto P : Method->parameters()) {
Douglas Gregorac322ec2010-08-27 21:18:54 +00003351 if (FirstParam)
3352 FirstParam = false;
3353 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003354 Builder.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregorac322ec2010-08-27 21:18:54 +00003355
Aaron Ballman43b68be2014-03-07 17:50:17 +00003356 Builder.AddPlaceholderChunk(
3357 Results.getAllocator().CopyString(P->getIdentifier()->getName()));
Douglas Gregorac322ec2010-08-27 21:18:54 +00003358 }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003359 Builder.AddChunk(CodeCompletionString::CK_RightParen);
3360 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregorac322ec2010-08-27 21:18:54 +00003361 CCP_SuperCompletion,
Douglas Gregor78254c82012-03-27 23:34:16 +00003362 CXCursor_CXXMethod,
3363 CXAvailability_Available,
3364 Overridden));
Douglas Gregorac322ec2010-08-27 21:18:54 +00003365 Results.Ignore(Overridden);
3366 }
3367}
3368
Douglas Gregor07f43572012-01-29 18:15:03 +00003369void Sema::CodeCompleteModuleImport(SourceLocation ImportLoc,
3370 ModuleIdPath Path) {
3371 typedef CodeCompletionResult Result;
3372 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003373 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor07f43572012-01-29 18:15:03 +00003374 CodeCompletionContext::CCC_Other);
3375 Results.EnterNewScope();
3376
3377 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003378 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Douglas Gregor07f43572012-01-29 18:15:03 +00003379 typedef CodeCompletionResult Result;
3380 if (Path.empty()) {
3381 // Enumerate all top-level modules.
Dmitri Gribenkof8579502013-01-12 19:30:44 +00003382 SmallVector<Module *, 8> Modules;
Douglas Gregor07f43572012-01-29 18:15:03 +00003383 PP.getHeaderSearchInfo().collectAllModules(Modules);
3384 for (unsigned I = 0, N = Modules.size(); I != N; ++I) {
3385 Builder.AddTypedTextChunk(
3386 Builder.getAllocator().CopyString(Modules[I]->Name));
3387 Results.AddResult(Result(Builder.TakeString(),
3388 CCP_Declaration,
Argyrios Kyrtzidis345d05f2013-05-29 18:50:15 +00003389 CXCursor_ModuleImportDecl,
Douglas Gregor07f43572012-01-29 18:15:03 +00003390 Modules[I]->isAvailable()
3391 ? CXAvailability_Available
3392 : CXAvailability_NotAvailable));
3393 }
Daniel Jasper07e6c402013-08-05 20:26:17 +00003394 } else if (getLangOpts().Modules) {
Douglas Gregor07f43572012-01-29 18:15:03 +00003395 // Load the named module.
3396 Module *Mod = PP.getModuleLoader().loadModule(ImportLoc, Path,
3397 Module::AllVisible,
3398 /*IsInclusionDirective=*/false);
3399 // Enumerate submodules.
3400 if (Mod) {
3401 for (Module::submodule_iterator Sub = Mod->submodule_begin(),
3402 SubEnd = Mod->submodule_end();
3403 Sub != SubEnd; ++Sub) {
3404
3405 Builder.AddTypedTextChunk(
3406 Builder.getAllocator().CopyString((*Sub)->Name));
3407 Results.AddResult(Result(Builder.TakeString(),
3408 CCP_Declaration,
Argyrios Kyrtzidis345d05f2013-05-29 18:50:15 +00003409 CXCursor_ModuleImportDecl,
Douglas Gregor07f43572012-01-29 18:15:03 +00003410 (*Sub)->isAvailable()
3411 ? CXAvailability_Available
3412 : CXAvailability_NotAvailable));
3413 }
3414 }
3415 }
3416 Results.ExitScope();
3417 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
3418 Results.data(),Results.size());
3419}
3420
Douglas Gregor504a6ae2010-01-10 23:08:15 +00003421void Sema::CodeCompleteOrdinaryName(Scope *S,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003422 ParserCompletionContext CompletionContext) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003423 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003424 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00003425 mapCodeCompletionContext(*this, CompletionContext));
Douglas Gregorac322ec2010-08-27 21:18:54 +00003426 Results.EnterNewScope();
Douglas Gregor50832e02010-09-20 22:39:41 +00003427
Douglas Gregor504a6ae2010-01-10 23:08:15 +00003428 // Determine how to filter results, e.g., so that the names of
3429 // values (functions, enumerators, function templates, etc.) are
3430 // only allowed where we can have an expression.
3431 switch (CompletionContext) {
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003432 case PCC_Namespace:
3433 case PCC_Class:
3434 case PCC_ObjCInterface:
3435 case PCC_ObjCImplementation:
3436 case PCC_ObjCInstanceVariableList:
3437 case PCC_Template:
3438 case PCC_MemberTemplate:
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003439 case PCC_Type:
Douglas Gregor80039242011-02-15 20:33:25 +00003440 case PCC_LocalDeclarationSpecifiers:
Douglas Gregor504a6ae2010-01-10 23:08:15 +00003441 Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
3442 break;
3443
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003444 case PCC_Statement:
Douglas Gregor5e35d592010-09-14 23:59:36 +00003445 case PCC_ParenthesizedExpression:
Douglas Gregor4d755e82010-08-24 23:58:17 +00003446 case PCC_Expression:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003447 case PCC_ForInit:
3448 case PCC_Condition:
David Blaikiebbafb8a2012-03-11 07:00:24 +00003449 if (WantTypesInContext(CompletionContext, getLangOpts()))
Douglas Gregor70febae2010-05-28 00:49:12 +00003450 Results.setFilter(&ResultBuilder::IsOrdinaryName);
3451 else
3452 Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
Douglas Gregorac322ec2010-08-27 21:18:54 +00003453
David Blaikiebbafb8a2012-03-11 07:00:24 +00003454 if (getLangOpts().CPlusPlus)
Craig Topperc3ec1492014-05-26 06:22:03 +00003455 MaybeAddOverrideCalls(*this, /*InContext=*/nullptr, Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00003456 break;
Douglas Gregor6da3db42010-05-25 05:58:43 +00003457
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003458 case PCC_RecoveryInFunction:
Douglas Gregor6da3db42010-05-25 05:58:43 +00003459 // Unfiltered
3460 break;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00003461 }
3462
Douglas Gregor9be0ed42010-08-26 16:36:48 +00003463 // If we are in a C++ non-static member function, check the qualifiers on
3464 // the member function to filter/prioritize the results list.
3465 if (CXXMethodDecl *CurMethod = dyn_cast<CXXMethodDecl>(CurContext))
3466 if (CurMethod->isInstance())
3467 Results.setObjectTypeQualifiers(
3468 Qualifiers::fromCVRMask(CurMethod->getTypeQualifiers()));
3469
Douglas Gregorc580c522010-01-14 01:09:38 +00003470 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00003471 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3472 CodeCompleter->includeGlobals());
Douglas Gregor92253692009-12-07 09:54:55 +00003473
Douglas Gregorf98e6a22010-01-13 23:51:12 +00003474 AddOrdinaryNameResults(CompletionContext, S, *this, Results);
Douglas Gregor92253692009-12-07 09:54:55 +00003475 Results.ExitScope();
3476
Douglas Gregorce0e8562010-08-23 21:54:33 +00003477 switch (CompletionContext) {
Douglas Gregor5e35d592010-09-14 23:59:36 +00003478 case PCC_ParenthesizedExpression:
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003479 case PCC_Expression:
3480 case PCC_Statement:
3481 case PCC_RecoveryInFunction:
3482 if (S->getFnParent())
Craig Topper12126262015-11-15 17:27:57 +00003483 AddPrettyFunctionResults(getLangOpts(), Results);
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003484 break;
3485
3486 case PCC_Namespace:
3487 case PCC_Class:
3488 case PCC_ObjCInterface:
3489 case PCC_ObjCImplementation:
3490 case PCC_ObjCInstanceVariableList:
3491 case PCC_Template:
3492 case PCC_MemberTemplate:
3493 case PCC_ForInit:
3494 case PCC_Condition:
3495 case PCC_Type:
Douglas Gregor80039242011-02-15 20:33:25 +00003496 case PCC_LocalDeclarationSpecifiers:
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003497 break;
Douglas Gregorce0e8562010-08-23 21:54:33 +00003498 }
3499
Douglas Gregor9eb77012009-11-07 00:00:49 +00003500 if (CodeCompleter->includeMacros())
Douglas Gregor8cb17462012-10-09 16:01:50 +00003501 AddMacroResults(PP, Results, false);
Douglas Gregorce0e8562010-08-23 21:54:33 +00003502
Douglas Gregor50832e02010-09-20 22:39:41 +00003503 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003504 Results.data(),Results.size());
Douglas Gregor9d64c5e2009-09-21 20:51:25 +00003505}
3506
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003507static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
3508 ParsedType Receiver,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00003509 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00003510 bool AtArgumentExpression,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003511 bool IsSuper,
3512 ResultBuilder &Results);
3513
3514void Sema::CodeCompleteDeclSpec(Scope *S, DeclSpec &DS,
3515 bool AllowNonIdentifiers,
3516 bool AllowNestedNameSpecifiers) {
John McCall276321a2010-08-25 06:19:51 +00003517 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003518 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003519 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00003520 AllowNestedNameSpecifiers
3521 ? CodeCompletionContext::CCC_PotentiallyQualifiedName
3522 : CodeCompletionContext::CCC_Name);
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003523 Results.EnterNewScope();
3524
3525 // Type qualifiers can come after names.
3526 Results.AddResult(Result("const"));
3527 Results.AddResult(Result("volatile"));
David Blaikiebbafb8a2012-03-11 07:00:24 +00003528 if (getLangOpts().C99)
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003529 Results.AddResult(Result("restrict"));
3530
David Blaikiebbafb8a2012-03-11 07:00:24 +00003531 if (getLangOpts().CPlusPlus) {
Alex Lorenz8f4d3992017-02-13 23:19:40 +00003532 if (getLangOpts().CPlusPlus11 &&
3533 (DS.getTypeSpecType() == DeclSpec::TST_class ||
3534 DS.getTypeSpecType() == DeclSpec::TST_struct))
3535 Results.AddResult("final");
3536
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003537 if (AllowNonIdentifiers) {
3538 Results.AddResult(Result("operator"));
3539 }
3540
3541 // Add nested-name-specifiers.
3542 if (AllowNestedNameSpecifiers) {
3543 Results.allowNestedNameSpecifiers();
Douglas Gregor0ac41382010-09-23 23:01:17 +00003544 Results.setFilter(&ResultBuilder::IsImpossibleToSatisfy);
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003545 CodeCompletionDeclConsumer Consumer(Results, CurContext);
3546 LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer,
3547 CodeCompleter->includeGlobals());
Craig Topperc3ec1492014-05-26 06:22:03 +00003548 Results.setFilter(nullptr);
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003549 }
3550 }
3551 Results.ExitScope();
3552
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003553 // If we're in a context where we might have an expression (rather than a
3554 // declaration), and what we've seen so far is an Objective-C type that could
3555 // be a receiver of a class message, this may be a class message send with
3556 // the initial opening bracket '[' missing. Add appropriate completions.
3557 if (AllowNonIdentifiers && !AllowNestedNameSpecifiers &&
Richard Smithb4a9e862013-04-12 22:46:28 +00003558 DS.getParsedSpecifiers() == DeclSpec::PQ_TypeSpecifier &&
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003559 DS.getTypeSpecType() == DeclSpec::TST_typename &&
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003560 DS.getTypeSpecComplex() == DeclSpec::TSC_unspecified &&
3561 DS.getTypeSpecSign() == DeclSpec::TSS_unspecified &&
Richard Smithb4a9e862013-04-12 22:46:28 +00003562 !DS.isTypeAltiVecVector() &&
3563 S &&
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003564 (S->getFlags() & Scope::DeclScope) != 0 &&
3565 (S->getFlags() & (Scope::ClassScope | Scope::TemplateParamScope |
3566 Scope::FunctionPrototypeScope |
3567 Scope::AtCatchScope)) == 0) {
3568 ParsedType T = DS.getRepAsType();
3569 if (!T.get().isNull() && T.get()->isObjCObjectOrInterfaceType())
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00003570 AddClassMessageCompletions(*this, S, T, None, false, false, Results);
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003571 }
3572
Douglas Gregor56ccce02010-08-24 04:59:56 +00003573 // Note that we intentionally suppress macro results here, since we do not
3574 // encourage using macros to produce the names of entities.
3575
Douglas Gregor0ac41382010-09-23 23:01:17 +00003576 HandleCodeCompleteResults(this, CodeCompleter,
3577 Results.getCompletionContext(),
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003578 Results.data(), Results.size());
3579}
3580
Douglas Gregor68762e72010-08-23 21:17:50 +00003581struct Sema::CodeCompleteExpressionData {
3582 CodeCompleteExpressionData(QualType PreferredType = QualType())
3583 : PreferredType(PreferredType), IntegralConstantExpression(false),
3584 ObjCCollection(false) { }
3585
3586 QualType PreferredType;
3587 bool IntegralConstantExpression;
3588 bool ObjCCollection;
Chris Lattner0e62c1c2011-07-23 10:55:15 +00003589 SmallVector<Decl *, 4> IgnoreDecls;
Douglas Gregor68762e72010-08-23 21:17:50 +00003590};
3591
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003592/// \brief Perform code-completion in an expression context when we know what
3593/// type we're looking for.
Douglas Gregor68762e72010-08-23 21:17:50 +00003594void Sema::CodeCompleteExpression(Scope *S,
3595 const CodeCompleteExpressionData &Data) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003596 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003597 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003598 CodeCompletionContext::CCC_Expression);
Douglas Gregor68762e72010-08-23 21:17:50 +00003599 if (Data.ObjCCollection)
3600 Results.setFilter(&ResultBuilder::IsObjCCollection);
3601 else if (Data.IntegralConstantExpression)
Douglas Gregor85b50632010-07-28 21:50:18 +00003602 Results.setFilter(&ResultBuilder::IsIntegralConstantValue);
David Blaikiebbafb8a2012-03-11 07:00:24 +00003603 else if (WantTypesInContext(PCC_Expression, getLangOpts()))
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003604 Results.setFilter(&ResultBuilder::IsOrdinaryName);
3605 else
3606 Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
Douglas Gregor68762e72010-08-23 21:17:50 +00003607
3608 if (!Data.PreferredType.isNull())
3609 Results.setPreferredType(Data.PreferredType.getNonReferenceType());
3610
3611 // Ignore any declarations that we were told that we don't care about.
3612 for (unsigned I = 0, N = Data.IgnoreDecls.size(); I != N; ++I)
3613 Results.Ignore(Data.IgnoreDecls[I]);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003614
3615 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00003616 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3617 CodeCompleter->includeGlobals());
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003618
3619 Results.EnterNewScope();
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003620 AddOrdinaryNameResults(PCC_Expression, S, *this, Results);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003621 Results.ExitScope();
3622
Douglas Gregor55b037b2010-07-08 20:55:51 +00003623 bool PreferredTypeIsPointer = false;
Douglas Gregor68762e72010-08-23 21:17:50 +00003624 if (!Data.PreferredType.isNull())
3625 PreferredTypeIsPointer = Data.PreferredType->isAnyPointerType()
3626 || Data.PreferredType->isMemberPointerType()
3627 || Data.PreferredType->isBlockPointerType();
Douglas Gregor55b037b2010-07-08 20:55:51 +00003628
Douglas Gregorce0e8562010-08-23 21:54:33 +00003629 if (S->getFnParent() &&
3630 !Data.ObjCCollection &&
3631 !Data.IntegralConstantExpression)
Craig Topper12126262015-11-15 17:27:57 +00003632 AddPrettyFunctionResults(getLangOpts(), Results);
Douglas Gregorce0e8562010-08-23 21:54:33 +00003633
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003634 if (CodeCompleter->includeMacros())
Douglas Gregor8cb17462012-10-09 16:01:50 +00003635 AddMacroResults(PP, Results, false, PreferredTypeIsPointer);
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003636 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor68762e72010-08-23 21:17:50 +00003637 CodeCompletionContext(CodeCompletionContext::CCC_Expression,
3638 Data.PreferredType),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003639 Results.data(),Results.size());
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003640}
3641
Douglas Gregoreda7e542010-09-18 01:28:11 +00003642void Sema::CodeCompletePostfixExpression(Scope *S, ExprResult E) {
3643 if (E.isInvalid())
3644 CodeCompleteOrdinaryName(S, PCC_RecoveryInFunction);
David Blaikiebbafb8a2012-03-11 07:00:24 +00003645 else if (getLangOpts().ObjC1)
Nikola Smiljanic01a75982014-05-29 10:55:11 +00003646 CodeCompleteObjCInstanceMessage(S, E.get(), None, false);
Douglas Gregored0b69d2010-09-15 16:23:04 +00003647}
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003648
Douglas Gregorb888acf2010-12-09 23:01:55 +00003649/// \brief The set of properties that have already been added, referenced by
3650/// property name.
3651typedef llvm::SmallPtrSet<IdentifierInfo*, 16> AddedPropertiesSet;
3652
Douglas Gregor9b4f3702012-06-12 13:44:08 +00003653/// \brief Retrieve the container definition, if any?
3654static ObjCContainerDecl *getContainerDef(ObjCContainerDecl *Container) {
3655 if (ObjCInterfaceDecl *Interface = dyn_cast<ObjCInterfaceDecl>(Container)) {
3656 if (Interface->hasDefinition())
3657 return Interface->getDefinition();
3658
3659 return Interface;
3660 }
3661
3662 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
3663 if (Protocol->hasDefinition())
3664 return Protocol->getDefinition();
3665
3666 return Protocol;
3667 }
3668 return Container;
3669}
3670
Alex Lorenzbaef8022016-11-09 13:43:18 +00003671/// \brief Adds a block invocation code completion result for the given block
3672/// declaration \p BD.
3673static void AddObjCBlockCall(ASTContext &Context, const PrintingPolicy &Policy,
3674 CodeCompletionBuilder &Builder,
3675 const NamedDecl *BD,
3676 const FunctionTypeLoc &BlockLoc,
3677 const FunctionProtoTypeLoc &BlockProtoLoc) {
3678 Builder.AddResultTypeChunk(
3679 GetCompletionTypeString(BlockLoc.getReturnLoc().getType(), Context,
3680 Policy, Builder.getAllocator()));
3681
3682 AddTypedNameChunk(Context, Policy, BD, Builder);
3683 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
3684
3685 if (BlockProtoLoc && BlockProtoLoc.getTypePtr()->isVariadic()) {
3686 Builder.AddPlaceholderChunk("...");
3687 } else {
3688 for (unsigned I = 0, N = BlockLoc.getNumParams(); I != N; ++I) {
3689 if (I)
3690 Builder.AddChunk(CodeCompletionString::CK_Comma);
3691
3692 // Format the placeholder string.
3693 std::string PlaceholderStr =
3694 FormatFunctionParameter(Policy, BlockLoc.getParam(I));
3695
3696 if (I == N - 1 && BlockProtoLoc &&
3697 BlockProtoLoc.getTypePtr()->isVariadic())
3698 PlaceholderStr += ", ...";
3699
3700 // Add the placeholder string.
3701 Builder.AddPlaceholderChunk(
3702 Builder.getAllocator().CopyString(PlaceholderStr));
3703 }
3704 }
3705
3706 Builder.AddChunk(CodeCompletionString::CK_RightParen);
3707}
3708
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003709static void AddObjCProperties(
3710 const CodeCompletionContext &CCContext, ObjCContainerDecl *Container,
3711 bool AllowCategories, bool AllowNullaryMethods, DeclContext *CurContext,
3712 AddedPropertiesSet &AddedProperties, ResultBuilder &Results,
3713 bool IsBaseExprStatement = false, bool IsClassProperty = false) {
John McCall276321a2010-08-25 06:19:51 +00003714 typedef CodeCompletionResult Result;
Douglas Gregor9291bad2009-11-18 01:29:26 +00003715
Douglas Gregor9b4f3702012-06-12 13:44:08 +00003716 // Retrieve the definition.
3717 Container = getContainerDef(Container);
3718
Douglas Gregor9291bad2009-11-18 01:29:26 +00003719 // Add properties in this container.
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003720 const auto AddProperty = [&](const ObjCPropertyDecl *P) {
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003721 if (!AddedProperties.insert(P->getIdentifier()).second)
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003722 return;
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003723
Alex Lorenzbaef8022016-11-09 13:43:18 +00003724 // FIXME: Provide block invocation completion for non-statement
3725 // expressions.
3726 if (!P->getType().getTypePtr()->isBlockPointerType() ||
3727 !IsBaseExprStatement) {
3728 Results.MaybeAddResult(Result(P, Results.getBasePriority(P), nullptr),
3729 CurContext);
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003730 return;
Alex Lorenzbaef8022016-11-09 13:43:18 +00003731 }
3732
3733 // Block setter and invocation completion is provided only when we are able
3734 // to find the FunctionProtoTypeLoc with parameter names for the block.
3735 FunctionTypeLoc BlockLoc;
3736 FunctionProtoTypeLoc BlockProtoLoc;
3737 findTypeLocationForBlockDecl(P->getTypeSourceInfo(), BlockLoc,
3738 BlockProtoLoc);
3739 if (!BlockLoc) {
3740 Results.MaybeAddResult(Result(P, Results.getBasePriority(P), nullptr),
3741 CurContext);
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003742 return;
Alex Lorenzbaef8022016-11-09 13:43:18 +00003743 }
3744
3745 // The default completion result for block properties should be the block
3746 // invocation completion when the base expression is a statement.
3747 CodeCompletionBuilder Builder(Results.getAllocator(),
3748 Results.getCodeCompletionTUInfo());
3749 AddObjCBlockCall(Container->getASTContext(),
3750 getCompletionPrintingPolicy(Results.getSema()), Builder, P,
3751 BlockLoc, BlockProtoLoc);
3752 Results.MaybeAddResult(
3753 Result(Builder.TakeString(), P, Results.getBasePriority(P)),
3754 CurContext);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003755
3756 // Provide additional block setter completion iff the base expression is a
Alex Lorenzbaef8022016-11-09 13:43:18 +00003757 // statement and the block property is mutable.
3758 if (!P->isReadOnly()) {
3759 CodeCompletionBuilder Builder(Results.getAllocator(),
3760 Results.getCodeCompletionTUInfo());
3761 AddResultTypeChunk(Container->getASTContext(),
3762 getCompletionPrintingPolicy(Results.getSema()), P,
3763 CCContext.getBaseType(), Builder);
3764 Builder.AddTypedTextChunk(
3765 Results.getAllocator().CopyString(P->getName()));
3766 Builder.AddChunk(CodeCompletionString::CK_Equal);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003767
Alex Lorenzbaef8022016-11-09 13:43:18 +00003768 std::string PlaceholderStr = formatBlockPlaceholder(
3769 getCompletionPrintingPolicy(Results.getSema()), P, BlockLoc,
3770 BlockProtoLoc, /*SuppressBlockName=*/true);
3771 // Add the placeholder string.
3772 Builder.AddPlaceholderChunk(
3773 Builder.getAllocator().CopyString(PlaceholderStr));
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003774
Alex Lorenz6e0f3932017-01-06 12:00:44 +00003775 // When completing blocks properties that return void the default
3776 // property completion result should show up before the setter,
3777 // otherwise the setter completion should show up before the default
3778 // property completion, as we normally want to use the result of the
3779 // call.
Alex Lorenzbaef8022016-11-09 13:43:18 +00003780 Results.MaybeAddResult(
3781 Result(Builder.TakeString(), P,
Alex Lorenz6e0f3932017-01-06 12:00:44 +00003782 Results.getBasePriority(P) +
3783 (BlockLoc.getTypePtr()->getReturnType()->isVoidType()
3784 ? CCD_BlockPropertySetter
3785 : -CCD_BlockPropertySetter)),
Alex Lorenzbaef8022016-11-09 13:43:18 +00003786 CurContext);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003787 }
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003788 };
3789
3790 if (IsClassProperty) {
3791 for (const auto *P : Container->class_properties())
3792 AddProperty(P);
3793 } else {
3794 for (const auto *P : Container->instance_properties())
3795 AddProperty(P);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003796 }
Craig Topperc3ec1492014-05-26 06:22:03 +00003797
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003798 // Add nullary methods or implicit class properties
Douglas Gregor95147142011-05-05 15:50:42 +00003799 if (AllowNullaryMethods) {
3800 ASTContext &Context = Container->getASTContext();
Douglas Gregor75acd922011-09-27 23:30:47 +00003801 PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema());
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003802 // Adds a method result
3803 const auto AddMethod = [&](const ObjCMethodDecl *M) {
3804 IdentifierInfo *Name = M->getSelector().getIdentifierInfoForSlot(0);
3805 if (!Name)
3806 return;
3807 if (!AddedProperties.insert(Name).second)
3808 return;
3809 CodeCompletionBuilder Builder(Results.getAllocator(),
3810 Results.getCodeCompletionTUInfo());
3811 AddResultTypeChunk(Context, Policy, M, CCContext.getBaseType(), Builder);
3812 Builder.AddTypedTextChunk(
3813 Results.getAllocator().CopyString(Name->getName()));
3814 Results.MaybeAddResult(
3815 Result(Builder.TakeString(), M,
3816 CCP_MemberDeclaration + CCD_MethodAsProperty),
3817 CurContext);
3818 };
3819
3820 if (IsClassProperty) {
3821 for (const auto *M : Container->methods()) {
3822 // Gather the class method that can be used as implicit property
3823 // getters. Methods with arguments or methods that return void aren't
3824 // added to the results as they can't be used as a getter.
3825 if (!M->getSelector().isUnarySelector() ||
3826 M->getReturnType()->isVoidType() || M->isInstanceMethod())
3827 continue;
3828 AddMethod(M);
3829 }
3830 } else {
3831 for (auto *M : Container->methods()) {
3832 if (M->getSelector().isUnarySelector())
3833 AddMethod(M);
3834 }
Douglas Gregor95147142011-05-05 15:50:42 +00003835 }
3836 }
Douglas Gregor95147142011-05-05 15:50:42 +00003837
Douglas Gregor9291bad2009-11-18 01:29:26 +00003838 // Add properties in referenced protocols.
3839 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Aaron Ballman0f6e64d2014-03-13 22:58:06 +00003840 for (auto *P : Protocol->protocols())
Douglas Gregorc3425b12015-07-07 06:20:19 +00003841 AddObjCProperties(CCContext, P, AllowCategories, AllowNullaryMethods,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003842 CurContext, AddedProperties, Results,
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003843 IsBaseExprStatement, IsClassProperty);
Douglas Gregor9291bad2009-11-18 01:29:26 +00003844 } else if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)){
Douglas Gregor5d649882009-11-18 22:32:06 +00003845 if (AllowCategories) {
3846 // Look through categories.
Aaron Ballman15063e12014-03-13 21:35:02 +00003847 for (auto *Cat : IFace->known_categories())
Douglas Gregorc3425b12015-07-07 06:20:19 +00003848 AddObjCProperties(CCContext, Cat, AllowCategories, AllowNullaryMethods,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003849 CurContext, AddedProperties, Results,
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003850 IsBaseExprStatement, IsClassProperty);
Douglas Gregor5d649882009-11-18 22:32:06 +00003851 }
Aaron Ballman15063e12014-03-13 21:35:02 +00003852
Douglas Gregor9291bad2009-11-18 01:29:26 +00003853 // Look through protocols.
Aaron Ballmana9f49e32014-03-13 20:55:22 +00003854 for (auto *I : IFace->all_referenced_protocols())
Douglas Gregorc3425b12015-07-07 06:20:19 +00003855 AddObjCProperties(CCContext, I, AllowCategories, AllowNullaryMethods,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003856 CurContext, AddedProperties, Results,
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003857 IsBaseExprStatement, IsClassProperty);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003858
Douglas Gregor9291bad2009-11-18 01:29:26 +00003859 // Look in the superclass.
3860 if (IFace->getSuperClass())
Douglas Gregorc3425b12015-07-07 06:20:19 +00003861 AddObjCProperties(CCContext, IFace->getSuperClass(), AllowCategories,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003862 AllowNullaryMethods, CurContext, AddedProperties,
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003863 Results, IsBaseExprStatement, IsClassProperty);
Douglas Gregor9291bad2009-11-18 01:29:26 +00003864 } else if (const ObjCCategoryDecl *Category
3865 = dyn_cast<ObjCCategoryDecl>(Container)) {
3866 // Look through protocols.
Aaron Ballman19a41762014-03-14 12:55:57 +00003867 for (auto *P : Category->protocols())
Douglas Gregorc3425b12015-07-07 06:20:19 +00003868 AddObjCProperties(CCContext, P, AllowCategories, AllowNullaryMethods,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003869 CurContext, AddedProperties, Results,
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003870 IsBaseExprStatement, IsClassProperty);
Douglas Gregor9291bad2009-11-18 01:29:26 +00003871 }
3872}
3873
Alex Lorenz0fe0d982017-05-11 13:41:00 +00003874static void AddRecordMembersCompletionResults(Sema &SemaRef,
3875 ResultBuilder &Results, Scope *S,
3876 QualType BaseType,
3877 RecordDecl *RD) {
3878 // Indicate that we are performing a member access, and the cv-qualifiers
3879 // for the base object type.
3880 Results.setObjectTypeQualifiers(BaseType.getQualifiers());
3881
3882 // Access to a C/C++ class, struct, or union.
3883 Results.allowNestedNameSpecifiers();
3884 CodeCompletionDeclConsumer Consumer(Results, SemaRef.CurContext);
3885 SemaRef.LookupVisibleDecls(RD, Sema::LookupMemberName, Consumer,
Alex Lorenze6afa392017-05-11 13:48:57 +00003886 SemaRef.CodeCompleter->includeGlobals(),
3887 /*IncludeDependentBases=*/true);
Alex Lorenz0fe0d982017-05-11 13:41:00 +00003888
3889 if (SemaRef.getLangOpts().CPlusPlus) {
3890 if (!Results.empty()) {
3891 // The "template" keyword can follow "->" or "." in the grammar.
3892 // However, we only want to suggest the template keyword if something
3893 // is dependent.
3894 bool IsDependent = BaseType->isDependentType();
3895 if (!IsDependent) {
3896 for (Scope *DepScope = S; DepScope; DepScope = DepScope->getParent())
3897 if (DeclContext *Ctx = DepScope->getEntity()) {
3898 IsDependent = Ctx->isDependentContext();
3899 break;
3900 }
3901 }
3902
3903 if (IsDependent)
3904 Results.AddResult(CodeCompletionResult("template"));
3905 }
3906 }
3907}
3908
Douglas Gregor1cc88a92012-01-23 15:59:30 +00003909void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003910 SourceLocation OpLoc, bool IsArrow,
3911 bool IsBaseExprStatement) {
Douglas Gregor1cc88a92012-01-23 15:59:30 +00003912 if (!Base || !CodeCompleter)
Douglas Gregor2436e712009-09-17 21:32:03 +00003913 return;
3914
Douglas Gregor1cc88a92012-01-23 15:59:30 +00003915 ExprResult ConvertedBase = PerformMemberExprBaseConversion(Base, IsArrow);
3916 if (ConvertedBase.isInvalid())
3917 return;
3918 Base = ConvertedBase.get();
Douglas Gregor3545ff42009-09-21 16:56:56 +00003919
Douglas Gregor2436e712009-09-17 21:32:03 +00003920 QualType BaseType = Base->getType();
Douglas Gregor3545ff42009-09-21 16:56:56 +00003921
3922 if (IsArrow) {
3923 if (const PointerType *Ptr = BaseType->getAs<PointerType>())
3924 BaseType = Ptr->getPointeeType();
3925 else if (BaseType->isObjCObjectPointerType())
Douglas Gregor9be0ed42010-08-26 16:36:48 +00003926 /*Do nothing*/ ;
Douglas Gregor3545ff42009-09-21 16:56:56 +00003927 else
3928 return;
3929 }
3930
Douglas Gregor21325842011-07-07 16:03:39 +00003931 enum CodeCompletionContext::Kind contextKind;
3932
3933 if (IsArrow) {
3934 contextKind = CodeCompletionContext::CCC_ArrowMemberAccess;
3935 }
3936 else {
3937 if (BaseType->isObjCObjectPointerType() ||
3938 BaseType->isObjCObjectOrInterfaceType()) {
3939 contextKind = CodeCompletionContext::CCC_ObjCPropertyAccess;
3940 }
3941 else {
3942 contextKind = CodeCompletionContext::CCC_DotMemberAccess;
3943 }
3944 }
Douglas Gregorc3425b12015-07-07 06:20:19 +00003945
3946 CodeCompletionContext CCContext(contextKind, BaseType);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003947 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003948 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorc3425b12015-07-07 06:20:19 +00003949 CCContext,
Douglas Gregor0ac41382010-09-23 23:01:17 +00003950 &ResultBuilder::IsMember);
Douglas Gregor9291bad2009-11-18 01:29:26 +00003951 Results.EnterNewScope();
3952 if (const RecordType *Record = BaseType->getAs<RecordType>()) {
Alex Lorenz0fe0d982017-05-11 13:41:00 +00003953 AddRecordMembersCompletionResults(*this, Results, S, BaseType,
3954 Record->getDecl());
Alex Lorenze6afa392017-05-11 13:48:57 +00003955 } else if (const auto *TST = BaseType->getAs<TemplateSpecializationType>()) {
3956 TemplateName TN = TST->getTemplateName();
3957 if (const auto *TD =
3958 dyn_cast_or_null<ClassTemplateDecl>(TN.getAsTemplateDecl())) {
3959 CXXRecordDecl *RD = TD->getTemplatedDecl();
3960 AddRecordMembersCompletionResults(*this, Results, S, BaseType, RD);
3961 }
3962 } else if (const auto *ICNT = BaseType->getAs<InjectedClassNameType>()) {
3963 if (auto *RD = ICNT->getDecl())
3964 AddRecordMembersCompletionResults(*this, Results, S, BaseType, RD);
Alex Lorenz06cfa992016-10-12 11:40:15 +00003965 } else if (!IsArrow && BaseType->isObjCObjectPointerType()) {
Douglas Gregor9291bad2009-11-18 01:29:26 +00003966 // Objective-C property reference.
Douglas Gregorb888acf2010-12-09 23:01:55 +00003967 AddedPropertiesSet AddedProperties;
Alex Lorenz06cfa992016-10-12 11:40:15 +00003968
3969 if (const ObjCObjectPointerType *ObjCPtr =
3970 BaseType->getAsObjCInterfacePointerType()) {
3971 // Add property results based on our interface.
3972 assert(ObjCPtr && "Non-NULL pointer guaranteed above!");
3973 AddObjCProperties(CCContext, ObjCPtr->getInterfaceDecl(), true,
3974 /*AllowNullaryMethods=*/true, CurContext,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003975 AddedProperties, Results, IsBaseExprStatement);
Alex Lorenz06cfa992016-10-12 11:40:15 +00003976 }
3977
Douglas Gregor9291bad2009-11-18 01:29:26 +00003978 // Add properties from the protocols in a qualified interface.
Alex Lorenz06cfa992016-10-12 11:40:15 +00003979 for (auto *I : BaseType->getAs<ObjCObjectPointerType>()->quals())
Douglas Gregorc3425b12015-07-07 06:20:19 +00003980 AddObjCProperties(CCContext, I, true, /*AllowNullaryMethods=*/true,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003981 CurContext, AddedProperties, Results,
3982 IsBaseExprStatement);
Douglas Gregor9291bad2009-11-18 01:29:26 +00003983 } else if ((IsArrow && BaseType->isObjCObjectPointerType()) ||
John McCall8b07ec22010-05-15 11:32:37 +00003984 (!IsArrow && BaseType->isObjCObjectType())) {
Douglas Gregor9291bad2009-11-18 01:29:26 +00003985 // Objective-C instance variable access.
Craig Topperc3ec1492014-05-26 06:22:03 +00003986 ObjCInterfaceDecl *Class = nullptr;
Douglas Gregor9291bad2009-11-18 01:29:26 +00003987 if (const ObjCObjectPointerType *ObjCPtr
3988 = BaseType->getAs<ObjCObjectPointerType>())
3989 Class = ObjCPtr->getInterfaceDecl();
3990 else
John McCall8b07ec22010-05-15 11:32:37 +00003991 Class = BaseType->getAs<ObjCObjectType>()->getInterface();
Douglas Gregor9291bad2009-11-18 01:29:26 +00003992
3993 // Add all ivars from this class and its superclasses.
Douglas Gregor2b8162b2010-01-14 16:08:12 +00003994 if (Class) {
3995 CodeCompletionDeclConsumer Consumer(Results, CurContext);
3996 Results.setFilter(&ResultBuilder::IsObjCIvar);
Douglas Gregor39982192010-08-15 06:18:01 +00003997 LookupVisibleDecls(Class, LookupMemberName, Consumer,
3998 CodeCompleter->includeGlobals());
Douglas Gregor9291bad2009-11-18 01:29:26 +00003999 }
Douglas Gregor3545ff42009-09-21 16:56:56 +00004000 }
Douglas Gregor9291bad2009-11-18 01:29:26 +00004001
4002 // FIXME: How do we cope with isa?
4003
4004 Results.ExitScope();
Daniel Dunbar242ea9a2009-11-13 08:58:20 +00004005
Daniel Dunbar242ea9a2009-11-13 08:58:20 +00004006 // Hand off the results found for code completion.
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004007 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004008 Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004009 Results.data(),Results.size());
Douglas Gregor2436e712009-09-17 21:32:03 +00004010}
4011
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004012void Sema::CodeCompleteObjCClassPropertyRefExpr(Scope *S,
4013 IdentifierInfo &ClassName,
4014 SourceLocation ClassNameLoc,
4015 bool IsBaseExprStatement) {
4016 IdentifierInfo *ClassNamePtr = &ClassName;
4017 ObjCInterfaceDecl *IFace = getObjCInterfaceDecl(ClassNamePtr, ClassNameLoc);
4018 if (!IFace)
4019 return;
4020 CodeCompletionContext CCContext(
4021 CodeCompletionContext::CCC_ObjCPropertyAccess);
4022 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4023 CodeCompleter->getCodeCompletionTUInfo(), CCContext,
4024 &ResultBuilder::IsMember);
4025 Results.EnterNewScope();
4026 AddedPropertiesSet AddedProperties;
4027 AddObjCProperties(CCContext, IFace, true,
4028 /*AllowNullaryMethods=*/true, CurContext, AddedProperties,
4029 Results, IsBaseExprStatement,
4030 /*IsClassProperty=*/true);
4031 Results.ExitScope();
4032 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4033 Results.data(), Results.size());
4034}
4035
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004036void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) {
4037 if (!CodeCompleter)
4038 return;
Craig Topperc3ec1492014-05-26 06:22:03 +00004039
4040 ResultBuilder::LookupFilter Filter = nullptr;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004041 enum CodeCompletionContext::Kind ContextKind
4042 = CodeCompletionContext::CCC_Other;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004043 switch ((DeclSpec::TST)TagSpec) {
4044 case DeclSpec::TST_enum:
Douglas Gregor3545ff42009-09-21 16:56:56 +00004045 Filter = &ResultBuilder::IsEnum;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004046 ContextKind = CodeCompletionContext::CCC_EnumTag;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004047 break;
4048
4049 case DeclSpec::TST_union:
Douglas Gregor3545ff42009-09-21 16:56:56 +00004050 Filter = &ResultBuilder::IsUnion;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004051 ContextKind = CodeCompletionContext::CCC_UnionTag;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004052 break;
4053
4054 case DeclSpec::TST_struct:
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004055 case DeclSpec::TST_class:
Joao Matosdc86f942012-08-31 18:45:21 +00004056 case DeclSpec::TST_interface:
Douglas Gregor3545ff42009-09-21 16:56:56 +00004057 Filter = &ResultBuilder::IsClassOrStruct;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004058 ContextKind = CodeCompletionContext::CCC_ClassOrStructTag;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004059 break;
4060
4061 default:
David Blaikie83d382b2011-09-23 05:06:16 +00004062 llvm_unreachable("Unknown type specifier kind in CodeCompleteTag");
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004063 }
Douglas Gregor3545ff42009-09-21 16:56:56 +00004064
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004065 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4066 CodeCompleter->getCodeCompletionTUInfo(), ContextKind);
Douglas Gregora6e2edc2010-01-14 03:27:13 +00004067 CodeCompletionDeclConsumer Consumer(Results, CurContext);
John McCalle87beb22010-04-23 18:46:30 +00004068
4069 // First pass: look for tags.
4070 Results.setFilter(Filter);
Douglas Gregor39982192010-08-15 06:18:01 +00004071 LookupVisibleDecls(S, LookupTagName, Consumer,
4072 CodeCompleter->includeGlobals());
John McCalle87beb22010-04-23 18:46:30 +00004073
Douglas Gregor39982192010-08-15 06:18:01 +00004074 if (CodeCompleter->includeGlobals()) {
4075 // Second pass: look for nested name specifiers.
4076 Results.setFilter(&ResultBuilder::IsNestedNameSpecifier);
4077 LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer);
4078 }
Douglas Gregor3545ff42009-09-21 16:56:56 +00004079
Douglas Gregor0ac41382010-09-23 23:01:17 +00004080 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004081 Results.data(),Results.size());
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004082}
4083
Alex Lorenz8f4d3992017-02-13 23:19:40 +00004084static void AddTypeQualifierResults(DeclSpec &DS, ResultBuilder &Results,
4085 const LangOptions &LangOpts) {
4086 if (!(DS.getTypeQualifiers() & DeclSpec::TQ_const))
4087 Results.AddResult("const");
4088 if (!(DS.getTypeQualifiers() & DeclSpec::TQ_volatile))
4089 Results.AddResult("volatile");
4090 if (LangOpts.C99 && !(DS.getTypeQualifiers() & DeclSpec::TQ_restrict))
4091 Results.AddResult("restrict");
4092 if (LangOpts.C11 && !(DS.getTypeQualifiers() & DeclSpec::TQ_atomic))
4093 Results.AddResult("_Atomic");
4094 if (LangOpts.MSVCCompat && !(DS.getTypeQualifiers() & DeclSpec::TQ_unaligned))
4095 Results.AddResult("__unaligned");
4096}
4097
Douglas Gregor28c78432010-08-27 17:35:51 +00004098void Sema::CodeCompleteTypeQualifiers(DeclSpec &DS) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004099 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004100 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004101 CodeCompletionContext::CCC_TypeQualifiers);
Douglas Gregor28c78432010-08-27 17:35:51 +00004102 Results.EnterNewScope();
Alex Lorenz8f4d3992017-02-13 23:19:40 +00004103 AddTypeQualifierResults(DS, Results, LangOpts);
Douglas Gregor28c78432010-08-27 17:35:51 +00004104 Results.ExitScope();
4105 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004106 Results.getCompletionContext(),
Douglas Gregor28c78432010-08-27 17:35:51 +00004107 Results.data(), Results.size());
4108}
4109
Alex Lorenz8f4d3992017-02-13 23:19:40 +00004110void Sema::CodeCompleteFunctionQualifiers(DeclSpec &DS, Declarator &D,
4111 const VirtSpecifiers *VS) {
4112 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4113 CodeCompleter->getCodeCompletionTUInfo(),
4114 CodeCompletionContext::CCC_TypeQualifiers);
4115 Results.EnterNewScope();
4116 AddTypeQualifierResults(DS, Results, LangOpts);
4117 if (LangOpts.CPlusPlus11) {
4118 Results.AddResult("noexcept");
4119 if (D.getContext() == Declarator::MemberContext && !D.isCtorOrDtor() &&
4120 !D.isStaticMember()) {
4121 if (!VS || !VS->isFinalSpecified())
4122 Results.AddResult("final");
4123 if (!VS || !VS->isOverrideSpecified())
4124 Results.AddResult("override");
4125 }
4126 }
4127 Results.ExitScope();
4128 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4129 Results.data(), Results.size());
4130}
4131
Benjamin Kramer72dae622016-02-18 15:30:24 +00004132void Sema::CodeCompleteBracketDeclarator(Scope *S) {
4133 CodeCompleteExpression(S, QualType(getASTContext().getSizeType()));
4134}
4135
Douglas Gregord328d572009-09-21 18:10:23 +00004136void Sema::CodeCompleteCase(Scope *S) {
John McCallaab3e412010-08-25 08:40:02 +00004137 if (getCurFunction()->SwitchStack.empty() || !CodeCompleter)
Douglas Gregord328d572009-09-21 18:10:23 +00004138 return;
John McCall5939b162011-08-06 07:30:58 +00004139
John McCallaab3e412010-08-25 08:40:02 +00004140 SwitchStmt *Switch = getCurFunction()->SwitchStack.back();
John McCall5939b162011-08-06 07:30:58 +00004141 QualType type = Switch->getCond()->IgnoreImplicit()->getType();
4142 if (!type->isEnumeralType()) {
4143 CodeCompleteExpressionData Data(type);
Douglas Gregor68762e72010-08-23 21:17:50 +00004144 Data.IntegralConstantExpression = true;
4145 CodeCompleteExpression(S, Data);
Douglas Gregord328d572009-09-21 18:10:23 +00004146 return;
Douglas Gregor85b50632010-07-28 21:50:18 +00004147 }
Douglas Gregord328d572009-09-21 18:10:23 +00004148
4149 // Code-complete the cases of a switch statement over an enumeration type
4150 // by providing the list of
John McCall5939b162011-08-06 07:30:58 +00004151 EnumDecl *Enum = type->castAs<EnumType>()->getDecl();
Douglas Gregor9b4f3702012-06-12 13:44:08 +00004152 if (EnumDecl *Def = Enum->getDefinition())
4153 Enum = Def;
Douglas Gregord328d572009-09-21 18:10:23 +00004154
4155 // Determine which enumerators we have already seen in the switch statement.
4156 // FIXME: Ideally, we would also be able to look *past* the code-completion
4157 // token, in case we are code-completing in the middle of the switch and not
4158 // at the end. However, we aren't able to do so at the moment.
4159 llvm::SmallPtrSet<EnumConstantDecl *, 8> EnumeratorsSeen;
Craig Topperc3ec1492014-05-26 06:22:03 +00004160 NestedNameSpecifier *Qualifier = nullptr;
Douglas Gregord328d572009-09-21 18:10:23 +00004161 for (SwitchCase *SC = Switch->getSwitchCaseList(); SC;
4162 SC = SC->getNextSwitchCase()) {
4163 CaseStmt *Case = dyn_cast<CaseStmt>(SC);
4164 if (!Case)
4165 continue;
4166
4167 Expr *CaseVal = Case->getLHS()->IgnoreParenCasts();
4168 if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CaseVal))
4169 if (EnumConstantDecl *Enumerator
4170 = dyn_cast<EnumConstantDecl>(DRE->getDecl())) {
4171 // We look into the AST of the case statement to determine which
4172 // enumerator was named. Alternatively, we could compute the value of
4173 // the integral constant expression, then compare it against the
4174 // values of each enumerator. However, value-based approach would not
4175 // work as well with C++ templates where enumerators declared within a
4176 // template are type- and value-dependent.
4177 EnumeratorsSeen.insert(Enumerator);
4178
Douglas Gregorf2510672009-09-21 19:57:38 +00004179 // If this is a qualified-id, keep track of the nested-name-specifier
4180 // so that we can reproduce it as part of code completion, e.g.,
Douglas Gregord328d572009-09-21 18:10:23 +00004181 //
4182 // switch (TagD.getKind()) {
4183 // case TagDecl::TK_enum:
4184 // break;
4185 // case XXX
4186 //
Douglas Gregorf2510672009-09-21 19:57:38 +00004187 // At the XXX, our completions are TagDecl::TK_union,
Douglas Gregord328d572009-09-21 18:10:23 +00004188 // TagDecl::TK_struct, and TagDecl::TK_class, rather than TK_union,
4189 // TK_struct, and TK_class.
Douglas Gregor4bd90e52009-10-23 18:54:35 +00004190 Qualifier = DRE->getQualifier();
Douglas Gregord328d572009-09-21 18:10:23 +00004191 }
4192 }
4193
David Blaikiebbafb8a2012-03-11 07:00:24 +00004194 if (getLangOpts().CPlusPlus && !Qualifier && EnumeratorsSeen.empty()) {
Douglas Gregorf2510672009-09-21 19:57:38 +00004195 // If there are no prior enumerators in C++, check whether we have to
4196 // qualify the names of the enumerators that we suggest, because they
4197 // may not be visible in this scope.
Douglas Gregord3cebdb2012-02-01 05:02:47 +00004198 Qualifier = getRequiredQualification(Context, CurContext, Enum);
Douglas Gregorf2510672009-09-21 19:57:38 +00004199 }
4200
Douglas Gregord328d572009-09-21 18:10:23 +00004201 // Add any enumerators that have not yet been mentioned.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004202 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004203 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004204 CodeCompletionContext::CCC_Expression);
Douglas Gregord328d572009-09-21 18:10:23 +00004205 Results.EnterNewScope();
Aaron Ballman23a6dcb2014-03-08 18:45:14 +00004206 for (auto *E : Enum->enumerators()) {
4207 if (EnumeratorsSeen.count(E))
Douglas Gregord328d572009-09-21 18:10:23 +00004208 continue;
4209
Aaron Ballman23a6dcb2014-03-08 18:45:14 +00004210 CodeCompletionResult R(E, CCP_EnumInCase, Qualifier);
Craig Topperc3ec1492014-05-26 06:22:03 +00004211 Results.AddResult(R, CurContext, nullptr, false);
Douglas Gregord328d572009-09-21 18:10:23 +00004212 }
4213 Results.ExitScope();
Douglas Gregor285560922010-04-06 20:02:15 +00004214
Douglas Gregor21325842011-07-07 16:03:39 +00004215 //We need to make sure we're setting the right context,
4216 //so only say we include macros if the code completer says we do
4217 enum CodeCompletionContext::Kind kind = CodeCompletionContext::CCC_Other;
4218 if (CodeCompleter->includeMacros()) {
Douglas Gregor8cb17462012-10-09 16:01:50 +00004219 AddMacroResults(PP, Results, false);
Douglas Gregor21325842011-07-07 16:03:39 +00004220 kind = CodeCompletionContext::CCC_OtherWithMacros;
4221 }
4222
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004223 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor21325842011-07-07 16:03:39 +00004224 kind,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004225 Results.data(),Results.size());
Douglas Gregord328d572009-09-21 18:10:23 +00004226}
4227
Robert Wilhelm16e94b92013-08-09 18:02:13 +00004228static bool anyNullArguments(ArrayRef<Expr *> Args) {
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00004229 if (Args.size() && !Args.data())
Douglas Gregor6ed3eb82010-05-30 06:10:08 +00004230 return true;
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00004231
4232 for (unsigned I = 0; I != Args.size(); ++I)
Douglas Gregor6ed3eb82010-05-30 06:10:08 +00004233 if (!Args[I])
4234 return true;
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00004235
Douglas Gregor6ed3eb82010-05-30 06:10:08 +00004236 return false;
4237}
4238
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004239typedef CodeCompleteConsumer::OverloadCandidate ResultCandidate;
4240
Francisco Lopes da Silva8cafefa2015-01-29 05:54:59 +00004241static void mergeCandidatesWithResults(Sema &SemaRef,
4242 SmallVectorImpl<ResultCandidate> &Results,
4243 OverloadCandidateSet &CandidateSet,
4244 SourceLocation Loc) {
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004245 if (!CandidateSet.empty()) {
4246 // Sort the overload candidate set by placing the best overloads first.
4247 std::stable_sort(
4248 CandidateSet.begin(), CandidateSet.end(),
4249 [&](const OverloadCandidate &X, const OverloadCandidate &Y) {
4250 return isBetterOverloadCandidate(SemaRef, X, Y, Loc);
4251 });
4252
4253 // Add the remaining viable overload candidates as code-completion results.
4254 for (auto &Candidate : CandidateSet)
4255 if (Candidate.Viable)
4256 Results.push_back(ResultCandidate(Candidate.Function));
4257 }
4258}
4259
4260/// \brief Get the type of the Nth parameter from a given set of overload
4261/// candidates.
Francisco Lopes da Silva8cafefa2015-01-29 05:54:59 +00004262static QualType getParamType(Sema &SemaRef,
4263 ArrayRef<ResultCandidate> Candidates,
4264 unsigned N) {
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004265
4266 // Given the overloads 'Candidates' for a function call matching all arguments
4267 // up to N, return the type of the Nth parameter if it is the same for all
4268 // overload candidates.
4269 QualType ParamType;
4270 for (auto &Candidate : Candidates) {
4271 if (auto FType = Candidate.getFunctionType())
4272 if (auto Proto = dyn_cast<FunctionProtoType>(FType))
4273 if (N < Proto->getNumParams()) {
4274 if (ParamType.isNull())
4275 ParamType = Proto->getParamType(N);
4276 else if (!SemaRef.Context.hasSameUnqualifiedType(
4277 ParamType.getNonReferenceType(),
4278 Proto->getParamType(N).getNonReferenceType()))
4279 // Otherwise return a default-constructed QualType.
4280 return QualType();
4281 }
4282 }
4283
4284 return ParamType;
4285}
4286
Francisco Lopes da Silva8cafefa2015-01-29 05:54:59 +00004287static void CodeCompleteOverloadResults(Sema &SemaRef, Scope *S,
4288 MutableArrayRef<ResultCandidate> Candidates,
4289 unsigned CurrentArg,
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004290 bool CompleteExpressionWithCurrentArg = true) {
4291 QualType ParamType;
4292 if (CompleteExpressionWithCurrentArg)
4293 ParamType = getParamType(SemaRef, Candidates, CurrentArg);
4294
4295 if (ParamType.isNull())
4296 SemaRef.CodeCompleteOrdinaryName(S, Sema::PCC_Expression);
4297 else
4298 SemaRef.CodeCompleteExpression(S, ParamType);
4299
4300 if (!Candidates.empty())
4301 SemaRef.CodeCompleter->ProcessOverloadCandidates(SemaRef, CurrentArg,
4302 Candidates.data(),
4303 Candidates.size());
4304}
4305
4306void Sema::CodeCompleteCall(Scope *S, Expr *Fn, ArrayRef<Expr *> Args) {
Douglas Gregorcabea402009-09-22 15:41:20 +00004307 if (!CodeCompleter)
4308 return;
Douglas Gregor3ef59522009-12-11 19:06:04 +00004309
4310 // When we're code-completing for a call, we fall back to ordinary
4311 // name code-completion whenever we can't produce specific
4312 // results. We may want to revisit this strategy in the future,
4313 // e.g., by merging the two kinds of results.
4314
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004315 // FIXME: Provide support for variadic template functions.
Douglas Gregor3ef59522009-12-11 19:06:04 +00004316
Douglas Gregorcabea402009-09-22 15:41:20 +00004317 // Ignore type-dependent call expressions entirely.
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00004318 if (!Fn || Fn->isTypeDependent() || anyNullArguments(Args) ||
4319 Expr::hasAnyTypeDependentArguments(Args)) {
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004320 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregorcabea402009-09-22 15:41:20 +00004321 return;
Douglas Gregor3ef59522009-12-11 19:06:04 +00004322 }
Douglas Gregorcabea402009-09-22 15:41:20 +00004323
John McCall57500772009-12-16 12:17:52 +00004324 // Build an overload candidate set based on the functions we find.
John McCallbc077cf2010-02-08 23:07:23 +00004325 SourceLocation Loc = Fn->getExprLoc();
Richard Smith100b24a2014-04-17 01:52:14 +00004326 OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal);
John McCall57500772009-12-16 12:17:52 +00004327
Chris Lattner0e62c1c2011-07-23 10:55:15 +00004328 SmallVector<ResultCandidate, 8> Results;
Douglas Gregorff59f672010-01-21 15:46:19 +00004329
John McCall57500772009-12-16 12:17:52 +00004330 Expr *NakedFn = Fn->IgnoreParenCasts();
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004331 if (auto ULE = dyn_cast<UnresolvedLookupExpr>(NakedFn))
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00004332 AddOverloadedCallCandidates(ULE, Args, CandidateSet,
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004333 /*PartialOverloading=*/true);
4334 else if (auto UME = dyn_cast<UnresolvedMemberExpr>(NakedFn)) {
4335 TemplateArgumentListInfo TemplateArgsBuffer, *TemplateArgs = nullptr;
4336 if (UME->hasExplicitTemplateArgs()) {
4337 UME->copyTemplateArgumentsInto(TemplateArgsBuffer);
4338 TemplateArgs = &TemplateArgsBuffer;
Douglas Gregorff59f672010-01-21 15:46:19 +00004339 }
Erik Verbruggenf1898cf2017-03-28 07:22:21 +00004340
4341 // Add the base as first argument (use a nullptr if the base is implicit).
4342 SmallVector<Expr *, 12> ArgExprs(
4343 1, UME->isImplicitAccess() ? nullptr : UME->getBase());
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004344 ArgExprs.append(Args.begin(), Args.end());
4345 UnresolvedSet<8> Decls;
4346 Decls.append(UME->decls_begin(), UME->decls_end());
4347 AddFunctionCandidates(Decls, ArgExprs, CandidateSet, TemplateArgs,
4348 /*SuppressUsedConversions=*/false,
4349 /*PartialOverloading=*/true);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004350 } else {
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004351 FunctionDecl *FD = nullptr;
4352 if (auto MCE = dyn_cast<MemberExpr>(NakedFn))
4353 FD = dyn_cast<FunctionDecl>(MCE->getMemberDecl());
4354 else if (auto DRE = dyn_cast<DeclRefExpr>(NakedFn))
4355 FD = dyn_cast<FunctionDecl>(DRE->getDecl());
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00004356 if (FD) { // We check whether it's a resolved function declaration.
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00004357 if (!getLangOpts().CPlusPlus ||
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004358 !FD->getType()->getAs<FunctionProtoType>())
4359 Results.push_back(ResultCandidate(FD));
4360 else
4361 AddOverloadCandidate(FD, DeclAccessPair::make(FD, FD->getAccess()),
4362 Args, CandidateSet,
4363 /*SuppressUsedConversions=*/false,
4364 /*PartialOverloading=*/true);
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00004365
4366 } else if (auto DC = NakedFn->getType()->getAsCXXRecordDecl()) {
4367 // If expression's type is CXXRecordDecl, it may overload the function
4368 // call operator, so we check if it does and add them as candidates.
Francisco Lopes da Silvaa349a8a2015-01-25 08:47:59 +00004369 // A complete type is needed to lookup for member function call operators.
Richard Smithdb0ac552015-12-18 22:40:25 +00004370 if (isCompleteType(Loc, NakedFn->getType())) {
Francisco Lopes da Silvaa349a8a2015-01-25 08:47:59 +00004371 DeclarationName OpName = Context.DeclarationNames
4372 .getCXXOperatorName(OO_Call);
4373 LookupResult R(*this, OpName, Loc, LookupOrdinaryName);
4374 LookupQualifiedName(R, DC);
4375 R.suppressDiagnostics();
4376 SmallVector<Expr *, 12> ArgExprs(1, NakedFn);
4377 ArgExprs.append(Args.begin(), Args.end());
4378 AddFunctionCandidates(R.asUnresolvedSet(), ArgExprs, CandidateSet,
4379 /*ExplicitArgs=*/nullptr,
4380 /*SuppressUsedConversions=*/false,
4381 /*PartialOverloading=*/true);
4382 }
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00004383 } else {
4384 // Lastly we check whether expression's type is function pointer or
4385 // function.
4386 QualType T = NakedFn->getType();
4387 if (!T->getPointeeType().isNull())
4388 T = T->getPointeeType();
4389
4390 if (auto FP = T->getAs<FunctionProtoType>()) {
4391 if (!TooManyArguments(FP->getNumParams(), Args.size(),
Francisco Lopes da Silva62a9a4f2015-01-23 13:17:51 +00004392 /*PartialOverloading=*/true) ||
4393 FP->isVariadic())
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00004394 Results.push_back(ResultCandidate(FP));
4395 } else if (auto FT = T->getAs<FunctionType>())
Francisco Lopes da Silva62a9a4f2015-01-23 13:17:51 +00004396 // No prototype and declaration, it may be a K & R style function.
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00004397 Results.push_back(ResultCandidate(FT));
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004398 }
Douglas Gregorcabea402009-09-22 15:41:20 +00004399 }
Douglas Gregor3ef59522009-12-11 19:06:04 +00004400
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004401 mergeCandidatesWithResults(*this, Results, CandidateSet, Loc);
4402 CodeCompleteOverloadResults(*this, S, Results, Args.size(),
4403 !CandidateSet.empty());
4404}
4405
4406void Sema::CodeCompleteConstructor(Scope *S, QualType Type, SourceLocation Loc,
4407 ArrayRef<Expr *> Args) {
4408 if (!CodeCompleter)
4409 return;
4410
4411 // A complete type is needed to lookup for constructors.
Richard Smithdb0ac552015-12-18 22:40:25 +00004412 if (!isCompleteType(Loc, Type))
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004413 return;
4414
Argyrios Kyrtzidisee1d76f2015-03-13 07:39:30 +00004415 CXXRecordDecl *RD = Type->getAsCXXRecordDecl();
4416 if (!RD) {
4417 CodeCompleteExpression(S, Type);
4418 return;
4419 }
4420
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004421 // FIXME: Provide support for member initializers.
4422 // FIXME: Provide support for variadic template constructors.
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004423
4424 OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal);
4425
Argyrios Kyrtzidisee1d76f2015-03-13 07:39:30 +00004426 for (auto C : LookupConstructors(RD)) {
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004427 if (auto FD = dyn_cast<FunctionDecl>(C)) {
4428 AddOverloadCandidate(FD, DeclAccessPair::make(FD, C->getAccess()),
4429 Args, CandidateSet,
4430 /*SuppressUsedConversions=*/false,
4431 /*PartialOverloading=*/true);
4432 } else if (auto FTD = dyn_cast<FunctionTemplateDecl>(C)) {
4433 AddTemplateOverloadCandidate(FTD,
4434 DeclAccessPair::make(FTD, C->getAccess()),
4435 /*ExplicitTemplateArgs=*/nullptr,
4436 Args, CandidateSet,
4437 /*SuppressUsedConversions=*/false,
4438 /*PartialOverloading=*/true);
4439 }
4440 }
4441
4442 SmallVector<ResultCandidate, 8> Results;
4443 mergeCandidatesWithResults(*this, Results, CandidateSet, Loc);
4444 CodeCompleteOverloadResults(*this, S, Results, Args.size());
Douglas Gregorcabea402009-09-22 15:41:20 +00004445}
4446
John McCall48871652010-08-21 09:40:31 +00004447void Sema::CodeCompleteInitializer(Scope *S, Decl *D) {
4448 ValueDecl *VD = dyn_cast_or_null<ValueDecl>(D);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004449 if (!VD) {
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004450 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004451 return;
4452 }
4453
4454 CodeCompleteExpression(S, VD->getType());
4455}
4456
4457void Sema::CodeCompleteReturn(Scope *S) {
4458 QualType ResultType;
4459 if (isa<BlockDecl>(CurContext)) {
4460 if (BlockScopeInfo *BSI = getCurBlock())
4461 ResultType = BSI->ReturnType;
4462 } else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(CurContext))
Alp Toker314cc812014-01-25 16:55:45 +00004463 ResultType = Function->getReturnType();
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004464 else if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(CurContext))
Alp Toker314cc812014-01-25 16:55:45 +00004465 ResultType = Method->getReturnType();
4466
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004467 if (ResultType.isNull())
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004468 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004469 else
4470 CodeCompleteExpression(S, ResultType);
4471}
4472
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004473void Sema::CodeCompleteAfterIf(Scope *S) {
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004474 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004475 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004476 mapCodeCompletionContext(*this, PCC_Statement));
4477 Results.setFilter(&ResultBuilder::IsOrdinaryName);
4478 Results.EnterNewScope();
4479
4480 CodeCompletionDeclConsumer Consumer(Results, CurContext);
4481 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4482 CodeCompleter->includeGlobals());
4483
4484 AddOrdinaryNameResults(PCC_Statement, S, *this, Results);
4485
4486 // "else" block
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004487 CodeCompletionBuilder Builder(Results.getAllocator(),
4488 Results.getCodeCompletionTUInfo());
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004489 Builder.AddTypedTextChunk("else");
Douglas Gregor3a5d6c22012-02-16 17:49:04 +00004490 if (Results.includeCodePatterns()) {
4491 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4492 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4493 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
4494 Builder.AddPlaceholderChunk("statements");
4495 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
4496 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4497 }
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004498 Results.AddResult(Builder.TakeString());
4499
4500 // "else if" block
4501 Builder.AddTypedTextChunk("else");
4502 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4503 Builder.AddTextChunk("if");
4504 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4505 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00004506 if (getLangOpts().CPlusPlus)
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004507 Builder.AddPlaceholderChunk("condition");
4508 else
4509 Builder.AddPlaceholderChunk("expression");
4510 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor3a5d6c22012-02-16 17:49:04 +00004511 if (Results.includeCodePatterns()) {
4512 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4513 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4514 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
4515 Builder.AddPlaceholderChunk("statements");
4516 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
4517 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4518 }
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004519 Results.AddResult(Builder.TakeString());
4520
4521 Results.ExitScope();
4522
4523 if (S->getFnParent())
Craig Topper12126262015-11-15 17:27:57 +00004524 AddPrettyFunctionResults(getLangOpts(), Results);
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004525
4526 if (CodeCompleter->includeMacros())
Douglas Gregor8cb17462012-10-09 16:01:50 +00004527 AddMacroResults(PP, Results, false);
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004528
4529 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4530 Results.data(),Results.size());
4531}
4532
Richard Trieu2bd04012011-09-09 02:00:50 +00004533void Sema::CodeCompleteAssignmentRHS(Scope *S, Expr *LHS) {
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004534 if (LHS)
4535 CodeCompleteExpression(S, static_cast<Expr *>(LHS)->getType());
4536 else
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004537 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004538}
4539
Jeffrey Yasskinc76498d2010-04-08 16:38:48 +00004540void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS,
Douglas Gregor2436e712009-09-17 21:32:03 +00004541 bool EnteringContext) {
4542 if (!SS.getScopeRep() || !CodeCompleter)
4543 return;
4544
Douglas Gregor3545ff42009-09-21 16:56:56 +00004545 DeclContext *Ctx = computeDeclContext(SS, EnteringContext);
4546 if (!Ctx)
4547 return;
Douglas Gregor800f2f02009-12-11 18:28:39 +00004548
4549 // Try to instantiate any non-dependent declaration contexts before
4550 // we look in them.
John McCall0b66eb32010-05-01 00:40:08 +00004551 if (!isDependentScopeSpecifier(SS) && RequireCompleteDeclContext(SS, Ctx))
Douglas Gregor800f2f02009-12-11 18:28:39 +00004552 return;
4553
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004554 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004555 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004556 CodeCompletionContext::CCC_Name);
Douglas Gregorac322ec2010-08-27 21:18:54 +00004557 Results.EnterNewScope();
Douglas Gregor0ac41382010-09-23 23:01:17 +00004558
Douglas Gregor3545ff42009-09-21 16:56:56 +00004559 // The "template" keyword can follow "::" in the grammar, but only
4560 // put it into the grammar if the nested-name-specifier is dependent.
Aaron Ballman4a979672014-01-03 13:56:08 +00004561 NestedNameSpecifier *NNS = SS.getScopeRep();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004562 if (!Results.empty() && NNS->isDependent())
Douglas Gregor78a21012010-01-14 16:01:26 +00004563 Results.AddResult("template");
Douglas Gregorac322ec2010-08-27 21:18:54 +00004564
4565 // Add calls to overridden virtual functions, if there are any.
4566 //
4567 // FIXME: This isn't wonderful, because we don't know whether we're actually
4568 // in a context that permits expressions. This is a general issue with
4569 // qualified-id completions.
4570 if (!EnteringContext)
4571 MaybeAddOverrideCalls(*this, Ctx, Results);
4572 Results.ExitScope();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004573
Douglas Gregorac322ec2010-08-27 21:18:54 +00004574 CodeCompletionDeclConsumer Consumer(Results, CurContext);
4575 LookupVisibleDecls(Ctx, LookupOrdinaryName, Consumer);
4576
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004577 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregorc1679ec2011-07-25 17:48:11 +00004578 Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004579 Results.data(),Results.size());
Douglas Gregor2436e712009-09-17 21:32:03 +00004580}
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00004581
4582void Sema::CodeCompleteUsing(Scope *S) {
4583 if (!CodeCompleter)
4584 return;
4585
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004586 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004587 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00004588 CodeCompletionContext::CCC_PotentiallyQualifiedName,
4589 &ResultBuilder::IsNestedNameSpecifier);
Douglas Gregor64b12b52009-09-22 23:31:26 +00004590 Results.EnterNewScope();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004591
4592 // If we aren't in class scope, we could see the "namespace" keyword.
4593 if (!S->isClassScope())
John McCall276321a2010-08-25 06:19:51 +00004594 Results.AddResult(CodeCompletionResult("namespace"));
Douglas Gregor3545ff42009-09-21 16:56:56 +00004595
4596 // After "using", we can see anything that would start a
4597 // nested-name-specifier.
Douglas Gregora6e2edc2010-01-14 03:27:13 +00004598 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00004599 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4600 CodeCompleter->includeGlobals());
Douglas Gregor64b12b52009-09-22 23:31:26 +00004601 Results.ExitScope();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004602
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004603 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004604 CodeCompletionContext::CCC_PotentiallyQualifiedName,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004605 Results.data(),Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00004606}
4607
4608void Sema::CodeCompleteUsingDirective(Scope *S) {
4609 if (!CodeCompleter)
4610 return;
4611
Douglas Gregor3545ff42009-09-21 16:56:56 +00004612 // After "using namespace", we expect to see a namespace name or namespace
4613 // alias.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004614 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004615 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004616 CodeCompletionContext::CCC_Namespace,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004617 &ResultBuilder::IsNamespaceOrAlias);
Douglas Gregor64b12b52009-09-22 23:31:26 +00004618 Results.EnterNewScope();
Douglas Gregora6e2edc2010-01-14 03:27:13 +00004619 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00004620 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4621 CodeCompleter->includeGlobals());
Douglas Gregor64b12b52009-09-22 23:31:26 +00004622 Results.ExitScope();
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004623 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor39982192010-08-15 06:18:01 +00004624 CodeCompletionContext::CCC_Namespace,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004625 Results.data(),Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00004626}
4627
4628void Sema::CodeCompleteNamespaceDecl(Scope *S) {
4629 if (!CodeCompleter)
4630 return;
4631
Ted Kremenekc37877d2013-10-08 17:08:03 +00004632 DeclContext *Ctx = S->getEntity();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004633 if (!S->getParent())
4634 Ctx = Context.getTranslationUnitDecl();
4635
Douglas Gregor0ac41382010-09-23 23:01:17 +00004636 bool SuppressedGlobalResults
4637 = Ctx && !CodeCompleter->includeGlobals() && isa<TranslationUnitDecl>(Ctx);
4638
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004639 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004640 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00004641 SuppressedGlobalResults
4642 ? CodeCompletionContext::CCC_Namespace
4643 : CodeCompletionContext::CCC_Other,
4644 &ResultBuilder::IsNamespace);
4645
4646 if (Ctx && Ctx->isFileContext() && !SuppressedGlobalResults) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00004647 // We only want to see those namespaces that have already been defined
4648 // within this scope, because its likely that the user is creating an
4649 // extended namespace declaration. Keep track of the most recent
4650 // definition of each namespace.
4651 std::map<NamespaceDecl *, NamespaceDecl *> OrigToLatest;
4652 for (DeclContext::specific_decl_iterator<NamespaceDecl>
4653 NS(Ctx->decls_begin()), NSEnd(Ctx->decls_end());
4654 NS != NSEnd; ++NS)
David Blaikie40ed2972012-06-06 20:45:41 +00004655 OrigToLatest[NS->getOriginalNamespace()] = *NS;
Douglas Gregor3545ff42009-09-21 16:56:56 +00004656
4657 // Add the most recent definition (or extended definition) of each
4658 // namespace to the list of results.
Douglas Gregor64b12b52009-09-22 23:31:26 +00004659 Results.EnterNewScope();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004660 for (std::map<NamespaceDecl *, NamespaceDecl *>::iterator
Douglas Gregor78254c82012-03-27 23:34:16 +00004661 NS = OrigToLatest.begin(),
4662 NSEnd = OrigToLatest.end();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004663 NS != NSEnd; ++NS)
Douglas Gregor0a0e2b32013-01-31 04:52:16 +00004664 Results.AddResult(CodeCompletionResult(
Craig Topperc3ec1492014-05-26 06:22:03 +00004665 NS->second, Results.getBasePriority(NS->second),
4666 nullptr),
4667 CurContext, nullptr, false);
Douglas Gregor64b12b52009-09-22 23:31:26 +00004668 Results.ExitScope();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004669 }
4670
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004671 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004672 Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004673 Results.data(),Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00004674}
4675
4676void Sema::CodeCompleteNamespaceAliasDecl(Scope *S) {
4677 if (!CodeCompleter)
4678 return;
4679
Douglas Gregor3545ff42009-09-21 16:56:56 +00004680 // After "namespace", we expect to see a namespace or alias.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004681 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004682 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004683 CodeCompletionContext::CCC_Namespace,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004684 &ResultBuilder::IsNamespaceOrAlias);
Douglas Gregora6e2edc2010-01-14 03:27:13 +00004685 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00004686 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4687 CodeCompleter->includeGlobals());
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004688 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004689 Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004690 Results.data(),Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00004691}
4692
Douglas Gregorc811ede2009-09-18 20:05:18 +00004693void Sema::CodeCompleteOperatorName(Scope *S) {
4694 if (!CodeCompleter)
4695 return;
Douglas Gregor3545ff42009-09-21 16:56:56 +00004696
John McCall276321a2010-08-25 06:19:51 +00004697 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004698 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004699 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004700 CodeCompletionContext::CCC_Type,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004701 &ResultBuilder::IsType);
Douglas Gregor64b12b52009-09-22 23:31:26 +00004702 Results.EnterNewScope();
Douglas Gregorc811ede2009-09-18 20:05:18 +00004703
Douglas Gregor3545ff42009-09-21 16:56:56 +00004704 // Add the names of overloadable operators.
4705#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
4706 if (std::strcmp(Spelling, "?")) \
Douglas Gregor78a21012010-01-14 16:01:26 +00004707 Results.AddResult(Result(Spelling));
Douglas Gregor3545ff42009-09-21 16:56:56 +00004708#include "clang/Basic/OperatorKinds.def"
4709
4710 // Add any type names visible from the current scope
Douglas Gregor6ae4c522010-01-14 03:21:49 +00004711 Results.allowNestedNameSpecifiers();
Douglas Gregora6e2edc2010-01-14 03:27:13 +00004712 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00004713 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4714 CodeCompleter->includeGlobals());
Douglas Gregor3545ff42009-09-21 16:56:56 +00004715
4716 // Add any type specifiers
David Blaikiebbafb8a2012-03-11 07:00:24 +00004717 AddTypeSpecifierResults(getLangOpts(), Results);
Douglas Gregor64b12b52009-09-22 23:31:26 +00004718 Results.ExitScope();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004719
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004720 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor39982192010-08-15 06:18:01 +00004721 CodeCompletionContext::CCC_Type,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004722 Results.data(),Results.size());
Douglas Gregorc811ede2009-09-18 20:05:18 +00004723}
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00004724
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00004725void Sema::CodeCompleteConstructorInitializer(
4726 Decl *ConstructorD,
4727 ArrayRef <CXXCtorInitializer *> Initializers) {
Benjamin Kramera4f8df02015-07-09 15:31:10 +00004728 if (!ConstructorD)
4729 return;
4730
4731 AdjustDeclIfTemplate(ConstructorD);
4732
4733 CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(ConstructorD);
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004734 if (!Constructor)
4735 return;
4736
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004737 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004738 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00004739 CodeCompletionContext::CCC_PotentiallyQualifiedName);
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004740 Results.EnterNewScope();
4741
4742 // Fill in any already-initialized fields or base classes.
4743 llvm::SmallPtrSet<FieldDecl *, 4> InitializedFields;
4744 llvm::SmallPtrSet<CanQualType, 4> InitializedBases;
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00004745 for (unsigned I = 0, E = Initializers.size(); I != E; ++I) {
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004746 if (Initializers[I]->isBaseInitializer())
4747 InitializedBases.insert(
4748 Context.getCanonicalType(QualType(Initializers[I]->getBaseClass(), 0)));
4749 else
Francois Pichetd583da02010-12-04 09:14:42 +00004750 InitializedFields.insert(cast<FieldDecl>(
4751 Initializers[I]->getAnyMember()));
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004752 }
4753
4754 // Add completions for base classes.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004755 CodeCompletionBuilder Builder(Results.getAllocator(),
4756 Results.getCodeCompletionTUInfo());
Benjamin Kramera4f8df02015-07-09 15:31:10 +00004757 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00004758 bool SawLastInitializer = Initializers.empty();
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004759 CXXRecordDecl *ClassDecl = Constructor->getParent();
Aaron Ballman574705e2014-03-13 15:41:46 +00004760 for (const auto &Base : ClassDecl->bases()) {
David Blaikie82e95a32014-11-19 07:49:47 +00004761 if (!InitializedBases.insert(Context.getCanonicalType(Base.getType()))
4762 .second) {
Douglas Gregor99129ef2010-08-29 19:27:27 +00004763 SawLastInitializer
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00004764 = !Initializers.empty() &&
4765 Initializers.back()->isBaseInitializer() &&
Aaron Ballman574705e2014-03-13 15:41:46 +00004766 Context.hasSameUnqualifiedType(Base.getType(),
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00004767 QualType(Initializers.back()->getBaseClass(), 0));
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004768 continue;
Douglas Gregor99129ef2010-08-29 19:27:27 +00004769 }
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004770
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004771 Builder.AddTypedTextChunk(
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00004772 Results.getAllocator().CopyString(
Aaron Ballman574705e2014-03-13 15:41:46 +00004773 Base.getType().getAsString(Policy)));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004774 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4775 Builder.AddPlaceholderChunk("args");
4776 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4777 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor99129ef2010-08-29 19:27:27 +00004778 SawLastInitializer? CCP_NextInitializer
4779 : CCP_MemberDeclaration));
4780 SawLastInitializer = false;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004781 }
4782
4783 // Add completions for virtual base classes.
Aaron Ballman445a9392014-03-13 16:15:17 +00004784 for (const auto &Base : ClassDecl->vbases()) {
David Blaikie82e95a32014-11-19 07:49:47 +00004785 if (!InitializedBases.insert(Context.getCanonicalType(Base.getType()))
4786 .second) {
Douglas Gregor99129ef2010-08-29 19:27:27 +00004787 SawLastInitializer
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00004788 = !Initializers.empty() &&
4789 Initializers.back()->isBaseInitializer() &&
Aaron Ballman445a9392014-03-13 16:15:17 +00004790 Context.hasSameUnqualifiedType(Base.getType(),
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00004791 QualType(Initializers.back()->getBaseClass(), 0));
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004792 continue;
Douglas Gregor99129ef2010-08-29 19:27:27 +00004793 }
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004794
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004795 Builder.AddTypedTextChunk(
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00004796 Builder.getAllocator().CopyString(
Aaron Ballman445a9392014-03-13 16:15:17 +00004797 Base.getType().getAsString(Policy)));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004798 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4799 Builder.AddPlaceholderChunk("args");
4800 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4801 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor99129ef2010-08-29 19:27:27 +00004802 SawLastInitializer? CCP_NextInitializer
4803 : CCP_MemberDeclaration));
4804 SawLastInitializer = false;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004805 }
4806
4807 // Add completions for members.
Aaron Ballmane8a8bae2014-03-08 20:12:42 +00004808 for (auto *Field : ClassDecl->fields()) {
David Blaikie82e95a32014-11-19 07:49:47 +00004809 if (!InitializedFields.insert(cast<FieldDecl>(Field->getCanonicalDecl()))
4810 .second) {
Douglas Gregor99129ef2010-08-29 19:27:27 +00004811 SawLastInitializer
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00004812 = !Initializers.empty() &&
4813 Initializers.back()->isAnyMemberInitializer() &&
Aaron Ballmane8a8bae2014-03-08 20:12:42 +00004814 Initializers.back()->getAnyMember() == Field;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004815 continue;
Douglas Gregor99129ef2010-08-29 19:27:27 +00004816 }
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004817
4818 if (!Field->getDeclName())
4819 continue;
4820
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00004821 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004822 Field->getIdentifier()->getName()));
4823 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4824 Builder.AddPlaceholderChunk("args");
4825 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4826 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor99129ef2010-08-29 19:27:27 +00004827 SawLastInitializer? CCP_NextInitializer
Douglas Gregorf3af3112010-09-09 21:42:20 +00004828 : CCP_MemberDeclaration,
Douglas Gregor78254c82012-03-27 23:34:16 +00004829 CXCursor_MemberRef,
4830 CXAvailability_Available,
Aaron Ballmane8a8bae2014-03-08 20:12:42 +00004831 Field));
Douglas Gregor99129ef2010-08-29 19:27:27 +00004832 SawLastInitializer = false;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004833 }
4834 Results.ExitScope();
4835
Douglas Gregor0ac41382010-09-23 23:01:17 +00004836 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004837 Results.data(), Results.size());
4838}
4839
Douglas Gregord8c61782012-02-15 15:34:24 +00004840/// \brief Determine whether this scope denotes a namespace.
4841static bool isNamespaceScope(Scope *S) {
Ted Kremenekc37877d2013-10-08 17:08:03 +00004842 DeclContext *DC = S->getEntity();
Douglas Gregord8c61782012-02-15 15:34:24 +00004843 if (!DC)
4844 return false;
4845
4846 return DC->isFileContext();
4847}
4848
4849void Sema::CodeCompleteLambdaIntroducer(Scope *S, LambdaIntroducer &Intro,
4850 bool AfterAmpersand) {
4851 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004852 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregord8c61782012-02-15 15:34:24 +00004853 CodeCompletionContext::CCC_Other);
4854 Results.EnterNewScope();
4855
4856 // Note what has already been captured.
4857 llvm::SmallPtrSet<IdentifierInfo *, 4> Known;
4858 bool IncludedThis = false;
Benjamin Kramerf3ca26982014-05-10 16:31:55 +00004859 for (const auto &C : Intro.Captures) {
4860 if (C.Kind == LCK_This) {
Douglas Gregord8c61782012-02-15 15:34:24 +00004861 IncludedThis = true;
4862 continue;
4863 }
4864
Benjamin Kramerf3ca26982014-05-10 16:31:55 +00004865 Known.insert(C.Id);
Douglas Gregord8c61782012-02-15 15:34:24 +00004866 }
4867
4868 // Look for other capturable variables.
4869 for (; S && !isNamespaceScope(S); S = S->getParent()) {
Aaron Ballman35c54952014-03-17 16:55:25 +00004870 for (const auto *D : S->decls()) {
4871 const auto *Var = dyn_cast<VarDecl>(D);
Douglas Gregord8c61782012-02-15 15:34:24 +00004872 if (!Var ||
4873 !Var->hasLocalStorage() ||
4874 Var->hasAttr<BlocksAttr>())
4875 continue;
4876
David Blaikie82e95a32014-11-19 07:49:47 +00004877 if (Known.insert(Var->getIdentifier()).second)
Douglas Gregor0a0e2b32013-01-31 04:52:16 +00004878 Results.AddResult(CodeCompletionResult(Var, CCP_LocalDeclaration),
Craig Topperc3ec1492014-05-26 06:22:03 +00004879 CurContext, nullptr, false);
Douglas Gregord8c61782012-02-15 15:34:24 +00004880 }
4881 }
4882
4883 // Add 'this', if it would be valid.
4884 if (!IncludedThis && !AfterAmpersand && Intro.Default != LCD_ByCopy)
4885 addThisCompletion(*this, Results);
4886
4887 Results.ExitScope();
4888
4889 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4890 Results.data(), Results.size());
4891}
4892
James Dennett596e4752012-06-14 03:11:41 +00004893/// Macro that optionally prepends an "@" to the string literal passed in via
4894/// Keyword, depending on whether NeedAt is true or false.
4895#define OBJC_AT_KEYWORD_NAME(NeedAt,Keyword) ((NeedAt)? "@" Keyword : Keyword)
4896
Douglas Gregorf98e6a22010-01-13 23:51:12 +00004897static void AddObjCImplementationResults(const LangOptions &LangOpts,
Douglas Gregorf1934162010-01-13 21:24:21 +00004898 ResultBuilder &Results,
4899 bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00004900 typedef CodeCompletionResult Result;
Douglas Gregorf1934162010-01-13 21:24:21 +00004901 // Since we have an implementation, we can end it.
James Dennett596e4752012-06-14 03:11:41 +00004902 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"end")));
Douglas Gregorf1934162010-01-13 21:24:21 +00004903
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004904 CodeCompletionBuilder Builder(Results.getAllocator(),
4905 Results.getCodeCompletionTUInfo());
Douglas Gregorf1934162010-01-13 21:24:21 +00004906 if (LangOpts.ObjC2) {
4907 // @dynamic
James Dennett596e4752012-06-14 03:11:41 +00004908 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"dynamic"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004909 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4910 Builder.AddPlaceholderChunk("property");
4911 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf1934162010-01-13 21:24:21 +00004912
4913 // @synthesize
James Dennett596e4752012-06-14 03:11:41 +00004914 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"synthesize"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004915 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4916 Builder.AddPlaceholderChunk("property");
4917 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf1934162010-01-13 21:24:21 +00004918 }
4919}
4920
Douglas Gregorf98e6a22010-01-13 23:51:12 +00004921static void AddObjCInterfaceResults(const LangOptions &LangOpts,
Douglas Gregorf1934162010-01-13 21:24:21 +00004922 ResultBuilder &Results,
4923 bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00004924 typedef CodeCompletionResult Result;
Douglas Gregorf1934162010-01-13 21:24:21 +00004925
4926 // Since we have an interface or protocol, we can end it.
James Dennett596e4752012-06-14 03:11:41 +00004927 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"end")));
Douglas Gregorf1934162010-01-13 21:24:21 +00004928
4929 if (LangOpts.ObjC2) {
4930 // @property
James Dennett596e4752012-06-14 03:11:41 +00004931 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"property")));
Douglas Gregorf1934162010-01-13 21:24:21 +00004932
4933 // @required
James Dennett596e4752012-06-14 03:11:41 +00004934 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"required")));
Douglas Gregorf1934162010-01-13 21:24:21 +00004935
4936 // @optional
James Dennett596e4752012-06-14 03:11:41 +00004937 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"optional")));
Douglas Gregorf1934162010-01-13 21:24:21 +00004938 }
4939}
4940
Douglas Gregorf98e6a22010-01-13 23:51:12 +00004941static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00004942 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004943 CodeCompletionBuilder Builder(Results.getAllocator(),
4944 Results.getCodeCompletionTUInfo());
Douglas Gregorf1934162010-01-13 21:24:21 +00004945
4946 // @class name ;
James Dennett596e4752012-06-14 03:11:41 +00004947 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"class"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004948 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4949 Builder.AddPlaceholderChunk("name");
4950 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf1934162010-01-13 21:24:21 +00004951
Douglas Gregorf4c33342010-05-28 00:22:41 +00004952 if (Results.includeCodePatterns()) {
4953 // @interface name
4954 // FIXME: Could introduce the whole pattern, including superclasses and
4955 // such.
James Dennett596e4752012-06-14 03:11:41 +00004956 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"interface"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004957 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4958 Builder.AddPlaceholderChunk("class");
4959 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf1934162010-01-13 21:24:21 +00004960
Douglas Gregorf4c33342010-05-28 00:22:41 +00004961 // @protocol name
James Dennett596e4752012-06-14 03:11:41 +00004962 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"protocol"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004963 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4964 Builder.AddPlaceholderChunk("protocol");
4965 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00004966
4967 // @implementation name
James Dennett596e4752012-06-14 03:11:41 +00004968 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"implementation"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004969 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4970 Builder.AddPlaceholderChunk("class");
4971 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00004972 }
Douglas Gregorf1934162010-01-13 21:24:21 +00004973
4974 // @compatibility_alias name
James Dennett596e4752012-06-14 03:11:41 +00004975 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"compatibility_alias"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004976 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4977 Builder.AddPlaceholderChunk("alias");
4978 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4979 Builder.AddPlaceholderChunk("class");
4980 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor61e36812013-03-07 23:26:24 +00004981
4982 if (Results.getSema().getLangOpts().Modules) {
4983 // @import name
4984 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "import"));
4985 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4986 Builder.AddPlaceholderChunk("module");
4987 Results.AddResult(Result(Builder.TakeString()));
4988 }
Douglas Gregorf1934162010-01-13 21:24:21 +00004989}
4990
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00004991void Sema::CodeCompleteObjCAtDirective(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004992 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004993 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004994 CodeCompletionContext::CCC_Other);
Douglas Gregorf48706c2009-12-07 09:27:33 +00004995 Results.EnterNewScope();
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00004996 if (isa<ObjCImplDecl>(CurContext))
David Blaikiebbafb8a2012-03-11 07:00:24 +00004997 AddObjCImplementationResults(getLangOpts(), Results, false);
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00004998 else if (CurContext->isObjCContainer())
David Blaikiebbafb8a2012-03-11 07:00:24 +00004999 AddObjCInterfaceResults(getLangOpts(), Results, false);
Douglas Gregorf1934162010-01-13 21:24:21 +00005000 else
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005001 AddObjCTopLevelResults(Results, false);
Douglas Gregorf48706c2009-12-07 09:27:33 +00005002 Results.ExitScope();
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005003 HandleCodeCompleteResults(this, CodeCompleter,
5004 CodeCompletionContext::CCC_Other,
5005 Results.data(),Results.size());
Douglas Gregorf48706c2009-12-07 09:27:33 +00005006}
5007
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005008static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005009 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005010 CodeCompletionBuilder Builder(Results.getAllocator(),
5011 Results.getCodeCompletionTUInfo());
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005012
5013 // @encode ( type-name )
Douglas Gregore5c79d52011-10-18 21:20:17 +00005014 const char *EncodeType = "char[]";
David Blaikiebbafb8a2012-03-11 07:00:24 +00005015 if (Results.getSema().getLangOpts().CPlusPlus ||
5016 Results.getSema().getLangOpts().ConstStrings)
Jordan Rose9da05852012-06-15 18:19:56 +00005017 EncodeType = "const char[]";
Douglas Gregore5c79d52011-10-18 21:20:17 +00005018 Builder.AddResultTypeChunk(EncodeType);
James Dennett596e4752012-06-14 03:11:41 +00005019 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"encode"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005020 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5021 Builder.AddPlaceholderChunk("type-name");
5022 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5023 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005024
5025 // @protocol ( protocol-name )
Douglas Gregore5c79d52011-10-18 21:20:17 +00005026 Builder.AddResultTypeChunk("Protocol *");
James Dennett596e4752012-06-14 03:11:41 +00005027 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"protocol"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005028 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5029 Builder.AddPlaceholderChunk("protocol-name");
5030 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5031 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005032
5033 // @selector ( selector )
Douglas Gregore5c79d52011-10-18 21:20:17 +00005034 Builder.AddResultTypeChunk("SEL");
James Dennett596e4752012-06-14 03:11:41 +00005035 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"selector"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005036 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5037 Builder.AddPlaceholderChunk("selector");
5038 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5039 Results.AddResult(Result(Builder.TakeString()));
Jordan Rose9da05852012-06-15 18:19:56 +00005040
5041 // @"string"
5042 Builder.AddResultTypeChunk("NSString *");
5043 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"\""));
5044 Builder.AddPlaceholderChunk("string");
5045 Builder.AddTextChunk("\"");
5046 Results.AddResult(Result(Builder.TakeString()));
5047
Douglas Gregor951de302012-07-17 23:24:47 +00005048 // @[objects, ...]
Jordan Rose9da05852012-06-15 18:19:56 +00005049 Builder.AddResultTypeChunk("NSArray *");
James Dennett596e4752012-06-14 03:11:41 +00005050 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"["));
Ted Kremeneke65b0862012-03-06 20:05:56 +00005051 Builder.AddPlaceholderChunk("objects, ...");
Ted Kremeneke65b0862012-03-06 20:05:56 +00005052 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
5053 Results.AddResult(Result(Builder.TakeString()));
5054
Douglas Gregor951de302012-07-17 23:24:47 +00005055 // @{key : object, ...}
Jordan Rose9da05852012-06-15 18:19:56 +00005056 Builder.AddResultTypeChunk("NSDictionary *");
James Dennett596e4752012-06-14 03:11:41 +00005057 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"{"));
Ted Kremeneke65b0862012-03-06 20:05:56 +00005058 Builder.AddPlaceholderChunk("key");
Ted Kremeneke65b0862012-03-06 20:05:56 +00005059 Builder.AddChunk(CodeCompletionString::CK_Colon);
5060 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5061 Builder.AddPlaceholderChunk("object, ...");
Ted Kremeneke65b0862012-03-06 20:05:56 +00005062 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5063 Results.AddResult(Result(Builder.TakeString()));
Jordan Rose9da05852012-06-15 18:19:56 +00005064
Douglas Gregor951de302012-07-17 23:24:47 +00005065 // @(expression)
Jordan Rose9da05852012-06-15 18:19:56 +00005066 Builder.AddResultTypeChunk("id");
5067 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "("));
Jordan Rose9da05852012-06-15 18:19:56 +00005068 Builder.AddPlaceholderChunk("expression");
Jordan Rose9da05852012-06-15 18:19:56 +00005069 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5070 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005071}
5072
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005073static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005074 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005075 CodeCompletionBuilder Builder(Results.getAllocator(),
5076 Results.getCodeCompletionTUInfo());
Douglas Gregorf1934162010-01-13 21:24:21 +00005077
Douglas Gregorf4c33342010-05-28 00:22:41 +00005078 if (Results.includeCodePatterns()) {
5079 // @try { statements } @catch ( declaration ) { statements } @finally
5080 // { statements }
James Dennett596e4752012-06-14 03:11:41 +00005081 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"try"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005082 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5083 Builder.AddPlaceholderChunk("statements");
5084 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5085 Builder.AddTextChunk("@catch");
5086 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5087 Builder.AddPlaceholderChunk("parameter");
5088 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5089 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5090 Builder.AddPlaceholderChunk("statements");
5091 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5092 Builder.AddTextChunk("@finally");
5093 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5094 Builder.AddPlaceholderChunk("statements");
5095 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5096 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00005097 }
Douglas Gregorf1934162010-01-13 21:24:21 +00005098
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005099 // @throw
James Dennett596e4752012-06-14 03:11:41 +00005100 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"throw"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005101 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5102 Builder.AddPlaceholderChunk("expression");
5103 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf1934162010-01-13 21:24:21 +00005104
Douglas Gregorf4c33342010-05-28 00:22:41 +00005105 if (Results.includeCodePatterns()) {
5106 // @synchronized ( expression ) { statements }
James Dennett596e4752012-06-14 03:11:41 +00005107 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"synchronized"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005108 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5109 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5110 Builder.AddPlaceholderChunk("expression");
5111 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5112 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5113 Builder.AddPlaceholderChunk("statements");
5114 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5115 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00005116 }
Douglas Gregorf1934162010-01-13 21:24:21 +00005117}
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005118
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005119static void AddObjCVisibilityResults(const LangOptions &LangOpts,
Douglas Gregor48d46252010-01-13 21:54:15 +00005120 ResultBuilder &Results,
5121 bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005122 typedef CodeCompletionResult Result;
James Dennett596e4752012-06-14 03:11:41 +00005123 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"private")));
5124 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"protected")));
5125 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"public")));
Douglas Gregor48d46252010-01-13 21:54:15 +00005126 if (LangOpts.ObjC2)
James Dennett596e4752012-06-14 03:11:41 +00005127 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"package")));
Douglas Gregor48d46252010-01-13 21:54:15 +00005128}
5129
5130void Sema::CodeCompleteObjCAtVisibility(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005131 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005132 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005133 CodeCompletionContext::CCC_Other);
Douglas Gregor48d46252010-01-13 21:54:15 +00005134 Results.EnterNewScope();
David Blaikiebbafb8a2012-03-11 07:00:24 +00005135 AddObjCVisibilityResults(getLangOpts(), Results, false);
Douglas Gregor48d46252010-01-13 21:54:15 +00005136 Results.ExitScope();
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005137 HandleCodeCompleteResults(this, CodeCompleter,
5138 CodeCompletionContext::CCC_Other,
5139 Results.data(),Results.size());
Douglas Gregor48d46252010-01-13 21:54:15 +00005140}
5141
5142void Sema::CodeCompleteObjCAtStatement(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005143 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005144 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005145 CodeCompletionContext::CCC_Other);
Douglas Gregorf1934162010-01-13 21:24:21 +00005146 Results.EnterNewScope();
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005147 AddObjCStatementResults(Results, false);
5148 AddObjCExpressionResults(Results, false);
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005149 Results.ExitScope();
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005150 HandleCodeCompleteResults(this, CodeCompleter,
5151 CodeCompletionContext::CCC_Other,
5152 Results.data(),Results.size());
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005153}
5154
5155void Sema::CodeCompleteObjCAtExpression(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005156 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005157 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005158 CodeCompletionContext::CCC_Other);
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005159 Results.EnterNewScope();
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005160 AddObjCExpressionResults(Results, false);
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005161 Results.ExitScope();
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005162 HandleCodeCompleteResults(this, CodeCompleter,
5163 CodeCompletionContext::CCC_Other,
5164 Results.data(),Results.size());
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005165}
5166
Douglas Gregore6078da2009-11-19 00:14:45 +00005167/// \brief Determine whether the addition of the given flag to an Objective-C
5168/// property's attributes will cause a conflict.
Bill Wendling44426052012-12-20 19:22:21 +00005169static bool ObjCPropertyFlagConflicts(unsigned Attributes, unsigned NewFlag) {
Douglas Gregore6078da2009-11-19 00:14:45 +00005170 // Check if we've already added this flag.
Bill Wendling44426052012-12-20 19:22:21 +00005171 if (Attributes & NewFlag)
Douglas Gregore6078da2009-11-19 00:14:45 +00005172 return true;
5173
Bill Wendling44426052012-12-20 19:22:21 +00005174 Attributes |= NewFlag;
Douglas Gregore6078da2009-11-19 00:14:45 +00005175
5176 // Check for collisions with "readonly".
Bill Wendling44426052012-12-20 19:22:21 +00005177 if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) &&
5178 (Attributes & ObjCDeclSpec::DQ_PR_readwrite))
Douglas Gregore6078da2009-11-19 00:14:45 +00005179 return true;
5180
Jordan Rose53cb2f32012-08-20 20:01:13 +00005181 // Check for more than one of { assign, copy, retain, strong, weak }.
Bill Wendling44426052012-12-20 19:22:21 +00005182 unsigned AssignCopyRetMask = Attributes & (ObjCDeclSpec::DQ_PR_assign |
John McCall31168b02011-06-15 23:02:42 +00005183 ObjCDeclSpec::DQ_PR_unsafe_unretained |
Douglas Gregore6078da2009-11-19 00:14:45 +00005184 ObjCDeclSpec::DQ_PR_copy |
Jordan Rose53cb2f32012-08-20 20:01:13 +00005185 ObjCDeclSpec::DQ_PR_retain |
5186 ObjCDeclSpec::DQ_PR_strong |
5187 ObjCDeclSpec::DQ_PR_weak);
Douglas Gregore6078da2009-11-19 00:14:45 +00005188 if (AssignCopyRetMask &&
5189 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_assign &&
John McCall31168b02011-06-15 23:02:42 +00005190 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_unsafe_unretained &&
Douglas Gregore6078da2009-11-19 00:14:45 +00005191 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_copy &&
John McCall31168b02011-06-15 23:02:42 +00005192 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_retain &&
Jordan Rose53cb2f32012-08-20 20:01:13 +00005193 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_strong &&
5194 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_weak)
Douglas Gregore6078da2009-11-19 00:14:45 +00005195 return true;
5196
5197 return false;
5198}
5199
Douglas Gregor36029f42009-11-18 23:08:07 +00005200void Sema::CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS) {
Steve Naroff936354c2009-10-08 21:55:05 +00005201 if (!CodeCompleter)
5202 return;
Douglas Gregor1b605f72009-11-19 01:08:35 +00005203
Bill Wendling44426052012-12-20 19:22:21 +00005204 unsigned Attributes = ODS.getPropertyAttributes();
Steve Naroff936354c2009-10-08 21:55:05 +00005205
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005206 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005207 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005208 CodeCompletionContext::CCC_Other);
Steve Naroff936354c2009-10-08 21:55:05 +00005209 Results.EnterNewScope();
Bill Wendling44426052012-12-20 19:22:21 +00005210 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readonly))
John McCall276321a2010-08-25 06:19:51 +00005211 Results.AddResult(CodeCompletionResult("readonly"));
Bill Wendling44426052012-12-20 19:22:21 +00005212 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_assign))
John McCall276321a2010-08-25 06:19:51 +00005213 Results.AddResult(CodeCompletionResult("assign"));
Bill Wendling44426052012-12-20 19:22:21 +00005214 if (!ObjCPropertyFlagConflicts(Attributes,
John McCall31168b02011-06-15 23:02:42 +00005215 ObjCDeclSpec::DQ_PR_unsafe_unretained))
5216 Results.AddResult(CodeCompletionResult("unsafe_unretained"));
Bill Wendling44426052012-12-20 19:22:21 +00005217 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readwrite))
John McCall276321a2010-08-25 06:19:51 +00005218 Results.AddResult(CodeCompletionResult("readwrite"));
Bill Wendling44426052012-12-20 19:22:21 +00005219 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_retain))
John McCall276321a2010-08-25 06:19:51 +00005220 Results.AddResult(CodeCompletionResult("retain"));
Bill Wendling44426052012-12-20 19:22:21 +00005221 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_strong))
John McCall31168b02011-06-15 23:02:42 +00005222 Results.AddResult(CodeCompletionResult("strong"));
Bill Wendling44426052012-12-20 19:22:21 +00005223 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_copy))
John McCall276321a2010-08-25 06:19:51 +00005224 Results.AddResult(CodeCompletionResult("copy"));
Bill Wendling44426052012-12-20 19:22:21 +00005225 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_nonatomic))
John McCall276321a2010-08-25 06:19:51 +00005226 Results.AddResult(CodeCompletionResult("nonatomic"));
Bill Wendling44426052012-12-20 19:22:21 +00005227 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_atomic))
Fariborz Jahanian1c2d29e2011-06-11 17:14:27 +00005228 Results.AddResult(CodeCompletionResult("atomic"));
Jordan Rose53cb2f32012-08-20 20:01:13 +00005229
5230 // Only suggest "weak" if we're compiling for ARC-with-weak-references or GC.
John McCall460ce582015-10-22 18:38:17 +00005231 if (getLangOpts().ObjCWeak || getLangOpts().getGC() != LangOptions::NonGC)
Bill Wendling44426052012-12-20 19:22:21 +00005232 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_weak))
Jordan Rose53cb2f32012-08-20 20:01:13 +00005233 Results.AddResult(CodeCompletionResult("weak"));
5234
Bill Wendling44426052012-12-20 19:22:21 +00005235 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_setter)) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005236 CodeCompletionBuilder Setter(Results.getAllocator(),
5237 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005238 Setter.AddTypedTextChunk("setter");
Argyrios Kyrtzidis7bbb8812014-02-20 07:55:15 +00005239 Setter.AddTextChunk("=");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005240 Setter.AddPlaceholderChunk("method");
5241 Results.AddResult(CodeCompletionResult(Setter.TakeString()));
Douglas Gregor45f83ee2009-11-19 00:01:57 +00005242 }
Bill Wendling44426052012-12-20 19:22:21 +00005243 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_getter)) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005244 CodeCompletionBuilder Getter(Results.getAllocator(),
5245 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005246 Getter.AddTypedTextChunk("getter");
Argyrios Kyrtzidis7bbb8812014-02-20 07:55:15 +00005247 Getter.AddTextChunk("=");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005248 Getter.AddPlaceholderChunk("method");
5249 Results.AddResult(CodeCompletionResult(Getter.TakeString()));
Douglas Gregor45f83ee2009-11-19 00:01:57 +00005250 }
Douglas Gregor86b42682015-06-19 18:27:52 +00005251 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_nullability)) {
5252 Results.AddResult(CodeCompletionResult("nonnull"));
5253 Results.AddResult(CodeCompletionResult("nullable"));
5254 Results.AddResult(CodeCompletionResult("null_unspecified"));
5255 Results.AddResult(CodeCompletionResult("null_resettable"));
5256 }
Steve Naroff936354c2009-10-08 21:55:05 +00005257 Results.ExitScope();
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005258 HandleCodeCompleteResults(this, CodeCompleter,
5259 CodeCompletionContext::CCC_Other,
5260 Results.data(),Results.size());
Steve Naroff936354c2009-10-08 21:55:05 +00005261}
Steve Naroffeae65032009-11-07 02:08:14 +00005262
James Dennettf1243872012-06-17 05:33:25 +00005263/// \brief Describes the kind of Objective-C method that we want to find
Douglas Gregorc8537c52009-11-19 07:41:15 +00005264/// via code completion.
5265enum ObjCMethodKind {
Dmitri Gribenko4280e5c2012-06-08 23:13:42 +00005266 MK_Any, ///< Any kind of method, provided it means other specified criteria.
5267 MK_ZeroArgSelector, ///< Zero-argument (unary) selector.
5268 MK_OneArgSelector ///< One-argument selector.
Douglas Gregorc8537c52009-11-19 07:41:15 +00005269};
5270
Douglas Gregor67c692c2010-08-26 15:07:07 +00005271static bool isAcceptableObjCSelector(Selector Sel,
5272 ObjCMethodKind WantKind,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005273 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005274 bool AllowSameLength = true) {
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005275 unsigned NumSelIdents = SelIdents.size();
Douglas Gregor67c692c2010-08-26 15:07:07 +00005276 if (NumSelIdents > Sel.getNumArgs())
5277 return false;
5278
5279 switch (WantKind) {
5280 case MK_Any: break;
5281 case MK_ZeroArgSelector: return Sel.isUnarySelector();
5282 case MK_OneArgSelector: return Sel.getNumArgs() == 1;
5283 }
5284
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005285 if (!AllowSameLength && NumSelIdents && NumSelIdents == Sel.getNumArgs())
5286 return false;
5287
Douglas Gregor67c692c2010-08-26 15:07:07 +00005288 for (unsigned I = 0; I != NumSelIdents; ++I)
5289 if (SelIdents[I] != Sel.getIdentifierInfoForSlot(I))
5290 return false;
5291
5292 return true;
5293}
5294
Douglas Gregorc8537c52009-11-19 07:41:15 +00005295static bool isAcceptableObjCMethod(ObjCMethodDecl *Method,
5296 ObjCMethodKind WantKind,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005297 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005298 bool AllowSameLength = true) {
Douglas Gregor67c692c2010-08-26 15:07:07 +00005299 return isAcceptableObjCSelector(Method->getSelector(), WantKind, SelIdents,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005300 AllowSameLength);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005301}
Douglas Gregor1154e272010-09-16 16:06:31 +00005302
5303namespace {
5304 /// \brief A set of selectors, which is used to avoid introducing multiple
5305 /// completions with the same selector into the result set.
5306 typedef llvm::SmallPtrSet<Selector, 16> VisitedSelectorSet;
5307}
5308
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005309/// \brief Add all of the Objective-C methods in the given Objective-C
5310/// container to the set of results.
5311///
5312/// The container will be a class, protocol, category, or implementation of
5313/// any of the above. This mether will recurse to include methods from
5314/// the superclasses of classes along with their categories, protocols, and
5315/// implementations.
5316///
5317/// \param Container the container in which we'll look to find methods.
5318///
James Dennett596e4752012-06-14 03:11:41 +00005319/// \param WantInstanceMethods Whether to add instance methods (only); if
5320/// false, this routine will add factory methods (only).
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005321///
5322/// \param CurContext the context in which we're performing the lookup that
5323/// finds methods.
5324///
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005325/// \param AllowSameLength Whether we allow a method to be added to the list
5326/// when it has the same number of parameters as we have selector identifiers.
5327///
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005328/// \param Results the structure into which we'll add results.
Alex Lorenz638dbc32017-01-24 14:15:08 +00005329static void AddObjCMethods(ObjCContainerDecl *Container,
5330 bool WantInstanceMethods, ObjCMethodKind WantKind,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005331 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005332 DeclContext *CurContext,
Alex Lorenz638dbc32017-01-24 14:15:08 +00005333 VisitedSelectorSet &Selectors, bool AllowSameLength,
5334 ResultBuilder &Results, bool InOriginalClass = true,
5335 bool IsRootClass = false) {
John McCall276321a2010-08-25 06:19:51 +00005336 typedef CodeCompletionResult Result;
Douglas Gregor9b4f3702012-06-12 13:44:08 +00005337 Container = getContainerDef(Container);
Douglas Gregor41778c32013-01-30 06:58:39 +00005338 ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container);
Alex Lorenz638dbc32017-01-24 14:15:08 +00005339 IsRootClass = IsRootClass || (IFace && !IFace->getSuperClass());
Aaron Ballmanaff18c02014-03-13 19:03:34 +00005340 for (auto *M : Container->methods()) {
Douglas Gregor41778c32013-01-30 06:58:39 +00005341 // The instance methods on the root class can be messaged via the
5342 // metaclass.
5343 if (M->isInstanceMethod() == WantInstanceMethods ||
Alex Lorenz638dbc32017-01-24 14:15:08 +00005344 (IsRootClass && !WantInstanceMethods)) {
Douglas Gregor1b605f72009-11-19 01:08:35 +00005345 // Check whether the selector identifiers we've been given are a
5346 // subset of the identifiers for this particular method.
Aaron Ballmanaff18c02014-03-13 19:03:34 +00005347 if (!isAcceptableObjCMethod(M, WantKind, SelIdents, AllowSameLength))
Douglas Gregor1b605f72009-11-19 01:08:35 +00005348 continue;
Douglas Gregorc8537c52009-11-19 07:41:15 +00005349
David Blaikie82e95a32014-11-19 07:49:47 +00005350 if (!Selectors.insert(M->getSelector()).second)
Douglas Gregor1154e272010-09-16 16:06:31 +00005351 continue;
Craig Topperc3ec1492014-05-26 06:22:03 +00005352
5353 Result R = Result(M, Results.getBasePriority(M), nullptr);
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005354 R.StartParameter = SelIdents.size();
Douglas Gregorc8537c52009-11-19 07:41:15 +00005355 R.AllParametersAreInformative = (WantKind != MK_Any);
Douglas Gregor416b5752010-08-25 01:08:01 +00005356 if (!InOriginalClass)
5357 R.Priority += CCD_InBaseClass;
Douglas Gregor1b605f72009-11-19 01:08:35 +00005358 Results.MaybeAddResult(R, CurContext);
5359 }
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005360 }
5361
Douglas Gregorf37c9492010-09-16 15:34:59 +00005362 // Visit the protocols of protocols.
5363 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Douglas Gregore6e48b12012-01-01 19:29:29 +00005364 if (Protocol->hasDefinition()) {
5365 const ObjCList<ObjCProtocolDecl> &Protocols
5366 = Protocol->getReferencedProtocols();
5367 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
5368 E = Protocols.end();
5369 I != E; ++I)
Alex Lorenz638dbc32017-01-24 14:15:08 +00005370 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, CurContext,
5371 Selectors, AllowSameLength, Results, false, IsRootClass);
Douglas Gregore6e48b12012-01-01 19:29:29 +00005372 }
Douglas Gregorf37c9492010-09-16 15:34:59 +00005373 }
5374
Douglas Gregorc0ac7d62011-12-15 05:27:12 +00005375 if (!IFace || !IFace->hasDefinition())
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005376 return;
5377
5378 // Add methods in protocols.
Aaron Ballmana49c5062014-03-13 20:29:09 +00005379 for (auto *I : IFace->protocols())
Alex Lorenz638dbc32017-01-24 14:15:08 +00005380 AddObjCMethods(I, WantInstanceMethods, WantKind, SelIdents, CurContext,
5381 Selectors, AllowSameLength, Results, false, IsRootClass);
5382
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005383 // Add methods in categories.
Aaron Ballman15063e12014-03-13 21:35:02 +00005384 for (auto *CatDecl : IFace->known_categories()) {
Douglas Gregor048fbfa2013-01-16 23:00:23 +00005385 AddObjCMethods(CatDecl, WantInstanceMethods, WantKind, SelIdents,
Alex Lorenz638dbc32017-01-24 14:15:08 +00005386 CurContext, Selectors, AllowSameLength, Results,
5387 InOriginalClass, IsRootClass);
5388
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005389 // Add a categories protocol methods.
5390 const ObjCList<ObjCProtocolDecl> &Protocols
5391 = CatDecl->getReferencedProtocols();
5392 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
5393 E = Protocols.end();
5394 I != E; ++I)
Alex Lorenz638dbc32017-01-24 14:15:08 +00005395 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, CurContext,
5396 Selectors, AllowSameLength, Results, false, IsRootClass);
5397
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005398 // Add methods in category implementations.
5399 if (ObjCCategoryImplDecl *Impl = CatDecl->getImplementation())
Alex Lorenz638dbc32017-01-24 14:15:08 +00005400 AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents, CurContext,
5401 Selectors, AllowSameLength, Results, InOriginalClass,
5402 IsRootClass);
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005403 }
5404
5405 // Add methods in superclass.
Alex Lorenz638dbc32017-01-24 14:15:08 +00005406 // Avoid passing in IsRootClass since root classes won't have super classes.
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005407 if (IFace->getSuperClass())
Alex Lorenz638dbc32017-01-24 14:15:08 +00005408 AddObjCMethods(IFace->getSuperClass(), WantInstanceMethods, WantKind,
5409 SelIdents, CurContext, Selectors, AllowSameLength, Results,
5410 /*IsRootClass=*/false);
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005411
5412 // Add methods in our implementation, if any.
5413 if (ObjCImplementationDecl *Impl = IFace->getImplementation())
Alex Lorenz638dbc32017-01-24 14:15:08 +00005414 AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents, CurContext,
5415 Selectors, AllowSameLength, Results, InOriginalClass,
5416 IsRootClass);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005417}
5418
5419
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005420void Sema::CodeCompleteObjCPropertyGetter(Scope *S) {
Douglas Gregorc8537c52009-11-19 07:41:15 +00005421 // Try to find the interface where getters might live.
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005422 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005423 if (!Class) {
5424 if (ObjCCategoryDecl *Category
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005425 = dyn_cast_or_null<ObjCCategoryDecl>(CurContext))
Douglas Gregorc8537c52009-11-19 07:41:15 +00005426 Class = Category->getClassInterface();
5427
5428 if (!Class)
5429 return;
5430 }
5431
5432 // Find all of the potential getters.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005433 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005434 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005435 CodeCompletionContext::CCC_Other);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005436 Results.EnterNewScope();
5437
Douglas Gregor1154e272010-09-16 16:06:31 +00005438 VisitedSelectorSet Selectors;
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005439 AddObjCMethods(Class, true, MK_ZeroArgSelector, None, CurContext, Selectors,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005440 /*AllowSameLength=*/true, Results);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005441 Results.ExitScope();
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005442 HandleCodeCompleteResults(this, CodeCompleter,
5443 CodeCompletionContext::CCC_Other,
5444 Results.data(),Results.size());
Douglas Gregorc8537c52009-11-19 07:41:15 +00005445}
5446
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005447void Sema::CodeCompleteObjCPropertySetter(Scope *S) {
Douglas Gregorc8537c52009-11-19 07:41:15 +00005448 // Try to find the interface where setters might live.
5449 ObjCInterfaceDecl *Class
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005450 = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005451 if (!Class) {
5452 if (ObjCCategoryDecl *Category
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005453 = dyn_cast_or_null<ObjCCategoryDecl>(CurContext))
Douglas Gregorc8537c52009-11-19 07:41:15 +00005454 Class = Category->getClassInterface();
5455
5456 if (!Class)
5457 return;
5458 }
5459
5460 // Find all of the potential getters.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005461 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005462 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005463 CodeCompletionContext::CCC_Other);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005464 Results.EnterNewScope();
5465
Douglas Gregor1154e272010-09-16 16:06:31 +00005466 VisitedSelectorSet Selectors;
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005467 AddObjCMethods(Class, true, MK_OneArgSelector, None, CurContext,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005468 Selectors, /*AllowSameLength=*/true, Results);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005469
5470 Results.ExitScope();
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005471 HandleCodeCompleteResults(this, CodeCompleter,
5472 CodeCompletionContext::CCC_Other,
5473 Results.data(),Results.size());
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005474}
5475
Douglas Gregorf34a6f02011-02-15 22:19:42 +00005476void Sema::CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS,
5477 bool IsParameter) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005478 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005479 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005480 CodeCompletionContext::CCC_Type);
Douglas Gregor99fa2642010-08-24 01:06:58 +00005481 Results.EnterNewScope();
5482
5483 // Add context-sensitive, Objective-C parameter-passing keywords.
5484 bool AddedInOut = false;
5485 if ((DS.getObjCDeclQualifier() &
5486 (ObjCDeclSpec::DQ_In | ObjCDeclSpec::DQ_Inout)) == 0) {
5487 Results.AddResult("in");
5488 Results.AddResult("inout");
5489 AddedInOut = true;
5490 }
5491 if ((DS.getObjCDeclQualifier() &
5492 (ObjCDeclSpec::DQ_Out | ObjCDeclSpec::DQ_Inout)) == 0) {
5493 Results.AddResult("out");
5494 if (!AddedInOut)
5495 Results.AddResult("inout");
5496 }
5497 if ((DS.getObjCDeclQualifier() &
5498 (ObjCDeclSpec::DQ_Bycopy | ObjCDeclSpec::DQ_Byref |
5499 ObjCDeclSpec::DQ_Oneway)) == 0) {
5500 Results.AddResult("bycopy");
5501 Results.AddResult("byref");
5502 Results.AddResult("oneway");
5503 }
Douglas Gregor86b42682015-06-19 18:27:52 +00005504 if ((DS.getObjCDeclQualifier() & ObjCDeclSpec::DQ_CSNullability) == 0) {
5505 Results.AddResult("nonnull");
5506 Results.AddResult("nullable");
5507 Results.AddResult("null_unspecified");
5508 }
Douglas Gregor99fa2642010-08-24 01:06:58 +00005509
Douglas Gregorf34a6f02011-02-15 22:19:42 +00005510 // If we're completing the return type of an Objective-C method and the
5511 // identifier IBAction refers to a macro, provide a completion item for
5512 // an action, e.g.,
5513 // IBAction)<#selector#>:(id)sender
5514 if (DS.getObjCDeclQualifier() == 0 && !IsParameter &&
Richard Smith20e883e2015-04-29 23:20:19 +00005515 PP.isMacroDefined("IBAction")) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005516 CodeCompletionBuilder Builder(Results.getAllocator(),
5517 Results.getCodeCompletionTUInfo(),
5518 CCP_CodePattern, CXAvailability_Available);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00005519 Builder.AddTypedTextChunk("IBAction");
Benjamin Kramerdb534a42012-03-26 16:57:36 +00005520 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00005521 Builder.AddPlaceholderChunk("selector");
Benjamin Kramerdb534a42012-03-26 16:57:36 +00005522 Builder.AddChunk(CodeCompletionString::CK_Colon);
5523 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00005524 Builder.AddTextChunk("id");
Benjamin Kramerdb534a42012-03-26 16:57:36 +00005525 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00005526 Builder.AddTextChunk("sender");
5527 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
5528 }
Douglas Gregored1f5972013-01-30 07:11:43 +00005529
5530 // If we're completing the return type, provide 'instancetype'.
5531 if (!IsParameter) {
5532 Results.AddResult(CodeCompletionResult("instancetype"));
5533 }
Douglas Gregorf34a6f02011-02-15 22:19:42 +00005534
Douglas Gregor99fa2642010-08-24 01:06:58 +00005535 // Add various builtin type names and specifiers.
5536 AddOrdinaryNameResults(PCC_Type, S, *this, Results);
5537 Results.ExitScope();
5538
5539 // Add the various type names
5540 Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
5541 CodeCompletionDeclConsumer Consumer(Results, CurContext);
5542 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
5543 CodeCompleter->includeGlobals());
5544
5545 if (CodeCompleter->includeMacros())
Douglas Gregor8cb17462012-10-09 16:01:50 +00005546 AddMacroResults(PP, Results, false);
Douglas Gregor99fa2642010-08-24 01:06:58 +00005547
5548 HandleCodeCompleteResults(this, CodeCompleter,
5549 CodeCompletionContext::CCC_Type,
5550 Results.data(), Results.size());
5551}
5552
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005553/// \brief When we have an expression with type "id", we may assume
5554/// that it has some more-specific class type based on knowledge of
5555/// common uses of Objective-C. This routine returns that class type,
5556/// or NULL if no better result could be determined.
5557static ObjCInterfaceDecl *GetAssumedMessageSendExprType(Expr *E) {
Douglas Gregored0b69d2010-09-15 16:23:04 +00005558 ObjCMessageExpr *Msg = dyn_cast_or_null<ObjCMessageExpr>(E);
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005559 if (!Msg)
Craig Topperc3ec1492014-05-26 06:22:03 +00005560 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005561
5562 Selector Sel = Msg->getSelector();
5563 if (Sel.isNull())
Craig Topperc3ec1492014-05-26 06:22:03 +00005564 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005565
5566 IdentifierInfo *Id = Sel.getIdentifierInfoForSlot(0);
5567 if (!Id)
Craig Topperc3ec1492014-05-26 06:22:03 +00005568 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005569
5570 ObjCMethodDecl *Method = Msg->getMethodDecl();
5571 if (!Method)
Craig Topperc3ec1492014-05-26 06:22:03 +00005572 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005573
5574 // Determine the class that we're sending the message to.
Craig Topperc3ec1492014-05-26 06:22:03 +00005575 ObjCInterfaceDecl *IFace = nullptr;
Douglas Gregor9a129192010-04-21 00:45:42 +00005576 switch (Msg->getReceiverKind()) {
5577 case ObjCMessageExpr::Class:
John McCall8b07ec22010-05-15 11:32:37 +00005578 if (const ObjCObjectType *ObjType
5579 = Msg->getClassReceiver()->getAs<ObjCObjectType>())
5580 IFace = ObjType->getInterface();
Douglas Gregor9a129192010-04-21 00:45:42 +00005581 break;
5582
5583 case ObjCMessageExpr::Instance: {
5584 QualType T = Msg->getInstanceReceiver()->getType();
5585 if (const ObjCObjectPointerType *Ptr = T->getAs<ObjCObjectPointerType>())
5586 IFace = Ptr->getInterfaceDecl();
5587 break;
5588 }
5589
5590 case ObjCMessageExpr::SuperInstance:
5591 case ObjCMessageExpr::SuperClass:
5592 break;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005593 }
5594
5595 if (!IFace)
Craig Topperc3ec1492014-05-26 06:22:03 +00005596 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005597
5598 ObjCInterfaceDecl *Super = IFace->getSuperClass();
5599 if (Method->isInstanceMethod())
5600 return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
5601 .Case("retain", IFace)
John McCall31168b02011-06-15 23:02:42 +00005602 .Case("strong", IFace)
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005603 .Case("autorelease", IFace)
5604 .Case("copy", IFace)
5605 .Case("copyWithZone", IFace)
5606 .Case("mutableCopy", IFace)
5607 .Case("mutableCopyWithZone", IFace)
5608 .Case("awakeFromCoder", IFace)
5609 .Case("replacementObjectFromCoder", IFace)
5610 .Case("class", IFace)
5611 .Case("classForCoder", IFace)
5612 .Case("superclass", Super)
Craig Topperc3ec1492014-05-26 06:22:03 +00005613 .Default(nullptr);
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005614
5615 return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
5616 .Case("new", IFace)
5617 .Case("alloc", IFace)
5618 .Case("allocWithZone", IFace)
5619 .Case("class", IFace)
5620 .Case("superclass", Super)
Craig Topperc3ec1492014-05-26 06:22:03 +00005621 .Default(nullptr);
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005622}
5623
Douglas Gregor6fc04132010-08-27 15:10:57 +00005624// Add a special completion for a message send to "super", which fills in the
5625// most likely case of forwarding all of our arguments to the superclass
5626// function.
5627///
5628/// \param S The semantic analysis object.
5629///
Dmitri Gribenkoadba9be2012-08-23 17:58:28 +00005630/// \param NeedSuperKeyword Whether we need to prefix this completion with
Douglas Gregor6fc04132010-08-27 15:10:57 +00005631/// the "super" keyword. Otherwise, we just need to provide the arguments.
5632///
5633/// \param SelIdents The identifiers in the selector that have already been
5634/// provided as arguments for a send to "super".
5635///
Douglas Gregor6fc04132010-08-27 15:10:57 +00005636/// \param Results The set of results to augment.
5637///
5638/// \returns the Objective-C method declaration that would be invoked by
5639/// this "super" completion. If NULL, no completion was added.
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005640static ObjCMethodDecl *AddSuperSendCompletion(
5641 Sema &S, bool NeedSuperKeyword,
5642 ArrayRef<IdentifierInfo *> SelIdents,
5643 ResultBuilder &Results) {
Douglas Gregor6fc04132010-08-27 15:10:57 +00005644 ObjCMethodDecl *CurMethod = S.getCurMethodDecl();
5645 if (!CurMethod)
Craig Topperc3ec1492014-05-26 06:22:03 +00005646 return nullptr;
5647
Douglas Gregor6fc04132010-08-27 15:10:57 +00005648 ObjCInterfaceDecl *Class = CurMethod->getClassInterface();
5649 if (!Class)
Craig Topperc3ec1492014-05-26 06:22:03 +00005650 return nullptr;
5651
Douglas Gregor6fc04132010-08-27 15:10:57 +00005652 // Try to find a superclass method with the same selector.
Craig Topperc3ec1492014-05-26 06:22:03 +00005653 ObjCMethodDecl *SuperMethod = nullptr;
Douglas Gregorb5f1e462011-02-16 00:51:18 +00005654 while ((Class = Class->getSuperClass()) && !SuperMethod) {
5655 // Check in the class
Douglas Gregor6fc04132010-08-27 15:10:57 +00005656 SuperMethod = Class->getMethod(CurMethod->getSelector(),
5657 CurMethod->isInstanceMethod());
5658
Douglas Gregorb5f1e462011-02-16 00:51:18 +00005659 // Check in categories or class extensions.
5660 if (!SuperMethod) {
Aaron Ballman15063e12014-03-13 21:35:02 +00005661 for (const auto *Cat : Class->known_categories()) {
Douglas Gregor048fbfa2013-01-16 23:00:23 +00005662 if ((SuperMethod = Cat->getMethod(CurMethod->getSelector(),
Douglas Gregorb5f1e462011-02-16 00:51:18 +00005663 CurMethod->isInstanceMethod())))
5664 break;
Douglas Gregor048fbfa2013-01-16 23:00:23 +00005665 }
Douglas Gregorb5f1e462011-02-16 00:51:18 +00005666 }
5667 }
5668
Douglas Gregor6fc04132010-08-27 15:10:57 +00005669 if (!SuperMethod)
Craig Topperc3ec1492014-05-26 06:22:03 +00005670 return nullptr;
5671
Douglas Gregor6fc04132010-08-27 15:10:57 +00005672 // Check whether the superclass method has the same signature.
5673 if (CurMethod->param_size() != SuperMethod->param_size() ||
5674 CurMethod->isVariadic() != SuperMethod->isVariadic())
Craig Topperc3ec1492014-05-26 06:22:03 +00005675 return nullptr;
5676
Douglas Gregor6fc04132010-08-27 15:10:57 +00005677 for (ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin(),
5678 CurPEnd = CurMethod->param_end(),
5679 SuperP = SuperMethod->param_begin();
5680 CurP != CurPEnd; ++CurP, ++SuperP) {
5681 // Make sure the parameter types are compatible.
5682 if (!S.Context.hasSameUnqualifiedType((*CurP)->getType(),
5683 (*SuperP)->getType()))
Craig Topperc3ec1492014-05-26 06:22:03 +00005684 return nullptr;
5685
Douglas Gregor6fc04132010-08-27 15:10:57 +00005686 // Make sure we have a parameter name to forward!
5687 if (!(*CurP)->getIdentifier())
Craig Topperc3ec1492014-05-26 06:22:03 +00005688 return nullptr;
Douglas Gregor6fc04132010-08-27 15:10:57 +00005689 }
5690
5691 // We have a superclass method. Now, form the send-to-super completion.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005692 CodeCompletionBuilder Builder(Results.getAllocator(),
5693 Results.getCodeCompletionTUInfo());
Douglas Gregor6fc04132010-08-27 15:10:57 +00005694
5695 // Give this completion a return type.
Douglas Gregorc3425b12015-07-07 06:20:19 +00005696 AddResultTypeChunk(S.Context, getCompletionPrintingPolicy(S), SuperMethod,
5697 Results.getCompletionContext().getBaseType(),
Douglas Gregor75acd922011-09-27 23:30:47 +00005698 Builder);
Douglas Gregor6fc04132010-08-27 15:10:57 +00005699
5700 // If we need the "super" keyword, add it (plus some spacing).
5701 if (NeedSuperKeyword) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005702 Builder.AddTypedTextChunk("super");
5703 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregor6fc04132010-08-27 15:10:57 +00005704 }
5705
5706 Selector Sel = CurMethod->getSelector();
5707 if (Sel.isUnarySelector()) {
5708 if (NeedSuperKeyword)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005709 Builder.AddTextChunk(Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00005710 Sel.getNameForSlot(0)));
Douglas Gregor6fc04132010-08-27 15:10:57 +00005711 else
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005712 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00005713 Sel.getNameForSlot(0)));
Douglas Gregor6fc04132010-08-27 15:10:57 +00005714 } else {
5715 ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin();
5716 for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I, ++CurP) {
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005717 if (I > SelIdents.size())
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005718 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregor6fc04132010-08-27 15:10:57 +00005719
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005720 if (I < SelIdents.size())
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005721 Builder.AddInformativeChunk(
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005722 Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00005723 Sel.getNameForSlot(I) + ":"));
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005724 else if (NeedSuperKeyword || I > SelIdents.size()) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005725 Builder.AddTextChunk(
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005726 Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00005727 Sel.getNameForSlot(I) + ":"));
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005728 Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005729 (*CurP)->getIdentifier()->getName()));
Douglas Gregor6fc04132010-08-27 15:10:57 +00005730 } else {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005731 Builder.AddTypedTextChunk(
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005732 Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00005733 Sel.getNameForSlot(I) + ":"));
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005734 Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005735 (*CurP)->getIdentifier()->getName()));
Douglas Gregor6fc04132010-08-27 15:10:57 +00005736 }
5737 }
5738 }
5739
Douglas Gregor78254c82012-03-27 23:34:16 +00005740 Results.AddResult(CodeCompletionResult(Builder.TakeString(), SuperMethod,
5741 CCP_SuperCompletion));
Douglas Gregor6fc04132010-08-27 15:10:57 +00005742 return SuperMethod;
5743}
5744
Douglas Gregora817a192010-05-27 23:06:34 +00005745void Sema::CodeCompleteObjCMessageReceiver(Scope *S) {
John McCall276321a2010-08-25 06:19:51 +00005746 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005747 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005748 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005749 CodeCompletionContext::CCC_ObjCMessageReceiver,
Richard Smith2bf7fdb2013-01-02 11:42:31 +00005750 getLangOpts().CPlusPlus11
Douglas Gregord8c61782012-02-15 15:34:24 +00005751 ? &ResultBuilder::IsObjCMessageReceiverOrLambdaCapture
5752 : &ResultBuilder::IsObjCMessageReceiver);
Douglas Gregora817a192010-05-27 23:06:34 +00005753
Douglas Gregora817a192010-05-27 23:06:34 +00005754 CodeCompletionDeclConsumer Consumer(Results, CurContext);
5755 Results.EnterNewScope();
Douglas Gregor39982192010-08-15 06:18:01 +00005756 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
5757 CodeCompleter->includeGlobals());
Douglas Gregora817a192010-05-27 23:06:34 +00005758
5759 // If we are in an Objective-C method inside a class that has a superclass,
5760 // add "super" as an option.
5761 if (ObjCMethodDecl *Method = getCurMethodDecl())
5762 if (ObjCInterfaceDecl *Iface = Method->getClassInterface())
Douglas Gregor6fc04132010-08-27 15:10:57 +00005763 if (Iface->getSuperClass()) {
Douglas Gregora817a192010-05-27 23:06:34 +00005764 Results.AddResult(Result("super"));
Douglas Gregor6fc04132010-08-27 15:10:57 +00005765
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005766 AddSuperSendCompletion(*this, /*NeedSuperKeyword=*/true, None, Results);
Douglas Gregor6fc04132010-08-27 15:10:57 +00005767 }
Douglas Gregora817a192010-05-27 23:06:34 +00005768
Richard Smith2bf7fdb2013-01-02 11:42:31 +00005769 if (getLangOpts().CPlusPlus11)
Douglas Gregord8c61782012-02-15 15:34:24 +00005770 addThisCompletion(*this, Results);
5771
Douglas Gregora817a192010-05-27 23:06:34 +00005772 Results.ExitScope();
5773
5774 if (CodeCompleter->includeMacros())
Douglas Gregor8cb17462012-10-09 16:01:50 +00005775 AddMacroResults(PP, Results, false);
Douglas Gregor50832e02010-09-20 22:39:41 +00005776 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005777 Results.data(), Results.size());
Douglas Gregora817a192010-05-27 23:06:34 +00005778
5779}
5780
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005781void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005782 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00005783 bool AtArgumentExpression) {
Craig Topperc3ec1492014-05-26 06:22:03 +00005784 ObjCInterfaceDecl *CDecl = nullptr;
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005785 if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
5786 // Figure out which interface we're in.
5787 CDecl = CurMethod->getClassInterface();
5788 if (!CDecl)
5789 return;
5790
5791 // Find the superclass of this class.
5792 CDecl = CDecl->getSuperClass();
5793 if (!CDecl)
5794 return;
5795
5796 if (CurMethod->isInstanceMethod()) {
5797 // We are inside an instance method, which means that the message
5798 // send [super ...] is actually calling an instance method on the
Douglas Gregor392a84b2010-10-13 21:24:53 +00005799 // current object.
Craig Topperc3ec1492014-05-26 06:22:03 +00005800 return CodeCompleteObjCInstanceMessage(S, nullptr, SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00005801 AtArgumentExpression,
Douglas Gregor392a84b2010-10-13 21:24:53 +00005802 CDecl);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005803 }
5804
5805 // Fall through to send to the superclass in CDecl.
5806 } else {
5807 // "super" may be the name of a type or variable. Figure out which
5808 // it is.
Argyrios Kyrtzidis3e56dd42013-03-14 22:56:43 +00005809 IdentifierInfo *Super = getSuperIdentifier();
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005810 NamedDecl *ND = LookupSingleName(S, Super, SuperLoc,
5811 LookupOrdinaryName);
5812 if ((CDecl = dyn_cast_or_null<ObjCInterfaceDecl>(ND))) {
5813 // "super" names an interface. Use it.
5814 } else if (TypeDecl *TD = dyn_cast_or_null<TypeDecl>(ND)) {
John McCall8b07ec22010-05-15 11:32:37 +00005815 if (const ObjCObjectType *Iface
5816 = Context.getTypeDeclType(TD)->getAs<ObjCObjectType>())
5817 CDecl = Iface->getInterface();
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005818 } else if (ND && isa<UnresolvedUsingTypenameDecl>(ND)) {
5819 // "super" names an unresolved type; we can't be more specific.
5820 } else {
5821 // Assume that "super" names some kind of value and parse that way.
5822 CXXScopeSpec SS;
Abramo Bagnara7945c982012-01-27 09:46:47 +00005823 SourceLocation TemplateKWLoc;
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005824 UnqualifiedId id;
5825 id.setIdentifier(Super, SuperLoc);
Abramo Bagnara7945c982012-01-27 09:46:47 +00005826 ExprResult SuperExpr = ActOnIdExpression(S, SS, TemplateKWLoc, id,
5827 false, false);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005828 return CodeCompleteObjCInstanceMessage(S, (Expr *)SuperExpr.get(),
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005829 SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00005830 AtArgumentExpression);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005831 }
5832
5833 // Fall through
5834 }
5835
John McCallba7bf592010-08-24 05:47:05 +00005836 ParsedType Receiver;
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005837 if (CDecl)
John McCallba7bf592010-08-24 05:47:05 +00005838 Receiver = ParsedType::make(Context.getObjCInterfaceType(CDecl));
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005839 return CodeCompleteObjCClassMessage(S, Receiver, SelIdents,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005840 AtArgumentExpression,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00005841 /*IsSuper=*/true);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005842}
5843
Douglas Gregor74661272010-09-21 00:03:25 +00005844/// \brief Given a set of code-completion results for the argument of a message
5845/// send, determine the preferred type (if any) for that argument expression.
5846static QualType getPreferredArgumentTypeForMessageSend(ResultBuilder &Results,
5847 unsigned NumSelIdents) {
5848 typedef CodeCompletionResult Result;
5849 ASTContext &Context = Results.getSema().Context;
5850
5851 QualType PreferredType;
5852 unsigned BestPriority = CCP_Unlikely * 2;
5853 Result *ResultsData = Results.data();
5854 for (unsigned I = 0, N = Results.size(); I != N; ++I) {
5855 Result &R = ResultsData[I];
5856 if (R.Kind == Result::RK_Declaration &&
5857 isa<ObjCMethodDecl>(R.Declaration)) {
5858 if (R.Priority <= BestPriority) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00005859 const ObjCMethodDecl *Method = cast<ObjCMethodDecl>(R.Declaration);
Douglas Gregor74661272010-09-21 00:03:25 +00005860 if (NumSelIdents <= Method->param_size()) {
Alp Toker03376dc2014-07-07 09:02:20 +00005861 QualType MyPreferredType = Method->parameters()[NumSelIdents - 1]
Douglas Gregor74661272010-09-21 00:03:25 +00005862 ->getType();
5863 if (R.Priority < BestPriority || PreferredType.isNull()) {
5864 BestPriority = R.Priority;
5865 PreferredType = MyPreferredType;
5866 } else if (!Context.hasSameUnqualifiedType(PreferredType,
5867 MyPreferredType)) {
5868 PreferredType = QualType();
5869 }
5870 }
5871 }
5872 }
5873 }
5874
5875 return PreferredType;
5876}
5877
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005878static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
5879 ParsedType Receiver,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005880 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00005881 bool AtArgumentExpression,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005882 bool IsSuper,
5883 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00005884 typedef CodeCompletionResult Result;
Craig Topperc3ec1492014-05-26 06:22:03 +00005885 ObjCInterfaceDecl *CDecl = nullptr;
5886
Douglas Gregor8ce33212009-11-17 17:59:40 +00005887 // If the given name refers to an interface type, retrieve the
5888 // corresponding declaration.
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005889 if (Receiver) {
Craig Topperc3ec1492014-05-26 06:22:03 +00005890 QualType T = SemaRef.GetTypeFromParser(Receiver, nullptr);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005891 if (!T.isNull())
John McCall8b07ec22010-05-15 11:32:37 +00005892 if (const ObjCObjectType *Interface = T->getAs<ObjCObjectType>())
5893 CDecl = Interface->getInterface();
Douglas Gregor8ce33212009-11-17 17:59:40 +00005894 }
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005895
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005896 // Add all of the factory methods in this Objective-C class, its protocols,
5897 // superclasses, categories, implementation, etc.
Steve Naroffeae65032009-11-07 02:08:14 +00005898 Results.EnterNewScope();
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005899
Douglas Gregor6fc04132010-08-27 15:10:57 +00005900 // If this is a send-to-super, try to add the special "super" send
5901 // completion.
5902 if (IsSuper) {
5903 if (ObjCMethodDecl *SuperMethod
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005904 = AddSuperSendCompletion(SemaRef, false, SelIdents, Results))
Douglas Gregor6fc04132010-08-27 15:10:57 +00005905 Results.Ignore(SuperMethod);
5906 }
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005907
Douglas Gregorc2cb2e22010-08-27 15:29:55 +00005908 // If we're inside an Objective-C method definition, prefer its selector to
5909 // others.
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005910 if (ObjCMethodDecl *CurMethod = SemaRef.getCurMethodDecl())
Douglas Gregorc2cb2e22010-08-27 15:29:55 +00005911 Results.setPreferredSelector(CurMethod->getSelector());
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005912
Douglas Gregor1154e272010-09-16 16:06:31 +00005913 VisitedSelectorSet Selectors;
Douglas Gregor6285f752010-04-06 16:40:00 +00005914 if (CDecl)
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005915 AddObjCMethods(CDecl, false, MK_Any, SelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005916 SemaRef.CurContext, Selectors, AtArgumentExpression,
5917 Results);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005918 else {
Douglas Gregor6285f752010-04-06 16:40:00 +00005919 // We're messaging "id" as a type; provide all class/factory methods.
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005920
Douglas Gregord720daf2010-04-06 17:30:22 +00005921 // If we have an external source, load the entire class method
Sebastian Redld44cd6a2010-08-18 23:57:06 +00005922 // pool from the AST file.
Axel Naumanndd433f02012-10-18 19:05:02 +00005923 if (SemaRef.getExternalSource()) {
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005924 for (uint32_t I = 0,
Axel Naumanndd433f02012-10-18 19:05:02 +00005925 N = SemaRef.getExternalSource()->GetNumExternalSelectors();
John McCall75b960e2010-06-01 09:23:16 +00005926 I != N; ++I) {
Axel Naumanndd433f02012-10-18 19:05:02 +00005927 Selector Sel = SemaRef.getExternalSource()->GetExternalSelector(I);
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005928 if (Sel.isNull() || SemaRef.MethodPool.count(Sel))
Douglas Gregord720daf2010-04-06 17:30:22 +00005929 continue;
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005930
5931 SemaRef.ReadMethodPool(Sel);
Douglas Gregord720daf2010-04-06 17:30:22 +00005932 }
5933 }
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005934
5935 for (Sema::GlobalMethodPool::iterator M = SemaRef.MethodPool.begin(),
5936 MEnd = SemaRef.MethodPool.end();
Sebastian Redl75d8a322010-08-02 23:18:59 +00005937 M != MEnd; ++M) {
5938 for (ObjCMethodList *MethList = &M->second.second;
Nico Weber2e0c8f72014-12-27 03:58:08 +00005939 MethList && MethList->getMethod();
Argyrios Kyrtzidisd3da6e02013-04-17 00:08:58 +00005940 MethList = MethList->getNext()) {
Nico Weber2e0c8f72014-12-27 03:58:08 +00005941 if (!isAcceptableObjCMethod(MethList->getMethod(), MK_Any, SelIdents))
Douglas Gregor6285f752010-04-06 16:40:00 +00005942 continue;
Craig Topperc3ec1492014-05-26 06:22:03 +00005943
Nico Weber2e0c8f72014-12-27 03:58:08 +00005944 Result R(MethList->getMethod(),
5945 Results.getBasePriority(MethList->getMethod()), nullptr);
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005946 R.StartParameter = SelIdents.size();
Douglas Gregor6285f752010-04-06 16:40:00 +00005947 R.AllParametersAreInformative = false;
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005948 Results.MaybeAddResult(R, SemaRef.CurContext);
Douglas Gregor6285f752010-04-06 16:40:00 +00005949 }
5950 }
5951 }
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005952
5953 Results.ExitScope();
5954}
Douglas Gregor6285f752010-04-06 16:40:00 +00005955
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005956void Sema::CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005957 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00005958 bool AtArgumentExpression,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005959 bool IsSuper) {
Douglas Gregor63745d52011-07-21 01:05:26 +00005960
5961 QualType T = this->GetTypeFromParser(Receiver);
5962
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005963 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005964 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor63745d52011-07-21 01:05:26 +00005965 CodeCompletionContext(CodeCompletionContext::CCC_ObjCClassMessage,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005966 T, SelIdents));
Douglas Gregor63745d52011-07-21 01:05:26 +00005967
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005968 AddClassMessageCompletions(*this, S, Receiver, SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00005969 AtArgumentExpression, IsSuper, Results);
Douglas Gregor74661272010-09-21 00:03:25 +00005970
5971 // If we're actually at the argument expression (rather than prior to the
5972 // selector), we're actually performing code completion for an expression.
5973 // Determine whether we have a single, best method. If so, we can
5974 // code-complete the expression using the corresponding parameter type as
5975 // our preferred type, improving completion results.
5976 if (AtArgumentExpression) {
5977 QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005978 SelIdents.size());
Douglas Gregor74661272010-09-21 00:03:25 +00005979 if (PreferredType.isNull())
5980 CodeCompleteOrdinaryName(S, PCC_Expression);
5981 else
5982 CodeCompleteExpression(S, PreferredType);
5983 return;
5984 }
5985
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005986 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor63745d52011-07-21 01:05:26 +00005987 Results.getCompletionContext(),
Douglas Gregor6fc04132010-08-27 15:10:57 +00005988 Results.data(), Results.size());
Steve Naroffeae65032009-11-07 02:08:14 +00005989}
5990
Richard Trieu2bd04012011-09-09 02:00:50 +00005991void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005992 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00005993 bool AtArgumentExpression,
Douglas Gregor392a84b2010-10-13 21:24:53 +00005994 ObjCInterfaceDecl *Super) {
John McCall276321a2010-08-25 06:19:51 +00005995 typedef CodeCompletionResult Result;
Steve Naroffeae65032009-11-07 02:08:14 +00005996
5997 Expr *RecExpr = static_cast<Expr *>(Receiver);
Steve Naroffeae65032009-11-07 02:08:14 +00005998
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005999 // If necessary, apply function/array conversion to the receiver.
6000 // C99 6.7.5.3p[7,8].
John Wiegley01296292011-04-08 18:41:53 +00006001 if (RecExpr) {
6002 ExprResult Conv = DefaultFunctionArrayLvalueConversion(RecExpr);
6003 if (Conv.isInvalid()) // conversion failed. bail.
6004 return;
Nikola Smiljanic01a75982014-05-29 10:55:11 +00006005 RecExpr = Conv.get();
John Wiegley01296292011-04-08 18:41:53 +00006006 }
Douglas Gregor392a84b2010-10-13 21:24:53 +00006007 QualType ReceiverType = RecExpr? RecExpr->getType()
6008 : Super? Context.getObjCObjectPointerType(
6009 Context.getObjCInterfaceType(Super))
6010 : Context.getObjCIdType();
Steve Naroffeae65032009-11-07 02:08:14 +00006011
Douglas Gregordc520b02010-11-08 21:12:30 +00006012 // If we're messaging an expression with type "id" or "Class", check
6013 // whether we know something special about the receiver that allows
6014 // us to assume a more-specific receiver type.
Anders Carlsson382ba412014-02-28 19:07:22 +00006015 if (ReceiverType->isObjCIdType() || ReceiverType->isObjCClassType()) {
Douglas Gregordc520b02010-11-08 21:12:30 +00006016 if (ObjCInterfaceDecl *IFace = GetAssumedMessageSendExprType(RecExpr)) {
6017 if (ReceiverType->isObjCClassType())
6018 return CodeCompleteObjCClassMessage(S,
6019 ParsedType::make(Context.getObjCInterfaceType(IFace)),
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006020 SelIdents,
Douglas Gregordc520b02010-11-08 21:12:30 +00006021 AtArgumentExpression, Super);
6022
6023 ReceiverType = Context.getObjCObjectPointerType(
6024 Context.getObjCInterfaceType(IFace));
6025 }
Anders Carlsson382ba412014-02-28 19:07:22 +00006026 } else if (RecExpr && getLangOpts().CPlusPlus) {
6027 ExprResult Conv = PerformContextuallyConvertToObjCPointer(RecExpr);
6028 if (Conv.isUsable()) {
Nikola Smiljanic01a75982014-05-29 10:55:11 +00006029 RecExpr = Conv.get();
Anders Carlsson382ba412014-02-28 19:07:22 +00006030 ReceiverType = RecExpr->getType();
6031 }
6032 }
Douglas Gregordc520b02010-11-08 21:12:30 +00006033
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006034 // Build the set of methods we can see.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006035 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006036 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor63745d52011-07-21 01:05:26 +00006037 CodeCompletionContext(CodeCompletionContext::CCC_ObjCInstanceMessage,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006038 ReceiverType, SelIdents));
Douglas Gregor63745d52011-07-21 01:05:26 +00006039
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006040 Results.EnterNewScope();
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006041
Douglas Gregor6fc04132010-08-27 15:10:57 +00006042 // If this is a send-to-super, try to add the special "super" send
6043 // completion.
Douglas Gregor392a84b2010-10-13 21:24:53 +00006044 if (Super) {
Douglas Gregor6fc04132010-08-27 15:10:57 +00006045 if (ObjCMethodDecl *SuperMethod
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006046 = AddSuperSendCompletion(*this, false, SelIdents, Results))
Douglas Gregor6fc04132010-08-27 15:10:57 +00006047 Results.Ignore(SuperMethod);
6048 }
6049
Douglas Gregorc2cb2e22010-08-27 15:29:55 +00006050 // If we're inside an Objective-C method definition, prefer its selector to
6051 // others.
6052 if (ObjCMethodDecl *CurMethod = getCurMethodDecl())
6053 Results.setPreferredSelector(CurMethod->getSelector());
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006054
Douglas Gregor1154e272010-09-16 16:06:31 +00006055 // Keep track of the selectors we've already added.
6056 VisitedSelectorSet Selectors;
6057
Douglas Gregora3329fa2009-11-18 00:06:18 +00006058 // Handle messages to Class. This really isn't a message to an instance
6059 // method, so we treat it the same way we would treat a message send to a
6060 // class method.
6061 if (ReceiverType->isObjCClassType() ||
6062 ReceiverType->isObjCQualifiedClassType()) {
6063 if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
6064 if (ObjCInterfaceDecl *ClassDecl = CurMethod->getClassInterface())
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006065 AddObjCMethods(ClassDecl, false, MK_Any, SelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00006066 CurContext, Selectors, AtArgumentExpression, Results);
Douglas Gregora3329fa2009-11-18 00:06:18 +00006067 }
6068 }
6069 // Handle messages to a qualified ID ("id<foo>").
6070 else if (const ObjCObjectPointerType *QualID
6071 = ReceiverType->getAsObjCQualifiedIdType()) {
6072 // Search protocols for instance methods.
Aaron Ballman83731462014-03-17 16:14:00 +00006073 for (auto *I : QualID->quals())
6074 AddObjCMethods(I, true, MK_Any, SelIdents, CurContext,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00006075 Selectors, AtArgumentExpression, Results);
Douglas Gregora3329fa2009-11-18 00:06:18 +00006076 }
6077 // Handle messages to a pointer to interface type.
6078 else if (const ObjCObjectPointerType *IFacePtr
6079 = ReceiverType->getAsObjCInterfacePointerType()) {
6080 // Search the class, its superclasses, etc., for instance methods.
Douglas Gregorc8537c52009-11-19 07:41:15 +00006081 AddObjCMethods(IFacePtr->getInterfaceDecl(), true, MK_Any, SelIdents,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006082 CurContext, Selectors, AtArgumentExpression,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00006083 Results);
Douglas Gregora3329fa2009-11-18 00:06:18 +00006084
6085 // Search protocols for instance methods.
Aaron Ballman83731462014-03-17 16:14:00 +00006086 for (auto *I : IFacePtr->quals())
6087 AddObjCMethods(I, true, MK_Any, SelIdents, CurContext,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00006088 Selectors, AtArgumentExpression, Results);
Douglas Gregora3329fa2009-11-18 00:06:18 +00006089 }
Douglas Gregor6285f752010-04-06 16:40:00 +00006090 // Handle messages to "id".
6091 else if (ReceiverType->isObjCIdType()) {
Douglas Gregord720daf2010-04-06 17:30:22 +00006092 // We're messaging "id", so provide all instance methods we know
6093 // about as code-completion results.
6094
6095 // If we have an external source, load the entire class method
Sebastian Redld44cd6a2010-08-18 23:57:06 +00006096 // pool from the AST file.
Douglas Gregord720daf2010-04-06 17:30:22 +00006097 if (ExternalSource) {
John McCall75b960e2010-06-01 09:23:16 +00006098 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
6099 I != N; ++I) {
6100 Selector Sel = ExternalSource->GetExternalSelector(I);
Sebastian Redl75d8a322010-08-02 23:18:59 +00006101 if (Sel.isNull() || MethodPool.count(Sel))
Douglas Gregord720daf2010-04-06 17:30:22 +00006102 continue;
6103
Sebastian Redl75d8a322010-08-02 23:18:59 +00006104 ReadMethodPool(Sel);
Douglas Gregord720daf2010-04-06 17:30:22 +00006105 }
6106 }
6107
Sebastian Redl75d8a322010-08-02 23:18:59 +00006108 for (GlobalMethodPool::iterator M = MethodPool.begin(),
6109 MEnd = MethodPool.end();
6110 M != MEnd; ++M) {
6111 for (ObjCMethodList *MethList = &M->second.first;
Nico Weber2e0c8f72014-12-27 03:58:08 +00006112 MethList && MethList->getMethod();
Argyrios Kyrtzidisd3da6e02013-04-17 00:08:58 +00006113 MethList = MethList->getNext()) {
Nico Weber2e0c8f72014-12-27 03:58:08 +00006114 if (!isAcceptableObjCMethod(MethList->getMethod(), MK_Any, SelIdents))
Douglas Gregor6285f752010-04-06 16:40:00 +00006115 continue;
Douglas Gregor1154e272010-09-16 16:06:31 +00006116
Nico Weber2e0c8f72014-12-27 03:58:08 +00006117 if (!Selectors.insert(MethList->getMethod()->getSelector()).second)
Douglas Gregor1154e272010-09-16 16:06:31 +00006118 continue;
Craig Topperc3ec1492014-05-26 06:22:03 +00006119
Nico Weber2e0c8f72014-12-27 03:58:08 +00006120 Result R(MethList->getMethod(),
6121 Results.getBasePriority(MethList->getMethod()), nullptr);
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006122 R.StartParameter = SelIdents.size();
Douglas Gregor6285f752010-04-06 16:40:00 +00006123 R.AllParametersAreInformative = false;
6124 Results.MaybeAddResult(R, CurContext);
6125 }
6126 }
6127 }
Steve Naroffeae65032009-11-07 02:08:14 +00006128 Results.ExitScope();
Douglas Gregor74661272010-09-21 00:03:25 +00006129
6130
6131 // If we're actually at the argument expression (rather than prior to the
6132 // selector), we're actually performing code completion for an expression.
6133 // Determine whether we have a single, best method. If so, we can
6134 // code-complete the expression using the corresponding parameter type as
6135 // our preferred type, improving completion results.
6136 if (AtArgumentExpression) {
6137 QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006138 SelIdents.size());
Douglas Gregor74661272010-09-21 00:03:25 +00006139 if (PreferredType.isNull())
6140 CodeCompleteOrdinaryName(S, PCC_Expression);
6141 else
6142 CodeCompleteExpression(S, PreferredType);
6143 return;
6144 }
6145
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006146 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor63745d52011-07-21 01:05:26 +00006147 Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006148 Results.data(),Results.size());
Steve Naroffeae65032009-11-07 02:08:14 +00006149}
Douglas Gregorbaf69612009-11-18 04:19:12 +00006150
Douglas Gregor68762e72010-08-23 21:17:50 +00006151void Sema::CodeCompleteObjCForCollection(Scope *S,
6152 DeclGroupPtrTy IterationVar) {
6153 CodeCompleteExpressionData Data;
6154 Data.ObjCCollection = true;
6155
6156 if (IterationVar.getAsOpaquePtr()) {
Serge Pavlov9ddb76e2013-08-27 13:15:56 +00006157 DeclGroupRef DG = IterationVar.get();
Douglas Gregor68762e72010-08-23 21:17:50 +00006158 for (DeclGroupRef::iterator I = DG.begin(), End = DG.end(); I != End; ++I) {
6159 if (*I)
6160 Data.IgnoreDecls.push_back(*I);
6161 }
6162 }
6163
6164 CodeCompleteExpression(S, Data);
6165}
6166
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006167void Sema::CodeCompleteObjCSelector(Scope *S,
6168 ArrayRef<IdentifierInfo *> SelIdents) {
Douglas Gregor67c692c2010-08-26 15:07:07 +00006169 // If we have an external source, load the entire class method
6170 // pool from the AST file.
6171 if (ExternalSource) {
6172 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
6173 I != N; ++I) {
6174 Selector Sel = ExternalSource->GetExternalSelector(I);
6175 if (Sel.isNull() || MethodPool.count(Sel))
6176 continue;
6177
6178 ReadMethodPool(Sel);
6179 }
6180 }
6181
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006182 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006183 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006184 CodeCompletionContext::CCC_SelectorName);
Douglas Gregor67c692c2010-08-26 15:07:07 +00006185 Results.EnterNewScope();
6186 for (GlobalMethodPool::iterator M = MethodPool.begin(),
6187 MEnd = MethodPool.end();
6188 M != MEnd; ++M) {
6189
6190 Selector Sel = M->first;
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006191 if (!isAcceptableObjCSelector(Sel, MK_Any, SelIdents))
Douglas Gregor67c692c2010-08-26 15:07:07 +00006192 continue;
6193
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006194 CodeCompletionBuilder Builder(Results.getAllocator(),
6195 Results.getCodeCompletionTUInfo());
Douglas Gregor67c692c2010-08-26 15:07:07 +00006196 if (Sel.isUnarySelector()) {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00006197 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00006198 Sel.getNameForSlot(0)));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006199 Results.AddResult(Builder.TakeString());
Douglas Gregor67c692c2010-08-26 15:07:07 +00006200 continue;
6201 }
6202
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00006203 std::string Accumulator;
Douglas Gregor67c692c2010-08-26 15:07:07 +00006204 for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I) {
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006205 if (I == SelIdents.size()) {
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00006206 if (!Accumulator.empty()) {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00006207 Builder.AddInformativeChunk(Builder.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006208 Accumulator));
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00006209 Accumulator.clear();
6210 }
6211 }
6212
Benjamin Kramer632500c2011-07-26 16:59:25 +00006213 Accumulator += Sel.getNameForSlot(I);
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00006214 Accumulator += ':';
Douglas Gregor67c692c2010-08-26 15:07:07 +00006215 }
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00006216 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString( Accumulator));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006217 Results.AddResult(Builder.TakeString());
Douglas Gregor67c692c2010-08-26 15:07:07 +00006218 }
6219 Results.ExitScope();
6220
6221 HandleCodeCompleteResults(this, CodeCompleter,
6222 CodeCompletionContext::CCC_SelectorName,
6223 Results.data(), Results.size());
6224}
6225
Douglas Gregorbaf69612009-11-18 04:19:12 +00006226/// \brief Add all of the protocol declarations that we find in the given
6227/// (translation unit) context.
6228static void AddProtocolResults(DeclContext *Ctx, DeclContext *CurContext,
Douglas Gregor5b4671c2009-11-18 04:49:41 +00006229 bool OnlyForwardDeclarations,
Douglas Gregorbaf69612009-11-18 04:19:12 +00006230 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00006231 typedef CodeCompletionResult Result;
Douglas Gregorbaf69612009-11-18 04:19:12 +00006232
Aaron Ballman629afae2014-03-07 19:56:05 +00006233 for (const auto *D : Ctx->decls()) {
Douglas Gregorbaf69612009-11-18 04:19:12 +00006234 // Record any protocols we find.
Aaron Ballman629afae2014-03-07 19:56:05 +00006235 if (const auto *Proto = dyn_cast<ObjCProtocolDecl>(D))
Douglas Gregore6e48b12012-01-01 19:29:29 +00006236 if (!OnlyForwardDeclarations || !Proto->hasDefinition())
Craig Topperc3ec1492014-05-26 06:22:03 +00006237 Results.AddResult(Result(Proto, Results.getBasePriority(Proto),nullptr),
6238 CurContext, nullptr, false);
Douglas Gregorbaf69612009-11-18 04:19:12 +00006239 }
6240}
6241
Craig Topper883dd332015-12-24 23:58:11 +00006242void Sema::CodeCompleteObjCProtocolReferences(
6243 ArrayRef<IdentifierLocPair> Protocols) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006244 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006245 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006246 CodeCompletionContext::CCC_ObjCProtocolName);
Douglas Gregorbaf69612009-11-18 04:19:12 +00006247
Chandler Carruthede11632016-11-04 06:06:50 +00006248 if (CodeCompleter->includeGlobals()) {
Douglas Gregora3b23b02010-12-09 21:44:02 +00006249 Results.EnterNewScope();
6250
6251 // Tell the result set to ignore all of the protocols we have
6252 // already seen.
6253 // FIXME: This doesn't work when caching code-completion results.
Craig Topper883dd332015-12-24 23:58:11 +00006254 for (const IdentifierLocPair &Pair : Protocols)
6255 if (ObjCProtocolDecl *Protocol = LookupProtocol(Pair.first,
6256 Pair.second))
Douglas Gregora3b23b02010-12-09 21:44:02 +00006257 Results.Ignore(Protocol);
Douglas Gregorbaf69612009-11-18 04:19:12 +00006258
Douglas Gregora3b23b02010-12-09 21:44:02 +00006259 // Add all protocols.
6260 AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, false,
6261 Results);
Douglas Gregor5b4671c2009-11-18 04:49:41 +00006262
Douglas Gregora3b23b02010-12-09 21:44:02 +00006263 Results.ExitScope();
6264 }
6265
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006266 HandleCodeCompleteResults(this, CodeCompleter,
6267 CodeCompletionContext::CCC_ObjCProtocolName,
6268 Results.data(),Results.size());
Douglas Gregor5b4671c2009-11-18 04:49:41 +00006269}
6270
6271void Sema::CodeCompleteObjCProtocolDecl(Scope *) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006272 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006273 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006274 CodeCompletionContext::CCC_ObjCProtocolName);
Douglas Gregor5b4671c2009-11-18 04:49:41 +00006275
Chandler Carruthede11632016-11-04 06:06:50 +00006276 if (CodeCompleter->includeGlobals()) {
Douglas Gregora3b23b02010-12-09 21:44:02 +00006277 Results.EnterNewScope();
6278
6279 // Add all protocols.
6280 AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, true,
6281 Results);
Douglas Gregorbaf69612009-11-18 04:19:12 +00006282
Douglas Gregora3b23b02010-12-09 21:44:02 +00006283 Results.ExitScope();
6284 }
6285
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006286 HandleCodeCompleteResults(this, CodeCompleter,
6287 CodeCompletionContext::CCC_ObjCProtocolName,
6288 Results.data(),Results.size());
Douglas Gregorbaf69612009-11-18 04:19:12 +00006289}
Douglas Gregor49c22a72009-11-18 16:26:39 +00006290
6291/// \brief Add all of the Objective-C interface declarations that we find in
6292/// the given (translation unit) context.
6293static void AddInterfaceResults(DeclContext *Ctx, DeclContext *CurContext,
6294 bool OnlyForwardDeclarations,
6295 bool OnlyUnimplemented,
6296 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00006297 typedef CodeCompletionResult Result;
Douglas Gregor49c22a72009-11-18 16:26:39 +00006298
Aaron Ballman629afae2014-03-07 19:56:05 +00006299 for (const auto *D : Ctx->decls()) {
Douglas Gregor1c283312010-08-11 12:19:30 +00006300 // Record any interfaces we find.
Aaron Ballman629afae2014-03-07 19:56:05 +00006301 if (const auto *Class = dyn_cast<ObjCInterfaceDecl>(D))
Douglas Gregordc9166c2011-12-15 20:29:51 +00006302 if ((!OnlyForwardDeclarations || !Class->hasDefinition()) &&
Douglas Gregor1c283312010-08-11 12:19:30 +00006303 (!OnlyUnimplemented || !Class->getImplementation()))
Craig Topperc3ec1492014-05-26 06:22:03 +00006304 Results.AddResult(Result(Class, Results.getBasePriority(Class),nullptr),
6305 CurContext, nullptr, false);
Douglas Gregor49c22a72009-11-18 16:26:39 +00006306 }
6307}
6308
6309void Sema::CodeCompleteObjCInterfaceDecl(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006310 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006311 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006312 CodeCompletionContext::CCC_Other);
Douglas Gregor49c22a72009-11-18 16:26:39 +00006313 Results.EnterNewScope();
6314
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006315 if (CodeCompleter->includeGlobals()) {
6316 // Add all classes.
6317 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
6318 false, Results);
6319 }
6320
Douglas Gregor49c22a72009-11-18 16:26:39 +00006321 Results.ExitScope();
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006322
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006323 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006324 CodeCompletionContext::CCC_ObjCInterfaceName,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006325 Results.data(),Results.size());
Douglas Gregor49c22a72009-11-18 16:26:39 +00006326}
6327
Douglas Gregorb2ccf012010-04-15 22:33:43 +00006328void Sema::CodeCompleteObjCSuperclass(Scope *S, IdentifierInfo *ClassName,
6329 SourceLocation ClassNameLoc) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006330 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006331 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006332 CodeCompletionContext::CCC_ObjCInterfaceName);
Douglas Gregor49c22a72009-11-18 16:26:39 +00006333 Results.EnterNewScope();
6334
6335 // Make sure that we ignore the class we're currently defining.
6336 NamedDecl *CurClass
Douglas Gregorb2ccf012010-04-15 22:33:43 +00006337 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006338 if (CurClass && isa<ObjCInterfaceDecl>(CurClass))
Douglas Gregor49c22a72009-11-18 16:26:39 +00006339 Results.Ignore(CurClass);
6340
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006341 if (CodeCompleter->includeGlobals()) {
6342 // Add all classes.
6343 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
6344 false, Results);
6345 }
6346
Douglas Gregor49c22a72009-11-18 16:26:39 +00006347 Results.ExitScope();
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006348
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006349 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006350 CodeCompletionContext::CCC_ObjCInterfaceName,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006351 Results.data(),Results.size());
Douglas Gregor49c22a72009-11-18 16:26:39 +00006352}
6353
6354void Sema::CodeCompleteObjCImplementationDecl(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006355 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006356 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006357 CodeCompletionContext::CCC_Other);
Douglas Gregor49c22a72009-11-18 16:26:39 +00006358 Results.EnterNewScope();
6359
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006360 if (CodeCompleter->includeGlobals()) {
6361 // Add all unimplemented classes.
6362 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
6363 true, Results);
6364 }
6365
Douglas Gregor49c22a72009-11-18 16:26:39 +00006366 Results.ExitScope();
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006367
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006368 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006369 CodeCompletionContext::CCC_ObjCInterfaceName,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006370 Results.data(),Results.size());
Douglas Gregor49c22a72009-11-18 16:26:39 +00006371}
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006372
6373void Sema::CodeCompleteObjCInterfaceCategory(Scope *S,
Douglas Gregorb2ccf012010-04-15 22:33:43 +00006374 IdentifierInfo *ClassName,
6375 SourceLocation ClassNameLoc) {
John McCall276321a2010-08-25 06:19:51 +00006376 typedef CodeCompletionResult Result;
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006377
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006378 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006379 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor21325842011-07-07 16:03:39 +00006380 CodeCompletionContext::CCC_ObjCCategoryName);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006381
6382 // Ignore any categories we find that have already been implemented by this
6383 // interface.
6384 llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
6385 NamedDecl *CurClass
Douglas Gregorb2ccf012010-04-15 22:33:43 +00006386 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006387 if (ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass)){
Aaron Ballman3fe486a2014-03-13 21:23:55 +00006388 for (const auto *Cat : Class->visible_categories())
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006389 CategoryNames.insert(Cat->getIdentifier());
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006390 }
6391
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006392 // Add all of the categories we know about.
6393 Results.EnterNewScope();
6394 TranslationUnitDecl *TU = Context.getTranslationUnitDecl();
Aaron Ballman629afae2014-03-07 19:56:05 +00006395 for (const auto *D : TU->decls())
6396 if (const auto *Category = dyn_cast<ObjCCategoryDecl>(D))
David Blaikie82e95a32014-11-19 07:49:47 +00006397 if (CategoryNames.insert(Category->getIdentifier()).second)
Craig Topperc3ec1492014-05-26 06:22:03 +00006398 Results.AddResult(Result(Category, Results.getBasePriority(Category),
6399 nullptr),
6400 CurContext, nullptr, false);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006401 Results.ExitScope();
6402
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006403 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor21325842011-07-07 16:03:39 +00006404 CodeCompletionContext::CCC_ObjCCategoryName,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006405 Results.data(),Results.size());
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006406}
6407
6408void Sema::CodeCompleteObjCImplementationCategory(Scope *S,
Douglas Gregorb2ccf012010-04-15 22:33:43 +00006409 IdentifierInfo *ClassName,
6410 SourceLocation ClassNameLoc) {
John McCall276321a2010-08-25 06:19:51 +00006411 typedef CodeCompletionResult Result;
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006412
6413 // Find the corresponding interface. If we couldn't find the interface, the
6414 // program itself is ill-formed. However, we'll try to be helpful still by
6415 // providing the list of all of the categories we know about.
6416 NamedDecl *CurClass
Douglas Gregorb2ccf012010-04-15 22:33:43 +00006417 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006418 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass);
6419 if (!Class)
Douglas Gregorb2ccf012010-04-15 22:33:43 +00006420 return CodeCompleteObjCInterfaceCategory(S, ClassName, ClassNameLoc);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006421
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006422 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006423 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor21325842011-07-07 16:03:39 +00006424 CodeCompletionContext::CCC_ObjCCategoryName);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006425
6426 // Add all of the categories that have have corresponding interface
6427 // declarations in this class and any of its superclasses, except for
6428 // already-implemented categories in the class itself.
6429 llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
6430 Results.EnterNewScope();
6431 bool IgnoreImplemented = true;
6432 while (Class) {
Aaron Ballman3fe486a2014-03-13 21:23:55 +00006433 for (const auto *Cat : Class->visible_categories()) {
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006434 if ((!IgnoreImplemented || !Cat->getImplementation()) &&
David Blaikie82e95a32014-11-19 07:49:47 +00006435 CategoryNames.insert(Cat->getIdentifier()).second)
Craig Topperc3ec1492014-05-26 06:22:03 +00006436 Results.AddResult(Result(Cat, Results.getBasePriority(Cat), nullptr),
6437 CurContext, nullptr, false);
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006438 }
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006439
6440 Class = Class->getSuperClass();
6441 IgnoreImplemented = false;
6442 }
6443 Results.ExitScope();
6444
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006445 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor21325842011-07-07 16:03:39 +00006446 CodeCompletionContext::CCC_ObjCCategoryName,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006447 Results.data(),Results.size());
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006448}
Douglas Gregor5d649882009-11-18 22:32:06 +00006449
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00006450void Sema::CodeCompleteObjCPropertyDefinition(Scope *S) {
Douglas Gregorc3425b12015-07-07 06:20:19 +00006451 CodeCompletionContext CCContext(CodeCompletionContext::CCC_Other);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006452 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006453 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorc3425b12015-07-07 06:20:19 +00006454 CCContext);
Douglas Gregor5d649882009-11-18 22:32:06 +00006455
6456 // Figure out where this @synthesize lives.
6457 ObjCContainerDecl *Container
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00006458 = dyn_cast_or_null<ObjCContainerDecl>(CurContext);
Douglas Gregor5d649882009-11-18 22:32:06 +00006459 if (!Container ||
6460 (!isa<ObjCImplementationDecl>(Container) &&
6461 !isa<ObjCCategoryImplDecl>(Container)))
6462 return;
6463
6464 // Ignore any properties that have already been implemented.
Douglas Gregor9b4f3702012-06-12 13:44:08 +00006465 Container = getContainerDef(Container);
Aaron Ballman629afae2014-03-07 19:56:05 +00006466 for (const auto *D : Container->decls())
6467 if (const auto *PropertyImpl = dyn_cast<ObjCPropertyImplDecl>(D))
Douglas Gregor5d649882009-11-18 22:32:06 +00006468 Results.Ignore(PropertyImpl->getPropertyDecl());
6469
6470 // Add any properties that we find.
Douglas Gregorb888acf2010-12-09 23:01:55 +00006471 AddedPropertiesSet AddedProperties;
Douglas Gregor5d649882009-11-18 22:32:06 +00006472 Results.EnterNewScope();
6473 if (ObjCImplementationDecl *ClassImpl
6474 = dyn_cast<ObjCImplementationDecl>(Container))
Douglas Gregorc3425b12015-07-07 06:20:19 +00006475 AddObjCProperties(CCContext, ClassImpl->getClassInterface(), false,
Douglas Gregor95147142011-05-05 15:50:42 +00006476 /*AllowNullaryMethods=*/false, CurContext,
Douglas Gregorb888acf2010-12-09 23:01:55 +00006477 AddedProperties, Results);
Douglas Gregor5d649882009-11-18 22:32:06 +00006478 else
Douglas Gregorc3425b12015-07-07 06:20:19 +00006479 AddObjCProperties(CCContext,
6480 cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl(),
Douglas Gregor95147142011-05-05 15:50:42 +00006481 false, /*AllowNullaryMethods=*/false, CurContext,
6482 AddedProperties, Results);
Douglas Gregor5d649882009-11-18 22:32:06 +00006483 Results.ExitScope();
6484
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006485 HandleCodeCompleteResults(this, CodeCompleter,
6486 CodeCompletionContext::CCC_Other,
6487 Results.data(),Results.size());
Douglas Gregor5d649882009-11-18 22:32:06 +00006488}
6489
6490void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S,
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00006491 IdentifierInfo *PropertyName) {
John McCall276321a2010-08-25 06:19:51 +00006492 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006493 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006494 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006495 CodeCompletionContext::CCC_Other);
Douglas Gregor5d649882009-11-18 22:32:06 +00006496
6497 // Figure out where this @synthesize lives.
6498 ObjCContainerDecl *Container
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00006499 = dyn_cast_or_null<ObjCContainerDecl>(CurContext);
Douglas Gregor5d649882009-11-18 22:32:06 +00006500 if (!Container ||
6501 (!isa<ObjCImplementationDecl>(Container) &&
6502 !isa<ObjCCategoryImplDecl>(Container)))
6503 return;
6504
6505 // Figure out which interface we're looking into.
Craig Topperc3ec1492014-05-26 06:22:03 +00006506 ObjCInterfaceDecl *Class = nullptr;
Douglas Gregor5d649882009-11-18 22:32:06 +00006507 if (ObjCImplementationDecl *ClassImpl
Manman Ren5b786402016-01-28 18:49:28 +00006508 = dyn_cast<ObjCImplementationDecl>(Container))
Douglas Gregor5d649882009-11-18 22:32:06 +00006509 Class = ClassImpl->getClassInterface();
6510 else
6511 Class = cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl()
6512 ->getClassInterface();
6513
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006514 // Determine the type of the property we're synthesizing.
6515 QualType PropertyType = Context.getObjCIdType();
6516 if (Class) {
Manman Ren5b786402016-01-28 18:49:28 +00006517 if (ObjCPropertyDecl *Property = Class->FindPropertyDeclaration(
6518 PropertyName, ObjCPropertyQueryKind::OBJC_PR_query_instance)) {
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006519 PropertyType
6520 = Property->getType().getNonReferenceType().getUnqualifiedType();
6521
6522 // Give preference to ivars
6523 Results.setPreferredType(PropertyType);
6524 }
6525 }
6526
Douglas Gregor5d649882009-11-18 22:32:06 +00006527 // Add all of the instance variables in this class and its superclasses.
6528 Results.EnterNewScope();
Douglas Gregor331faa02011-04-18 14:13:53 +00006529 bool SawSimilarlyNamedIvar = false;
6530 std::string NameWithPrefix;
6531 NameWithPrefix += '_';
Benjamin Kramer632500c2011-07-26 16:59:25 +00006532 NameWithPrefix += PropertyName->getName();
Douglas Gregor331faa02011-04-18 14:13:53 +00006533 std::string NameWithSuffix = PropertyName->getName().str();
6534 NameWithSuffix += '_';
Douglas Gregor5d649882009-11-18 22:32:06 +00006535 for(; Class; Class = Class->getSuperClass()) {
Douglas Gregor331faa02011-04-18 14:13:53 +00006536 for (ObjCIvarDecl *Ivar = Class->all_declared_ivar_begin(); Ivar;
6537 Ivar = Ivar->getNextIvar()) {
Craig Topperc3ec1492014-05-26 06:22:03 +00006538 Results.AddResult(Result(Ivar, Results.getBasePriority(Ivar), nullptr),
6539 CurContext, nullptr, false);
6540
Douglas Gregor331faa02011-04-18 14:13:53 +00006541 // Determine whether we've seen an ivar with a name similar to the
6542 // property.
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006543 if ((PropertyName == Ivar->getIdentifier() ||
Douglas Gregor331faa02011-04-18 14:13:53 +00006544 NameWithPrefix == Ivar->getName() ||
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006545 NameWithSuffix == Ivar->getName())) {
Douglas Gregor331faa02011-04-18 14:13:53 +00006546 SawSimilarlyNamedIvar = true;
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006547
6548 // Reduce the priority of this result by one, to give it a slight
6549 // advantage over other results whose names don't match so closely.
6550 if (Results.size() &&
6551 Results.data()[Results.size() - 1].Kind
6552 == CodeCompletionResult::RK_Declaration &&
6553 Results.data()[Results.size() - 1].Declaration == Ivar)
6554 Results.data()[Results.size() - 1].Priority--;
6555 }
Douglas Gregor331faa02011-04-18 14:13:53 +00006556 }
Douglas Gregor5d649882009-11-18 22:32:06 +00006557 }
Douglas Gregor331faa02011-04-18 14:13:53 +00006558
6559 if (!SawSimilarlyNamedIvar) {
6560 // Create ivar result _propName, that the user can use to synthesize
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006561 // an ivar of the appropriate type.
6562 unsigned Priority = CCP_MemberDeclaration + 1;
Douglas Gregor331faa02011-04-18 14:13:53 +00006563 typedef CodeCompletionResult Result;
6564 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006565 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo(),
6566 Priority,CXAvailability_Available);
Douglas Gregor331faa02011-04-18 14:13:53 +00006567
Douglas Gregor75acd922011-09-27 23:30:47 +00006568 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006569 Builder.AddResultTypeChunk(GetCompletionTypeString(PropertyType, Context,
Douglas Gregor75acd922011-09-27 23:30:47 +00006570 Policy, Allocator));
Douglas Gregor331faa02011-04-18 14:13:53 +00006571 Builder.AddTypedTextChunk(Allocator.CopyString(NameWithPrefix));
6572 Results.AddResult(Result(Builder.TakeString(), Priority,
6573 CXCursor_ObjCIvarDecl));
6574 }
6575
Douglas Gregor5d649882009-11-18 22:32:06 +00006576 Results.ExitScope();
6577
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006578 HandleCodeCompleteResults(this, CodeCompleter,
6579 CodeCompletionContext::CCC_Other,
6580 Results.data(),Results.size());
Douglas Gregor5d649882009-11-18 22:32:06 +00006581}
Douglas Gregor636a61e2010-04-07 00:21:17 +00006582
Douglas Gregor416b5752010-08-25 01:08:01 +00006583// Mapping from selectors to the methods that implement that selector, along
6584// with the "in original class" flag.
Benjamin Kramereb8c4462013-06-29 17:52:13 +00006585typedef llvm::DenseMap<
6586 Selector, llvm::PointerIntPair<ObjCMethodDecl *, 1, bool> > KnownMethodsMap;
Douglas Gregor636a61e2010-04-07 00:21:17 +00006587
6588/// \brief Find all of the methods that reside in the given container
6589/// (and its superclasses, protocols, etc.) that meet the given
6590/// criteria. Insert those methods into the map of known methods,
6591/// indexed by selector so they can be easily found.
6592static void FindImplementableMethods(ASTContext &Context,
6593 ObjCContainerDecl *Container,
6594 bool WantInstanceMethods,
6595 QualType ReturnType,
Douglas Gregor416b5752010-08-25 01:08:01 +00006596 KnownMethodsMap &KnownMethods,
6597 bool InOriginalClass = true) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00006598 if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)) {
Douglas Gregor9b4f3702012-06-12 13:44:08 +00006599 // Make sure we have a definition; that's what we'll walk.
Douglas Gregorc0ac7d62011-12-15 05:27:12 +00006600 if (!IFace->hasDefinition())
6601 return;
Douglas Gregor9b4f3702012-06-12 13:44:08 +00006602
6603 IFace = IFace->getDefinition();
6604 Container = IFace;
Douglas Gregorc0ac7d62011-12-15 05:27:12 +00006605
Douglas Gregor636a61e2010-04-07 00:21:17 +00006606 const ObjCList<ObjCProtocolDecl> &Protocols
6607 = IFace->getReferencedProtocols();
6608 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006609 E = Protocols.end();
Douglas Gregor636a61e2010-04-07 00:21:17 +00006610 I != E; ++I)
6611 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006612 KnownMethods, InOriginalClass);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006613
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006614 // Add methods from any class extensions and categories.
Aaron Ballman3fe486a2014-03-13 21:23:55 +00006615 for (auto *Cat : IFace->visible_categories()) {
6616 FindImplementableMethods(Context, Cat, WantInstanceMethods, ReturnType,
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006617 KnownMethods, false);
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006618 }
6619
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006620 // Visit the superclass.
6621 if (IFace->getSuperClass())
6622 FindImplementableMethods(Context, IFace->getSuperClass(),
6623 WantInstanceMethods, ReturnType,
6624 KnownMethods, false);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006625 }
6626
6627 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(Container)) {
6628 // Recurse into protocols.
6629 const ObjCList<ObjCProtocolDecl> &Protocols
6630 = Category->getReferencedProtocols();
6631 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006632 E = Protocols.end();
Douglas Gregor636a61e2010-04-07 00:21:17 +00006633 I != E; ++I)
6634 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006635 KnownMethods, InOriginalClass);
6636
6637 // If this category is the original class, jump to the interface.
6638 if (InOriginalClass && Category->getClassInterface())
6639 FindImplementableMethods(Context, Category->getClassInterface(),
6640 WantInstanceMethods, ReturnType, KnownMethods,
6641 false);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006642 }
6643
6644 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Douglas Gregor9b4f3702012-06-12 13:44:08 +00006645 // Make sure we have a definition; that's what we'll walk.
6646 if (!Protocol->hasDefinition())
6647 return;
6648 Protocol = Protocol->getDefinition();
6649 Container = Protocol;
6650
6651 // Recurse into protocols.
6652 const ObjCList<ObjCProtocolDecl> &Protocols
6653 = Protocol->getReferencedProtocols();
6654 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
6655 E = Protocols.end();
6656 I != E; ++I)
6657 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
6658 KnownMethods, false);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006659 }
6660
6661 // Add methods in this container. This operation occurs last because
6662 // we want the methods from this container to override any methods
6663 // we've previously seen with the same selector.
Aaron Ballmanaff18c02014-03-13 19:03:34 +00006664 for (auto *M : Container->methods()) {
David Blaikie2d7c57e2012-04-30 02:36:29 +00006665 if (M->isInstanceMethod() == WantInstanceMethods) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00006666 if (!ReturnType.isNull() &&
Alp Toker314cc812014-01-25 16:55:45 +00006667 !Context.hasSameUnqualifiedType(ReturnType, M->getReturnType()))
Douglas Gregor636a61e2010-04-07 00:21:17 +00006668 continue;
6669
Benjamin Kramereb8c4462013-06-29 17:52:13 +00006670 KnownMethods[M->getSelector()] =
Aaron Ballmanaff18c02014-03-13 19:03:34 +00006671 KnownMethodsMap::mapped_type(M, InOriginalClass);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006672 }
6673 }
6674}
6675
Douglas Gregor669a25a2011-02-17 00:22:45 +00006676/// \brief Add the parenthesized return or parameter type chunk to a code
6677/// completion string.
6678static void AddObjCPassingTypeChunk(QualType Type,
Douglas Gregor29979142012-04-10 18:35:07 +00006679 unsigned ObjCDeclQuals,
Douglas Gregor669a25a2011-02-17 00:22:45 +00006680 ASTContext &Context,
Douglas Gregor75acd922011-09-27 23:30:47 +00006681 const PrintingPolicy &Policy,
Douglas Gregor669a25a2011-02-17 00:22:45 +00006682 CodeCompletionBuilder &Builder) {
6683 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregor86b42682015-06-19 18:27:52 +00006684 std::string Quals = formatObjCParamQualifiers(ObjCDeclQuals, Type);
Douglas Gregor29979142012-04-10 18:35:07 +00006685 if (!Quals.empty())
6686 Builder.AddTextChunk(Builder.getAllocator().CopyString(Quals));
Douglas Gregor75acd922011-09-27 23:30:47 +00006687 Builder.AddTextChunk(GetCompletionTypeString(Type, Context, Policy,
Douglas Gregor669a25a2011-02-17 00:22:45 +00006688 Builder.getAllocator()));
6689 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6690}
6691
6692/// \brief Determine whether the given class is or inherits from a class by
6693/// the given name.
6694static bool InheritsFromClassNamed(ObjCInterfaceDecl *Class,
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006695 StringRef Name) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006696 if (!Class)
6697 return false;
6698
6699 if (Class->getIdentifier() && Class->getIdentifier()->getName() == Name)
6700 return true;
6701
6702 return InheritsFromClassNamed(Class->getSuperClass(), Name);
6703}
6704
6705/// \brief Add code completions for Objective-C Key-Value Coding (KVC) and
6706/// Key-Value Observing (KVO).
6707static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
6708 bool IsInstanceMethod,
6709 QualType ReturnType,
6710 ASTContext &Context,
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006711 VisitedSelectorSet &KnownSelectors,
Douglas Gregor669a25a2011-02-17 00:22:45 +00006712 ResultBuilder &Results) {
6713 IdentifierInfo *PropName = Property->getIdentifier();
6714 if (!PropName || PropName->getLength() == 0)
6715 return;
6716
Douglas Gregor75acd922011-09-27 23:30:47 +00006717 PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema());
6718
Douglas Gregor669a25a2011-02-17 00:22:45 +00006719 // Builder that will create each code completion.
6720 typedef CodeCompletionResult Result;
6721 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006722 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Douglas Gregor669a25a2011-02-17 00:22:45 +00006723
6724 // The selector table.
6725 SelectorTable &Selectors = Context.Selectors;
6726
6727 // The property name, copied into the code completion allocation region
6728 // on demand.
6729 struct KeyHolder {
6730 CodeCompletionAllocator &Allocator;
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006731 StringRef Key;
Douglas Gregor669a25a2011-02-17 00:22:45 +00006732 const char *CopiedKey;
Craig Topperc3ec1492014-05-26 06:22:03 +00006733
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006734 KeyHolder(CodeCompletionAllocator &Allocator, StringRef Key)
Craig Topperc3ec1492014-05-26 06:22:03 +00006735 : Allocator(Allocator), Key(Key), CopiedKey(nullptr) {}
6736
Douglas Gregor669a25a2011-02-17 00:22:45 +00006737 operator const char *() {
6738 if (CopiedKey)
6739 return CopiedKey;
6740
6741 return CopiedKey = Allocator.CopyString(Key);
6742 }
6743 } Key(Allocator, PropName->getName());
6744
6745 // The uppercased name of the property name.
6746 std::string UpperKey = PropName->getName();
6747 if (!UpperKey.empty())
Jordan Rose4938f272013-02-09 10:09:43 +00006748 UpperKey[0] = toUppercase(UpperKey[0]);
Douglas Gregor669a25a2011-02-17 00:22:45 +00006749
6750 bool ReturnTypeMatchesProperty = ReturnType.isNull() ||
6751 Context.hasSameUnqualifiedType(ReturnType.getNonReferenceType(),
6752 Property->getType());
6753 bool ReturnTypeMatchesVoid
6754 = ReturnType.isNull() || ReturnType->isVoidType();
6755
6756 // Add the normal accessor -(type)key.
6757 if (IsInstanceMethod &&
David Blaikie82e95a32014-11-19 07:49:47 +00006758 KnownSelectors.insert(Selectors.getNullarySelector(PropName)).second &&
Douglas Gregor669a25a2011-02-17 00:22:45 +00006759 ReturnTypeMatchesProperty && !Property->getGetterMethodDecl()) {
6760 if (ReturnType.isNull())
Douglas Gregor29979142012-04-10 18:35:07 +00006761 AddObjCPassingTypeChunk(Property->getType(), /*Quals=*/0,
6762 Context, Policy, Builder);
Douglas Gregor669a25a2011-02-17 00:22:45 +00006763
6764 Builder.AddTypedTextChunk(Key);
6765 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
6766 CXCursor_ObjCInstanceMethodDecl));
6767 }
6768
6769 // If we have an integral or boolean property (or the user has provided
6770 // an integral or boolean return type), add the accessor -(type)isKey.
6771 if (IsInstanceMethod &&
6772 ((!ReturnType.isNull() &&
6773 (ReturnType->isIntegerType() || ReturnType->isBooleanType())) ||
6774 (ReturnType.isNull() &&
6775 (Property->getType()->isIntegerType() ||
6776 Property->getType()->isBooleanType())))) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006777 std::string SelectorName = (Twine("is") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006778 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00006779 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
6780 .second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006781 if (ReturnType.isNull()) {
6782 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6783 Builder.AddTextChunk("BOOL");
6784 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6785 }
6786
6787 Builder.AddTypedTextChunk(
6788 Allocator.CopyString(SelectorId->getName()));
6789 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
6790 CXCursor_ObjCInstanceMethodDecl));
6791 }
6792 }
6793
6794 // Add the normal mutator.
6795 if (IsInstanceMethod && ReturnTypeMatchesVoid &&
6796 !Property->getSetterMethodDecl()) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006797 std::string SelectorName = (Twine("set") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006798 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00006799 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006800 if (ReturnType.isNull()) {
6801 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6802 Builder.AddTextChunk("void");
6803 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6804 }
6805
6806 Builder.AddTypedTextChunk(
6807 Allocator.CopyString(SelectorId->getName()));
6808 Builder.AddTypedTextChunk(":");
Douglas Gregor29979142012-04-10 18:35:07 +00006809 AddObjCPassingTypeChunk(Property->getType(), /*Quals=*/0,
6810 Context, Policy, Builder);
Douglas Gregor669a25a2011-02-17 00:22:45 +00006811 Builder.AddTextChunk(Key);
6812 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
6813 CXCursor_ObjCInstanceMethodDecl));
6814 }
6815 }
6816
6817 // Indexed and unordered accessors
6818 unsigned IndexedGetterPriority = CCP_CodePattern;
6819 unsigned IndexedSetterPriority = CCP_CodePattern;
6820 unsigned UnorderedGetterPriority = CCP_CodePattern;
6821 unsigned UnorderedSetterPriority = CCP_CodePattern;
6822 if (const ObjCObjectPointerType *ObjCPointer
6823 = Property->getType()->getAs<ObjCObjectPointerType>()) {
6824 if (ObjCInterfaceDecl *IFace = ObjCPointer->getInterfaceDecl()) {
6825 // If this interface type is not provably derived from a known
6826 // collection, penalize the corresponding completions.
6827 if (!InheritsFromClassNamed(IFace, "NSMutableArray")) {
6828 IndexedSetterPriority += CCD_ProbablyNotObjCCollection;
6829 if (!InheritsFromClassNamed(IFace, "NSArray"))
6830 IndexedGetterPriority += CCD_ProbablyNotObjCCollection;
6831 }
6832
6833 if (!InheritsFromClassNamed(IFace, "NSMutableSet")) {
6834 UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;
6835 if (!InheritsFromClassNamed(IFace, "NSSet"))
6836 UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;
6837 }
6838 }
6839 } else {
6840 IndexedGetterPriority += CCD_ProbablyNotObjCCollection;
6841 IndexedSetterPriority += CCD_ProbablyNotObjCCollection;
6842 UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;
6843 UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;
6844 }
6845
6846 // Add -(NSUInteger)countOf<key>
6847 if (IsInstanceMethod &&
6848 (ReturnType.isNull() || ReturnType->isIntegerType())) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006849 std::string SelectorName = (Twine("countOf") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006850 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00006851 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
6852 .second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006853 if (ReturnType.isNull()) {
6854 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6855 Builder.AddTextChunk("NSUInteger");
6856 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6857 }
6858
6859 Builder.AddTypedTextChunk(
6860 Allocator.CopyString(SelectorId->getName()));
6861 Results.AddResult(Result(Builder.TakeString(),
6862 std::min(IndexedGetterPriority,
6863 UnorderedGetterPriority),
6864 CXCursor_ObjCInstanceMethodDecl));
6865 }
6866 }
6867
6868 // Indexed getters
6869 // Add -(id)objectInKeyAtIndex:(NSUInteger)index
6870 if (IsInstanceMethod &&
6871 (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006872 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006873 = (Twine("objectIn") + UpperKey + "AtIndex").str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006874 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00006875 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006876 if (ReturnType.isNull()) {
6877 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6878 Builder.AddTextChunk("id");
6879 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6880 }
6881
6882 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6883 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6884 Builder.AddTextChunk("NSUInteger");
6885 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6886 Builder.AddTextChunk("index");
6887 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
6888 CXCursor_ObjCInstanceMethodDecl));
6889 }
6890 }
6891
6892 // Add -(NSArray *)keyAtIndexes:(NSIndexSet *)indexes
6893 if (IsInstanceMethod &&
6894 (ReturnType.isNull() ||
6895 (ReturnType->isObjCObjectPointerType() &&
6896 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
6897 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
6898 ->getName() == "NSArray"))) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006899 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006900 = (Twine(Property->getName()) + "AtIndexes").str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006901 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00006902 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006903 if (ReturnType.isNull()) {
6904 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6905 Builder.AddTextChunk("NSArray *");
6906 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6907 }
6908
6909 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6910 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6911 Builder.AddTextChunk("NSIndexSet *");
6912 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6913 Builder.AddTextChunk("indexes");
6914 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
6915 CXCursor_ObjCInstanceMethodDecl));
6916 }
6917 }
6918
6919 // Add -(void)getKey:(type **)buffer range:(NSRange)inRange
6920 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006921 std::string SelectorName = (Twine("get") + UpperKey).str();
Douglas Gregor669a25a2011-02-17 00:22:45 +00006922 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006923 &Context.Idents.get(SelectorName),
Douglas Gregor669a25a2011-02-17 00:22:45 +00006924 &Context.Idents.get("range")
6925 };
6926
David Blaikie82e95a32014-11-19 07:49:47 +00006927 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006928 if (ReturnType.isNull()) {
6929 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6930 Builder.AddTextChunk("void");
6931 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6932 }
6933
6934 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6935 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6936 Builder.AddPlaceholderChunk("object-type");
6937 Builder.AddTextChunk(" **");
6938 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6939 Builder.AddTextChunk("buffer");
6940 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6941 Builder.AddTypedTextChunk("range:");
6942 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6943 Builder.AddTextChunk("NSRange");
6944 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6945 Builder.AddTextChunk("inRange");
6946 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
6947 CXCursor_ObjCInstanceMethodDecl));
6948 }
6949 }
6950
6951 // Mutable indexed accessors
6952
6953 // - (void)insertObject:(type *)object inKeyAtIndex:(NSUInteger)index
6954 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006955 std::string SelectorName = (Twine("in") + UpperKey + "AtIndex").str();
Douglas Gregor669a25a2011-02-17 00:22:45 +00006956 IdentifierInfo *SelectorIds[2] = {
6957 &Context.Idents.get("insertObject"),
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006958 &Context.Idents.get(SelectorName)
Douglas Gregor669a25a2011-02-17 00:22:45 +00006959 };
6960
David Blaikie82e95a32014-11-19 07:49:47 +00006961 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006962 if (ReturnType.isNull()) {
6963 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6964 Builder.AddTextChunk("void");
6965 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6966 }
6967
6968 Builder.AddTypedTextChunk("insertObject:");
6969 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6970 Builder.AddPlaceholderChunk("object-type");
6971 Builder.AddTextChunk(" *");
6972 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6973 Builder.AddTextChunk("object");
6974 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6975 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6976 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6977 Builder.AddPlaceholderChunk("NSUInteger");
6978 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6979 Builder.AddTextChunk("index");
6980 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6981 CXCursor_ObjCInstanceMethodDecl));
6982 }
6983 }
6984
6985 // - (void)insertKey:(NSArray *)array atIndexes:(NSIndexSet *)indexes
6986 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006987 std::string SelectorName = (Twine("insert") + UpperKey).str();
Douglas Gregor669a25a2011-02-17 00:22:45 +00006988 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006989 &Context.Idents.get(SelectorName),
Douglas Gregor669a25a2011-02-17 00:22:45 +00006990 &Context.Idents.get("atIndexes")
6991 };
6992
David Blaikie82e95a32014-11-19 07:49:47 +00006993 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006994 if (ReturnType.isNull()) {
6995 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6996 Builder.AddTextChunk("void");
6997 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6998 }
6999
7000 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7001 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7002 Builder.AddTextChunk("NSArray *");
7003 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7004 Builder.AddTextChunk("array");
7005 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7006 Builder.AddTypedTextChunk("atIndexes:");
7007 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7008 Builder.AddPlaceholderChunk("NSIndexSet *");
7009 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7010 Builder.AddTextChunk("indexes");
7011 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
7012 CXCursor_ObjCInstanceMethodDecl));
7013 }
7014 }
7015
7016 // -(void)removeObjectFromKeyAtIndex:(NSUInteger)index
7017 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007018 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007019 = (Twine("removeObjectFrom") + UpperKey + "AtIndex").str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007020 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007021 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007022 if (ReturnType.isNull()) {
7023 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7024 Builder.AddTextChunk("void");
7025 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7026 }
7027
7028 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7029 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7030 Builder.AddTextChunk("NSUInteger");
7031 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7032 Builder.AddTextChunk("index");
7033 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
7034 CXCursor_ObjCInstanceMethodDecl));
7035 }
7036 }
7037
7038 // -(void)removeKeyAtIndexes:(NSIndexSet *)indexes
7039 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007040 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007041 = (Twine("remove") + UpperKey + "AtIndexes").str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007042 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007043 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007044 if (ReturnType.isNull()) {
7045 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7046 Builder.AddTextChunk("void");
7047 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7048 }
7049
7050 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7051 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7052 Builder.AddTextChunk("NSIndexSet *");
7053 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7054 Builder.AddTextChunk("indexes");
7055 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
7056 CXCursor_ObjCInstanceMethodDecl));
7057 }
7058 }
7059
7060 // - (void)replaceObjectInKeyAtIndex:(NSUInteger)index withObject:(id)object
7061 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007062 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007063 = (Twine("replaceObjectIn") + UpperKey + "AtIndex").str();
Douglas Gregor669a25a2011-02-17 00:22:45 +00007064 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007065 &Context.Idents.get(SelectorName),
Douglas Gregor669a25a2011-02-17 00:22:45 +00007066 &Context.Idents.get("withObject")
7067 };
7068
David Blaikie82e95a32014-11-19 07:49:47 +00007069 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007070 if (ReturnType.isNull()) {
7071 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7072 Builder.AddTextChunk("void");
7073 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7074 }
7075
7076 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7077 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7078 Builder.AddPlaceholderChunk("NSUInteger");
7079 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7080 Builder.AddTextChunk("index");
7081 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7082 Builder.AddTypedTextChunk("withObject:");
7083 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7084 Builder.AddTextChunk("id");
7085 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7086 Builder.AddTextChunk("object");
7087 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
7088 CXCursor_ObjCInstanceMethodDecl));
7089 }
7090 }
7091
7092 // - (void)replaceKeyAtIndexes:(NSIndexSet *)indexes withKey:(NSArray *)array
7093 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007094 std::string SelectorName1
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007095 = (Twine("replace") + UpperKey + "AtIndexes").str();
7096 std::string SelectorName2 = (Twine("with") + UpperKey).str();
Douglas Gregor669a25a2011-02-17 00:22:45 +00007097 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007098 &Context.Idents.get(SelectorName1),
7099 &Context.Idents.get(SelectorName2)
Douglas Gregor669a25a2011-02-17 00:22:45 +00007100 };
7101
David Blaikie82e95a32014-11-19 07:49:47 +00007102 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007103 if (ReturnType.isNull()) {
7104 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7105 Builder.AddTextChunk("void");
7106 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7107 }
7108
7109 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName1 + ":"));
7110 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7111 Builder.AddPlaceholderChunk("NSIndexSet *");
7112 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7113 Builder.AddTextChunk("indexes");
7114 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7115 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName2 + ":"));
7116 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7117 Builder.AddTextChunk("NSArray *");
7118 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7119 Builder.AddTextChunk("array");
7120 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
7121 CXCursor_ObjCInstanceMethodDecl));
7122 }
7123 }
7124
7125 // Unordered getters
7126 // - (NSEnumerator *)enumeratorOfKey
7127 if (IsInstanceMethod &&
7128 (ReturnType.isNull() ||
7129 (ReturnType->isObjCObjectPointerType() &&
7130 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
7131 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
7132 ->getName() == "NSEnumerator"))) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007133 std::string SelectorName = (Twine("enumeratorOf") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007134 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007135 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
7136 .second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007137 if (ReturnType.isNull()) {
7138 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7139 Builder.AddTextChunk("NSEnumerator *");
7140 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7141 }
7142
7143 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
7144 Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
7145 CXCursor_ObjCInstanceMethodDecl));
7146 }
7147 }
7148
7149 // - (type *)memberOfKey:(type *)object
7150 if (IsInstanceMethod &&
7151 (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007152 std::string SelectorName = (Twine("memberOf") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007153 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007154 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007155 if (ReturnType.isNull()) {
7156 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7157 Builder.AddPlaceholderChunk("object-type");
7158 Builder.AddTextChunk(" *");
7159 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7160 }
7161
7162 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7163 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7164 if (ReturnType.isNull()) {
7165 Builder.AddPlaceholderChunk("object-type");
7166 Builder.AddTextChunk(" *");
7167 } else {
7168 Builder.AddTextChunk(GetCompletionTypeString(ReturnType, Context,
Douglas Gregor75acd922011-09-27 23:30:47 +00007169 Policy,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007170 Builder.getAllocator()));
7171 }
7172 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7173 Builder.AddTextChunk("object");
7174 Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
7175 CXCursor_ObjCInstanceMethodDecl));
7176 }
7177 }
7178
7179 // Mutable unordered accessors
7180 // - (void)addKeyObject:(type *)object
7181 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007182 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007183 = (Twine("add") + UpperKey + Twine("Object")).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007184 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007185 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007186 if (ReturnType.isNull()) {
7187 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7188 Builder.AddTextChunk("void");
7189 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7190 }
7191
7192 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7193 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7194 Builder.AddPlaceholderChunk("object-type");
7195 Builder.AddTextChunk(" *");
7196 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7197 Builder.AddTextChunk("object");
7198 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
7199 CXCursor_ObjCInstanceMethodDecl));
7200 }
7201 }
7202
7203 // - (void)addKey:(NSSet *)objects
7204 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007205 std::string SelectorName = (Twine("add") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007206 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007207 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007208 if (ReturnType.isNull()) {
7209 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7210 Builder.AddTextChunk("void");
7211 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7212 }
7213
7214 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7215 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7216 Builder.AddTextChunk("NSSet *");
7217 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7218 Builder.AddTextChunk("objects");
7219 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
7220 CXCursor_ObjCInstanceMethodDecl));
7221 }
7222 }
7223
7224 // - (void)removeKeyObject:(type *)object
7225 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007226 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007227 = (Twine("remove") + UpperKey + Twine("Object")).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007228 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007229 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007230 if (ReturnType.isNull()) {
7231 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7232 Builder.AddTextChunk("void");
7233 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7234 }
7235
7236 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7237 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7238 Builder.AddPlaceholderChunk("object-type");
7239 Builder.AddTextChunk(" *");
7240 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7241 Builder.AddTextChunk("object");
7242 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
7243 CXCursor_ObjCInstanceMethodDecl));
7244 }
7245 }
7246
7247 // - (void)removeKey:(NSSet *)objects
7248 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007249 std::string SelectorName = (Twine("remove") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007250 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007251 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007252 if (ReturnType.isNull()) {
7253 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7254 Builder.AddTextChunk("void");
7255 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7256 }
7257
7258 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7259 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7260 Builder.AddTextChunk("NSSet *");
7261 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7262 Builder.AddTextChunk("objects");
7263 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
7264 CXCursor_ObjCInstanceMethodDecl));
7265 }
7266 }
7267
7268 // - (void)intersectKey:(NSSet *)objects
7269 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007270 std::string SelectorName = (Twine("intersect") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007271 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007272 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007273 if (ReturnType.isNull()) {
7274 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7275 Builder.AddTextChunk("void");
7276 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7277 }
7278
7279 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7280 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7281 Builder.AddTextChunk("NSSet *");
7282 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7283 Builder.AddTextChunk("objects");
7284 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
7285 CXCursor_ObjCInstanceMethodDecl));
7286 }
7287 }
7288
7289 // Key-Value Observing
7290 // + (NSSet *)keyPathsForValuesAffectingKey
7291 if (!IsInstanceMethod &&
7292 (ReturnType.isNull() ||
7293 (ReturnType->isObjCObjectPointerType() &&
7294 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
7295 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
7296 ->getName() == "NSSet"))) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007297 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007298 = (Twine("keyPathsForValuesAffecting") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007299 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007300 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
7301 .second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007302 if (ReturnType.isNull()) {
7303 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Alex Lorenz71ecb072016-12-08 16:49:05 +00007304 Builder.AddTextChunk("NSSet<NSString *> *");
Douglas Gregor669a25a2011-02-17 00:22:45 +00007305 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7306 }
7307
7308 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
7309 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Douglas Gregor857bcda2011-06-02 04:02:27 +00007310 CXCursor_ObjCClassMethodDecl));
7311 }
7312 }
7313
7314 // + (BOOL)automaticallyNotifiesObserversForKey
7315 if (!IsInstanceMethod &&
7316 (ReturnType.isNull() ||
7317 ReturnType->isIntegerType() ||
7318 ReturnType->isBooleanType())) {
7319 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007320 = (Twine("automaticallyNotifiesObserversOf") + UpperKey).str();
Douglas Gregor857bcda2011-06-02 04:02:27 +00007321 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007322 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
7323 .second) {
Douglas Gregor857bcda2011-06-02 04:02:27 +00007324 if (ReturnType.isNull()) {
7325 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7326 Builder.AddTextChunk("BOOL");
7327 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7328 }
7329
7330 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
7331 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
7332 CXCursor_ObjCClassMethodDecl));
Douglas Gregor669a25a2011-02-17 00:22:45 +00007333 }
7334 }
7335}
7336
Douglas Gregor636a61e2010-04-07 00:21:17 +00007337void Sema::CodeCompleteObjCMethodDecl(Scope *S,
7338 bool IsInstanceMethod,
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00007339 ParsedType ReturnTy) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00007340 // Determine the return type of the method we're declaring, if
7341 // provided.
7342 QualType ReturnType = GetTypeFromParser(ReturnTy);
Craig Topperc3ec1492014-05-26 06:22:03 +00007343 Decl *IDecl = nullptr;
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00007344 if (CurContext->isObjCContainer()) {
7345 ObjCContainerDecl *OCD = dyn_cast<ObjCContainerDecl>(CurContext);
7346 IDecl = cast<Decl>(OCD);
7347 }
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007348 // Determine where we should start searching for methods.
Craig Topperc3ec1492014-05-26 06:22:03 +00007349 ObjCContainerDecl *SearchDecl = nullptr;
Douglas Gregor636a61e2010-04-07 00:21:17 +00007350 bool IsInImplementation = false;
John McCall48871652010-08-21 09:40:31 +00007351 if (Decl *D = IDecl) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00007352 if (ObjCImplementationDecl *Impl = dyn_cast<ObjCImplementationDecl>(D)) {
7353 SearchDecl = Impl->getClassInterface();
Douglas Gregor636a61e2010-04-07 00:21:17 +00007354 IsInImplementation = true;
7355 } else if (ObjCCategoryImplDecl *CatImpl
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007356 = dyn_cast<ObjCCategoryImplDecl>(D)) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00007357 SearchDecl = CatImpl->getCategoryDecl();
Douglas Gregor636a61e2010-04-07 00:21:17 +00007358 IsInImplementation = true;
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007359 } else
Douglas Gregor636a61e2010-04-07 00:21:17 +00007360 SearchDecl = dyn_cast<ObjCContainerDecl>(D);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007361 }
7362
7363 if (!SearchDecl && S) {
Ted Kremenekc37877d2013-10-08 17:08:03 +00007364 if (DeclContext *DC = S->getEntity())
Douglas Gregor636a61e2010-04-07 00:21:17 +00007365 SearchDecl = dyn_cast<ObjCContainerDecl>(DC);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007366 }
7367
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007368 if (!SearchDecl) {
Douglas Gregor00c37ef2010-08-11 21:23:17 +00007369 HandleCodeCompleteResults(this, CodeCompleter,
7370 CodeCompletionContext::CCC_Other,
Craig Topperc3ec1492014-05-26 06:22:03 +00007371 nullptr, 0);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007372 return;
7373 }
7374
7375 // Find all of the methods that we could declare/implement here.
7376 KnownMethodsMap KnownMethods;
7377 FindImplementableMethods(Context, SearchDecl, IsInstanceMethod,
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007378 ReturnType, KnownMethods);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007379
Douglas Gregor636a61e2010-04-07 00:21:17 +00007380 // Add declarations or definitions for each of the known methods.
John McCall276321a2010-08-25 06:19:51 +00007381 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007382 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007383 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007384 CodeCompletionContext::CCC_Other);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007385 Results.EnterNewScope();
Douglas Gregor75acd922011-09-27 23:30:47 +00007386 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007387 for (KnownMethodsMap::iterator M = KnownMethods.begin(),
7388 MEnd = KnownMethods.end();
7389 M != MEnd; ++M) {
Benjamin Kramereb8c4462013-06-29 17:52:13 +00007390 ObjCMethodDecl *Method = M->second.getPointer();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007391 CodeCompletionBuilder Builder(Results.getAllocator(),
7392 Results.getCodeCompletionTUInfo());
Douglas Gregor636a61e2010-04-07 00:21:17 +00007393
7394 // If the result type was not already provided, add it to the
7395 // pattern as (type).
Argyrios Kyrtzidisf0917ab2015-07-24 17:00:19 +00007396 if (ReturnType.isNull()) {
7397 QualType ResTy = Method->getSendResultType().stripObjCKindOfType(Context);
7398 AttributedType::stripOuterNullability(ResTy);
7399 AddObjCPassingTypeChunk(ResTy,
Alp Toker314cc812014-01-25 16:55:45 +00007400 Method->getObjCDeclQualifier(), Context, Policy,
7401 Builder);
Argyrios Kyrtzidisf0917ab2015-07-24 17:00:19 +00007402 }
Douglas Gregor636a61e2010-04-07 00:21:17 +00007403
7404 Selector Sel = Method->getSelector();
7405
7406 // Add the first part of the selector to the pattern.
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00007407 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00007408 Sel.getNameForSlot(0)));
Douglas Gregor636a61e2010-04-07 00:21:17 +00007409
7410 // Add parameters to the pattern.
7411 unsigned I = 0;
7412 for (ObjCMethodDecl::param_iterator P = Method->param_begin(),
7413 PEnd = Method->param_end();
7414 P != PEnd; (void)++P, ++I) {
7415 // Add the part of the selector name.
7416 if (I == 0)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007417 Builder.AddTypedTextChunk(":");
Douglas Gregor636a61e2010-04-07 00:21:17 +00007418 else if (I < Sel.getNumArgs()) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007419 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7420 Builder.AddTypedTextChunk(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00007421 Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":"));
Douglas Gregor636a61e2010-04-07 00:21:17 +00007422 } else
7423 break;
7424
7425 // Add the parameter type.
Douglas Gregor86b42682015-06-19 18:27:52 +00007426 QualType ParamType;
7427 if ((*P)->getObjCDeclQualifier() & Decl::OBJC_TQ_CSNullability)
7428 ParamType = (*P)->getType();
7429 else
7430 ParamType = (*P)->getOriginalType();
Douglas Gregor9b7b3e92015-07-07 06:20:27 +00007431 ParamType = ParamType.substObjCTypeArgs(Context, {},
7432 ObjCSubstitutionContext::Parameter);
Argyrios Kyrtzidisf0917ab2015-07-24 17:00:19 +00007433 AttributedType::stripOuterNullability(ParamType);
Douglas Gregor86b42682015-06-19 18:27:52 +00007434 AddObjCPassingTypeChunk(ParamType,
Douglas Gregor29979142012-04-10 18:35:07 +00007435 (*P)->getObjCDeclQualifier(),
7436 Context, Policy,
Douglas Gregor75acd922011-09-27 23:30:47 +00007437 Builder);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007438
7439 if (IdentifierInfo *Id = (*P)->getIdentifier())
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00007440 Builder.AddTextChunk(Builder.getAllocator().CopyString( Id->getName()));
Douglas Gregor636a61e2010-04-07 00:21:17 +00007441 }
7442
7443 if (Method->isVariadic()) {
7444 if (Method->param_size() > 0)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007445 Builder.AddChunk(CodeCompletionString::CK_Comma);
7446 Builder.AddTextChunk("...");
Douglas Gregor400f5972010-08-31 05:13:43 +00007447 }
Douglas Gregor636a61e2010-04-07 00:21:17 +00007448
Douglas Gregord37c59d2010-05-28 00:57:46 +00007449 if (IsInImplementation && Results.includeCodePatterns()) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00007450 // We will be defining the method here, so add a compound statement.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007451 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7452 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
7453 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
Alp Toker314cc812014-01-25 16:55:45 +00007454 if (!Method->getReturnType()->isVoidType()) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00007455 // If the result type is not void, add a return clause.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007456 Builder.AddTextChunk("return");
7457 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7458 Builder.AddPlaceholderChunk("expression");
7459 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007460 } else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007461 Builder.AddPlaceholderChunk("statements");
Douglas Gregor636a61e2010-04-07 00:21:17 +00007462
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007463 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
7464 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007465 }
7466
Douglas Gregor416b5752010-08-25 01:08:01 +00007467 unsigned Priority = CCP_CodePattern;
Benjamin Kramereb8c4462013-06-29 17:52:13 +00007468 if (!M->second.getInt())
Douglas Gregor416b5752010-08-25 01:08:01 +00007469 Priority += CCD_InBaseClass;
7470
Douglas Gregor78254c82012-03-27 23:34:16 +00007471 Results.AddResult(Result(Builder.TakeString(), Method, Priority));
Douglas Gregor636a61e2010-04-07 00:21:17 +00007472 }
7473
Douglas Gregor669a25a2011-02-17 00:22:45 +00007474 // Add Key-Value-Coding and Key-Value-Observing accessor methods for all of
7475 // the properties in this class and its categories.
David Blaikiebbafb8a2012-03-11 07:00:24 +00007476 if (Context.getLangOpts().ObjC2) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007477 SmallVector<ObjCContainerDecl *, 4> Containers;
Douglas Gregor669a25a2011-02-17 00:22:45 +00007478 Containers.push_back(SearchDecl);
7479
Douglas Gregord4a8ced2011-05-04 23:50:46 +00007480 VisitedSelectorSet KnownSelectors;
7481 for (KnownMethodsMap::iterator M = KnownMethods.begin(),
7482 MEnd = KnownMethods.end();
7483 M != MEnd; ++M)
7484 KnownSelectors.insert(M->first);
7485
7486
Douglas Gregor669a25a2011-02-17 00:22:45 +00007487 ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(SearchDecl);
7488 if (!IFace)
7489 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(SearchDecl))
7490 IFace = Category->getClassInterface();
7491
Aaron Ballman3fe486a2014-03-13 21:23:55 +00007492 if (IFace)
7493 for (auto *Cat : IFace->visible_categories())
7494 Containers.push_back(Cat);
Douglas Gregor669a25a2011-02-17 00:22:45 +00007495
Aaron Ballmandc4bea42014-03-13 18:47:37 +00007496 for (unsigned I = 0, N = Containers.size(); I != N; ++I)
Manman Rena7a8b1f2016-01-26 18:05:23 +00007497 for (auto *P : Containers[I]->instance_properties())
Aaron Ballmandc4bea42014-03-13 18:47:37 +00007498 AddObjCKeyValueCompletions(P, IsInstanceMethod, ReturnType, Context,
Douglas Gregord4a8ced2011-05-04 23:50:46 +00007499 KnownSelectors, Results);
Douglas Gregor669a25a2011-02-17 00:22:45 +00007500 }
7501
Douglas Gregor636a61e2010-04-07 00:21:17 +00007502 Results.ExitScope();
7503
Douglas Gregor00c37ef2010-08-11 21:23:17 +00007504 HandleCodeCompleteResults(this, CodeCompleter,
7505 CodeCompletionContext::CCC_Other,
7506 Results.data(),Results.size());
Douglas Gregor636a61e2010-04-07 00:21:17 +00007507}
Douglas Gregor95887f92010-07-08 23:20:03 +00007508
7509void Sema::CodeCompleteObjCMethodDeclSelector(Scope *S,
7510 bool IsInstanceMethod,
Douglas Gregor45879692010-07-08 23:37:41 +00007511 bool AtParameterName,
John McCallba7bf592010-08-24 05:47:05 +00007512 ParsedType ReturnTy,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00007513 ArrayRef<IdentifierInfo *> SelIdents) {
Douglas Gregor95887f92010-07-08 23:20:03 +00007514 // If we have an external source, load the entire class method
Sebastian Redld44cd6a2010-08-18 23:57:06 +00007515 // pool from the AST file.
Douglas Gregor95887f92010-07-08 23:20:03 +00007516 if (ExternalSource) {
7517 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
7518 I != N; ++I) {
7519 Selector Sel = ExternalSource->GetExternalSelector(I);
Sebastian Redl75d8a322010-08-02 23:18:59 +00007520 if (Sel.isNull() || MethodPool.count(Sel))
Douglas Gregor95887f92010-07-08 23:20:03 +00007521 continue;
Sebastian Redl75d8a322010-08-02 23:18:59 +00007522
7523 ReadMethodPool(Sel);
Douglas Gregor95887f92010-07-08 23:20:03 +00007524 }
7525 }
7526
7527 // Build the set of methods we can see.
John McCall276321a2010-08-25 06:19:51 +00007528 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007529 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007530 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007531 CodeCompletionContext::CCC_Other);
Douglas Gregor95887f92010-07-08 23:20:03 +00007532
7533 if (ReturnTy)
7534 Results.setPreferredType(GetTypeFromParser(ReturnTy).getNonReferenceType());
Sebastian Redl75d8a322010-08-02 23:18:59 +00007535
Douglas Gregor95887f92010-07-08 23:20:03 +00007536 Results.EnterNewScope();
Sebastian Redl75d8a322010-08-02 23:18:59 +00007537 for (GlobalMethodPool::iterator M = MethodPool.begin(),
7538 MEnd = MethodPool.end();
7539 M != MEnd; ++M) {
7540 for (ObjCMethodList *MethList = IsInstanceMethod ? &M->second.first :
7541 &M->second.second;
Nico Weber2e0c8f72014-12-27 03:58:08 +00007542 MethList && MethList->getMethod();
Argyrios Kyrtzidisd3da6e02013-04-17 00:08:58 +00007543 MethList = MethList->getNext()) {
Nico Weber2e0c8f72014-12-27 03:58:08 +00007544 if (!isAcceptableObjCMethod(MethList->getMethod(), MK_Any, SelIdents))
Douglas Gregor95887f92010-07-08 23:20:03 +00007545 continue;
7546
Douglas Gregor45879692010-07-08 23:37:41 +00007547 if (AtParameterName) {
7548 // Suggest parameter names we've seen before.
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00007549 unsigned NumSelIdents = SelIdents.size();
Nico Weber2e0c8f72014-12-27 03:58:08 +00007550 if (NumSelIdents &&
7551 NumSelIdents <= MethList->getMethod()->param_size()) {
7552 ParmVarDecl *Param =
7553 MethList->getMethod()->parameters()[NumSelIdents - 1];
Douglas Gregor45879692010-07-08 23:37:41 +00007554 if (Param->getIdentifier()) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007555 CodeCompletionBuilder Builder(Results.getAllocator(),
7556 Results.getCodeCompletionTUInfo());
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00007557 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007558 Param->getIdentifier()->getName()));
7559 Results.AddResult(Builder.TakeString());
Douglas Gregor45879692010-07-08 23:37:41 +00007560 }
7561 }
7562
7563 continue;
7564 }
Craig Topperc3ec1492014-05-26 06:22:03 +00007565
Nico Weber2e0c8f72014-12-27 03:58:08 +00007566 Result R(MethList->getMethod(),
7567 Results.getBasePriority(MethList->getMethod()), nullptr);
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00007568 R.StartParameter = SelIdents.size();
Douglas Gregor95887f92010-07-08 23:20:03 +00007569 R.AllParametersAreInformative = false;
7570 R.DeclaringEntity = true;
7571 Results.MaybeAddResult(R, CurContext);
7572 }
7573 }
7574
7575 Results.ExitScope();
Alex Lorenz847fda12017-01-03 11:56:40 +00007576
7577 if (!AtParameterName && !SelIdents.empty() &&
7578 SelIdents.front()->getName().startswith("init")) {
7579 for (const auto &M : PP.macros()) {
7580 if (M.first->getName() != "NS_DESIGNATED_INITIALIZER")
7581 continue;
7582 Results.EnterNewScope();
7583 CodeCompletionBuilder Builder(Results.getAllocator(),
7584 Results.getCodeCompletionTUInfo());
7585 Builder.AddTypedTextChunk(
7586 Builder.getAllocator().CopyString(M.first->getName()));
7587 Results.AddResult(CodeCompletionResult(Builder.TakeString(), CCP_Macro,
7588 CXCursor_MacroDefinition));
7589 Results.ExitScope();
7590 }
7591 }
7592
Douglas Gregor00c37ef2010-08-11 21:23:17 +00007593 HandleCodeCompleteResults(this, CodeCompleter,
7594 CodeCompletionContext::CCC_Other,
7595 Results.data(),Results.size());
Douglas Gregor95887f92010-07-08 23:20:03 +00007596}
Douglas Gregorb14904c2010-08-13 22:48:40 +00007597
Douglas Gregorec00a262010-08-24 22:20:20 +00007598void Sema::CodeCompletePreprocessorDirective(bool InConditional) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007599 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007600 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00007601 CodeCompletionContext::CCC_PreprocessorDirective);
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007602 Results.EnterNewScope();
7603
7604 // #if <condition>
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007605 CodeCompletionBuilder Builder(Results.getAllocator(),
7606 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007607 Builder.AddTypedTextChunk("if");
7608 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7609 Builder.AddPlaceholderChunk("condition");
7610 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007611
7612 // #ifdef <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007613 Builder.AddTypedTextChunk("ifdef");
7614 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7615 Builder.AddPlaceholderChunk("macro");
7616 Results.AddResult(Builder.TakeString());
7617
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007618 // #ifndef <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007619 Builder.AddTypedTextChunk("ifndef");
7620 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7621 Builder.AddPlaceholderChunk("macro");
7622 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007623
7624 if (InConditional) {
7625 // #elif <condition>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007626 Builder.AddTypedTextChunk("elif");
7627 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7628 Builder.AddPlaceholderChunk("condition");
7629 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007630
7631 // #else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007632 Builder.AddTypedTextChunk("else");
7633 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007634
7635 // #endif
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007636 Builder.AddTypedTextChunk("endif");
7637 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007638 }
7639
7640 // #include "header"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007641 Builder.AddTypedTextChunk("include");
7642 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7643 Builder.AddTextChunk("\"");
7644 Builder.AddPlaceholderChunk("header");
7645 Builder.AddTextChunk("\"");
7646 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007647
7648 // #include <header>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007649 Builder.AddTypedTextChunk("include");
7650 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7651 Builder.AddTextChunk("<");
7652 Builder.AddPlaceholderChunk("header");
7653 Builder.AddTextChunk(">");
7654 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007655
7656 // #define <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007657 Builder.AddTypedTextChunk("define");
7658 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7659 Builder.AddPlaceholderChunk("macro");
7660 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007661
7662 // #define <macro>(<args>)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007663 Builder.AddTypedTextChunk("define");
7664 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7665 Builder.AddPlaceholderChunk("macro");
7666 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7667 Builder.AddPlaceholderChunk("args");
7668 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7669 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007670
7671 // #undef <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007672 Builder.AddTypedTextChunk("undef");
7673 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7674 Builder.AddPlaceholderChunk("macro");
7675 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007676
7677 // #line <number>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007678 Builder.AddTypedTextChunk("line");
7679 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7680 Builder.AddPlaceholderChunk("number");
7681 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007682
7683 // #line <number> "filename"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007684 Builder.AddTypedTextChunk("line");
7685 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7686 Builder.AddPlaceholderChunk("number");
7687 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7688 Builder.AddTextChunk("\"");
7689 Builder.AddPlaceholderChunk("filename");
7690 Builder.AddTextChunk("\"");
7691 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007692
7693 // #error <message>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007694 Builder.AddTypedTextChunk("error");
7695 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7696 Builder.AddPlaceholderChunk("message");
7697 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007698
7699 // #pragma <arguments>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007700 Builder.AddTypedTextChunk("pragma");
7701 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7702 Builder.AddPlaceholderChunk("arguments");
7703 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007704
David Blaikiebbafb8a2012-03-11 07:00:24 +00007705 if (getLangOpts().ObjC1) {
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007706 // #import "header"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007707 Builder.AddTypedTextChunk("import");
7708 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7709 Builder.AddTextChunk("\"");
7710 Builder.AddPlaceholderChunk("header");
7711 Builder.AddTextChunk("\"");
7712 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007713
7714 // #import <header>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007715 Builder.AddTypedTextChunk("import");
7716 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7717 Builder.AddTextChunk("<");
7718 Builder.AddPlaceholderChunk("header");
7719 Builder.AddTextChunk(">");
7720 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007721 }
7722
7723 // #include_next "header"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007724 Builder.AddTypedTextChunk("include_next");
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 // #include_next <header>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007732 Builder.AddTypedTextChunk("include_next");
7733 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7734 Builder.AddTextChunk("<");
7735 Builder.AddPlaceholderChunk("header");
7736 Builder.AddTextChunk(">");
7737 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007738
7739 // #warning <message>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007740 Builder.AddTypedTextChunk("warning");
7741 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7742 Builder.AddPlaceholderChunk("message");
7743 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007744
7745 // Note: #ident and #sccs are such crazy anachronisms that we don't provide
7746 // completions for them. And __include_macros is a Clang-internal extension
7747 // that we don't want to encourage anyone to use.
7748
7749 // FIXME: we don't support #assert or #unassert, so don't suggest them.
7750 Results.ExitScope();
7751
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007752 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0de55ce2010-08-25 18:41:16 +00007753 CodeCompletionContext::CCC_PreprocessorDirective,
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007754 Results.data(), Results.size());
7755}
7756
7757void Sema::CodeCompleteInPreprocessorConditionalExclusion(Scope *S) {
Douglas Gregorec00a262010-08-24 22:20:20 +00007758 CodeCompleteOrdinaryName(S,
John McCallfaf5fb42010-08-26 23:41:50 +00007759 S->getFnParent()? Sema::PCC_RecoveryInFunction
7760 : Sema::PCC_Namespace);
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007761}
7762
Douglas Gregorec00a262010-08-24 22:20:20 +00007763void Sema::CodeCompletePreprocessorMacroName(bool IsDefinition) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007764 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007765 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00007766 IsDefinition? CodeCompletionContext::CCC_MacroName
7767 : CodeCompletionContext::CCC_MacroNameUse);
Douglas Gregor12785102010-08-24 20:21:13 +00007768 if (!IsDefinition && (!CodeCompleter || CodeCompleter->includeMacros())) {
7769 // Add just the names of macros, not their arguments.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007770 CodeCompletionBuilder Builder(Results.getAllocator(),
7771 Results.getCodeCompletionTUInfo());
Douglas Gregor12785102010-08-24 20:21:13 +00007772 Results.EnterNewScope();
7773 for (Preprocessor::macro_iterator M = PP.macro_begin(),
7774 MEnd = PP.macro_end();
7775 M != MEnd; ++M) {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00007776 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007777 M->first->getName()));
Argyrios Kyrtzidis5c8b1cd2012-09-27 00:24:09 +00007778 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
7779 CCP_CodePattern,
7780 CXCursor_MacroDefinition));
Douglas Gregor12785102010-08-24 20:21:13 +00007781 }
7782 Results.ExitScope();
7783 } else if (IsDefinition) {
7784 // FIXME: Can we detect when the user just wrote an include guard above?
7785 }
7786
Douglas Gregor0ac41382010-09-23 23:01:17 +00007787 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor12785102010-08-24 20:21:13 +00007788 Results.data(), Results.size());
7789}
7790
Douglas Gregorec00a262010-08-24 22:20:20 +00007791void Sema::CodeCompletePreprocessorExpression() {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007792 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007793 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00007794 CodeCompletionContext::CCC_PreprocessorExpression);
Douglas Gregorec00a262010-08-24 22:20:20 +00007795
7796 if (!CodeCompleter || CodeCompleter->includeMacros())
Douglas Gregor8cb17462012-10-09 16:01:50 +00007797 AddMacroResults(PP, Results, true);
Douglas Gregorec00a262010-08-24 22:20:20 +00007798
7799 // defined (<macro>)
7800 Results.EnterNewScope();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007801 CodeCompletionBuilder Builder(Results.getAllocator(),
7802 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007803 Builder.AddTypedTextChunk("defined");
7804 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7805 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7806 Builder.AddPlaceholderChunk("macro");
7807 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7808 Results.AddResult(Builder.TakeString());
Douglas Gregorec00a262010-08-24 22:20:20 +00007809 Results.ExitScope();
7810
7811 HandleCodeCompleteResults(this, CodeCompleter,
7812 CodeCompletionContext::CCC_PreprocessorExpression,
7813 Results.data(), Results.size());
7814}
7815
7816void Sema::CodeCompletePreprocessorMacroArgument(Scope *S,
7817 IdentifierInfo *Macro,
7818 MacroInfo *MacroInfo,
7819 unsigned Argument) {
7820 // FIXME: In the future, we could provide "overload" results, much like we
7821 // do for function calls.
7822
Argyrios Kyrtzidis75f6cd22011-08-18 19:41:28 +00007823 // Now just ignore this. There will be another code-completion callback
7824 // for the expanded tokens.
Douglas Gregorec00a262010-08-24 22:20:20 +00007825}
7826
Douglas Gregor11583702010-08-25 17:04:25 +00007827void Sema::CodeCompleteNaturalLanguage() {
Douglas Gregor11583702010-08-25 17:04:25 +00007828 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregorea736372010-08-25 17:10:00 +00007829 CodeCompletionContext::CCC_NaturalLanguage,
Craig Topperc3ec1492014-05-26 06:22:03 +00007830 nullptr, 0);
Douglas Gregor11583702010-08-25 17:04:25 +00007831}
7832
Alex Lorenzf7f6f822017-05-09 16:05:04 +00007833void Sema::CodeCompleteAvailabilityPlatformName() {
7834 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
7835 CodeCompleter->getCodeCompletionTUInfo(),
7836 CodeCompletionContext::CCC_Other);
7837 Results.EnterNewScope();
7838 static const char *Platforms[] = {"macOS", "iOS", "watchOS", "tvOS"};
7839 for (const char *Platform : llvm::makeArrayRef(Platforms)) {
7840 Results.AddResult(CodeCompletionResult(Platform));
7841 Results.AddResult(CodeCompletionResult(Results.getAllocator().CopyString(
7842 Twine(Platform) + "ApplicationExtension")));
7843 }
7844 Results.ExitScope();
7845 HandleCodeCompleteResults(this, CodeCompleter,
7846 CodeCompletionContext::CCC_Other, Results.data(),
7847 Results.size());
7848}
7849
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00007850void Sema::GatherGlobalCodeCompletions(CodeCompletionAllocator &Allocator,
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007851 CodeCompletionTUInfo &CCTUInfo,
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007852 SmallVectorImpl<CodeCompletionResult> &Results) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007853 ResultBuilder Builder(*this, Allocator, CCTUInfo,
7854 CodeCompletionContext::CCC_Recovery);
Douglas Gregor39982192010-08-15 06:18:01 +00007855 if (!CodeCompleter || CodeCompleter->includeGlobals()) {
7856 CodeCompletionDeclConsumer Consumer(Builder,
7857 Context.getTranslationUnitDecl());
7858 LookupVisibleDecls(Context.getTranslationUnitDecl(), LookupAnyName,
7859 Consumer);
7860 }
Douglas Gregorb14904c2010-08-13 22:48:40 +00007861
7862 if (!CodeCompleter || CodeCompleter->includeMacros())
Douglas Gregor8cb17462012-10-09 16:01:50 +00007863 AddMacroResults(PP, Builder, true);
Douglas Gregorb14904c2010-08-13 22:48:40 +00007864
7865 Results.clear();
7866 Results.insert(Results.end(),
7867 Builder.data(), Builder.data() + Builder.size());
7868}