blob: 3f6393724eeafc13d7443d3b0503b5a309e5e4f6 [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"
Douglas Gregor07f43572012-01-29 18:15:03 +000017#include "clang/Lex/HeaderSearch.h"
Douglas Gregorf329c7c2009-10-30 16:50:04 +000018#include "clang/Lex/MacroInfo.h"
19#include "clang/Lex/Preprocessor.h"
Chandler Carruth3a022472012-12-04 09:13:33 +000020#include "clang/Sema/CodeCompleteConsumer.h"
21#include "clang/Sema/ExternalSemaSource.h"
22#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;
106 DeclOrVector = ((NamedDecl *)0);
107 }
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,
174 LookupFilter Filter = 0)
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),
179 ObjCImplementation(0)
180 {
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 }
214
Douglas Gregor3545ff42009-09-21 16:56:56 +0000215 Result *data() { return Results.empty()? 0 : &Results.front(); }
216 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.
Douglas Gregor2af2f672009-09-21 20:12:40 +0000291 void MaybeAddResult(Result R, DeclContext *CurContext = 0);
Douglas Gregor3545ff42009-09-21 16:56:56 +0000292
Douglas Gregorc580c522010-01-14 01:09:38 +0000293 /// \brief Add a new result to this result set, where we already know
294 /// the hiding declation (if any).
295 ///
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.
317 void Ignore(Decl *D) { AllDeclsFound.insert(D->getCanonicalDecl()); }
318
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 };
344}
345
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 };
366
367 iterator() : DeclOrIterator((NamedDecl *)0), SingleDeclIndex(0) { }
368
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 *>()) {
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000377 DeclOrIterator = (NamedDecl *)0;
378 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 }
463
464 NestedNameSpecifier *Result = 0;
465 while (!TargetParents.empty()) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000466 const DeclContext *Parent = TargetParents.back();
Douglas Gregor2af2f672009-09-21 20:12:40 +0000467 TargetParents.pop_back();
468
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000469 if (const NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Parent)) {
Douglas Gregor68762e72010-08-23 21:17:50 +0000470 if (!Namespace->getIdentifier())
471 continue;
472
Douglas Gregor2af2f672009-09-21 20:12:40 +0000473 Result = NestedNameSpecifier::Create(Context, Result, Namespace);
Douglas Gregor68762e72010-08-23 21:17:50 +0000474 }
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000475 else if (const TagDecl *TD = dyn_cast<TagDecl>(Parent))
Douglas Gregor2af2f672009-09-21 20:12:40 +0000476 Result = NestedNameSpecifier::Create(Context, Result,
477 false,
478 Context.getTypeDeclType(TD).getTypePtr());
Douglas Gregor9eb77012009-11-07 00:00:49 +0000479 }
Douglas Gregor2af2f672009-09-21 20:12:40 +0000480 return Result;
481}
482
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000483bool ResultBuilder::isInterestingDecl(const NamedDecl *ND,
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000484 bool &AsNestedNameSpecifier) const {
485 AsNestedNameSpecifier = false;
486
Douglas Gregor7c208612010-01-14 00:20:49 +0000487 ND = ND->getUnderlyingDecl();
488 unsigned IDNS = ND->getIdentifierNamespace();
Douglas Gregor58acf322009-10-09 22:16:47 +0000489
490 // Skip unnamed entities.
Douglas Gregor7c208612010-01-14 00:20:49 +0000491 if (!ND->getDeclName())
492 return false;
Douglas Gregor3545ff42009-09-21 16:56:56 +0000493
494 // Friend declarations and declarations introduced due to friends are never
495 // added as results.
John McCallbbbbe4e2010-03-11 07:50:04 +0000496 if (IDNS & (Decl::IDNS_OrdinaryFriend | Decl::IDNS_TagFriend))
Douglas Gregor7c208612010-01-14 00:20:49 +0000497 return false;
498
Douglas Gregor99fe2ad2009-12-11 17:31:05 +0000499 // Class template (partial) specializations are never added as results.
Douglas Gregor7c208612010-01-14 00:20:49 +0000500 if (isa<ClassTemplateSpecializationDecl>(ND) ||
501 isa<ClassTemplatePartialSpecializationDecl>(ND))
502 return false;
Douglas Gregor3545ff42009-09-21 16:56:56 +0000503
Douglas Gregor99fe2ad2009-12-11 17:31:05 +0000504 // Using declarations themselves are never added as results.
Douglas Gregor7c208612010-01-14 00:20:49 +0000505 if (isa<UsingDecl>(ND))
506 return false;
507
508 // Some declarations have reserved names that we don't want to ever show.
509 if (const IdentifierInfo *Id = ND->getIdentifier()) {
Douglas Gregor3545ff42009-09-21 16:56:56 +0000510 // __va_list_tag is a freak of nature. Find it and skip it.
511 if (Id->isStr("__va_list_tag") || Id->isStr("__builtin_va_list"))
Douglas Gregor7c208612010-01-14 00:20:49 +0000512 return false;
Douglas Gregor3545ff42009-09-21 16:56:56 +0000513
Douglas Gregor58acf322009-10-09 22:16:47 +0000514 // Filter out names reserved for the implementation (C99 7.1.3,
Douglas Gregor9f1570d2010-07-14 17:44:04 +0000515 // C++ [lib.global.names]) if they come from a system header.
Daniel Dunbar2c422dc92009-10-18 20:26:12 +0000516 //
517 // FIXME: Add predicate for this.
Douglas Gregor58acf322009-10-09 22:16:47 +0000518 if (Id->getLength() >= 2) {
Daniel Dunbar2c422dc92009-10-18 20:26:12 +0000519 const char *Name = Id->getNameStart();
Douglas Gregor58acf322009-10-09 22:16:47 +0000520 if (Name[0] == '_' &&
Douglas Gregor9f1570d2010-07-14 17:44:04 +0000521 (Name[1] == '_' || (Name[1] >= 'A' && Name[1] <= 'Z')) &&
522 (ND->getLocation().isInvalid() ||
523 SemaRef.SourceMgr.isInSystemHeader(
524 SemaRef.SourceMgr.getSpellingLoc(ND->getLocation()))))
Douglas Gregor7c208612010-01-14 00:20:49 +0000525 return false;
Douglas Gregor58acf322009-10-09 22:16:47 +0000526 }
Douglas Gregor3545ff42009-09-21 16:56:56 +0000527 }
Douglas Gregor2927c0c2010-11-09 03:59:40 +0000528
Douglas Gregor59cab552010-08-16 23:05:20 +0000529 if (Filter == &ResultBuilder::IsNestedNameSpecifier ||
530 ((isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND)) &&
531 Filter != &ResultBuilder::IsNamespace &&
Douglas Gregor0ac41382010-09-23 23:01:17 +0000532 Filter != &ResultBuilder::IsNamespaceOrAlias &&
533 Filter != 0))
Douglas Gregor59cab552010-08-16 23:05:20 +0000534 AsNestedNameSpecifier = true;
535
Douglas Gregor3545ff42009-09-21 16:56:56 +0000536 // Filter out any unwanted results.
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000537 if (Filter && !(this->*Filter)(ND)) {
538 // Check whether it is interesting as a nested-name-specifier.
David Blaikiebbafb8a2012-03-11 07:00:24 +0000539 if (AllowNestedNameSpecifiers && SemaRef.getLangOpts().CPlusPlus &&
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000540 IsNestedNameSpecifier(ND) &&
541 (Filter != &ResultBuilder::IsMember ||
542 (isa<CXXRecordDecl>(ND) &&
543 cast<CXXRecordDecl>(ND)->isInjectedClassName()))) {
544 AsNestedNameSpecifier = true;
545 return true;
546 }
547
Douglas Gregor7c208612010-01-14 00:20:49 +0000548 return false;
Douglas Gregor59cab552010-08-16 23:05:20 +0000549 }
Douglas Gregor7c208612010-01-14 00:20:49 +0000550 // ... then it must be interesting!
551 return true;
552}
553
Douglas Gregore0717ab2010-01-14 00:41:07 +0000554bool ResultBuilder::CheckHiddenResult(Result &R, DeclContext *CurContext,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000555 const NamedDecl *Hiding) {
Douglas Gregore0717ab2010-01-14 00:41:07 +0000556 // In C, there is no way to refer to a hidden name.
557 // FIXME: This isn't true; we can find a tag name hidden by an ordinary
558 // name if we introduce the tag type.
David Blaikiebbafb8a2012-03-11 07:00:24 +0000559 if (!SemaRef.getLangOpts().CPlusPlus)
Douglas Gregore0717ab2010-01-14 00:41:07 +0000560 return true;
561
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000562 const DeclContext *HiddenCtx =
563 R.Declaration->getDeclContext()->getRedeclContext();
Douglas Gregore0717ab2010-01-14 00:41:07 +0000564
565 // There is no way to qualify a name declared in a function or method.
566 if (HiddenCtx->isFunctionOrMethod())
567 return true;
568
Sebastian Redl50c68252010-08-31 00:36:30 +0000569 if (HiddenCtx == Hiding->getDeclContext()->getRedeclContext())
Douglas Gregore0717ab2010-01-14 00:41:07 +0000570 return true;
571
572 // We can refer to the result with the appropriate qualification. Do it.
573 R.Hidden = true;
574 R.QualifierIsInformative = false;
575
576 if (!R.Qualifier)
577 R.Qualifier = getRequiredQualification(SemaRef.Context,
578 CurContext,
579 R.Declaration->getDeclContext());
580 return false;
581}
582
Douglas Gregor95887f92010-07-08 23:20:03 +0000583/// \brief A simplified classification of types used to determine whether two
584/// types are "similar enough" when adjusting priorities.
Douglas Gregor6e240332010-08-16 16:18:59 +0000585SimplifiedTypeClass clang::getSimplifiedTypeClass(CanQualType T) {
Douglas Gregor95887f92010-07-08 23:20:03 +0000586 switch (T->getTypeClass()) {
587 case Type::Builtin:
588 switch (cast<BuiltinType>(T)->getKind()) {
589 case BuiltinType::Void:
590 return STC_Void;
591
592 case BuiltinType::NullPtr:
593 return STC_Pointer;
594
595 case BuiltinType::Overload:
596 case BuiltinType::Dependent:
Douglas Gregor95887f92010-07-08 23:20:03 +0000597 return STC_Other;
598
599 case BuiltinType::ObjCId:
600 case BuiltinType::ObjCClass:
601 case BuiltinType::ObjCSel:
602 return STC_ObjectiveC;
603
604 default:
605 return STC_Arithmetic;
606 }
David Blaikie8a40f702012-01-17 06:56:22 +0000607
Douglas Gregor95887f92010-07-08 23:20:03 +0000608 case Type::Complex:
609 return STC_Arithmetic;
610
611 case Type::Pointer:
612 return STC_Pointer;
613
614 case Type::BlockPointer:
615 return STC_Block;
616
617 case Type::LValueReference:
618 case Type::RValueReference:
619 return getSimplifiedTypeClass(T->getAs<ReferenceType>()->getPointeeType());
620
621 case Type::ConstantArray:
622 case Type::IncompleteArray:
623 case Type::VariableArray:
624 case Type::DependentSizedArray:
625 return STC_Array;
626
627 case Type::DependentSizedExtVector:
628 case Type::Vector:
629 case Type::ExtVector:
630 return STC_Arithmetic;
631
632 case Type::FunctionProto:
633 case Type::FunctionNoProto:
634 return STC_Function;
635
636 case Type::Record:
637 return STC_Record;
638
639 case Type::Enum:
640 return STC_Arithmetic;
641
642 case Type::ObjCObject:
643 case Type::ObjCInterface:
644 case Type::ObjCObjectPointer:
645 return STC_ObjectiveC;
646
647 default:
648 return STC_Other;
649 }
650}
651
652/// \brief Get the type that a given expression will have if this declaration
653/// is used as an expression in its "typical" code-completion form.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000654QualType clang::getDeclUsageType(ASTContext &C, const NamedDecl *ND) {
Douglas Gregor95887f92010-07-08 23:20:03 +0000655 ND = cast<NamedDecl>(ND->getUnderlyingDecl());
656
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000657 if (const TypeDecl *Type = dyn_cast<TypeDecl>(ND))
Douglas Gregor95887f92010-07-08 23:20:03 +0000658 return C.getTypeDeclType(Type);
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000659 if (const ObjCInterfaceDecl *Iface = dyn_cast<ObjCInterfaceDecl>(ND))
Douglas Gregor95887f92010-07-08 23:20:03 +0000660 return C.getObjCInterfaceType(Iface);
661
662 QualType T;
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000663 if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(ND))
Douglas Gregor603d81b2010-07-13 08:18:22 +0000664 T = Function->getCallResultType();
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000665 else if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND))
Douglas Gregor603d81b2010-07-13 08:18:22 +0000666 T = Method->getSendResultType();
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000667 else if (const FunctionTemplateDecl *FunTmpl =
668 dyn_cast<FunctionTemplateDecl>(ND))
Douglas Gregor603d81b2010-07-13 08:18:22 +0000669 T = FunTmpl->getTemplatedDecl()->getCallResultType();
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000670 else if (const EnumConstantDecl *Enumerator = dyn_cast<EnumConstantDecl>(ND))
Douglas Gregor95887f92010-07-08 23:20:03 +0000671 T = C.getTypeDeclType(cast<EnumDecl>(Enumerator->getDeclContext()));
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000672 else if (const ObjCPropertyDecl *Property = dyn_cast<ObjCPropertyDecl>(ND))
Douglas Gregor95887f92010-07-08 23:20:03 +0000673 T = Property->getType();
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000674 else if (const ValueDecl *Value = dyn_cast<ValueDecl>(ND))
Douglas Gregor95887f92010-07-08 23:20:03 +0000675 T = Value->getType();
676 else
677 return QualType();
Douglas Gregoraf670a82011-04-14 20:33:34 +0000678
679 // Dig through references, function pointers, and block pointers to
680 // get down to the likely type of an expression when the entity is
681 // used.
682 do {
683 if (const ReferenceType *Ref = T->getAs<ReferenceType>()) {
684 T = Ref->getPointeeType();
685 continue;
686 }
687
688 if (const PointerType *Pointer = T->getAs<PointerType>()) {
689 if (Pointer->getPointeeType()->isFunctionType()) {
690 T = Pointer->getPointeeType();
691 continue;
692 }
693
694 break;
695 }
696
697 if (const BlockPointerType *Block = T->getAs<BlockPointerType>()) {
698 T = Block->getPointeeType();
699 continue;
700 }
701
702 if (const FunctionType *Function = T->getAs<FunctionType>()) {
703 T = Function->getResultType();
704 continue;
705 }
706
707 break;
708 } while (true);
709
710 return T;
Douglas Gregor95887f92010-07-08 23:20:03 +0000711}
712
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000713unsigned ResultBuilder::getBasePriority(const NamedDecl *ND) {
714 if (!ND)
715 return CCP_Unlikely;
716
717 // Context-based decisions.
718 const DeclContext *DC = ND->getDeclContext()->getRedeclContext();
719 if (DC->isFunctionOrMethod() || isa<BlockDecl>(DC)) {
720 // _cmd is relatively rare
721 if (const ImplicitParamDecl *ImplicitParam =
722 dyn_cast<ImplicitParamDecl>(ND))
723 if (ImplicitParam->getIdentifier() &&
724 ImplicitParam->getIdentifier()->isStr("_cmd"))
725 return CCP_ObjC_cmd;
726
727 return CCP_LocalDeclaration;
728 }
729 if (DC->isRecord() || isa<ObjCContainerDecl>(DC))
730 return CCP_MemberDeclaration;
731
732 // Content-based decisions.
733 if (isa<EnumConstantDecl>(ND))
734 return CCP_Constant;
735
736 if ((isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND)))
737 return CCP_Type;
738
739 return CCP_Declaration;
740}
741
Douglas Gregor50832e02010-09-20 22:39:41 +0000742void ResultBuilder::AdjustResultPriorityForDecl(Result &R) {
743 // If this is an Objective-C method declaration whose selector matches our
744 // preferred selector, give it a priority boost.
745 if (!PreferredSelector.isNull())
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000746 if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(R.Declaration))
Douglas Gregor50832e02010-09-20 22:39:41 +0000747 if (PreferredSelector == Method->getSelector())
748 R.Priority += CCD_SelectorMatch;
Douglas Gregor5fb901d2010-09-20 23:11:55 +0000749
Douglas Gregor50832e02010-09-20 22:39:41 +0000750 // If we have a preferred type, adjust the priority for results with exactly-
751 // matching or nearly-matching types.
752 if (!PreferredType.isNull()) {
753 QualType T = getDeclUsageType(SemaRef.Context, R.Declaration);
754 if (!T.isNull()) {
755 CanQualType TC = SemaRef.Context.getCanonicalType(T);
756 // Check for exactly-matching types (modulo qualifiers).
757 if (SemaRef.Context.hasSameUnqualifiedType(PreferredType, TC))
758 R.Priority /= CCF_ExactTypeMatch;
759 // Check for nearly-matching types, based on classification of each.
760 else if ((getSimplifiedTypeClass(PreferredType)
Douglas Gregor95887f92010-07-08 23:20:03 +0000761 == getSimplifiedTypeClass(TC)) &&
Douglas Gregor50832e02010-09-20 22:39:41 +0000762 !(PreferredType->isEnumeralType() && TC->isEnumeralType()))
763 R.Priority /= CCF_SimilarTypeMatch;
764 }
765 }
Douglas Gregor95887f92010-07-08 23:20:03 +0000766}
767
Douglas Gregor0212fd72010-09-21 16:06:22 +0000768void ResultBuilder::MaybeAddConstructorResults(Result R) {
David Blaikiebbafb8a2012-03-11 07:00:24 +0000769 if (!SemaRef.getLangOpts().CPlusPlus || !R.Declaration ||
Douglas Gregor0212fd72010-09-21 16:06:22 +0000770 !CompletionContext.wantConstructorResults())
771 return;
772
773 ASTContext &Context = SemaRef.Context;
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000774 const NamedDecl *D = R.Declaration;
775 const CXXRecordDecl *Record = 0;
776 if (const ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(D))
Douglas Gregor0212fd72010-09-21 16:06:22 +0000777 Record = ClassTemplate->getTemplatedDecl();
778 else if ((Record = dyn_cast<CXXRecordDecl>(D))) {
779 // Skip specializations and partial specializations.
780 if (isa<ClassTemplateSpecializationDecl>(Record))
781 return;
782 } else {
783 // There are no constructors here.
784 return;
785 }
786
787 Record = Record->getDefinition();
788 if (!Record)
789 return;
790
791
792 QualType RecordTy = Context.getTypeDeclType(Record);
793 DeclarationName ConstructorName
794 = Context.DeclarationNames.getCXXConstructorName(
795 Context.getCanonicalType(RecordTy));
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000796 DeclContext::lookup_const_result Ctors = Record->lookup(ConstructorName);
797 for (DeclContext::lookup_const_iterator I = Ctors.begin(),
798 E = Ctors.end();
799 I != E; ++I) {
David Blaikieff7d47a2012-12-19 00:45:41 +0000800 R.Declaration = *I;
Douglas Gregor0212fd72010-09-21 16:06:22 +0000801 R.CursorKind = getCursorKindForDecl(R.Declaration);
802 Results.push_back(R);
803 }
804}
805
Douglas Gregor7c208612010-01-14 00:20:49 +0000806void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) {
807 assert(!ShadowMaps.empty() && "Must enter into a results scope");
808
809 if (R.Kind != Result::RK_Declaration) {
810 // For non-declaration results, just add the result.
811 Results.push_back(R);
812 return;
813 }
814
815 // Look through using declarations.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000816 if (const UsingShadowDecl *Using =
817 dyn_cast<UsingShadowDecl>(R.Declaration)) {
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000818 MaybeAddResult(Result(Using->getTargetDecl(),
819 getBasePriority(Using->getTargetDecl()),
820 R.Qualifier),
821 CurContext);
Douglas Gregor7c208612010-01-14 00:20:49 +0000822 return;
823 }
824
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000825 const Decl *CanonDecl = R.Declaration->getCanonicalDecl();
Douglas Gregor7c208612010-01-14 00:20:49 +0000826 unsigned IDNS = CanonDecl->getIdentifierNamespace();
827
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000828 bool AsNestedNameSpecifier = false;
829 if (!isInterestingDecl(R.Declaration, AsNestedNameSpecifier))
Douglas Gregor7c208612010-01-14 00:20:49 +0000830 return;
831
Douglas Gregor0212fd72010-09-21 16:06:22 +0000832 // C++ constructors are never found by name lookup.
833 if (isa<CXXConstructorDecl>(R.Declaration))
834 return;
835
Douglas Gregor3545ff42009-09-21 16:56:56 +0000836 ShadowMap &SMap = ShadowMaps.back();
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000837 ShadowMapEntry::iterator I, IEnd;
838 ShadowMap::iterator NamePos = SMap.find(R.Declaration->getDeclName());
839 if (NamePos != SMap.end()) {
840 I = NamePos->second.begin();
841 IEnd = NamePos->second.end();
842 }
843
844 for (; I != IEnd; ++I) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000845 const NamedDecl *ND = I->first;
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000846 unsigned Index = I->second;
Douglas Gregor3545ff42009-09-21 16:56:56 +0000847 if (ND->getCanonicalDecl() == CanonDecl) {
848 // This is a redeclaration. Always pick the newer declaration.
Douglas Gregor3545ff42009-09-21 16:56:56 +0000849 Results[Index].Declaration = R.Declaration;
850
Douglas Gregor3545ff42009-09-21 16:56:56 +0000851 // We're done.
852 return;
853 }
854 }
855
856 // This is a new declaration in this scope. However, check whether this
857 // declaration name is hidden by a similarly-named declaration in an outer
858 // scope.
859 std::list<ShadowMap>::iterator SM, SMEnd = ShadowMaps.end();
860 --SMEnd;
861 for (SM = ShadowMaps.begin(); SM != SMEnd; ++SM) {
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000862 ShadowMapEntry::iterator I, IEnd;
863 ShadowMap::iterator NamePos = SM->find(R.Declaration->getDeclName());
864 if (NamePos != SM->end()) {
865 I = NamePos->second.begin();
866 IEnd = NamePos->second.end();
867 }
868 for (; I != IEnd; ++I) {
Douglas Gregor3545ff42009-09-21 16:56:56 +0000869 // A tag declaration does not hide a non-tag declaration.
John McCalle87beb22010-04-23 18:46:30 +0000870 if (I->first->hasTagIdentifierNamespace() &&
Douglas Gregor3545ff42009-09-21 16:56:56 +0000871 (IDNS & (Decl::IDNS_Member | Decl::IDNS_Ordinary |
872 Decl::IDNS_ObjCProtocol)))
873 continue;
874
875 // Protocols are in distinct namespaces from everything else.
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000876 if (((I->first->getIdentifierNamespace() & Decl::IDNS_ObjCProtocol)
Douglas Gregor3545ff42009-09-21 16:56:56 +0000877 || (IDNS & Decl::IDNS_ObjCProtocol)) &&
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000878 I->first->getIdentifierNamespace() != IDNS)
Douglas Gregor3545ff42009-09-21 16:56:56 +0000879 continue;
880
881 // The newly-added result is hidden by an entry in the shadow map.
Douglas Gregore0717ab2010-01-14 00:41:07 +0000882 if (CheckHiddenResult(R, CurContext, I->first))
Douglas Gregor3545ff42009-09-21 16:56:56 +0000883 return;
Douglas Gregor3545ff42009-09-21 16:56:56 +0000884
885 break;
886 }
887 }
888
889 // Make sure that any given declaration only shows up in the result set once.
890 if (!AllDeclsFound.insert(CanonDecl))
891 return;
Douglas Gregorc2cb2e22010-08-27 15:29:55 +0000892
Douglas Gregore412a5a2009-09-23 22:26:46 +0000893 // If the filter is for nested-name-specifiers, then this result starts a
894 // nested-name-specifier.
Douglas Gregora2db7932010-05-26 22:00:08 +0000895 if (AsNestedNameSpecifier) {
Douglas Gregore412a5a2009-09-23 22:26:46 +0000896 R.StartsNestedNameSpecifier = true;
Douglas Gregora2db7932010-05-26 22:00:08 +0000897 R.Priority = CCP_NestedNameSpecifier;
Douglas Gregor50832e02010-09-20 22:39:41 +0000898 } else
899 AdjustResultPriorityForDecl(R);
Douglas Gregorc2cb2e22010-08-27 15:29:55 +0000900
Douglas Gregor5bf52692009-09-22 23:15:58 +0000901 // If this result is supposed to have an informative qualifier, add one.
Douglas Gregore412a5a2009-09-23 22:26:46 +0000902 if (R.QualifierIsInformative && !R.Qualifier &&
903 !R.StartsNestedNameSpecifier) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000904 const DeclContext *Ctx = R.Declaration->getDeclContext();
905 if (const NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Ctx))
Douglas Gregor5bf52692009-09-22 23:15:58 +0000906 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, Namespace);
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000907 else if (const TagDecl *Tag = dyn_cast<TagDecl>(Ctx))
Douglas Gregor5bf52692009-09-22 23:15:58 +0000908 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, false,
909 SemaRef.Context.getTypeDeclType(Tag).getTypePtr());
910 else
911 R.QualifierIsInformative = false;
912 }
Douglas Gregore412a5a2009-09-23 22:26:46 +0000913
Douglas Gregor3545ff42009-09-21 16:56:56 +0000914 // Insert this result into the set of results and into the current shadow
915 // map.
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000916 SMap[R.Declaration->getDeclName()].Add(R.Declaration, Results.size());
Douglas Gregor3545ff42009-09-21 16:56:56 +0000917 Results.push_back(R);
Douglas Gregor0212fd72010-09-21 16:06:22 +0000918
919 if (!AsNestedNameSpecifier)
920 MaybeAddConstructorResults(R);
Douglas Gregor3545ff42009-09-21 16:56:56 +0000921}
922
Douglas Gregorc580c522010-01-14 01:09:38 +0000923void ResultBuilder::AddResult(Result R, DeclContext *CurContext,
Douglas Gregor09bbc652010-01-14 15:47:35 +0000924 NamedDecl *Hiding, bool InBaseClass = false) {
Douglas Gregor78a21012010-01-14 16:01:26 +0000925 if (R.Kind != Result::RK_Declaration) {
926 // For non-declaration results, just add the result.
927 Results.push_back(R);
928 return;
929 }
930
Douglas Gregorc580c522010-01-14 01:09:38 +0000931 // Look through using declarations.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000932 if (const UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(R.Declaration)) {
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000933 AddResult(Result(Using->getTargetDecl(),
934 getBasePriority(Using->getTargetDecl()),
935 R.Qualifier),
936 CurContext, Hiding);
Douglas Gregorc580c522010-01-14 01:09:38 +0000937 return;
938 }
939
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000940 bool AsNestedNameSpecifier = false;
941 if (!isInterestingDecl(R.Declaration, AsNestedNameSpecifier))
Douglas Gregorc580c522010-01-14 01:09:38 +0000942 return;
943
Douglas Gregor0212fd72010-09-21 16:06:22 +0000944 // C++ constructors are never found by name lookup.
945 if (isa<CXXConstructorDecl>(R.Declaration))
946 return;
947
Douglas Gregorc580c522010-01-14 01:09:38 +0000948 if (Hiding && CheckHiddenResult(R, CurContext, Hiding))
949 return;
Nick Lewyckyc3921482012-04-03 21:44:08 +0000950
Douglas Gregorc580c522010-01-14 01:09:38 +0000951 // Make sure that any given declaration only shows up in the result set once.
952 if (!AllDeclsFound.insert(R.Declaration->getCanonicalDecl()))
953 return;
954
955 // If the filter is for nested-name-specifiers, then this result starts a
956 // nested-name-specifier.
Douglas Gregora2db7932010-05-26 22:00:08 +0000957 if (AsNestedNameSpecifier) {
Douglas Gregorc580c522010-01-14 01:09:38 +0000958 R.StartsNestedNameSpecifier = true;
Douglas Gregora2db7932010-05-26 22:00:08 +0000959 R.Priority = CCP_NestedNameSpecifier;
960 }
Douglas Gregor09bbc652010-01-14 15:47:35 +0000961 else if (Filter == &ResultBuilder::IsMember && !R.Qualifier && InBaseClass &&
962 isa<CXXRecordDecl>(R.Declaration->getDeclContext()
Sebastian Redl50c68252010-08-31 00:36:30 +0000963 ->getRedeclContext()))
Douglas Gregor09bbc652010-01-14 15:47:35 +0000964 R.QualifierIsInformative = true;
965
Douglas Gregorc580c522010-01-14 01:09:38 +0000966 // If this result is supposed to have an informative qualifier, add one.
967 if (R.QualifierIsInformative && !R.Qualifier &&
968 !R.StartsNestedNameSpecifier) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000969 const DeclContext *Ctx = R.Declaration->getDeclContext();
970 if (const NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Ctx))
Douglas Gregorc580c522010-01-14 01:09:38 +0000971 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, Namespace);
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000972 else if (const TagDecl *Tag = dyn_cast<TagDecl>(Ctx))
Douglas Gregorc580c522010-01-14 01:09:38 +0000973 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, false,
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000974 SemaRef.Context.getTypeDeclType(Tag).getTypePtr());
Douglas Gregorc580c522010-01-14 01:09:38 +0000975 else
976 R.QualifierIsInformative = false;
977 }
978
Douglas Gregora2db7932010-05-26 22:00:08 +0000979 // Adjust the priority if this result comes from a base class.
980 if (InBaseClass)
981 R.Priority += CCD_InBaseClass;
982
Douglas Gregor50832e02010-09-20 22:39:41 +0000983 AdjustResultPriorityForDecl(R);
Douglas Gregor7aa6b222010-05-30 01:49:25 +0000984
Douglas Gregor9be0ed42010-08-26 16:36:48 +0000985 if (HasObjectTypeQualifiers)
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000986 if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(R.Declaration))
Douglas Gregor9be0ed42010-08-26 16:36:48 +0000987 if (Method->isInstance()) {
988 Qualifiers MethodQuals
989 = Qualifiers::fromCVRMask(Method->getTypeQualifiers());
990 if (ObjectTypeQualifiers == MethodQuals)
991 R.Priority += CCD_ObjectQualifierMatch;
992 else if (ObjectTypeQualifiers - MethodQuals) {
993 // The method cannot be invoked, because doing so would drop
994 // qualifiers.
995 return;
996 }
997 }
998
Douglas Gregorc580c522010-01-14 01:09:38 +0000999 // Insert this result into the set of results.
1000 Results.push_back(R);
Douglas Gregor0212fd72010-09-21 16:06:22 +00001001
1002 if (!AsNestedNameSpecifier)
1003 MaybeAddConstructorResults(R);
Douglas Gregorc580c522010-01-14 01:09:38 +00001004}
1005
Douglas Gregor78a21012010-01-14 16:01:26 +00001006void ResultBuilder::AddResult(Result R) {
1007 assert(R.Kind != Result::RK_Declaration &&
1008 "Declaration results need more context");
1009 Results.push_back(R);
1010}
1011
Douglas Gregor3545ff42009-09-21 16:56:56 +00001012/// \brief Enter into a new scope.
1013void ResultBuilder::EnterNewScope() {
1014 ShadowMaps.push_back(ShadowMap());
1015}
1016
1017/// \brief Exit from the current scope.
1018void ResultBuilder::ExitScope() {
Douglas Gregor05e7ca32009-12-06 20:23:50 +00001019 for (ShadowMap::iterator E = ShadowMaps.back().begin(),
1020 EEnd = ShadowMaps.back().end();
1021 E != EEnd;
1022 ++E)
1023 E->second.Destroy();
1024
Douglas Gregor3545ff42009-09-21 16:56:56 +00001025 ShadowMaps.pop_back();
1026}
1027
Douglas Gregor9d64c5e2009-09-21 20:51:25 +00001028/// \brief Determines whether this given declaration will be found by
1029/// ordinary name lookup.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001030bool ResultBuilder::IsOrdinaryName(const NamedDecl *ND) const {
Douglas Gregor70febae2010-05-28 00:49:12 +00001031 ND = cast<NamedDecl>(ND->getUnderlyingDecl());
1032
Douglas Gregor9d64c5e2009-09-21 20:51:25 +00001033 unsigned IDNS = Decl::IDNS_Ordinary;
David Blaikiebbafb8a2012-03-11 07:00:24 +00001034 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregor9858ed52010-06-15 20:26:51 +00001035 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member;
David Blaikiebbafb8a2012-03-11 07:00:24 +00001036 else if (SemaRef.getLangOpts().ObjC1) {
Douglas Gregor05fcf842010-11-02 20:36:02 +00001037 if (isa<ObjCIvarDecl>(ND))
1038 return true;
Douglas Gregor05fcf842010-11-02 20:36:02 +00001039 }
1040
Douglas Gregor9d64c5e2009-09-21 20:51:25 +00001041 return ND->getIdentifierNamespace() & IDNS;
1042}
1043
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001044/// \brief Determines whether this given declaration will be found by
Douglas Gregor70febae2010-05-28 00:49:12 +00001045/// ordinary name lookup but is not a type name.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001046bool ResultBuilder::IsOrdinaryNonTypeName(const NamedDecl *ND) const {
Douglas Gregor70febae2010-05-28 00:49:12 +00001047 ND = cast<NamedDecl>(ND->getUnderlyingDecl());
1048 if (isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND))
1049 return false;
1050
1051 unsigned IDNS = Decl::IDNS_Ordinary;
David Blaikiebbafb8a2012-03-11 07:00:24 +00001052 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregor9858ed52010-06-15 20:26:51 +00001053 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member;
David Blaikiebbafb8a2012-03-11 07:00:24 +00001054 else if (SemaRef.getLangOpts().ObjC1) {
Douglas Gregor05fcf842010-11-02 20:36:02 +00001055 if (isa<ObjCIvarDecl>(ND))
1056 return true;
Douglas Gregor05fcf842010-11-02 20:36:02 +00001057 }
1058
Douglas Gregor70febae2010-05-28 00:49:12 +00001059 return ND->getIdentifierNamespace() & IDNS;
1060}
1061
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001062bool ResultBuilder::IsIntegralConstantValue(const NamedDecl *ND) const {
Douglas Gregor85b50632010-07-28 21:50:18 +00001063 if (!IsOrdinaryNonTypeName(ND))
1064 return 0;
1065
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001066 if (const ValueDecl *VD = dyn_cast<ValueDecl>(ND->getUnderlyingDecl()))
Douglas Gregor85b50632010-07-28 21:50:18 +00001067 if (VD->getType()->isIntegralOrEnumerationType())
1068 return true;
1069
1070 return false;
1071}
1072
Douglas Gregor70febae2010-05-28 00:49:12 +00001073/// \brief Determines whether this given declaration will be found by
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001074/// ordinary name lookup.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001075bool ResultBuilder::IsOrdinaryNonValueName(const NamedDecl *ND) const {
Douglas Gregor70febae2010-05-28 00:49:12 +00001076 ND = cast<NamedDecl>(ND->getUnderlyingDecl());
1077
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001078 unsigned IDNS = Decl::IDNS_Ordinary;
David Blaikiebbafb8a2012-03-11 07:00:24 +00001079 if (SemaRef.getLangOpts().CPlusPlus)
John McCalle87beb22010-04-23 18:46:30 +00001080 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001081
1082 return (ND->getIdentifierNamespace() & IDNS) &&
Douglas Gregor70febae2010-05-28 00:49:12 +00001083 !isa<ValueDecl>(ND) && !isa<FunctionTemplateDecl>(ND) &&
1084 !isa<ObjCPropertyDecl>(ND);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001085}
1086
Douglas Gregor3545ff42009-09-21 16:56:56 +00001087/// \brief Determines whether the given declaration is suitable as the
1088/// start of a C++ nested-name-specifier, e.g., a class or namespace.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001089bool ResultBuilder::IsNestedNameSpecifier(const NamedDecl *ND) const {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001090 // Allow us to find class templates, too.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001091 if (const ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
Douglas Gregor3545ff42009-09-21 16:56:56 +00001092 ND = ClassTemplate->getTemplatedDecl();
1093
1094 return SemaRef.isAcceptableNestedNameSpecifier(ND);
1095}
1096
1097/// \brief Determines whether the given declaration is an enumeration.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001098bool ResultBuilder::IsEnum(const NamedDecl *ND) const {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001099 return isa<EnumDecl>(ND);
1100}
1101
1102/// \brief Determines whether the given declaration is a class or struct.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001103bool ResultBuilder::IsClassOrStruct(const NamedDecl *ND) const {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001104 // Allow us to find class templates, too.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001105 if (const ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
Douglas Gregor3545ff42009-09-21 16:56:56 +00001106 ND = ClassTemplate->getTemplatedDecl();
Joao Matosdc86f942012-08-31 18:45:21 +00001107
1108 // For purposes of this check, interfaces match too.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001109 if (const RecordDecl *RD = dyn_cast<RecordDecl>(ND))
Abramo Bagnara6150c882010-05-11 21:36:43 +00001110 return RD->getTagKind() == TTK_Class ||
Joao Matosdc86f942012-08-31 18:45:21 +00001111 RD->getTagKind() == TTK_Struct ||
1112 RD->getTagKind() == TTK_Interface;
Douglas Gregor3545ff42009-09-21 16:56:56 +00001113
1114 return false;
1115}
1116
1117/// \brief Determines whether the given declaration is a union.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001118bool ResultBuilder::IsUnion(const NamedDecl *ND) const {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001119 // Allow us to find class templates, too.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001120 if (const ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
Douglas Gregor3545ff42009-09-21 16:56:56 +00001121 ND = ClassTemplate->getTemplatedDecl();
1122
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001123 if (const RecordDecl *RD = dyn_cast<RecordDecl>(ND))
Abramo Bagnara6150c882010-05-11 21:36:43 +00001124 return RD->getTagKind() == TTK_Union;
Douglas Gregor3545ff42009-09-21 16:56:56 +00001125
1126 return false;
1127}
1128
1129/// \brief Determines whether the given declaration is a namespace.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001130bool ResultBuilder::IsNamespace(const NamedDecl *ND) const {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001131 return isa<NamespaceDecl>(ND);
1132}
1133
1134/// \brief Determines whether the given declaration is a namespace or
1135/// namespace alias.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001136bool ResultBuilder::IsNamespaceOrAlias(const NamedDecl *ND) const {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001137 return isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND);
1138}
1139
Douglas Gregor99fe2ad2009-12-11 17:31:05 +00001140/// \brief Determines whether the given declaration is a type.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001141bool ResultBuilder::IsType(const NamedDecl *ND) const {
1142 if (const UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(ND))
Douglas Gregor99fa2642010-08-24 01:06:58 +00001143 ND = Using->getTargetDecl();
1144
1145 return isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND);
Douglas Gregor3545ff42009-09-21 16:56:56 +00001146}
1147
Douglas Gregor99fe2ad2009-12-11 17:31:05 +00001148/// \brief Determines which members of a class should be visible via
1149/// "." or "->". Only value declarations, nested name specifiers, and
1150/// using declarations thereof should show up.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001151bool ResultBuilder::IsMember(const NamedDecl *ND) const {
1152 if (const UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(ND))
Douglas Gregor99fe2ad2009-12-11 17:31:05 +00001153 ND = Using->getTargetDecl();
1154
Douglas Gregor70788392009-12-11 18:14:22 +00001155 return isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND) ||
1156 isa<ObjCPropertyDecl>(ND);
Douglas Gregore412a5a2009-09-23 22:26:46 +00001157}
1158
Douglas Gregora817a192010-05-27 23:06:34 +00001159static bool isObjCReceiverType(ASTContext &C, QualType T) {
1160 T = C.getCanonicalType(T);
1161 switch (T->getTypeClass()) {
1162 case Type::ObjCObject:
1163 case Type::ObjCInterface:
1164 case Type::ObjCObjectPointer:
1165 return true;
1166
1167 case Type::Builtin:
1168 switch (cast<BuiltinType>(T)->getKind()) {
1169 case BuiltinType::ObjCId:
1170 case BuiltinType::ObjCClass:
1171 case BuiltinType::ObjCSel:
1172 return true;
1173
1174 default:
1175 break;
1176 }
1177 return false;
1178
1179 default:
1180 break;
1181 }
1182
David Blaikiebbafb8a2012-03-11 07:00:24 +00001183 if (!C.getLangOpts().CPlusPlus)
Douglas Gregora817a192010-05-27 23:06:34 +00001184 return false;
1185
1186 // FIXME: We could perform more analysis here to determine whether a
1187 // particular class type has any conversions to Objective-C types. For now,
1188 // just accept all class types.
1189 return T->isDependentType() || T->isRecordType();
1190}
1191
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001192bool ResultBuilder::IsObjCMessageReceiver(const NamedDecl *ND) const {
Douglas Gregora817a192010-05-27 23:06:34 +00001193 QualType T = getDeclUsageType(SemaRef.Context, ND);
1194 if (T.isNull())
1195 return false;
1196
1197 T = SemaRef.Context.getBaseElementType(T);
1198 return isObjCReceiverType(SemaRef.Context, T);
1199}
1200
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001201bool ResultBuilder::IsObjCMessageReceiverOrLambdaCapture(const NamedDecl *ND) const {
Douglas Gregord8c61782012-02-15 15:34:24 +00001202 if (IsObjCMessageReceiver(ND))
1203 return true;
1204
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001205 const VarDecl *Var = dyn_cast<VarDecl>(ND);
Douglas Gregord8c61782012-02-15 15:34:24 +00001206 if (!Var)
1207 return false;
1208
1209 return Var->hasLocalStorage() && !Var->hasAttr<BlocksAttr>();
1210}
1211
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001212bool ResultBuilder::IsObjCCollection(const NamedDecl *ND) const {
David Blaikiebbafb8a2012-03-11 07:00:24 +00001213 if ((SemaRef.getLangOpts().CPlusPlus && !IsOrdinaryName(ND)) ||
1214 (!SemaRef.getLangOpts().CPlusPlus && !IsOrdinaryNonTypeName(ND)))
Douglas Gregor68762e72010-08-23 21:17:50 +00001215 return false;
1216
1217 QualType T = getDeclUsageType(SemaRef.Context, ND);
1218 if (T.isNull())
1219 return false;
1220
1221 T = SemaRef.Context.getBaseElementType(T);
1222 return T->isObjCObjectType() || T->isObjCObjectPointerType() ||
1223 T->isObjCIdType() ||
David Blaikiebbafb8a2012-03-11 07:00:24 +00001224 (SemaRef.getLangOpts().CPlusPlus && T->isRecordType());
Douglas Gregor68762e72010-08-23 21:17:50 +00001225}
Douglas Gregora817a192010-05-27 23:06:34 +00001226
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001227bool ResultBuilder::IsImpossibleToSatisfy(const NamedDecl *ND) const {
Douglas Gregor0ac41382010-09-23 23:01:17 +00001228 return false;
1229}
1230
James Dennettf1243872012-06-17 05:33:25 +00001231/// \brief Determines whether the given declaration is an Objective-C
Douglas Gregor2b8162b2010-01-14 16:08:12 +00001232/// instance variable.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001233bool ResultBuilder::IsObjCIvar(const NamedDecl *ND) const {
Douglas Gregor2b8162b2010-01-14 16:08:12 +00001234 return isa<ObjCIvarDecl>(ND);
1235}
1236
Douglas Gregorc580c522010-01-14 01:09:38 +00001237namespace {
1238 /// \brief Visible declaration consumer that adds a code-completion result
1239 /// for each visible declaration.
1240 class CodeCompletionDeclConsumer : public VisibleDeclConsumer {
1241 ResultBuilder &Results;
1242 DeclContext *CurContext;
1243
1244 public:
1245 CodeCompletionDeclConsumer(ResultBuilder &Results, DeclContext *CurContext)
1246 : Results(Results), CurContext(CurContext) { }
1247
Erik Verbruggen2e657ff2011-10-06 07:27:49 +00001248 virtual void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx,
1249 bool InBaseClass) {
1250 bool Accessible = true;
Douglas Gregor03ba1882011-11-03 16:51:37 +00001251 if (Ctx)
1252 Accessible = Results.getSema().IsSimplyAccessible(ND, Ctx);
1253
Douglas Gregor0a0e2b32013-01-31 04:52:16 +00001254 ResultBuilder::Result Result(ND, Results.getBasePriority(ND), 0, false,
1255 Accessible);
Erik Verbruggen2e657ff2011-10-06 07:27:49 +00001256 Results.AddResult(Result, CurContext, Hiding, InBaseClass);
Douglas Gregorc580c522010-01-14 01:09:38 +00001257 }
1258 };
1259}
1260
Douglas Gregor3545ff42009-09-21 16:56:56 +00001261/// \brief Add type specifiers for the current language as keyword results.
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001262static void AddTypeSpecifierResults(const LangOptions &LangOpts,
Douglas Gregor3545ff42009-09-21 16:56:56 +00001263 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00001264 typedef CodeCompletionResult Result;
Douglas Gregora2db7932010-05-26 22:00:08 +00001265 Results.AddResult(Result("short", CCP_Type));
1266 Results.AddResult(Result("long", CCP_Type));
1267 Results.AddResult(Result("signed", CCP_Type));
1268 Results.AddResult(Result("unsigned", CCP_Type));
1269 Results.AddResult(Result("void", CCP_Type));
1270 Results.AddResult(Result("char", CCP_Type));
1271 Results.AddResult(Result("int", CCP_Type));
1272 Results.AddResult(Result("float", CCP_Type));
1273 Results.AddResult(Result("double", CCP_Type));
1274 Results.AddResult(Result("enum", CCP_Type));
1275 Results.AddResult(Result("struct", CCP_Type));
1276 Results.AddResult(Result("union", CCP_Type));
1277 Results.AddResult(Result("const", CCP_Type));
1278 Results.AddResult(Result("volatile", CCP_Type));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001279
Douglas Gregor3545ff42009-09-21 16:56:56 +00001280 if (LangOpts.C99) {
1281 // C99-specific
Douglas Gregora2db7932010-05-26 22:00:08 +00001282 Results.AddResult(Result("_Complex", CCP_Type));
1283 Results.AddResult(Result("_Imaginary", CCP_Type));
1284 Results.AddResult(Result("_Bool", CCP_Type));
1285 Results.AddResult(Result("restrict", CCP_Type));
Douglas Gregor3545ff42009-09-21 16:56:56 +00001286 }
1287
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00001288 CodeCompletionBuilder Builder(Results.getAllocator(),
1289 Results.getCodeCompletionTUInfo());
Douglas Gregor3545ff42009-09-21 16:56:56 +00001290 if (LangOpts.CPlusPlus) {
1291 // C++-specific
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00001292 Results.AddResult(Result("bool", CCP_Type +
1293 (LangOpts.ObjC1? CCD_bool_in_ObjC : 0)));
Douglas Gregora2db7932010-05-26 22:00:08 +00001294 Results.AddResult(Result("class", CCP_Type));
1295 Results.AddResult(Result("wchar_t", CCP_Type));
Douglas Gregor3545ff42009-09-21 16:56:56 +00001296
Douglas Gregorf4c33342010-05-28 00:22:41 +00001297 // typename qualified-id
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001298 Builder.AddTypedTextChunk("typename");
1299 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1300 Builder.AddPlaceholderChunk("qualifier");
1301 Builder.AddTextChunk("::");
1302 Builder.AddPlaceholderChunk("name");
1303 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf64acca2010-05-25 21:41:55 +00001304
Richard Smith2bf7fdb2013-01-02 11:42:31 +00001305 if (LangOpts.CPlusPlus11) {
Douglas Gregora2db7932010-05-26 22:00:08 +00001306 Results.AddResult(Result("auto", CCP_Type));
1307 Results.AddResult(Result("char16_t", CCP_Type));
1308 Results.AddResult(Result("char32_t", CCP_Type));
Douglas Gregorf4c33342010-05-28 00:22:41 +00001309
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001310 Builder.AddTypedTextChunk("decltype");
1311 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1312 Builder.AddPlaceholderChunk("expression");
1313 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1314 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor3545ff42009-09-21 16:56:56 +00001315 }
1316 }
1317
1318 // GNU extensions
1319 if (LangOpts.GNUMode) {
1320 // FIXME: Enable when we actually support decimal floating point.
Douglas Gregor78a21012010-01-14 16:01:26 +00001321 // Results.AddResult(Result("_Decimal32"));
1322 // Results.AddResult(Result("_Decimal64"));
1323 // Results.AddResult(Result("_Decimal128"));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001324
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001325 Builder.AddTypedTextChunk("typeof");
1326 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1327 Builder.AddPlaceholderChunk("expression");
1328 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00001329
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001330 Builder.AddTypedTextChunk("typeof");
1331 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1332 Builder.AddPlaceholderChunk("type");
1333 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1334 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor3545ff42009-09-21 16:56:56 +00001335 }
1336}
1337
John McCallfaf5fb42010-08-26 23:41:50 +00001338static void AddStorageSpecifiers(Sema::ParserCompletionContext CCC,
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001339 const LangOptions &LangOpts,
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001340 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00001341 typedef CodeCompletionResult Result;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001342 // Note: we don't suggest either "auto" or "register", because both
1343 // are pointless as storage specifiers. Elsewhere, we suggest "auto"
1344 // in C++0x as a type specifier.
Douglas Gregor78a21012010-01-14 16:01:26 +00001345 Results.AddResult(Result("extern"));
1346 Results.AddResult(Result("static"));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001347}
1348
John McCallfaf5fb42010-08-26 23:41:50 +00001349static void AddFunctionSpecifiers(Sema::ParserCompletionContext CCC,
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001350 const LangOptions &LangOpts,
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001351 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00001352 typedef CodeCompletionResult Result;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001353 switch (CCC) {
John McCallfaf5fb42010-08-26 23:41:50 +00001354 case Sema::PCC_Class:
1355 case Sema::PCC_MemberTemplate:
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001356 if (LangOpts.CPlusPlus) {
Douglas Gregor78a21012010-01-14 16:01:26 +00001357 Results.AddResult(Result("explicit"));
1358 Results.AddResult(Result("friend"));
1359 Results.AddResult(Result("mutable"));
1360 Results.AddResult(Result("virtual"));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001361 }
1362 // Fall through
1363
John McCallfaf5fb42010-08-26 23:41:50 +00001364 case Sema::PCC_ObjCInterface:
1365 case Sema::PCC_ObjCImplementation:
1366 case Sema::PCC_Namespace:
1367 case Sema::PCC_Template:
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001368 if (LangOpts.CPlusPlus || LangOpts.C99)
Douglas Gregor78a21012010-01-14 16:01:26 +00001369 Results.AddResult(Result("inline"));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001370 break;
1371
John McCallfaf5fb42010-08-26 23:41:50 +00001372 case Sema::PCC_ObjCInstanceVariableList:
1373 case Sema::PCC_Expression:
1374 case Sema::PCC_Statement:
1375 case Sema::PCC_ForInit:
1376 case Sema::PCC_Condition:
1377 case Sema::PCC_RecoveryInFunction:
1378 case Sema::PCC_Type:
Douglas Gregor5e35d592010-09-14 23:59:36 +00001379 case Sema::PCC_ParenthesizedExpression:
Douglas Gregor80039242011-02-15 20:33:25 +00001380 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001381 break;
1382 }
1383}
1384
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001385static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt);
1386static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt);
1387static void AddObjCVisibilityResults(const LangOptions &LangOpts,
Douglas Gregor48d46252010-01-13 21:54:15 +00001388 ResultBuilder &Results,
1389 bool NeedAt);
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001390static void AddObjCImplementationResults(const LangOptions &LangOpts,
Douglas Gregorf1934162010-01-13 21:24:21 +00001391 ResultBuilder &Results,
1392 bool NeedAt);
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001393static void AddObjCInterfaceResults(const LangOptions &LangOpts,
Douglas Gregorf1934162010-01-13 21:24:21 +00001394 ResultBuilder &Results,
1395 bool NeedAt);
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001396static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt);
Douglas Gregorf1934162010-01-13 21:24:21 +00001397
Douglas Gregorf4c33342010-05-28 00:22:41 +00001398static void AddTypedefResult(ResultBuilder &Results) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00001399 CodeCompletionBuilder Builder(Results.getAllocator(),
1400 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001401 Builder.AddTypedTextChunk("typedef");
1402 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1403 Builder.AddPlaceholderChunk("type");
1404 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1405 Builder.AddPlaceholderChunk("name");
1406 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00001407}
1408
John McCallfaf5fb42010-08-26 23:41:50 +00001409static bool WantTypesInContext(Sema::ParserCompletionContext CCC,
Douglas Gregor70febae2010-05-28 00:49:12 +00001410 const LangOptions &LangOpts) {
Douglas Gregor70febae2010-05-28 00:49:12 +00001411 switch (CCC) {
John McCallfaf5fb42010-08-26 23:41:50 +00001412 case Sema::PCC_Namespace:
1413 case Sema::PCC_Class:
1414 case Sema::PCC_ObjCInstanceVariableList:
1415 case Sema::PCC_Template:
1416 case Sema::PCC_MemberTemplate:
1417 case Sema::PCC_Statement:
1418 case Sema::PCC_RecoveryInFunction:
1419 case Sema::PCC_Type:
Douglas Gregor5e35d592010-09-14 23:59:36 +00001420 case Sema::PCC_ParenthesizedExpression:
Douglas Gregor80039242011-02-15 20:33:25 +00001421 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregor70febae2010-05-28 00:49:12 +00001422 return true;
1423
John McCallfaf5fb42010-08-26 23:41:50 +00001424 case Sema::PCC_Expression:
1425 case Sema::PCC_Condition:
Douglas Gregor5e35d592010-09-14 23:59:36 +00001426 return LangOpts.CPlusPlus;
1427
1428 case Sema::PCC_ObjCInterface:
1429 case Sema::PCC_ObjCImplementation:
Douglas Gregor70febae2010-05-28 00:49:12 +00001430 return false;
1431
John McCallfaf5fb42010-08-26 23:41:50 +00001432 case Sema::PCC_ForInit:
Douglas Gregor5e35d592010-09-14 23:59:36 +00001433 return LangOpts.CPlusPlus || LangOpts.ObjC1 || LangOpts.C99;
Douglas Gregor70febae2010-05-28 00:49:12 +00001434 }
David Blaikie8a40f702012-01-17 06:56:22 +00001435
1436 llvm_unreachable("Invalid ParserCompletionContext!");
Douglas Gregor70febae2010-05-28 00:49:12 +00001437}
1438
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00001439static PrintingPolicy getCompletionPrintingPolicy(const ASTContext &Context,
1440 const Preprocessor &PP) {
1441 PrintingPolicy Policy = Sema::getPrintingPolicy(Context, PP);
Douglas Gregore5c79d52011-10-18 21:20:17 +00001442 Policy.AnonymousTagLocations = false;
1443 Policy.SuppressStrongLifetime = true;
Douglas Gregor2e10cf92011-11-03 00:16:13 +00001444 Policy.SuppressUnwrittenScope = true;
Douglas Gregore5c79d52011-10-18 21:20:17 +00001445 return Policy;
1446}
1447
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00001448/// \brief Retrieve a printing policy suitable for code completion.
1449static PrintingPolicy getCompletionPrintingPolicy(Sema &S) {
1450 return getCompletionPrintingPolicy(S.Context, S.PP);
1451}
1452
Douglas Gregore5c79d52011-10-18 21:20:17 +00001453/// \brief Retrieve the string representation of the given type as a string
1454/// that has the appropriate lifetime for code completion.
1455///
1456/// This routine provides a fast path where we provide constant strings for
1457/// common type names.
1458static const char *GetCompletionTypeString(QualType T,
1459 ASTContext &Context,
1460 const PrintingPolicy &Policy,
1461 CodeCompletionAllocator &Allocator) {
1462 if (!T.getLocalQualifiers()) {
1463 // Built-in type names are constant strings.
1464 if (const BuiltinType *BT = dyn_cast<BuiltinType>(T))
Argyrios Kyrtzidisbbff3da2012-05-05 04:20:28 +00001465 return BT->getNameAsCString(Policy);
Douglas Gregore5c79d52011-10-18 21:20:17 +00001466
1467 // Anonymous tag types are constant strings.
1468 if (const TagType *TagT = dyn_cast<TagType>(T))
1469 if (TagDecl *Tag = TagT->getDecl())
1470 if (!Tag->getIdentifier() && !Tag->getTypedefNameForAnonDecl()) {
1471 switch (Tag->getTagKind()) {
1472 case TTK_Struct: return "struct <anonymous>";
Joao Matosdc86f942012-08-31 18:45:21 +00001473 case TTK_Interface: return "__interface <anonymous>";
1474 case TTK_Class: return "class <anonymous>";
Douglas Gregore5c79d52011-10-18 21:20:17 +00001475 case TTK_Union: return "union <anonymous>";
1476 case TTK_Enum: return "enum <anonymous>";
1477 }
1478 }
1479 }
1480
1481 // Slow path: format the type as a string.
1482 std::string Result;
1483 T.getAsStringInternal(Result, Policy);
1484 return Allocator.CopyString(Result);
1485}
1486
Douglas Gregord8c61782012-02-15 15:34:24 +00001487/// \brief Add a completion for "this", if we're in a member function.
1488static void addThisCompletion(Sema &S, ResultBuilder &Results) {
1489 QualType ThisTy = S.getCurrentThisType();
1490 if (ThisTy.isNull())
1491 return;
1492
1493 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00001494 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Douglas Gregord8c61782012-02-15 15:34:24 +00001495 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
1496 Builder.AddResultTypeChunk(GetCompletionTypeString(ThisTy,
1497 S.Context,
1498 Policy,
1499 Allocator));
1500 Builder.AddTypedTextChunk("this");
Joao Matosdc86f942012-08-31 18:45:21 +00001501 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
Douglas Gregord8c61782012-02-15 15:34:24 +00001502}
1503
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001504/// \brief Add language constructs that show up for "ordinary" names.
John McCallfaf5fb42010-08-26 23:41:50 +00001505static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001506 Scope *S,
1507 Sema &SemaRef,
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001508 ResultBuilder &Results) {
Douglas Gregore5c79d52011-10-18 21:20:17 +00001509 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00001510 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Douglas Gregore5c79d52011-10-18 21:20:17 +00001511 PrintingPolicy Policy = getCompletionPrintingPolicy(SemaRef);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001512
John McCall276321a2010-08-25 06:19:51 +00001513 typedef CodeCompletionResult Result;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001514 switch (CCC) {
John McCallfaf5fb42010-08-26 23:41:50 +00001515 case Sema::PCC_Namespace:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001516 if (SemaRef.getLangOpts().CPlusPlus) {
Douglas Gregorf4c33342010-05-28 00:22:41 +00001517 if (Results.includeCodePatterns()) {
1518 // namespace <identifier> { declarations }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001519 Builder.AddTypedTextChunk("namespace");
1520 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1521 Builder.AddPlaceholderChunk("identifier");
1522 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1523 Builder.AddPlaceholderChunk("declarations");
1524 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1525 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1526 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00001527 }
1528
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001529 // namespace identifier = identifier ;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001530 Builder.AddTypedTextChunk("namespace");
1531 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1532 Builder.AddPlaceholderChunk("name");
1533 Builder.AddChunk(CodeCompletionString::CK_Equal);
1534 Builder.AddPlaceholderChunk("namespace");
1535 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001536
1537 // Using directives
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001538 Builder.AddTypedTextChunk("using");
1539 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1540 Builder.AddTextChunk("namespace");
1541 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1542 Builder.AddPlaceholderChunk("identifier");
1543 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001544
1545 // asm(string-literal)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001546 Builder.AddTypedTextChunk("asm");
1547 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1548 Builder.AddPlaceholderChunk("string-literal");
1549 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1550 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001551
Douglas Gregorf4c33342010-05-28 00:22:41 +00001552 if (Results.includeCodePatterns()) {
1553 // Explicit template instantiation
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001554 Builder.AddTypedTextChunk("template");
1555 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1556 Builder.AddPlaceholderChunk("declaration");
1557 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00001558 }
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001559 }
Douglas Gregorf1934162010-01-13 21:24:21 +00001560
David Blaikiebbafb8a2012-03-11 07:00:24 +00001561 if (SemaRef.getLangOpts().ObjC1)
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001562 AddObjCTopLevelResults(Results, true);
Douglas Gregorf1934162010-01-13 21:24:21 +00001563
Douglas Gregorf4c33342010-05-28 00:22:41 +00001564 AddTypedefResult(Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001565 // Fall through
1566
John McCallfaf5fb42010-08-26 23:41:50 +00001567 case Sema::PCC_Class:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001568 if (SemaRef.getLangOpts().CPlusPlus) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001569 // Using declaration
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001570 Builder.AddTypedTextChunk("using");
1571 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1572 Builder.AddPlaceholderChunk("qualifier");
1573 Builder.AddTextChunk("::");
1574 Builder.AddPlaceholderChunk("name");
1575 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001576
Douglas Gregorf4c33342010-05-28 00:22:41 +00001577 // using typename qualifier::name (only in a dependent context)
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001578 if (SemaRef.CurContext->isDependentContext()) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001579 Builder.AddTypedTextChunk("using");
1580 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1581 Builder.AddTextChunk("typename");
1582 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1583 Builder.AddPlaceholderChunk("qualifier");
1584 Builder.AddTextChunk("::");
1585 Builder.AddPlaceholderChunk("name");
1586 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001587 }
1588
John McCallfaf5fb42010-08-26 23:41:50 +00001589 if (CCC == Sema::PCC_Class) {
Douglas Gregorf4c33342010-05-28 00:22:41 +00001590 AddTypedefResult(Results);
1591
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001592 // public:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001593 Builder.AddTypedTextChunk("public");
Douglas Gregor9489cdf2012-04-10 17:56:28 +00001594 if (Results.includeCodePatterns())
1595 Builder.AddChunk(CodeCompletionString::CK_Colon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001596 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001597
1598 // protected:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001599 Builder.AddTypedTextChunk("protected");
Douglas Gregor9489cdf2012-04-10 17:56:28 +00001600 if (Results.includeCodePatterns())
1601 Builder.AddChunk(CodeCompletionString::CK_Colon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001602 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001603
1604 // private:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001605 Builder.AddTypedTextChunk("private");
Douglas Gregor9489cdf2012-04-10 17:56:28 +00001606 if (Results.includeCodePatterns())
1607 Builder.AddChunk(CodeCompletionString::CK_Colon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001608 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001609 }
1610 }
1611 // Fall through
1612
John McCallfaf5fb42010-08-26 23:41:50 +00001613 case Sema::PCC_Template:
1614 case Sema::PCC_MemberTemplate:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001615 if (SemaRef.getLangOpts().CPlusPlus && Results.includeCodePatterns()) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001616 // template < parameters >
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001617 Builder.AddTypedTextChunk("template");
1618 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1619 Builder.AddPlaceholderChunk("parameters");
1620 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1621 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001622 }
1623
David Blaikiebbafb8a2012-03-11 07:00:24 +00001624 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
1625 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001626 break;
1627
John McCallfaf5fb42010-08-26 23:41:50 +00001628 case Sema::PCC_ObjCInterface:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001629 AddObjCInterfaceResults(SemaRef.getLangOpts(), Results, true);
1630 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
1631 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregorf1934162010-01-13 21:24:21 +00001632 break;
1633
John McCallfaf5fb42010-08-26 23:41:50 +00001634 case Sema::PCC_ObjCImplementation:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001635 AddObjCImplementationResults(SemaRef.getLangOpts(), Results, true);
1636 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
1637 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregorf1934162010-01-13 21:24:21 +00001638 break;
1639
John McCallfaf5fb42010-08-26 23:41:50 +00001640 case Sema::PCC_ObjCInstanceVariableList:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001641 AddObjCVisibilityResults(SemaRef.getLangOpts(), Results, true);
Douglas Gregor48d46252010-01-13 21:54:15 +00001642 break;
1643
John McCallfaf5fb42010-08-26 23:41:50 +00001644 case Sema::PCC_RecoveryInFunction:
1645 case Sema::PCC_Statement: {
Douglas Gregorf4c33342010-05-28 00:22:41 +00001646 AddTypedefResult(Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001647
David Blaikiebbafb8a2012-03-11 07:00:24 +00001648 if (SemaRef.getLangOpts().CPlusPlus && Results.includeCodePatterns() &&
1649 SemaRef.getLangOpts().CXXExceptions) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001650 Builder.AddTypedTextChunk("try");
1651 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1652 Builder.AddPlaceholderChunk("statements");
1653 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1654 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1655 Builder.AddTextChunk("catch");
1656 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1657 Builder.AddPlaceholderChunk("declaration");
1658 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1659 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1660 Builder.AddPlaceholderChunk("statements");
1661 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1662 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1663 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001664 }
David Blaikiebbafb8a2012-03-11 07:00:24 +00001665 if (SemaRef.getLangOpts().ObjC1)
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001666 AddObjCStatementResults(Results, true);
Douglas Gregorf1934162010-01-13 21:24:21 +00001667
Douglas Gregorf64acca2010-05-25 21:41:55 +00001668 if (Results.includeCodePatterns()) {
1669 // if (condition) { statements }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001670 Builder.AddTypedTextChunk("if");
1671 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00001672 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001673 Builder.AddPlaceholderChunk("condition");
Douglas Gregorf64acca2010-05-25 21:41:55 +00001674 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001675 Builder.AddPlaceholderChunk("expression");
1676 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1677 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1678 Builder.AddPlaceholderChunk("statements");
1679 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1680 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1681 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001682
Douglas Gregorf64acca2010-05-25 21:41:55 +00001683 // switch (condition) { }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001684 Builder.AddTypedTextChunk("switch");
1685 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00001686 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001687 Builder.AddPlaceholderChunk("condition");
Douglas Gregorf64acca2010-05-25 21:41:55 +00001688 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001689 Builder.AddPlaceholderChunk("expression");
1690 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1691 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1692 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1693 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1694 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf64acca2010-05-25 21:41:55 +00001695 }
1696
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001697 // Switch-specific statements.
John McCallaab3e412010-08-25 08:40:02 +00001698 if (!SemaRef.getCurFunction()->SwitchStack.empty()) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001699 // case expression:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001700 Builder.AddTypedTextChunk("case");
1701 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1702 Builder.AddPlaceholderChunk("expression");
1703 Builder.AddChunk(CodeCompletionString::CK_Colon);
1704 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001705
1706 // default:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001707 Builder.AddTypedTextChunk("default");
1708 Builder.AddChunk(CodeCompletionString::CK_Colon);
1709 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001710 }
1711
Douglas Gregorf64acca2010-05-25 21:41:55 +00001712 if (Results.includeCodePatterns()) {
1713 /// while (condition) { statements }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001714 Builder.AddTypedTextChunk("while");
1715 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00001716 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001717 Builder.AddPlaceholderChunk("condition");
Douglas Gregorf64acca2010-05-25 21:41:55 +00001718 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001719 Builder.AddPlaceholderChunk("expression");
1720 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1721 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1722 Builder.AddPlaceholderChunk("statements");
1723 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1724 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1725 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf64acca2010-05-25 21:41:55 +00001726
1727 // do { statements } while ( expression );
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001728 Builder.AddTypedTextChunk("do");
1729 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1730 Builder.AddPlaceholderChunk("statements");
1731 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1732 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1733 Builder.AddTextChunk("while");
1734 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1735 Builder.AddPlaceholderChunk("expression");
1736 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1737 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001738
Douglas Gregorf64acca2010-05-25 21:41:55 +00001739 // for ( for-init-statement ; condition ; expression ) { statements }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001740 Builder.AddTypedTextChunk("for");
1741 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00001742 if (SemaRef.getLangOpts().CPlusPlus || SemaRef.getLangOpts().C99)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001743 Builder.AddPlaceholderChunk("init-statement");
Douglas Gregorf64acca2010-05-25 21:41:55 +00001744 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001745 Builder.AddPlaceholderChunk("init-expression");
1746 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
1747 Builder.AddPlaceholderChunk("condition");
1748 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
1749 Builder.AddPlaceholderChunk("inc-expression");
1750 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1751 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1752 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1753 Builder.AddPlaceholderChunk("statements");
1754 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1755 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1756 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf64acca2010-05-25 21:41:55 +00001757 }
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001758
1759 if (S->getContinueParent()) {
1760 // continue ;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001761 Builder.AddTypedTextChunk("continue");
1762 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001763 }
1764
1765 if (S->getBreakParent()) {
1766 // break ;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001767 Builder.AddTypedTextChunk("break");
1768 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001769 }
1770
1771 // "return expression ;" or "return ;", depending on whether we
1772 // know the function is void or not.
1773 bool isVoid = false;
1774 if (FunctionDecl *Function = dyn_cast<FunctionDecl>(SemaRef.CurContext))
1775 isVoid = Function->getResultType()->isVoidType();
1776 else if (ObjCMethodDecl *Method
1777 = dyn_cast<ObjCMethodDecl>(SemaRef.CurContext))
1778 isVoid = Method->getResultType()->isVoidType();
Douglas Gregor9a28e842010-03-01 23:15:13 +00001779 else if (SemaRef.getCurBlock() &&
1780 !SemaRef.getCurBlock()->ReturnType.isNull())
1781 isVoid = SemaRef.getCurBlock()->ReturnType->isVoidType();
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001782 Builder.AddTypedTextChunk("return");
Douglas Gregor44272ca2010-02-18 04:06:48 +00001783 if (!isVoid) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001784 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1785 Builder.AddPlaceholderChunk("expression");
Douglas Gregor44272ca2010-02-18 04:06:48 +00001786 }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001787 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001788
Douglas Gregorf4c33342010-05-28 00:22:41 +00001789 // goto identifier ;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001790 Builder.AddTypedTextChunk("goto");
1791 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1792 Builder.AddPlaceholderChunk("label");
1793 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001794
Douglas Gregorf4c33342010-05-28 00:22:41 +00001795 // Using directives
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001796 Builder.AddTypedTextChunk("using");
1797 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1798 Builder.AddTextChunk("namespace");
1799 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1800 Builder.AddPlaceholderChunk("identifier");
1801 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001802 }
1803
1804 // Fall through (for statement expressions).
John McCallfaf5fb42010-08-26 23:41:50 +00001805 case Sema::PCC_ForInit:
1806 case Sema::PCC_Condition:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001807 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001808 // Fall through: conditions and statements can have expressions.
1809
Douglas Gregor5e35d592010-09-14 23:59:36 +00001810 case Sema::PCC_ParenthesizedExpression:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001811 if (SemaRef.getLangOpts().ObjCAutoRefCount &&
John McCall31168b02011-06-15 23:02:42 +00001812 CCC == Sema::PCC_ParenthesizedExpression) {
1813 // (__bridge <type>)<expression>
1814 Builder.AddTypedTextChunk("__bridge");
1815 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1816 Builder.AddPlaceholderChunk("type");
1817 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1818 Builder.AddPlaceholderChunk("expression");
1819 Results.AddResult(Result(Builder.TakeString()));
1820
1821 // (__bridge_transfer <Objective-C type>)<expression>
1822 Builder.AddTypedTextChunk("__bridge_transfer");
1823 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1824 Builder.AddPlaceholderChunk("Objective-C type");
1825 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1826 Builder.AddPlaceholderChunk("expression");
1827 Results.AddResult(Result(Builder.TakeString()));
1828
1829 // (__bridge_retained <CF type>)<expression>
1830 Builder.AddTypedTextChunk("__bridge_retained");
1831 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1832 Builder.AddPlaceholderChunk("CF type");
1833 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1834 Builder.AddPlaceholderChunk("expression");
1835 Results.AddResult(Result(Builder.TakeString()));
1836 }
1837 // Fall through
1838
John McCallfaf5fb42010-08-26 23:41:50 +00001839 case Sema::PCC_Expression: {
David Blaikiebbafb8a2012-03-11 07:00:24 +00001840 if (SemaRef.getLangOpts().CPlusPlus) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001841 // 'this', if we're in a non-static member function.
Douglas Gregord8c61782012-02-15 15:34:24 +00001842 addThisCompletion(SemaRef, Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001843
Douglas Gregore5c79d52011-10-18 21:20:17 +00001844 // true
1845 Builder.AddResultTypeChunk("bool");
1846 Builder.AddTypedTextChunk("true");
1847 Results.AddResult(Result(Builder.TakeString()));
1848
1849 // false
1850 Builder.AddResultTypeChunk("bool");
1851 Builder.AddTypedTextChunk("false");
1852 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001853
David Blaikiebbafb8a2012-03-11 07:00:24 +00001854 if (SemaRef.getLangOpts().RTTI) {
Douglas Gregorc05f6572011-04-12 02:47:21 +00001855 // dynamic_cast < type-id > ( expression )
1856 Builder.AddTypedTextChunk("dynamic_cast");
1857 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1858 Builder.AddPlaceholderChunk("type");
1859 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1860 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1861 Builder.AddPlaceholderChunk("expression");
1862 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1863 Results.AddResult(Result(Builder.TakeString()));
1864 }
Douglas Gregorf4c33342010-05-28 00:22:41 +00001865
1866 // static_cast < type-id > ( expression )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001867 Builder.AddTypedTextChunk("static_cast");
1868 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1869 Builder.AddPlaceholderChunk("type");
1870 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1871 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1872 Builder.AddPlaceholderChunk("expression");
1873 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1874 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001875
Douglas Gregorf4c33342010-05-28 00:22:41 +00001876 // reinterpret_cast < type-id > ( expression )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001877 Builder.AddTypedTextChunk("reinterpret_cast");
1878 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1879 Builder.AddPlaceholderChunk("type");
1880 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1881 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1882 Builder.AddPlaceholderChunk("expression");
1883 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1884 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001885
Douglas Gregorf4c33342010-05-28 00:22:41 +00001886 // const_cast < type-id > ( expression )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001887 Builder.AddTypedTextChunk("const_cast");
1888 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1889 Builder.AddPlaceholderChunk("type");
1890 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1891 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1892 Builder.AddPlaceholderChunk("expression");
1893 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1894 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001895
David Blaikiebbafb8a2012-03-11 07:00:24 +00001896 if (SemaRef.getLangOpts().RTTI) {
Douglas Gregorc05f6572011-04-12 02:47:21 +00001897 // typeid ( expression-or-type )
Douglas Gregore5c79d52011-10-18 21:20:17 +00001898 Builder.AddResultTypeChunk("std::type_info");
Douglas Gregorc05f6572011-04-12 02:47:21 +00001899 Builder.AddTypedTextChunk("typeid");
1900 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1901 Builder.AddPlaceholderChunk("expression-or-type");
1902 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1903 Results.AddResult(Result(Builder.TakeString()));
1904 }
1905
Douglas Gregorf4c33342010-05-28 00:22:41 +00001906 // new T ( ... )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001907 Builder.AddTypedTextChunk("new");
1908 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1909 Builder.AddPlaceholderChunk("type");
1910 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1911 Builder.AddPlaceholderChunk("expressions");
1912 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1913 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001914
Douglas Gregorf4c33342010-05-28 00:22:41 +00001915 // new T [ ] ( ... )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001916 Builder.AddTypedTextChunk("new");
1917 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1918 Builder.AddPlaceholderChunk("type");
1919 Builder.AddChunk(CodeCompletionString::CK_LeftBracket);
1920 Builder.AddPlaceholderChunk("size");
1921 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
1922 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1923 Builder.AddPlaceholderChunk("expressions");
1924 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1925 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001926
Douglas Gregorf4c33342010-05-28 00:22:41 +00001927 // delete expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00001928 Builder.AddResultTypeChunk("void");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001929 Builder.AddTypedTextChunk("delete");
1930 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1931 Builder.AddPlaceholderChunk("expression");
1932 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001933
Douglas Gregorf4c33342010-05-28 00:22:41 +00001934 // delete [] expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00001935 Builder.AddResultTypeChunk("void");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001936 Builder.AddTypedTextChunk("delete");
1937 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1938 Builder.AddChunk(CodeCompletionString::CK_LeftBracket);
1939 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
1940 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1941 Builder.AddPlaceholderChunk("expression");
1942 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001943
David Blaikiebbafb8a2012-03-11 07:00:24 +00001944 if (SemaRef.getLangOpts().CXXExceptions) {
Douglas Gregorc05f6572011-04-12 02:47:21 +00001945 // throw expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00001946 Builder.AddResultTypeChunk("void");
Douglas Gregorc05f6572011-04-12 02:47:21 +00001947 Builder.AddTypedTextChunk("throw");
1948 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1949 Builder.AddPlaceholderChunk("expression");
1950 Results.AddResult(Result(Builder.TakeString()));
1951 }
Douglas Gregor4205fef2011-10-18 16:29:03 +00001952
Douglas Gregora2db7932010-05-26 22:00:08 +00001953 // FIXME: Rethrow?
Douglas Gregor4205fef2011-10-18 16:29:03 +00001954
Richard Smith2bf7fdb2013-01-02 11:42:31 +00001955 if (SemaRef.getLangOpts().CPlusPlus11) {
Douglas Gregor4205fef2011-10-18 16:29:03 +00001956 // nullptr
Douglas Gregore5c79d52011-10-18 21:20:17 +00001957 Builder.AddResultTypeChunk("std::nullptr_t");
Douglas Gregor4205fef2011-10-18 16:29:03 +00001958 Builder.AddTypedTextChunk("nullptr");
1959 Results.AddResult(Result(Builder.TakeString()));
1960
1961 // alignof
Douglas Gregore5c79d52011-10-18 21:20:17 +00001962 Builder.AddResultTypeChunk("size_t");
Douglas Gregor4205fef2011-10-18 16:29:03 +00001963 Builder.AddTypedTextChunk("alignof");
1964 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1965 Builder.AddPlaceholderChunk("type");
1966 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1967 Results.AddResult(Result(Builder.TakeString()));
1968
1969 // noexcept
Douglas Gregore5c79d52011-10-18 21:20:17 +00001970 Builder.AddResultTypeChunk("bool");
Douglas Gregor4205fef2011-10-18 16:29:03 +00001971 Builder.AddTypedTextChunk("noexcept");
1972 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1973 Builder.AddPlaceholderChunk("expression");
1974 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1975 Results.AddResult(Result(Builder.TakeString()));
1976
1977 // sizeof... expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00001978 Builder.AddResultTypeChunk("size_t");
Douglas Gregor4205fef2011-10-18 16:29:03 +00001979 Builder.AddTypedTextChunk("sizeof...");
1980 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1981 Builder.AddPlaceholderChunk("parameter-pack");
1982 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1983 Results.AddResult(Result(Builder.TakeString()));
1984 }
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001985 }
1986
David Blaikiebbafb8a2012-03-11 07:00:24 +00001987 if (SemaRef.getLangOpts().ObjC1) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001988 // Add "super", if we're in an Objective-C class with a superclass.
Ted Kremenek305a0a72010-05-31 21:43:10 +00001989 if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl()) {
1990 // The interface can be NULL.
1991 if (ObjCInterfaceDecl *ID = Method->getClassInterface())
Douglas Gregore5c79d52011-10-18 21:20:17 +00001992 if (ID->getSuperClass()) {
1993 std::string SuperType;
1994 SuperType = ID->getSuperClass()->getNameAsString();
1995 if (Method->isInstanceMethod())
1996 SuperType += " *";
1997
1998 Builder.AddResultTypeChunk(Allocator.CopyString(SuperType));
1999 Builder.AddTypedTextChunk("super");
2000 Results.AddResult(Result(Builder.TakeString()));
2001 }
Ted Kremenek305a0a72010-05-31 21:43:10 +00002002 }
2003
Douglas Gregorf98e6a22010-01-13 23:51:12 +00002004 AddObjCExpressionResults(Results, true);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002005 }
2006
Jordan Rose58d54722012-06-30 21:33:57 +00002007 if (SemaRef.getLangOpts().C11) {
2008 // _Alignof
2009 Builder.AddResultTypeChunk("size_t");
2010 if (SemaRef.getASTContext().Idents.get("alignof").hasMacroDefinition())
2011 Builder.AddTypedTextChunk("alignof");
2012 else
2013 Builder.AddTypedTextChunk("_Alignof");
2014 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2015 Builder.AddPlaceholderChunk("type");
2016 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2017 Results.AddResult(Result(Builder.TakeString()));
2018 }
2019
Douglas Gregorf4c33342010-05-28 00:22:41 +00002020 // sizeof expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00002021 Builder.AddResultTypeChunk("size_t");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002022 Builder.AddTypedTextChunk("sizeof");
2023 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2024 Builder.AddPlaceholderChunk("expression-or-type");
2025 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2026 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002027 break;
2028 }
Douglas Gregor99fa2642010-08-24 01:06:58 +00002029
John McCallfaf5fb42010-08-26 23:41:50 +00002030 case Sema::PCC_Type:
Douglas Gregor80039242011-02-15 20:33:25 +00002031 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregor99fa2642010-08-24 01:06:58 +00002032 break;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002033 }
2034
David Blaikiebbafb8a2012-03-11 07:00:24 +00002035 if (WantTypesInContext(CCC, SemaRef.getLangOpts()))
2036 AddTypeSpecifierResults(SemaRef.getLangOpts(), Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002037
David Blaikiebbafb8a2012-03-11 07:00:24 +00002038 if (SemaRef.getLangOpts().CPlusPlus && CCC != Sema::PCC_Type)
Douglas Gregor78a21012010-01-14 16:01:26 +00002039 Results.AddResult(Result("operator"));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002040}
2041
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002042/// \brief If the given declaration has an associated type, add it as a result
2043/// type chunk.
2044static void AddResultTypeChunk(ASTContext &Context,
Douglas Gregor75acd922011-09-27 23:30:47 +00002045 const PrintingPolicy &Policy,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002046 const NamedDecl *ND,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002047 CodeCompletionBuilder &Result) {
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002048 if (!ND)
2049 return;
Douglas Gregor0212fd72010-09-21 16:06:22 +00002050
2051 // Skip constructors and conversion functions, which have their return types
2052 // built into their names.
2053 if (isa<CXXConstructorDecl>(ND) || isa<CXXConversionDecl>(ND))
2054 return;
2055
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002056 // Determine the type of the declaration (if it has a type).
Douglas Gregor0212fd72010-09-21 16:06:22 +00002057 QualType T;
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002058 if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(ND))
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002059 T = Function->getResultType();
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002060 else if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND))
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002061 T = Method->getResultType();
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002062 else if (const FunctionTemplateDecl *FunTmpl =
2063 dyn_cast<FunctionTemplateDecl>(ND))
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002064 T = FunTmpl->getTemplatedDecl()->getResultType();
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002065 else if (const EnumConstantDecl *Enumerator = dyn_cast<EnumConstantDecl>(ND))
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002066 T = Context.getTypeDeclType(cast<TypeDecl>(Enumerator->getDeclContext()));
2067 else if (isa<UnresolvedUsingValueDecl>(ND)) {
2068 /* Do nothing: ignore unresolved using declarations*/
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002069 } else if (const ValueDecl *Value = dyn_cast<ValueDecl>(ND)) {
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002070 T = Value->getType();
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002071 } else if (const ObjCPropertyDecl *Property = dyn_cast<ObjCPropertyDecl>(ND))
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002072 T = Property->getType();
2073
2074 if (T.isNull() || Context.hasSameType(T, Context.DependentTy))
2075 return;
2076
Douglas Gregor75acd922011-09-27 23:30:47 +00002077 Result.AddResultTypeChunk(GetCompletionTypeString(T, Context, Policy,
Douglas Gregor304f9b02011-02-01 21:15:40 +00002078 Result.getAllocator()));
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002079}
2080
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002081static void MaybeAddSentinel(ASTContext &Context,
2082 const NamedDecl *FunctionOrMethod,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002083 CodeCompletionBuilder &Result) {
Douglas Gregordbb71db2010-08-23 23:51:41 +00002084 if (SentinelAttr *Sentinel = FunctionOrMethod->getAttr<SentinelAttr>())
2085 if (Sentinel->getSentinel() == 0) {
David Blaikiebbafb8a2012-03-11 07:00:24 +00002086 if (Context.getLangOpts().ObjC1 &&
Douglas Gregordbb71db2010-08-23 23:51:41 +00002087 Context.Idents.get("nil").hasMacroDefinition())
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002088 Result.AddTextChunk(", nil");
Douglas Gregordbb71db2010-08-23 23:51:41 +00002089 else if (Context.Idents.get("NULL").hasMacroDefinition())
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002090 Result.AddTextChunk(", NULL");
Douglas Gregordbb71db2010-08-23 23:51:41 +00002091 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002092 Result.AddTextChunk(", (void*)0");
Douglas Gregordbb71db2010-08-23 23:51:41 +00002093 }
2094}
2095
Douglas Gregor8f08d742011-07-30 07:55:26 +00002096static std::string formatObjCParamQualifiers(unsigned ObjCQuals) {
2097 std::string Result;
2098 if (ObjCQuals & Decl::OBJC_TQ_In)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002099 Result += "in ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002100 else if (ObjCQuals & Decl::OBJC_TQ_Inout)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002101 Result += "inout ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002102 else if (ObjCQuals & Decl::OBJC_TQ_Out)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002103 Result += "out ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002104 if (ObjCQuals & Decl::OBJC_TQ_Bycopy)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002105 Result += "bycopy ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002106 else if (ObjCQuals & Decl::OBJC_TQ_Byref)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002107 Result += "byref ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002108 if (ObjCQuals & Decl::OBJC_TQ_Oneway)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002109 Result += "oneway ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002110 return Result;
2111}
2112
Douglas Gregore90dd002010-08-24 16:15:59 +00002113static std::string FormatFunctionParameter(ASTContext &Context,
Douglas Gregor75acd922011-09-27 23:30:47 +00002114 const PrintingPolicy &Policy,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002115 const ParmVarDecl *Param,
Douglas Gregord793e7c2011-10-18 04:23:19 +00002116 bool SuppressName = false,
2117 bool SuppressBlock = false) {
Douglas Gregore90dd002010-08-24 16:15:59 +00002118 bool ObjCMethodParam = isa<ObjCMethodDecl>(Param->getDeclContext());
2119 if (Param->getType()->isDependentType() ||
2120 !Param->getType()->isBlockPointerType()) {
2121 // The argument for a dependent or non-block parameter is a placeholder
2122 // containing that parameter's type.
2123 std::string Result;
2124
Douglas Gregor981a0c42010-08-29 19:47:46 +00002125 if (Param->getIdentifier() && !ObjCMethodParam && !SuppressName)
Douglas Gregore90dd002010-08-24 16:15:59 +00002126 Result = Param->getIdentifier()->getName();
2127
John McCall31168b02011-06-15 23:02:42 +00002128 Param->getType().getAsStringInternal(Result, Policy);
Douglas Gregore90dd002010-08-24 16:15:59 +00002129
2130 if (ObjCMethodParam) {
Douglas Gregor8f08d742011-07-30 07:55:26 +00002131 Result = "(" + formatObjCParamQualifiers(Param->getObjCDeclQualifier())
2132 + Result + ")";
Douglas Gregor981a0c42010-08-29 19:47:46 +00002133 if (Param->getIdentifier() && !SuppressName)
Douglas Gregore90dd002010-08-24 16:15:59 +00002134 Result += Param->getIdentifier()->getName();
2135 }
2136 return Result;
2137 }
2138
2139 // The argument for a block pointer parameter is a block literal with
2140 // the appropriate type.
Douglas Gregor24bbc462011-02-15 22:37:09 +00002141 FunctionTypeLoc *Block = 0;
2142 FunctionProtoTypeLoc *BlockProto = 0;
Douglas Gregore90dd002010-08-24 16:15:59 +00002143 TypeLoc TL;
2144 if (TypeSourceInfo *TSInfo = Param->getTypeSourceInfo()) {
2145 TL = TSInfo->getTypeLoc().getUnqualifiedLoc();
2146 while (true) {
2147 // Look through typedefs.
Douglas Gregord793e7c2011-10-18 04:23:19 +00002148 if (!SuppressBlock) {
2149 if (TypedefTypeLoc *TypedefTL = dyn_cast<TypedefTypeLoc>(&TL)) {
2150 if (TypeSourceInfo *InnerTSInfo
2151 = TypedefTL->getTypedefNameDecl()->getTypeSourceInfo()) {
2152 TL = InnerTSInfo->getTypeLoc().getUnqualifiedLoc();
2153 continue;
2154 }
2155 }
2156
2157 // Look through qualified types
2158 if (QualifiedTypeLoc *QualifiedTL = dyn_cast<QualifiedTypeLoc>(&TL)) {
2159 TL = QualifiedTL->getUnqualifiedLoc();
Douglas Gregore90dd002010-08-24 16:15:59 +00002160 continue;
2161 }
2162 }
2163
Douglas Gregore90dd002010-08-24 16:15:59 +00002164 // Try to get the function prototype behind the block pointer type,
2165 // then we're done.
2166 if (BlockPointerTypeLoc *BlockPtr
2167 = dyn_cast<BlockPointerTypeLoc>(&TL)) {
Abramo Bagnara6d810632010-12-14 22:11:44 +00002168 TL = BlockPtr->getPointeeLoc().IgnoreParens();
Douglas Gregor24bbc462011-02-15 22:37:09 +00002169 Block = dyn_cast<FunctionTypeLoc>(&TL);
2170 BlockProto = dyn_cast<FunctionProtoTypeLoc>(&TL);
Douglas Gregore90dd002010-08-24 16:15:59 +00002171 }
2172 break;
2173 }
2174 }
2175
2176 if (!Block) {
2177 // We were unable to find a FunctionProtoTypeLoc with parameter names
2178 // for the block; just use the parameter type as a placeholder.
2179 std::string Result;
Douglas Gregord793e7c2011-10-18 04:23:19 +00002180 if (!ObjCMethodParam && Param->getIdentifier())
2181 Result = Param->getIdentifier()->getName();
2182
John McCall31168b02011-06-15 23:02:42 +00002183 Param->getType().getUnqualifiedType().getAsStringInternal(Result, Policy);
Douglas Gregore90dd002010-08-24 16:15:59 +00002184
2185 if (ObjCMethodParam) {
Douglas Gregor8f08d742011-07-30 07:55:26 +00002186 Result = "(" + formatObjCParamQualifiers(Param->getObjCDeclQualifier())
2187 + Result + ")";
Douglas Gregore90dd002010-08-24 16:15:59 +00002188 if (Param->getIdentifier())
2189 Result += Param->getIdentifier()->getName();
2190 }
2191
2192 return Result;
2193 }
Douglas Gregord793e7c2011-10-18 04:23:19 +00002194
Douglas Gregore90dd002010-08-24 16:15:59 +00002195 // We have the function prototype behind the block pointer type, as it was
2196 // written in the source.
Douglas Gregor67da50e2010-09-08 22:47:51 +00002197 std::string Result;
2198 QualType ResultType = Block->getTypePtr()->getResultType();
Douglas Gregord793e7c2011-10-18 04:23:19 +00002199 if (!ResultType->isVoidType() || SuppressBlock)
John McCall31168b02011-06-15 23:02:42 +00002200 ResultType.getAsStringInternal(Result, Policy);
Douglas Gregord793e7c2011-10-18 04:23:19 +00002201
2202 // Format the parameter list.
2203 std::string Params;
Douglas Gregor24bbc462011-02-15 22:37:09 +00002204 if (!BlockProto || Block->getNumArgs() == 0) {
2205 if (BlockProto && BlockProto->getTypePtr()->isVariadic())
Douglas Gregord793e7c2011-10-18 04:23:19 +00002206 Params = "(...)";
Douglas Gregoraf25cfa2010-10-02 23:49:58 +00002207 else
Douglas Gregord793e7c2011-10-18 04:23:19 +00002208 Params = "(void)";
Douglas Gregor67da50e2010-09-08 22:47:51 +00002209 } else {
Douglas Gregord793e7c2011-10-18 04:23:19 +00002210 Params += "(";
Douglas Gregor67da50e2010-09-08 22:47:51 +00002211 for (unsigned I = 0, N = Block->getNumArgs(); I != N; ++I) {
2212 if (I)
Douglas Gregord793e7c2011-10-18 04:23:19 +00002213 Params += ", ";
2214 Params += FormatFunctionParameter(Context, Policy, Block->getArg(I),
2215 /*SuppressName=*/false,
2216 /*SuppressBlock=*/true);
Douglas Gregor67da50e2010-09-08 22:47:51 +00002217
Douglas Gregor24bbc462011-02-15 22:37:09 +00002218 if (I == N - 1 && BlockProto->getTypePtr()->isVariadic())
Douglas Gregord793e7c2011-10-18 04:23:19 +00002219 Params += ", ...";
Douglas Gregor67da50e2010-09-08 22:47:51 +00002220 }
Douglas Gregord793e7c2011-10-18 04:23:19 +00002221 Params += ")";
Douglas Gregor400f5972010-08-31 05:13:43 +00002222 }
Douglas Gregor67da50e2010-09-08 22:47:51 +00002223
Douglas Gregord793e7c2011-10-18 04:23:19 +00002224 if (SuppressBlock) {
2225 // Format as a parameter.
2226 Result = Result + " (^";
2227 if (Param->getIdentifier())
2228 Result += Param->getIdentifier()->getName();
2229 Result += ")";
2230 Result += Params;
2231 } else {
2232 // Format as a block literal argument.
2233 Result = '^' + Result;
2234 Result += Params;
2235
2236 if (Param->getIdentifier())
2237 Result += Param->getIdentifier()->getName();
2238 }
2239
Douglas Gregore90dd002010-08-24 16:15:59 +00002240 return Result;
2241}
2242
Douglas Gregor3545ff42009-09-21 16:56:56 +00002243/// \brief Add function parameter chunks to the given code completion string.
2244static void AddFunctionParameterChunks(ASTContext &Context,
Douglas Gregor75acd922011-09-27 23:30:47 +00002245 const PrintingPolicy &Policy,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002246 const FunctionDecl *Function,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002247 CodeCompletionBuilder &Result,
2248 unsigned Start = 0,
2249 bool InOptional = false) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002250 bool FirstParameter = true;
Douglas Gregor9eb77012009-11-07 00:00:49 +00002251
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002252 for (unsigned P = Start, N = Function->getNumParams(); P != N; ++P) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002253 const ParmVarDecl *Param = Function->getParamDecl(P);
Douglas Gregor3545ff42009-09-21 16:56:56 +00002254
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002255 if (Param->hasDefaultArg() && !InOptional) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002256 // When we see an optional default argument, put that argument and
2257 // the remaining default arguments into a new, optional string.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00002258 CodeCompletionBuilder Opt(Result.getAllocator(),
2259 Result.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002260 if (!FirstParameter)
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002261 Opt.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor75acd922011-09-27 23:30:47 +00002262 AddFunctionParameterChunks(Context, Policy, Function, Opt, P, true);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002263 Result.AddOptionalChunk(Opt.TakeString());
2264 break;
Douglas Gregor3545ff42009-09-21 16:56:56 +00002265 }
2266
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002267 if (FirstParameter)
2268 FirstParameter = false;
2269 else
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002270 Result.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002271
2272 InOptional = false;
Douglas Gregor3545ff42009-09-21 16:56:56 +00002273
2274 // Format the placeholder string.
Douglas Gregor75acd922011-09-27 23:30:47 +00002275 std::string PlaceholderStr = FormatFunctionParameter(Context, Policy,
2276 Param);
Douglas Gregore90dd002010-08-24 16:15:59 +00002277
Douglas Gregor400f5972010-08-31 05:13:43 +00002278 if (Function->isVariadic() && P == N - 1)
2279 PlaceholderStr += ", ...";
2280
Douglas Gregor3545ff42009-09-21 16:56:56 +00002281 // Add the placeholder string.
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002282 Result.AddPlaceholderChunk(
2283 Result.getAllocator().CopyString(PlaceholderStr));
Douglas Gregor3545ff42009-09-21 16:56:56 +00002284 }
Douglas Gregorba449032009-09-22 21:42:17 +00002285
2286 if (const FunctionProtoType *Proto
2287 = Function->getType()->getAs<FunctionProtoType>())
Douglas Gregordbb71db2010-08-23 23:51:41 +00002288 if (Proto->isVariadic()) {
Douglas Gregor400f5972010-08-31 05:13:43 +00002289 if (Proto->getNumArgs() == 0)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002290 Result.AddPlaceholderChunk("...");
Douglas Gregordbb71db2010-08-23 23:51:41 +00002291
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002292 MaybeAddSentinel(Context, Function, Result);
Douglas Gregordbb71db2010-08-23 23:51:41 +00002293 }
Douglas Gregor3545ff42009-09-21 16:56:56 +00002294}
2295
2296/// \brief Add template parameter chunks to the given code completion string.
2297static void AddTemplateParameterChunks(ASTContext &Context,
Douglas Gregor75acd922011-09-27 23:30:47 +00002298 const PrintingPolicy &Policy,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002299 const TemplateDecl *Template,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002300 CodeCompletionBuilder &Result,
2301 unsigned MaxParameters = 0,
2302 unsigned Start = 0,
2303 bool InDefaultArg = false) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002304 bool FirstParameter = true;
2305
2306 TemplateParameterList *Params = Template->getTemplateParameters();
2307 TemplateParameterList::iterator PEnd = Params->end();
2308 if (MaxParameters)
2309 PEnd = Params->begin() + MaxParameters;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002310 for (TemplateParameterList::iterator P = Params->begin() + Start;
2311 P != PEnd; ++P) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002312 bool HasDefaultArg = false;
2313 std::string PlaceholderStr;
2314 if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*P)) {
2315 if (TTP->wasDeclaredWithTypename())
2316 PlaceholderStr = "typename";
2317 else
2318 PlaceholderStr = "class";
2319
2320 if (TTP->getIdentifier()) {
2321 PlaceholderStr += ' ';
2322 PlaceholderStr += TTP->getIdentifier()->getName();
2323 }
2324
2325 HasDefaultArg = TTP->hasDefaultArgument();
2326 } else if (NonTypeTemplateParmDecl *NTTP
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002327 = dyn_cast<NonTypeTemplateParmDecl>(*P)) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002328 if (NTTP->getIdentifier())
2329 PlaceholderStr = NTTP->getIdentifier()->getName();
John McCall31168b02011-06-15 23:02:42 +00002330 NTTP->getType().getAsStringInternal(PlaceholderStr, Policy);
Douglas Gregor3545ff42009-09-21 16:56:56 +00002331 HasDefaultArg = NTTP->hasDefaultArgument();
2332 } else {
2333 assert(isa<TemplateTemplateParmDecl>(*P));
2334 TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*P);
2335
2336 // Since putting the template argument list into the placeholder would
2337 // be very, very long, we just use an abbreviation.
2338 PlaceholderStr = "template<...> class";
2339 if (TTP->getIdentifier()) {
2340 PlaceholderStr += ' ';
2341 PlaceholderStr += TTP->getIdentifier()->getName();
2342 }
2343
2344 HasDefaultArg = TTP->hasDefaultArgument();
2345 }
2346
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002347 if (HasDefaultArg && !InDefaultArg) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002348 // When we see an optional default argument, put that argument and
2349 // the remaining default arguments into a new, optional string.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00002350 CodeCompletionBuilder Opt(Result.getAllocator(),
2351 Result.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002352 if (!FirstParameter)
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002353 Opt.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor75acd922011-09-27 23:30:47 +00002354 AddTemplateParameterChunks(Context, Policy, Template, Opt, MaxParameters,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002355 P - Params->begin(), true);
2356 Result.AddOptionalChunk(Opt.TakeString());
2357 break;
Douglas Gregor3545ff42009-09-21 16:56:56 +00002358 }
2359
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002360 InDefaultArg = false;
2361
Douglas Gregor3545ff42009-09-21 16:56:56 +00002362 if (FirstParameter)
2363 FirstParameter = false;
2364 else
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002365 Result.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor3545ff42009-09-21 16:56:56 +00002366
2367 // Add the placeholder string.
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002368 Result.AddPlaceholderChunk(
2369 Result.getAllocator().CopyString(PlaceholderStr));
Douglas Gregor3545ff42009-09-21 16:56:56 +00002370 }
2371}
2372
Douglas Gregorf2510672009-09-21 19:57:38 +00002373/// \brief Add a qualifier to the given code-completion string, if the
2374/// provided nested-name-specifier is non-NULL.
Douglas Gregor0f622362009-12-11 18:44:16 +00002375static void
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002376AddQualifierToCompletionString(CodeCompletionBuilder &Result,
Douglas Gregor0f622362009-12-11 18:44:16 +00002377 NestedNameSpecifier *Qualifier,
2378 bool QualifierIsInformative,
Douglas Gregor75acd922011-09-27 23:30:47 +00002379 ASTContext &Context,
2380 const PrintingPolicy &Policy) {
Douglas Gregorf2510672009-09-21 19:57:38 +00002381 if (!Qualifier)
2382 return;
2383
2384 std::string PrintedNNS;
2385 {
2386 llvm::raw_string_ostream OS(PrintedNNS);
Douglas Gregor75acd922011-09-27 23:30:47 +00002387 Qualifier->print(OS, Policy);
Douglas Gregorf2510672009-09-21 19:57:38 +00002388 }
Douglas Gregor5bf52692009-09-22 23:15:58 +00002389 if (QualifierIsInformative)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002390 Result.AddInformativeChunk(Result.getAllocator().CopyString(PrintedNNS));
Douglas Gregor5bf52692009-09-22 23:15:58 +00002391 else
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002392 Result.AddTextChunk(Result.getAllocator().CopyString(PrintedNNS));
Douglas Gregorf2510672009-09-21 19:57:38 +00002393}
2394
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002395static void
2396AddFunctionTypeQualsToCompletionString(CodeCompletionBuilder &Result,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002397 const FunctionDecl *Function) {
Douglas Gregor0f622362009-12-11 18:44:16 +00002398 const FunctionProtoType *Proto
2399 = Function->getType()->getAs<FunctionProtoType>();
2400 if (!Proto || !Proto->getTypeQuals())
2401 return;
2402
Douglas Gregor304f9b02011-02-01 21:15:40 +00002403 // FIXME: Add ref-qualifier!
2404
2405 // Handle single qualifiers without copying
2406 if (Proto->getTypeQuals() == Qualifiers::Const) {
2407 Result.AddInformativeChunk(" const");
2408 return;
2409 }
2410
2411 if (Proto->getTypeQuals() == Qualifiers::Volatile) {
2412 Result.AddInformativeChunk(" volatile");
2413 return;
2414 }
2415
2416 if (Proto->getTypeQuals() == Qualifiers::Restrict) {
2417 Result.AddInformativeChunk(" restrict");
2418 return;
2419 }
2420
2421 // Handle multiple qualifiers.
Douglas Gregor0f622362009-12-11 18:44:16 +00002422 std::string QualsStr;
David Blaikief5697e52012-08-10 00:55:35 +00002423 if (Proto->isConst())
Douglas Gregor0f622362009-12-11 18:44:16 +00002424 QualsStr += " const";
David Blaikief5697e52012-08-10 00:55:35 +00002425 if (Proto->isVolatile())
Douglas Gregor0f622362009-12-11 18:44:16 +00002426 QualsStr += " volatile";
David Blaikief5697e52012-08-10 00:55:35 +00002427 if (Proto->isRestrict())
Douglas Gregor0f622362009-12-11 18:44:16 +00002428 QualsStr += " restrict";
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002429 Result.AddInformativeChunk(Result.getAllocator().CopyString(QualsStr));
Douglas Gregor0f622362009-12-11 18:44:16 +00002430}
2431
Douglas Gregor0212fd72010-09-21 16:06:22 +00002432/// \brief Add the name of the given declaration
Douglas Gregor75acd922011-09-27 23:30:47 +00002433static void AddTypedNameChunk(ASTContext &Context, const PrintingPolicy &Policy,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002434 const NamedDecl *ND,
2435 CodeCompletionBuilder &Result) {
Douglas Gregor0212fd72010-09-21 16:06:22 +00002436 DeclarationName Name = ND->getDeclName();
2437 if (!Name)
2438 return;
2439
2440 switch (Name.getNameKind()) {
Douglas Gregor304f9b02011-02-01 21:15:40 +00002441 case DeclarationName::CXXOperatorName: {
2442 const char *OperatorName = 0;
2443 switch (Name.getCXXOverloadedOperator()) {
2444 case OO_None:
2445 case OO_Conditional:
2446 case NUM_OVERLOADED_OPERATORS:
2447 OperatorName = "operator";
2448 break;
2449
2450#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
2451 case OO_##Name: OperatorName = "operator" Spelling; break;
2452#define OVERLOADED_OPERATOR_MULTI(Name,Spelling,Unary,Binary,MemberOnly)
2453#include "clang/Basic/OperatorKinds.def"
2454
2455 case OO_New: OperatorName = "operator new"; break;
2456 case OO_Delete: OperatorName = "operator delete"; break;
2457 case OO_Array_New: OperatorName = "operator new[]"; break;
2458 case OO_Array_Delete: OperatorName = "operator delete[]"; break;
2459 case OO_Call: OperatorName = "operator()"; break;
2460 case OO_Subscript: OperatorName = "operator[]"; break;
2461 }
2462 Result.AddTypedTextChunk(OperatorName);
2463 break;
2464 }
2465
Douglas Gregor0212fd72010-09-21 16:06:22 +00002466 case DeclarationName::Identifier:
2467 case DeclarationName::CXXConversionFunctionName:
Douglas Gregor0212fd72010-09-21 16:06:22 +00002468 case DeclarationName::CXXDestructorName:
2469 case DeclarationName::CXXLiteralOperatorName:
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002470 Result.AddTypedTextChunk(
2471 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor0212fd72010-09-21 16:06:22 +00002472 break;
2473
2474 case DeclarationName::CXXUsingDirective:
2475 case DeclarationName::ObjCZeroArgSelector:
2476 case DeclarationName::ObjCOneArgSelector:
2477 case DeclarationName::ObjCMultiArgSelector:
2478 break;
2479
2480 case DeclarationName::CXXConstructorName: {
2481 CXXRecordDecl *Record = 0;
2482 QualType Ty = Name.getCXXNameType();
2483 if (const RecordType *RecordTy = Ty->getAs<RecordType>())
2484 Record = cast<CXXRecordDecl>(RecordTy->getDecl());
2485 else if (const InjectedClassNameType *InjectedTy
2486 = Ty->getAs<InjectedClassNameType>())
2487 Record = InjectedTy->getDecl();
2488 else {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002489 Result.AddTypedTextChunk(
2490 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor0212fd72010-09-21 16:06:22 +00002491 break;
2492 }
2493
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002494 Result.AddTypedTextChunk(
2495 Result.getAllocator().CopyString(Record->getNameAsString()));
Douglas Gregor0212fd72010-09-21 16:06:22 +00002496 if (ClassTemplateDecl *Template = Record->getDescribedClassTemplate()) {
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002497 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Douglas Gregor75acd922011-09-27 23:30:47 +00002498 AddTemplateParameterChunks(Context, Policy, Template, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002499 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregor0212fd72010-09-21 16:06:22 +00002500 }
2501 break;
2502 }
2503 }
2504}
2505
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002506CodeCompletionString *CodeCompletionResult::CreateCodeCompletionString(Sema &S,
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00002507 CodeCompletionAllocator &Allocator,
Dmitri Gribenko3292d062012-07-02 17:35:10 +00002508 CodeCompletionTUInfo &CCTUInfo,
2509 bool IncludeBriefComments) {
2510 return CreateCodeCompletionString(S.Context, S.PP, Allocator, CCTUInfo,
2511 IncludeBriefComments);
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002512}
2513
Douglas Gregor3545ff42009-09-21 16:56:56 +00002514/// \brief If possible, create a new code completion string for the given
2515/// result.
2516///
2517/// \returns Either a new, heap-allocated code completion string describing
2518/// how to use this result, or NULL to indicate that the string or name of the
2519/// result is all that is needed.
2520CodeCompletionString *
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002521CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx,
2522 Preprocessor &PP,
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00002523 CodeCompletionAllocator &Allocator,
Dmitri Gribenko3292d062012-07-02 17:35:10 +00002524 CodeCompletionTUInfo &CCTUInfo,
2525 bool IncludeBriefComments) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00002526 CodeCompletionBuilder Result(Allocator, CCTUInfo, Priority, Availability);
Douglas Gregor9eb77012009-11-07 00:00:49 +00002527
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002528 PrintingPolicy Policy = getCompletionPrintingPolicy(Ctx, PP);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002529 if (Kind == RK_Pattern) {
2530 Pattern->Priority = Priority;
2531 Pattern->Availability = Availability;
Douglas Gregor78254c82012-03-27 23:34:16 +00002532
2533 if (Declaration) {
2534 Result.addParentContext(Declaration->getDeclContext());
Douglas Gregor78254c82012-03-27 23:34:16 +00002535 Pattern->ParentName = Result.getParentName();
2536 }
2537
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002538 return Pattern;
2539 }
Douglas Gregorf09935f2009-12-01 05:55:20 +00002540
Douglas Gregorf09935f2009-12-01 05:55:20 +00002541 if (Kind == RK_Keyword) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002542 Result.AddTypedTextChunk(Keyword);
2543 return Result.TakeString();
Douglas Gregorf09935f2009-12-01 05:55:20 +00002544 }
Douglas Gregor3545ff42009-09-21 16:56:56 +00002545
Douglas Gregorf329c7c2009-10-30 16:50:04 +00002546 if (Kind == RK_Macro) {
Douglas Gregor8cb17462012-10-09 16:01:50 +00002547 MacroInfo *MI = PP.getMacroInfoHistory(Macro);
Douglas Gregorf09935f2009-12-01 05:55:20 +00002548 assert(MI && "Not a macro?");
2549
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002550 Result.AddTypedTextChunk(
2551 Result.getAllocator().CopyString(Macro->getName()));
Douglas Gregorf09935f2009-12-01 05:55:20 +00002552
2553 if (!MI->isFunctionLike())
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002554 return Result.TakeString();
Douglas Gregorf329c7c2009-10-30 16:50:04 +00002555
2556 // Format a function-like macro with placeholders for the arguments.
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002557 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregor0c505312011-07-30 08:17:44 +00002558 MacroInfo::arg_iterator A = MI->arg_begin(), AEnd = MI->arg_end();
Douglas Gregor3aa55262012-01-21 00:43:38 +00002559
2560 // C99 variadic macros add __VA_ARGS__ at the end. Skip it.
2561 if (MI->isC99Varargs()) {
2562 --AEnd;
2563
2564 if (A == AEnd) {
2565 Result.AddPlaceholderChunk("...");
2566 }
Douglas Gregor0c505312011-07-30 08:17:44 +00002567 }
Douglas Gregor3aa55262012-01-21 00:43:38 +00002568
Douglas Gregor0c505312011-07-30 08:17:44 +00002569 for (MacroInfo::arg_iterator A = MI->arg_begin(); A != AEnd; ++A) {
Douglas Gregorf329c7c2009-10-30 16:50:04 +00002570 if (A != MI->arg_begin())
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002571 Result.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor3aa55262012-01-21 00:43:38 +00002572
2573 if (MI->isVariadic() && (A+1) == AEnd) {
Dylan Noblesmith2c1dd272012-02-05 02:13:05 +00002574 SmallString<32> Arg = (*A)->getName();
Douglas Gregor3aa55262012-01-21 00:43:38 +00002575 if (MI->isC99Varargs())
2576 Arg += ", ...";
2577 else
2578 Arg += "...";
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002579 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregor3aa55262012-01-21 00:43:38 +00002580 break;
Douglas Gregorf329c7c2009-10-30 16:50:04 +00002581 }
Douglas Gregor3aa55262012-01-21 00:43:38 +00002582
2583 // Non-variadic macros are simple.
2584 Result.AddPlaceholderChunk(
2585 Result.getAllocator().CopyString((*A)->getName()));
Douglas Gregor0c505312011-07-30 08:17:44 +00002586 }
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002587 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002588 return Result.TakeString();
Douglas Gregorf329c7c2009-10-30 16:50:04 +00002589 }
2590
Douglas Gregorf64acca2010-05-25 21:41:55 +00002591 assert(Kind == RK_Declaration && "Missed a result kind?");
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002592 const NamedDecl *ND = Declaration;
Douglas Gregor78254c82012-03-27 23:34:16 +00002593 Result.addParentContext(ND->getDeclContext());
Dmitri Gribenko3292d062012-07-02 17:35:10 +00002594
2595 if (IncludeBriefComments) {
2596 // Add documentation comment, if it exists.
Dmitri Gribenkoa43ec182012-08-11 00:51:43 +00002597 if (const RawComment *RC = Ctx.getRawCommentForAnyRedecl(ND)) {
Dmitri Gribenko3292d062012-07-02 17:35:10 +00002598 Result.addBriefComment(RC->getBriefText(Ctx));
2599 }
2600 }
2601
Douglas Gregor9eb77012009-11-07 00:00:49 +00002602 if (StartsNestedNameSpecifier) {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002603 Result.AddTypedTextChunk(
2604 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002605 Result.AddTextChunk("::");
2606 return Result.TakeString();
Douglas Gregor9eb77012009-11-07 00:00:49 +00002607 }
Erik Verbruggen98ea7f62011-10-14 15:31:08 +00002608
2609 for (Decl::attr_iterator i = ND->attr_begin(); i != ND->attr_end(); ++i) {
2610 if (AnnotateAttr *Attr = dyn_cast_or_null<AnnotateAttr>(*i)) {
2611 Result.AddAnnotation(Result.getAllocator().CopyString(Attr->getAnnotation()));
2612 }
2613 }
Douglas Gregor9eb77012009-11-07 00:00:49 +00002614
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002615 AddResultTypeChunk(Ctx, Policy, ND, Result);
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002616
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002617 if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(ND)) {
Douglas Gregor5bf52692009-09-22 23:15:58 +00002618 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002619 Ctx, Policy);
2620 AddTypedNameChunk(Ctx, Policy, ND, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002621 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002622 AddFunctionParameterChunks(Ctx, Policy, Function, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002623 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor0f622362009-12-11 18:44:16 +00002624 AddFunctionTypeQualsToCompletionString(Result, Function);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002625 return Result.TakeString();
Douglas Gregor3545ff42009-09-21 16:56:56 +00002626 }
2627
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002628 if (const FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND)) {
Douglas Gregor5bf52692009-09-22 23:15:58 +00002629 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002630 Ctx, Policy);
Douglas Gregor3545ff42009-09-21 16:56:56 +00002631 FunctionDecl *Function = FunTmpl->getTemplatedDecl();
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002632 AddTypedNameChunk(Ctx, Policy, Function, Result);
Douglas Gregor0212fd72010-09-21 16:06:22 +00002633
Douglas Gregor3545ff42009-09-21 16:56:56 +00002634 // Figure out which template parameters are deduced (or have default
2635 // arguments).
Benjamin Kramere0513cb2012-01-30 16:17:39 +00002636 llvm::SmallBitVector Deduced;
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002637 Sema::MarkDeducedTemplateParameters(Ctx, FunTmpl, Deduced);
Douglas Gregor3545ff42009-09-21 16:56:56 +00002638 unsigned LastDeducibleArgument;
2639 for (LastDeducibleArgument = Deduced.size(); LastDeducibleArgument > 0;
2640 --LastDeducibleArgument) {
2641 if (!Deduced[LastDeducibleArgument - 1]) {
2642 // C++0x: Figure out if the template argument has a default. If so,
2643 // the user doesn't need to type this argument.
2644 // FIXME: We need to abstract template parameters better!
2645 bool HasDefaultArg = false;
2646 NamedDecl *Param = FunTmpl->getTemplateParameters()->getParam(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002647 LastDeducibleArgument - 1);
Douglas Gregor3545ff42009-09-21 16:56:56 +00002648 if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param))
2649 HasDefaultArg = TTP->hasDefaultArgument();
2650 else if (NonTypeTemplateParmDecl *NTTP
2651 = dyn_cast<NonTypeTemplateParmDecl>(Param))
2652 HasDefaultArg = NTTP->hasDefaultArgument();
2653 else {
2654 assert(isa<TemplateTemplateParmDecl>(Param));
2655 HasDefaultArg
Douglas Gregor9eb77012009-11-07 00:00:49 +00002656 = cast<TemplateTemplateParmDecl>(Param)->hasDefaultArgument();
Douglas Gregor3545ff42009-09-21 16:56:56 +00002657 }
2658
2659 if (!HasDefaultArg)
2660 break;
2661 }
2662 }
2663
2664 if (LastDeducibleArgument) {
2665 // Some of the function template arguments cannot be deduced from a
2666 // function call, so we introduce an explicit template argument list
2667 // containing all of the arguments up to the first deducible argument.
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002668 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002669 AddTemplateParameterChunks(Ctx, Policy, FunTmpl, Result,
Douglas Gregor3545ff42009-09-21 16:56:56 +00002670 LastDeducibleArgument);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002671 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregor3545ff42009-09-21 16:56:56 +00002672 }
2673
2674 // Add the function parameters
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002675 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002676 AddFunctionParameterChunks(Ctx, Policy, Function, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002677 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor0f622362009-12-11 18:44:16 +00002678 AddFunctionTypeQualsToCompletionString(Result, Function);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002679 return Result.TakeString();
Douglas Gregor3545ff42009-09-21 16:56:56 +00002680 }
2681
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002682 if (const TemplateDecl *Template = dyn_cast<TemplateDecl>(ND)) {
Douglas Gregor5bf52692009-09-22 23:15:58 +00002683 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002684 Ctx, Policy);
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002685 Result.AddTypedTextChunk(
2686 Result.getAllocator().CopyString(Template->getNameAsString()));
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002687 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002688 AddTemplateParameterChunks(Ctx, Policy, Template, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002689 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002690 return Result.TakeString();
Douglas Gregor3545ff42009-09-21 16:56:56 +00002691 }
2692
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002693 if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND)) {
Douglas Gregord3c5d792009-11-17 16:44:22 +00002694 Selector Sel = Method->getSelector();
2695 if (Sel.isUnarySelector()) {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002696 Result.AddTypedTextChunk(Result.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00002697 Sel.getNameForSlot(0)));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002698 return Result.TakeString();
Douglas Gregord3c5d792009-11-17 16:44:22 +00002699 }
2700
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00002701 std::string SelName = Sel.getNameForSlot(0).str();
Douglas Gregor1b605f72009-11-19 01:08:35 +00002702 SelName += ':';
2703 if (StartParameter == 0)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002704 Result.AddTypedTextChunk(Result.getAllocator().CopyString(SelName));
Douglas Gregor1b605f72009-11-19 01:08:35 +00002705 else {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002706 Result.AddInformativeChunk(Result.getAllocator().CopyString(SelName));
Douglas Gregor1b605f72009-11-19 01:08:35 +00002707
2708 // If there is only one parameter, and we're past it, add an empty
2709 // typed-text chunk since there is nothing to type.
2710 if (Method->param_size() == 1)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002711 Result.AddTypedTextChunk("");
Douglas Gregor1b605f72009-11-19 01:08:35 +00002712 }
Douglas Gregord3c5d792009-11-17 16:44:22 +00002713 unsigned Idx = 0;
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002714 for (ObjCMethodDecl::param_const_iterator P = Method->param_begin(),
2715 PEnd = Method->param_end();
Douglas Gregord3c5d792009-11-17 16:44:22 +00002716 P != PEnd; (void)++P, ++Idx) {
2717 if (Idx > 0) {
Douglas Gregor1b605f72009-11-19 01:08:35 +00002718 std::string Keyword;
2719 if (Idx > StartParameter)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002720 Result.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregord3c5d792009-11-17 16:44:22 +00002721 if (IdentifierInfo *II = Sel.getIdentifierInfoForSlot(Idx))
Benjamin Kramer632500c2011-07-26 16:59:25 +00002722 Keyword += II->getName();
Douglas Gregord3c5d792009-11-17 16:44:22 +00002723 Keyword += ":";
Douglas Gregor95887f92010-07-08 23:20:03 +00002724 if (Idx < StartParameter || AllParametersAreInformative)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002725 Result.AddInformativeChunk(Result.getAllocator().CopyString(Keyword));
Douglas Gregor8e3e8742010-10-18 21:05:04 +00002726 else
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002727 Result.AddTypedTextChunk(Result.getAllocator().CopyString(Keyword));
Douglas Gregord3c5d792009-11-17 16:44:22 +00002728 }
Douglas Gregor1b605f72009-11-19 01:08:35 +00002729
2730 // If we're before the starting parameter, skip the placeholder.
2731 if (Idx < StartParameter)
2732 continue;
Douglas Gregord3c5d792009-11-17 16:44:22 +00002733
2734 std::string Arg;
Douglas Gregore90dd002010-08-24 16:15:59 +00002735
2736 if ((*P)->getType()->isBlockPointerType() && !DeclaringEntity)
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002737 Arg = FormatFunctionParameter(Ctx, Policy, *P, true);
Douglas Gregore90dd002010-08-24 16:15:59 +00002738 else {
John McCall31168b02011-06-15 23:02:42 +00002739 (*P)->getType().getAsStringInternal(Arg, Policy);
Douglas Gregor8f08d742011-07-30 07:55:26 +00002740 Arg = "(" + formatObjCParamQualifiers((*P)->getObjCDeclQualifier())
2741 + Arg + ")";
Douglas Gregore90dd002010-08-24 16:15:59 +00002742 if (IdentifierInfo *II = (*P)->getIdentifier())
Douglas Gregor981a0c42010-08-29 19:47:46 +00002743 if (DeclaringEntity || AllParametersAreInformative)
Benjamin Kramer632500c2011-07-26 16:59:25 +00002744 Arg += II->getName();
Douglas Gregore90dd002010-08-24 16:15:59 +00002745 }
2746
Douglas Gregor400f5972010-08-31 05:13:43 +00002747 if (Method->isVariadic() && (P + 1) == PEnd)
2748 Arg += ", ...";
2749
Douglas Gregor95887f92010-07-08 23:20:03 +00002750 if (DeclaringEntity)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002751 Result.AddTextChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregor95887f92010-07-08 23:20:03 +00002752 else if (AllParametersAreInformative)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002753 Result.AddInformativeChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregorc8537c52009-11-19 07:41:15 +00002754 else
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002755 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregord3c5d792009-11-17 16:44:22 +00002756 }
2757
Douglas Gregor04c5f972009-12-23 00:21:46 +00002758 if (Method->isVariadic()) {
Douglas Gregor400f5972010-08-31 05:13:43 +00002759 if (Method->param_size() == 0) {
2760 if (DeclaringEntity)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002761 Result.AddTextChunk(", ...");
Douglas Gregor400f5972010-08-31 05:13:43 +00002762 else if (AllParametersAreInformative)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002763 Result.AddInformativeChunk(", ...");
Douglas Gregor400f5972010-08-31 05:13:43 +00002764 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002765 Result.AddPlaceholderChunk(", ...");
Douglas Gregor400f5972010-08-31 05:13:43 +00002766 }
Douglas Gregordbb71db2010-08-23 23:51:41 +00002767
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002768 MaybeAddSentinel(Ctx, Method, Result);
Douglas Gregor04c5f972009-12-23 00:21:46 +00002769 }
2770
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002771 return Result.TakeString();
Douglas Gregord3c5d792009-11-17 16:44:22 +00002772 }
2773
Douglas Gregorf09935f2009-12-01 05:55:20 +00002774 if (Qualifier)
Douglas Gregor5bf52692009-09-22 23:15:58 +00002775 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002776 Ctx, Policy);
Douglas Gregorf09935f2009-12-01 05:55:20 +00002777
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002778 Result.AddTypedTextChunk(
2779 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002780 return Result.TakeString();
Douglas Gregor3545ff42009-09-21 16:56:56 +00002781}
2782
Douglas Gregorf0f51982009-09-23 00:34:09 +00002783CodeCompletionString *
2784CodeCompleteConsumer::OverloadCandidate::CreateSignatureString(
2785 unsigned CurrentArg,
Douglas Gregor36e3b5c2010-10-11 21:37:58 +00002786 Sema &S,
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00002787 CodeCompletionAllocator &Allocator,
2788 CodeCompletionTUInfo &CCTUInfo) const {
Douglas Gregor75acd922011-09-27 23:30:47 +00002789 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
John McCall31168b02011-06-15 23:02:42 +00002790
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002791 // FIXME: Set priority, availability appropriately.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00002792 CodeCompletionBuilder Result(Allocator,CCTUInfo, 1, CXAvailability_Available);
Douglas Gregorf0f51982009-09-23 00:34:09 +00002793 FunctionDecl *FDecl = getFunction();
Douglas Gregor75acd922011-09-27 23:30:47 +00002794 AddResultTypeChunk(S.Context, Policy, FDecl, Result);
Douglas Gregorf0f51982009-09-23 00:34:09 +00002795 const FunctionProtoType *Proto
2796 = dyn_cast<FunctionProtoType>(getFunctionType());
2797 if (!FDecl && !Proto) {
2798 // Function without a prototype. Just give the return type and a
2799 // highlighted ellipsis.
2800 const FunctionType *FT = getFunctionType();
Douglas Gregor304f9b02011-02-01 21:15:40 +00002801 Result.AddTextChunk(GetCompletionTypeString(FT->getResultType(),
Douglas Gregor75acd922011-09-27 23:30:47 +00002802 S.Context, Policy,
Douglas Gregor304f9b02011-02-01 21:15:40 +00002803 Result.getAllocator()));
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002804 Result.AddChunk(CodeCompletionString::CK_LeftParen);
2805 Result.AddChunk(CodeCompletionString::CK_CurrentParameter, "...");
2806 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002807 return Result.TakeString();
Douglas Gregorf0f51982009-09-23 00:34:09 +00002808 }
2809
2810 if (FDecl)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002811 Result.AddTextChunk(
2812 Result.getAllocator().CopyString(FDecl->getNameAsString()));
Douglas Gregorf0f51982009-09-23 00:34:09 +00002813 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002814 Result.AddTextChunk(
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002815 Result.getAllocator().CopyString(
John McCall31168b02011-06-15 23:02:42 +00002816 Proto->getResultType().getAsString(Policy)));
Douglas Gregorf0f51982009-09-23 00:34:09 +00002817
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002818 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregorf0f51982009-09-23 00:34:09 +00002819 unsigned NumParams = FDecl? FDecl->getNumParams() : Proto->getNumArgs();
2820 for (unsigned I = 0; I != NumParams; ++I) {
2821 if (I)
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002822 Result.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregorf0f51982009-09-23 00:34:09 +00002823
2824 std::string ArgString;
2825 QualType ArgType;
2826
2827 if (FDecl) {
2828 ArgString = FDecl->getParamDecl(I)->getNameAsString();
2829 ArgType = FDecl->getParamDecl(I)->getOriginalType();
2830 } else {
2831 ArgType = Proto->getArgType(I);
2832 }
2833
John McCall31168b02011-06-15 23:02:42 +00002834 ArgType.getAsStringInternal(ArgString, Policy);
Douglas Gregorf0f51982009-09-23 00:34:09 +00002835
2836 if (I == CurrentArg)
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002837 Result.AddChunk(CodeCompletionString::CK_CurrentParameter,
2838 Result.getAllocator().CopyString(ArgString));
Douglas Gregorf0f51982009-09-23 00:34:09 +00002839 else
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002840 Result.AddTextChunk(Result.getAllocator().CopyString(ArgString));
Douglas Gregorf0f51982009-09-23 00:34:09 +00002841 }
2842
2843 if (Proto && Proto->isVariadic()) {
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002844 Result.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregorf0f51982009-09-23 00:34:09 +00002845 if (CurrentArg < NumParams)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002846 Result.AddTextChunk("...");
Douglas Gregorf0f51982009-09-23 00:34:09 +00002847 else
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002848 Result.AddChunk(CodeCompletionString::CK_CurrentParameter, "...");
Douglas Gregorf0f51982009-09-23 00:34:09 +00002849 }
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002850 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorf0f51982009-09-23 00:34:09 +00002851
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002852 return Result.TakeString();
Douglas Gregorf0f51982009-09-23 00:34:09 +00002853}
2854
Chris Lattner0e62c1c2011-07-23 10:55:15 +00002855unsigned clang::getMacroUsagePriority(StringRef MacroName,
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00002856 const LangOptions &LangOpts,
Douglas Gregor6e240332010-08-16 16:18:59 +00002857 bool PreferredTypeIsPointer) {
2858 unsigned Priority = CCP_Macro;
2859
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00002860 // Treat the "nil", "Nil" and "NULL" macros as null pointer constants.
2861 if (MacroName.equals("nil") || MacroName.equals("NULL") ||
2862 MacroName.equals("Nil")) {
Douglas Gregor6e240332010-08-16 16:18:59 +00002863 Priority = CCP_Constant;
2864 if (PreferredTypeIsPointer)
2865 Priority = Priority / CCF_SimilarTypeMatch;
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00002866 }
2867 // Treat "YES", "NO", "true", and "false" as constants.
2868 else if (MacroName.equals("YES") || MacroName.equals("NO") ||
2869 MacroName.equals("true") || MacroName.equals("false"))
2870 Priority = CCP_Constant;
2871 // Treat "bool" as a type.
2872 else if (MacroName.equals("bool"))
2873 Priority = CCP_Type + (LangOpts.ObjC1? CCD_bool_in_ObjC : 0);
2874
Douglas Gregor6e240332010-08-16 16:18:59 +00002875
2876 return Priority;
2877}
2878
Dmitri Gribenkobdc80de2013-01-11 20:32:41 +00002879CXCursorKind clang::getCursorKindForDecl(const Decl *D) {
Douglas Gregor09c0eb12010-09-03 23:30:36 +00002880 if (!D)
2881 return CXCursor_UnexposedDecl;
2882
2883 switch (D->getKind()) {
2884 case Decl::Enum: return CXCursor_EnumDecl;
2885 case Decl::EnumConstant: return CXCursor_EnumConstantDecl;
2886 case Decl::Field: return CXCursor_FieldDecl;
2887 case Decl::Function:
2888 return CXCursor_FunctionDecl;
2889 case Decl::ObjCCategory: return CXCursor_ObjCCategoryDecl;
2890 case Decl::ObjCCategoryImpl: return CXCursor_ObjCCategoryImplDecl;
Douglas Gregor09c0eb12010-09-03 23:30:36 +00002891 case Decl::ObjCImplementation: return CXCursor_ObjCImplementationDecl;
Douglas Gregordeafd0b2011-12-27 22:43:10 +00002892
Argyrios Kyrtzidis3698cef2012-01-24 21:39:26 +00002893 case Decl::ObjCInterface: return CXCursor_ObjCInterfaceDecl;
Douglas Gregor09c0eb12010-09-03 23:30:36 +00002894 case Decl::ObjCIvar: return CXCursor_ObjCIvarDecl;
2895 case Decl::ObjCMethod:
2896 return cast<ObjCMethodDecl>(D)->isInstanceMethod()
2897 ? CXCursor_ObjCInstanceMethodDecl : CXCursor_ObjCClassMethodDecl;
2898 case Decl::CXXMethod: return CXCursor_CXXMethod;
2899 case Decl::CXXConstructor: return CXCursor_Constructor;
2900 case Decl::CXXDestructor: return CXCursor_Destructor;
2901 case Decl::CXXConversion: return CXCursor_ConversionFunction;
2902 case Decl::ObjCProperty: return CXCursor_ObjCPropertyDecl;
Argyrios Kyrtzidis3698cef2012-01-24 21:39:26 +00002903 case Decl::ObjCProtocol: return CXCursor_ObjCProtocolDecl;
Douglas Gregor09c0eb12010-09-03 23:30:36 +00002904 case Decl::ParmVar: return CXCursor_ParmDecl;
2905 case Decl::Typedef: return CXCursor_TypedefDecl;
Richard Smithdda56e42011-04-15 14:24:37 +00002906 case Decl::TypeAlias: return CXCursor_TypeAliasDecl;
Douglas Gregor09c0eb12010-09-03 23:30:36 +00002907 case Decl::Var: return CXCursor_VarDecl;
2908 case Decl::Namespace: return CXCursor_Namespace;
2909 case Decl::NamespaceAlias: return CXCursor_NamespaceAlias;
2910 case Decl::TemplateTypeParm: return CXCursor_TemplateTypeParameter;
2911 case Decl::NonTypeTemplateParm:return CXCursor_NonTypeTemplateParameter;
2912 case Decl::TemplateTemplateParm:return CXCursor_TemplateTemplateParameter;
2913 case Decl::FunctionTemplate: return CXCursor_FunctionTemplate;
2914 case Decl::ClassTemplate: return CXCursor_ClassTemplate;
Argyrios Kyrtzidis12afd702011-09-30 17:58:23 +00002915 case Decl::AccessSpec: return CXCursor_CXXAccessSpecifier;
Douglas Gregor09c0eb12010-09-03 23:30:36 +00002916 case Decl::ClassTemplatePartialSpecialization:
2917 return CXCursor_ClassTemplatePartialSpecialization;
2918 case Decl::UsingDirective: return CXCursor_UsingDirective;
Douglas Gregor3e653b32012-04-30 23:41:16 +00002919 case Decl::TranslationUnit: return CXCursor_TranslationUnit;
Douglas Gregor09c0eb12010-09-03 23:30:36 +00002920
2921 case Decl::Using:
2922 case Decl::UnresolvedUsingValue:
2923 case Decl::UnresolvedUsingTypename:
2924 return CXCursor_UsingDeclaration;
2925
Douglas Gregor4cd65962011-06-03 23:08:58 +00002926 case Decl::ObjCPropertyImpl:
2927 switch (cast<ObjCPropertyImplDecl>(D)->getPropertyImplementation()) {
2928 case ObjCPropertyImplDecl::Dynamic:
2929 return CXCursor_ObjCDynamicDecl;
2930
2931 case ObjCPropertyImplDecl::Synthesize:
2932 return CXCursor_ObjCSynthesizeDecl;
2933 }
Argyrios Kyrtzidis50e5b1d2012-10-05 00:22:24 +00002934
2935 case Decl::Import:
2936 return CXCursor_ModuleImportDecl;
Douglas Gregor4cd65962011-06-03 23:08:58 +00002937
Douglas Gregor09c0eb12010-09-03 23:30:36 +00002938 default:
Dmitri Gribenkobdc80de2013-01-11 20:32:41 +00002939 if (const TagDecl *TD = dyn_cast<TagDecl>(D)) {
Douglas Gregor09c0eb12010-09-03 23:30:36 +00002940 switch (TD->getTagKind()) {
Joao Matosdc86f942012-08-31 18:45:21 +00002941 case TTK_Interface: // fall through
Douglas Gregor09c0eb12010-09-03 23:30:36 +00002942 case TTK_Struct: return CXCursor_StructDecl;
2943 case TTK_Class: return CXCursor_ClassDecl;
2944 case TTK_Union: return CXCursor_UnionDecl;
2945 case TTK_Enum: return CXCursor_EnumDecl;
2946 }
2947 }
2948 }
2949
2950 return CXCursor_UnexposedDecl;
2951}
2952
Douglas Gregor55b037b2010-07-08 20:55:51 +00002953static void AddMacroResults(Preprocessor &PP, ResultBuilder &Results,
Douglas Gregor8cb17462012-10-09 16:01:50 +00002954 bool IncludeUndefined,
Douglas Gregor55b037b2010-07-08 20:55:51 +00002955 bool TargetTypeIsPointer = false) {
John McCall276321a2010-08-25 06:19:51 +00002956 typedef CodeCompletionResult Result;
Douglas Gregor55b037b2010-07-08 20:55:51 +00002957
Douglas Gregorf329c7c2009-10-30 16:50:04 +00002958 Results.EnterNewScope();
Douglas Gregor8e3e8742010-10-18 21:05:04 +00002959
Douglas Gregor9eb77012009-11-07 00:00:49 +00002960 for (Preprocessor::macro_iterator M = PP.macro_begin(),
2961 MEnd = PP.macro_end();
Douglas Gregor55b037b2010-07-08 20:55:51 +00002962 M != MEnd; ++M) {
Douglas Gregor8cb17462012-10-09 16:01:50 +00002963 if (IncludeUndefined || M->first->hasMacroDefinition())
2964 Results.AddResult(Result(M->first,
Douglas Gregor6e240332010-08-16 16:18:59 +00002965 getMacroUsagePriority(M->first->getName(),
David Blaikiebbafb8a2012-03-11 07:00:24 +00002966 PP.getLangOpts(),
Douglas Gregor6e240332010-08-16 16:18:59 +00002967 TargetTypeIsPointer)));
Douglas Gregor55b037b2010-07-08 20:55:51 +00002968 }
Douglas Gregor8e3e8742010-10-18 21:05:04 +00002969
Douglas Gregorf329c7c2009-10-30 16:50:04 +00002970 Results.ExitScope();
Douglas Gregor8e3e8742010-10-18 21:05:04 +00002971
Douglas Gregorf329c7c2009-10-30 16:50:04 +00002972}
2973
Douglas Gregorce0e8562010-08-23 21:54:33 +00002974static void AddPrettyFunctionResults(const LangOptions &LangOpts,
2975 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00002976 typedef CodeCompletionResult Result;
Douglas Gregorce0e8562010-08-23 21:54:33 +00002977
2978 Results.EnterNewScope();
Douglas Gregor8e3e8742010-10-18 21:05:04 +00002979
Douglas Gregorce0e8562010-08-23 21:54:33 +00002980 Results.AddResult(Result("__PRETTY_FUNCTION__", CCP_Constant));
2981 Results.AddResult(Result("__FUNCTION__", CCP_Constant));
Richard Smith2bf7fdb2013-01-02 11:42:31 +00002982 if (LangOpts.C99 || LangOpts.CPlusPlus11)
Douglas Gregorce0e8562010-08-23 21:54:33 +00002983 Results.AddResult(Result("__func__", CCP_Constant));
2984 Results.ExitScope();
2985}
2986
Daniel Dunbar242ea9a2009-11-13 08:58:20 +00002987static void HandleCodeCompleteResults(Sema *S,
2988 CodeCompleteConsumer *CodeCompleter,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00002989 CodeCompletionContext Context,
John McCall276321a2010-08-25 06:19:51 +00002990 CodeCompletionResult *Results,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00002991 unsigned NumResults) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002992 if (CodeCompleter)
Douglas Gregor00c37ef2010-08-11 21:23:17 +00002993 CodeCompleter->ProcessCodeCompleteResults(*S, Context, Results, NumResults);
Douglas Gregor3545ff42009-09-21 16:56:56 +00002994}
2995
Douglas Gregor00c37ef2010-08-11 21:23:17 +00002996static enum CodeCompletionContext::Kind mapCodeCompletionContext(Sema &S,
2997 Sema::ParserCompletionContext PCC) {
2998 switch (PCC) {
John McCallfaf5fb42010-08-26 23:41:50 +00002999 case Sema::PCC_Namespace:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003000 return CodeCompletionContext::CCC_TopLevel;
3001
John McCallfaf5fb42010-08-26 23:41:50 +00003002 case Sema::PCC_Class:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003003 return CodeCompletionContext::CCC_ClassStructUnion;
3004
John McCallfaf5fb42010-08-26 23:41:50 +00003005 case Sema::PCC_ObjCInterface:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003006 return CodeCompletionContext::CCC_ObjCInterface;
3007
John McCallfaf5fb42010-08-26 23:41:50 +00003008 case Sema::PCC_ObjCImplementation:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003009 return CodeCompletionContext::CCC_ObjCImplementation;
3010
John McCallfaf5fb42010-08-26 23:41:50 +00003011 case Sema::PCC_ObjCInstanceVariableList:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003012 return CodeCompletionContext::CCC_ObjCIvarList;
3013
John McCallfaf5fb42010-08-26 23:41:50 +00003014 case Sema::PCC_Template:
3015 case Sema::PCC_MemberTemplate:
Douglas Gregor0ac41382010-09-23 23:01:17 +00003016 if (S.CurContext->isFileContext())
3017 return CodeCompletionContext::CCC_TopLevel;
David Blaikie8a40f702012-01-17 06:56:22 +00003018 if (S.CurContext->isRecord())
Douglas Gregor0ac41382010-09-23 23:01:17 +00003019 return CodeCompletionContext::CCC_ClassStructUnion;
David Blaikie8a40f702012-01-17 06:56:22 +00003020 return CodeCompletionContext::CCC_Other;
Douglas Gregor0ac41382010-09-23 23:01:17 +00003021
John McCallfaf5fb42010-08-26 23:41:50 +00003022 case Sema::PCC_RecoveryInFunction:
Douglas Gregor0ac41382010-09-23 23:01:17 +00003023 return CodeCompletionContext::CCC_Recovery;
Douglas Gregorc769d6e2010-10-18 22:01:46 +00003024
John McCallfaf5fb42010-08-26 23:41:50 +00003025 case Sema::PCC_ForInit:
David Blaikiebbafb8a2012-03-11 07:00:24 +00003026 if (S.getLangOpts().CPlusPlus || S.getLangOpts().C99 ||
3027 S.getLangOpts().ObjC1)
Douglas Gregorc769d6e2010-10-18 22:01:46 +00003028 return CodeCompletionContext::CCC_ParenthesizedExpression;
3029 else
3030 return CodeCompletionContext::CCC_Expression;
3031
3032 case Sema::PCC_Expression:
John McCallfaf5fb42010-08-26 23:41:50 +00003033 case Sema::PCC_Condition:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003034 return CodeCompletionContext::CCC_Expression;
3035
John McCallfaf5fb42010-08-26 23:41:50 +00003036 case Sema::PCC_Statement:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003037 return CodeCompletionContext::CCC_Statement;
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003038
John McCallfaf5fb42010-08-26 23:41:50 +00003039 case Sema::PCC_Type:
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003040 return CodeCompletionContext::CCC_Type;
Douglas Gregor5e35d592010-09-14 23:59:36 +00003041
3042 case Sema::PCC_ParenthesizedExpression:
3043 return CodeCompletionContext::CCC_ParenthesizedExpression;
Douglas Gregor80039242011-02-15 20:33:25 +00003044
3045 case Sema::PCC_LocalDeclarationSpecifiers:
3046 return CodeCompletionContext::CCC_Type;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003047 }
David Blaikie8a40f702012-01-17 06:56:22 +00003048
3049 llvm_unreachable("Invalid ParserCompletionContext!");
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003050}
3051
Douglas Gregorac322ec2010-08-27 21:18:54 +00003052/// \brief If we're in a C++ virtual member function, add completion results
3053/// that invoke the functions we override, since it's common to invoke the
3054/// overridden function as well as adding new functionality.
3055///
3056/// \param S The semantic analysis object for which we are generating results.
3057///
3058/// \param InContext This context in which the nested-name-specifier preceding
3059/// the code-completion point
3060static void MaybeAddOverrideCalls(Sema &S, DeclContext *InContext,
3061 ResultBuilder &Results) {
3062 // Look through blocks.
3063 DeclContext *CurContext = S.CurContext;
3064 while (isa<BlockDecl>(CurContext))
3065 CurContext = CurContext->getParent();
3066
3067
3068 CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(CurContext);
3069 if (!Method || !Method->isVirtual())
3070 return;
3071
3072 // We need to have names for all of the parameters, if we're going to
3073 // generate a forwarding call.
3074 for (CXXMethodDecl::param_iterator P = Method->param_begin(),
3075 PEnd = Method->param_end();
3076 P != PEnd;
3077 ++P) {
3078 if (!(*P)->getDeclName())
3079 return;
3080 }
3081
Douglas Gregor75acd922011-09-27 23:30:47 +00003082 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
Douglas Gregorac322ec2010-08-27 21:18:54 +00003083 for (CXXMethodDecl::method_iterator M = Method->begin_overridden_methods(),
3084 MEnd = Method->end_overridden_methods();
3085 M != MEnd; ++M) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003086 CodeCompletionBuilder Builder(Results.getAllocator(),
3087 Results.getCodeCompletionTUInfo());
Douglas Gregorac322ec2010-08-27 21:18:54 +00003088 CXXMethodDecl *Overridden = const_cast<CXXMethodDecl *>(*M);
3089 if (Overridden->getCanonicalDecl() == Method->getCanonicalDecl())
3090 continue;
3091
3092 // If we need a nested-name-specifier, add one now.
3093 if (!InContext) {
3094 NestedNameSpecifier *NNS
3095 = getRequiredQualification(S.Context, CurContext,
3096 Overridden->getDeclContext());
3097 if (NNS) {
3098 std::string Str;
3099 llvm::raw_string_ostream OS(Str);
Douglas Gregor75acd922011-09-27 23:30:47 +00003100 NNS->print(OS, Policy);
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003101 Builder.AddTextChunk(Results.getAllocator().CopyString(OS.str()));
Douglas Gregorac322ec2010-08-27 21:18:54 +00003102 }
3103 } else if (!InContext->Equals(Overridden->getDeclContext()))
3104 continue;
3105
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003106 Builder.AddTypedTextChunk(Results.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003107 Overridden->getNameAsString()));
3108 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregorac322ec2010-08-27 21:18:54 +00003109 bool FirstParam = true;
3110 for (CXXMethodDecl::param_iterator P = Method->param_begin(),
3111 PEnd = Method->param_end();
3112 P != PEnd; ++P) {
3113 if (FirstParam)
3114 FirstParam = false;
3115 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003116 Builder.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregorac322ec2010-08-27 21:18:54 +00003117
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003118 Builder.AddPlaceholderChunk(Results.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003119 (*P)->getIdentifier()->getName()));
Douglas Gregorac322ec2010-08-27 21:18:54 +00003120 }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003121 Builder.AddChunk(CodeCompletionString::CK_RightParen);
3122 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregorac322ec2010-08-27 21:18:54 +00003123 CCP_SuperCompletion,
Douglas Gregor78254c82012-03-27 23:34:16 +00003124 CXCursor_CXXMethod,
3125 CXAvailability_Available,
3126 Overridden));
Douglas Gregorac322ec2010-08-27 21:18:54 +00003127 Results.Ignore(Overridden);
3128 }
3129}
3130
Douglas Gregor07f43572012-01-29 18:15:03 +00003131void Sema::CodeCompleteModuleImport(SourceLocation ImportLoc,
3132 ModuleIdPath Path) {
3133 typedef CodeCompletionResult Result;
3134 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003135 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor07f43572012-01-29 18:15:03 +00003136 CodeCompletionContext::CCC_Other);
3137 Results.EnterNewScope();
3138
3139 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003140 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Douglas Gregor07f43572012-01-29 18:15:03 +00003141 typedef CodeCompletionResult Result;
3142 if (Path.empty()) {
3143 // Enumerate all top-level modules.
Dmitri Gribenkof8579502013-01-12 19:30:44 +00003144 SmallVector<Module *, 8> Modules;
Douglas Gregor07f43572012-01-29 18:15:03 +00003145 PP.getHeaderSearchInfo().collectAllModules(Modules);
3146 for (unsigned I = 0, N = Modules.size(); I != N; ++I) {
3147 Builder.AddTypedTextChunk(
3148 Builder.getAllocator().CopyString(Modules[I]->Name));
3149 Results.AddResult(Result(Builder.TakeString(),
3150 CCP_Declaration,
3151 CXCursor_NotImplemented,
3152 Modules[I]->isAvailable()
3153 ? CXAvailability_Available
3154 : CXAvailability_NotAvailable));
3155 }
3156 } else {
3157 // Load the named module.
3158 Module *Mod = PP.getModuleLoader().loadModule(ImportLoc, Path,
3159 Module::AllVisible,
3160 /*IsInclusionDirective=*/false);
3161 // Enumerate submodules.
3162 if (Mod) {
3163 for (Module::submodule_iterator Sub = Mod->submodule_begin(),
3164 SubEnd = Mod->submodule_end();
3165 Sub != SubEnd; ++Sub) {
3166
3167 Builder.AddTypedTextChunk(
3168 Builder.getAllocator().CopyString((*Sub)->Name));
3169 Results.AddResult(Result(Builder.TakeString(),
3170 CCP_Declaration,
3171 CXCursor_NotImplemented,
3172 (*Sub)->isAvailable()
3173 ? CXAvailability_Available
3174 : CXAvailability_NotAvailable));
3175 }
3176 }
3177 }
3178 Results.ExitScope();
3179 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
3180 Results.data(),Results.size());
3181}
3182
Douglas Gregor504a6ae2010-01-10 23:08:15 +00003183void Sema::CodeCompleteOrdinaryName(Scope *S,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003184 ParserCompletionContext CompletionContext) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003185 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003186 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00003187 mapCodeCompletionContext(*this, CompletionContext));
Douglas Gregorac322ec2010-08-27 21:18:54 +00003188 Results.EnterNewScope();
Douglas Gregor50832e02010-09-20 22:39:41 +00003189
Douglas Gregor504a6ae2010-01-10 23:08:15 +00003190 // Determine how to filter results, e.g., so that the names of
3191 // values (functions, enumerators, function templates, etc.) are
3192 // only allowed where we can have an expression.
3193 switch (CompletionContext) {
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003194 case PCC_Namespace:
3195 case PCC_Class:
3196 case PCC_ObjCInterface:
3197 case PCC_ObjCImplementation:
3198 case PCC_ObjCInstanceVariableList:
3199 case PCC_Template:
3200 case PCC_MemberTemplate:
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003201 case PCC_Type:
Douglas Gregor80039242011-02-15 20:33:25 +00003202 case PCC_LocalDeclarationSpecifiers:
Douglas Gregor504a6ae2010-01-10 23:08:15 +00003203 Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
3204 break;
3205
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003206 case PCC_Statement:
Douglas Gregor5e35d592010-09-14 23:59:36 +00003207 case PCC_ParenthesizedExpression:
Douglas Gregor4d755e82010-08-24 23:58:17 +00003208 case PCC_Expression:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003209 case PCC_ForInit:
3210 case PCC_Condition:
David Blaikiebbafb8a2012-03-11 07:00:24 +00003211 if (WantTypesInContext(CompletionContext, getLangOpts()))
Douglas Gregor70febae2010-05-28 00:49:12 +00003212 Results.setFilter(&ResultBuilder::IsOrdinaryName);
3213 else
3214 Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
Douglas Gregorac322ec2010-08-27 21:18:54 +00003215
David Blaikiebbafb8a2012-03-11 07:00:24 +00003216 if (getLangOpts().CPlusPlus)
Douglas Gregorac322ec2010-08-27 21:18:54 +00003217 MaybeAddOverrideCalls(*this, /*InContext=*/0, Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00003218 break;
Douglas Gregor6da3db42010-05-25 05:58:43 +00003219
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003220 case PCC_RecoveryInFunction:
Douglas Gregor6da3db42010-05-25 05:58:43 +00003221 // Unfiltered
3222 break;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00003223 }
3224
Douglas Gregor9be0ed42010-08-26 16:36:48 +00003225 // If we are in a C++ non-static member function, check the qualifiers on
3226 // the member function to filter/prioritize the results list.
3227 if (CXXMethodDecl *CurMethod = dyn_cast<CXXMethodDecl>(CurContext))
3228 if (CurMethod->isInstance())
3229 Results.setObjectTypeQualifiers(
3230 Qualifiers::fromCVRMask(CurMethod->getTypeQualifiers()));
3231
Douglas Gregorc580c522010-01-14 01:09:38 +00003232 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00003233 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3234 CodeCompleter->includeGlobals());
Douglas Gregor92253692009-12-07 09:54:55 +00003235
Douglas Gregorf98e6a22010-01-13 23:51:12 +00003236 AddOrdinaryNameResults(CompletionContext, S, *this, Results);
Douglas Gregor92253692009-12-07 09:54:55 +00003237 Results.ExitScope();
3238
Douglas Gregorce0e8562010-08-23 21:54:33 +00003239 switch (CompletionContext) {
Douglas Gregor5e35d592010-09-14 23:59:36 +00003240 case PCC_ParenthesizedExpression:
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003241 case PCC_Expression:
3242 case PCC_Statement:
3243 case PCC_RecoveryInFunction:
3244 if (S->getFnParent())
David Blaikiebbafb8a2012-03-11 07:00:24 +00003245 AddPrettyFunctionResults(PP.getLangOpts(), Results);
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003246 break;
3247
3248 case PCC_Namespace:
3249 case PCC_Class:
3250 case PCC_ObjCInterface:
3251 case PCC_ObjCImplementation:
3252 case PCC_ObjCInstanceVariableList:
3253 case PCC_Template:
3254 case PCC_MemberTemplate:
3255 case PCC_ForInit:
3256 case PCC_Condition:
3257 case PCC_Type:
Douglas Gregor80039242011-02-15 20:33:25 +00003258 case PCC_LocalDeclarationSpecifiers:
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003259 break;
Douglas Gregorce0e8562010-08-23 21:54:33 +00003260 }
3261
Douglas Gregor9eb77012009-11-07 00:00:49 +00003262 if (CodeCompleter->includeMacros())
Douglas Gregor8cb17462012-10-09 16:01:50 +00003263 AddMacroResults(PP, Results, false);
Douglas Gregorce0e8562010-08-23 21:54:33 +00003264
Douglas Gregor50832e02010-09-20 22:39:41 +00003265 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003266 Results.data(),Results.size());
Douglas Gregor9d64c5e2009-09-21 20:51:25 +00003267}
3268
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003269static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
3270 ParsedType Receiver,
3271 IdentifierInfo **SelIdents,
3272 unsigned NumSelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00003273 bool AtArgumentExpression,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003274 bool IsSuper,
3275 ResultBuilder &Results);
3276
3277void Sema::CodeCompleteDeclSpec(Scope *S, DeclSpec &DS,
3278 bool AllowNonIdentifiers,
3279 bool AllowNestedNameSpecifiers) {
John McCall276321a2010-08-25 06:19:51 +00003280 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003281 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003282 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00003283 AllowNestedNameSpecifiers
3284 ? CodeCompletionContext::CCC_PotentiallyQualifiedName
3285 : CodeCompletionContext::CCC_Name);
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003286 Results.EnterNewScope();
3287
3288 // Type qualifiers can come after names.
3289 Results.AddResult(Result("const"));
3290 Results.AddResult(Result("volatile"));
David Blaikiebbafb8a2012-03-11 07:00:24 +00003291 if (getLangOpts().C99)
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003292 Results.AddResult(Result("restrict"));
3293
David Blaikiebbafb8a2012-03-11 07:00:24 +00003294 if (getLangOpts().CPlusPlus) {
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003295 if (AllowNonIdentifiers) {
3296 Results.AddResult(Result("operator"));
3297 }
3298
3299 // Add nested-name-specifiers.
3300 if (AllowNestedNameSpecifiers) {
3301 Results.allowNestedNameSpecifiers();
Douglas Gregor0ac41382010-09-23 23:01:17 +00003302 Results.setFilter(&ResultBuilder::IsImpossibleToSatisfy);
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003303 CodeCompletionDeclConsumer Consumer(Results, CurContext);
3304 LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer,
3305 CodeCompleter->includeGlobals());
Douglas Gregor0ac41382010-09-23 23:01:17 +00003306 Results.setFilter(0);
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003307 }
3308 }
3309 Results.ExitScope();
3310
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003311 // If we're in a context where we might have an expression (rather than a
3312 // declaration), and what we've seen so far is an Objective-C type that could
3313 // be a receiver of a class message, this may be a class message send with
3314 // the initial opening bracket '[' missing. Add appropriate completions.
3315 if (AllowNonIdentifiers && !AllowNestedNameSpecifiers &&
3316 DS.getTypeSpecType() == DeclSpec::TST_typename &&
3317 DS.getStorageClassSpecAsWritten() == DeclSpec::SCS_unspecified &&
3318 !DS.isThreadSpecified() && !DS.isExternInLinkageSpec() &&
3319 DS.getTypeSpecComplex() == DeclSpec::TSC_unspecified &&
3320 DS.getTypeSpecSign() == DeclSpec::TSS_unspecified &&
3321 DS.getTypeQualifiers() == 0 &&
3322 S &&
3323 (S->getFlags() & Scope::DeclScope) != 0 &&
3324 (S->getFlags() & (Scope::ClassScope | Scope::TemplateParamScope |
3325 Scope::FunctionPrototypeScope |
3326 Scope::AtCatchScope)) == 0) {
3327 ParsedType T = DS.getRepAsType();
3328 if (!T.get().isNull() && T.get()->isObjCObjectOrInterfaceType())
Douglas Gregorf86e4da2010-09-20 23:34:21 +00003329 AddClassMessageCompletions(*this, S, T, 0, 0, false, false, Results);
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003330 }
3331
Douglas Gregor56ccce02010-08-24 04:59:56 +00003332 // Note that we intentionally suppress macro results here, since we do not
3333 // encourage using macros to produce the names of entities.
3334
Douglas Gregor0ac41382010-09-23 23:01:17 +00003335 HandleCodeCompleteResults(this, CodeCompleter,
3336 Results.getCompletionContext(),
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003337 Results.data(), Results.size());
3338}
3339
Douglas Gregor68762e72010-08-23 21:17:50 +00003340struct Sema::CodeCompleteExpressionData {
3341 CodeCompleteExpressionData(QualType PreferredType = QualType())
3342 : PreferredType(PreferredType), IntegralConstantExpression(false),
3343 ObjCCollection(false) { }
3344
3345 QualType PreferredType;
3346 bool IntegralConstantExpression;
3347 bool ObjCCollection;
Chris Lattner0e62c1c2011-07-23 10:55:15 +00003348 SmallVector<Decl *, 4> IgnoreDecls;
Douglas Gregor68762e72010-08-23 21:17:50 +00003349};
3350
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003351/// \brief Perform code-completion in an expression context when we know what
3352/// type we're looking for.
Douglas Gregor68762e72010-08-23 21:17:50 +00003353void Sema::CodeCompleteExpression(Scope *S,
3354 const CodeCompleteExpressionData &Data) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003355 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003356 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003357 CodeCompletionContext::CCC_Expression);
Douglas Gregor68762e72010-08-23 21:17:50 +00003358 if (Data.ObjCCollection)
3359 Results.setFilter(&ResultBuilder::IsObjCCollection);
3360 else if (Data.IntegralConstantExpression)
Douglas Gregor85b50632010-07-28 21:50:18 +00003361 Results.setFilter(&ResultBuilder::IsIntegralConstantValue);
David Blaikiebbafb8a2012-03-11 07:00:24 +00003362 else if (WantTypesInContext(PCC_Expression, getLangOpts()))
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003363 Results.setFilter(&ResultBuilder::IsOrdinaryName);
3364 else
3365 Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
Douglas Gregor68762e72010-08-23 21:17:50 +00003366
3367 if (!Data.PreferredType.isNull())
3368 Results.setPreferredType(Data.PreferredType.getNonReferenceType());
3369
3370 // Ignore any declarations that we were told that we don't care about.
3371 for (unsigned I = 0, N = Data.IgnoreDecls.size(); I != N; ++I)
3372 Results.Ignore(Data.IgnoreDecls[I]);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003373
3374 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00003375 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3376 CodeCompleter->includeGlobals());
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003377
3378 Results.EnterNewScope();
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003379 AddOrdinaryNameResults(PCC_Expression, S, *this, Results);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003380 Results.ExitScope();
3381
Douglas Gregor55b037b2010-07-08 20:55:51 +00003382 bool PreferredTypeIsPointer = false;
Douglas Gregor68762e72010-08-23 21:17:50 +00003383 if (!Data.PreferredType.isNull())
3384 PreferredTypeIsPointer = Data.PreferredType->isAnyPointerType()
3385 || Data.PreferredType->isMemberPointerType()
3386 || Data.PreferredType->isBlockPointerType();
Douglas Gregor55b037b2010-07-08 20:55:51 +00003387
Douglas Gregorce0e8562010-08-23 21:54:33 +00003388 if (S->getFnParent() &&
3389 !Data.ObjCCollection &&
3390 !Data.IntegralConstantExpression)
David Blaikiebbafb8a2012-03-11 07:00:24 +00003391 AddPrettyFunctionResults(PP.getLangOpts(), Results);
Douglas Gregorce0e8562010-08-23 21:54:33 +00003392
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003393 if (CodeCompleter->includeMacros())
Douglas Gregor8cb17462012-10-09 16:01:50 +00003394 AddMacroResults(PP, Results, false, PreferredTypeIsPointer);
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003395 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor68762e72010-08-23 21:17:50 +00003396 CodeCompletionContext(CodeCompletionContext::CCC_Expression,
3397 Data.PreferredType),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003398 Results.data(),Results.size());
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003399}
3400
Douglas Gregoreda7e542010-09-18 01:28:11 +00003401void Sema::CodeCompletePostfixExpression(Scope *S, ExprResult E) {
3402 if (E.isInvalid())
3403 CodeCompleteOrdinaryName(S, PCC_RecoveryInFunction);
David Blaikiebbafb8a2012-03-11 07:00:24 +00003404 else if (getLangOpts().ObjC1)
Douglas Gregoreda7e542010-09-18 01:28:11 +00003405 CodeCompleteObjCInstanceMessage(S, E.take(), 0, 0, false);
Douglas Gregored0b69d2010-09-15 16:23:04 +00003406}
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003407
Douglas Gregorb888acf2010-12-09 23:01:55 +00003408/// \brief The set of properties that have already been added, referenced by
3409/// property name.
3410typedef llvm::SmallPtrSet<IdentifierInfo*, 16> AddedPropertiesSet;
3411
Douglas Gregor9b4f3702012-06-12 13:44:08 +00003412/// \brief Retrieve the container definition, if any?
3413static ObjCContainerDecl *getContainerDef(ObjCContainerDecl *Container) {
3414 if (ObjCInterfaceDecl *Interface = dyn_cast<ObjCInterfaceDecl>(Container)) {
3415 if (Interface->hasDefinition())
3416 return Interface->getDefinition();
3417
3418 return Interface;
3419 }
3420
3421 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
3422 if (Protocol->hasDefinition())
3423 return Protocol->getDefinition();
3424
3425 return Protocol;
3426 }
3427 return Container;
3428}
3429
3430static void AddObjCProperties(ObjCContainerDecl *Container,
Douglas Gregor5d649882009-11-18 22:32:06 +00003431 bool AllowCategories,
Douglas Gregor95147142011-05-05 15:50:42 +00003432 bool AllowNullaryMethods,
Douglas Gregor9291bad2009-11-18 01:29:26 +00003433 DeclContext *CurContext,
Douglas Gregorb888acf2010-12-09 23:01:55 +00003434 AddedPropertiesSet &AddedProperties,
Douglas Gregor9291bad2009-11-18 01:29:26 +00003435 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00003436 typedef CodeCompletionResult Result;
Douglas Gregor9291bad2009-11-18 01:29:26 +00003437
Douglas Gregor9b4f3702012-06-12 13:44:08 +00003438 // Retrieve the definition.
3439 Container = getContainerDef(Container);
3440
Douglas Gregor9291bad2009-11-18 01:29:26 +00003441 // Add properties in this container.
3442 for (ObjCContainerDecl::prop_iterator P = Container->prop_begin(),
3443 PEnd = Container->prop_end();
3444 P != PEnd;
Douglas Gregorb888acf2010-12-09 23:01:55 +00003445 ++P) {
3446 if (AddedProperties.insert(P->getIdentifier()))
Douglas Gregor0a0e2b32013-01-31 04:52:16 +00003447 Results.MaybeAddResult(Result(*P, Results.getBasePriority(*P), 0),
3448 CurContext);
Douglas Gregorb888acf2010-12-09 23:01:55 +00003449 }
Douglas Gregor9291bad2009-11-18 01:29:26 +00003450
Douglas Gregor95147142011-05-05 15:50:42 +00003451 // Add nullary methods
3452 if (AllowNullaryMethods) {
3453 ASTContext &Context = Container->getASTContext();
Douglas Gregor75acd922011-09-27 23:30:47 +00003454 PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema());
Douglas Gregor95147142011-05-05 15:50:42 +00003455 for (ObjCContainerDecl::method_iterator M = Container->meth_begin(),
3456 MEnd = Container->meth_end();
3457 M != MEnd; ++M) {
3458 if (M->getSelector().isUnarySelector())
3459 if (IdentifierInfo *Name = M->getSelector().getIdentifierInfoForSlot(0))
3460 if (AddedProperties.insert(Name)) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003461 CodeCompletionBuilder Builder(Results.getAllocator(),
3462 Results.getCodeCompletionTUInfo());
David Blaikie40ed2972012-06-06 20:45:41 +00003463 AddResultTypeChunk(Context, Policy, *M, Builder);
Douglas Gregor95147142011-05-05 15:50:42 +00003464 Builder.AddTypedTextChunk(
3465 Results.getAllocator().CopyString(Name->getName()));
3466
David Blaikie40ed2972012-06-06 20:45:41 +00003467 Results.MaybeAddResult(Result(Builder.TakeString(), *M,
Douglas Gregor78254c82012-03-27 23:34:16 +00003468 CCP_MemberDeclaration + CCD_MethodAsProperty),
Douglas Gregor95147142011-05-05 15:50:42 +00003469 CurContext);
3470 }
3471 }
3472 }
3473
3474
Douglas Gregor9291bad2009-11-18 01:29:26 +00003475 // Add properties in referenced protocols.
3476 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
3477 for (ObjCProtocolDecl::protocol_iterator P = Protocol->protocol_begin(),
3478 PEnd = Protocol->protocol_end();
3479 P != PEnd; ++P)
Douglas Gregor95147142011-05-05 15:50:42 +00003480 AddObjCProperties(*P, AllowCategories, AllowNullaryMethods, CurContext,
3481 AddedProperties, Results);
Douglas Gregor9291bad2009-11-18 01:29:26 +00003482 } else if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)){
Douglas Gregor5d649882009-11-18 22:32:06 +00003483 if (AllowCategories) {
3484 // Look through categories.
Douglas Gregor048fbfa2013-01-16 23:00:23 +00003485 for (ObjCInterfaceDecl::known_categories_iterator
3486 Cat = IFace->known_categories_begin(),
3487 CatEnd = IFace->known_categories_end();
3488 Cat != CatEnd; ++Cat)
3489 AddObjCProperties(*Cat, AllowCategories, AllowNullaryMethods,
Douglas Gregor95147142011-05-05 15:50:42 +00003490 CurContext, AddedProperties, Results);
Douglas Gregor5d649882009-11-18 22:32:06 +00003491 }
Douglas Gregor9291bad2009-11-18 01:29:26 +00003492
3493 // Look through protocols.
Ted Kremenek0ef508d2010-09-01 01:21:15 +00003494 for (ObjCInterfaceDecl::all_protocol_iterator
3495 I = IFace->all_referenced_protocol_begin(),
3496 E = IFace->all_referenced_protocol_end(); I != E; ++I)
Douglas Gregor95147142011-05-05 15:50:42 +00003497 AddObjCProperties(*I, AllowCategories, AllowNullaryMethods, CurContext,
3498 AddedProperties, Results);
Douglas Gregor9291bad2009-11-18 01:29:26 +00003499
3500 // Look in the superclass.
3501 if (IFace->getSuperClass())
Douglas Gregor95147142011-05-05 15:50:42 +00003502 AddObjCProperties(IFace->getSuperClass(), AllowCategories,
3503 AllowNullaryMethods, CurContext,
Douglas Gregorb888acf2010-12-09 23:01:55 +00003504 AddedProperties, Results);
Douglas Gregor9291bad2009-11-18 01:29:26 +00003505 } else if (const ObjCCategoryDecl *Category
3506 = dyn_cast<ObjCCategoryDecl>(Container)) {
3507 // Look through protocols.
Ted Kremenek0ef508d2010-09-01 01:21:15 +00003508 for (ObjCCategoryDecl::protocol_iterator P = Category->protocol_begin(),
3509 PEnd = Category->protocol_end();
Douglas Gregor9291bad2009-11-18 01:29:26 +00003510 P != PEnd; ++P)
Douglas Gregor95147142011-05-05 15:50:42 +00003511 AddObjCProperties(*P, AllowCategories, AllowNullaryMethods, CurContext,
3512 AddedProperties, Results);
Douglas Gregor9291bad2009-11-18 01:29:26 +00003513 }
3514}
3515
Douglas Gregor1cc88a92012-01-23 15:59:30 +00003516void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base,
Douglas Gregor2436e712009-09-17 21:32:03 +00003517 SourceLocation OpLoc,
3518 bool IsArrow) {
Douglas Gregor1cc88a92012-01-23 15:59:30 +00003519 if (!Base || !CodeCompleter)
Douglas Gregor2436e712009-09-17 21:32:03 +00003520 return;
3521
Douglas Gregor1cc88a92012-01-23 15:59:30 +00003522 ExprResult ConvertedBase = PerformMemberExprBaseConversion(Base, IsArrow);
3523 if (ConvertedBase.isInvalid())
3524 return;
3525 Base = ConvertedBase.get();
3526
John McCall276321a2010-08-25 06:19:51 +00003527 typedef CodeCompletionResult Result;
Douglas Gregor3545ff42009-09-21 16:56:56 +00003528
Douglas Gregor2436e712009-09-17 21:32:03 +00003529 QualType BaseType = Base->getType();
Douglas Gregor3545ff42009-09-21 16:56:56 +00003530
3531 if (IsArrow) {
3532 if (const PointerType *Ptr = BaseType->getAs<PointerType>())
3533 BaseType = Ptr->getPointeeType();
3534 else if (BaseType->isObjCObjectPointerType())
Douglas Gregor9be0ed42010-08-26 16:36:48 +00003535 /*Do nothing*/ ;
Douglas Gregor3545ff42009-09-21 16:56:56 +00003536 else
3537 return;
3538 }
3539
Douglas Gregor21325842011-07-07 16:03:39 +00003540 enum CodeCompletionContext::Kind contextKind;
3541
3542 if (IsArrow) {
3543 contextKind = CodeCompletionContext::CCC_ArrowMemberAccess;
3544 }
3545 else {
3546 if (BaseType->isObjCObjectPointerType() ||
3547 BaseType->isObjCObjectOrInterfaceType()) {
3548 contextKind = CodeCompletionContext::CCC_ObjCPropertyAccess;
3549 }
3550 else {
3551 contextKind = CodeCompletionContext::CCC_DotMemberAccess;
3552 }
3553 }
3554
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003555 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003556 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor21325842011-07-07 16:03:39 +00003557 CodeCompletionContext(contextKind,
Douglas Gregor0ac41382010-09-23 23:01:17 +00003558 BaseType),
3559 &ResultBuilder::IsMember);
Douglas Gregor9291bad2009-11-18 01:29:26 +00003560 Results.EnterNewScope();
3561 if (const RecordType *Record = BaseType->getAs<RecordType>()) {
Douglas Gregor9be0ed42010-08-26 16:36:48 +00003562 // Indicate that we are performing a member access, and the cv-qualifiers
3563 // for the base object type.
3564 Results.setObjectTypeQualifiers(BaseType.getQualifiers());
3565
Douglas Gregor9291bad2009-11-18 01:29:26 +00003566 // Access to a C/C++ class, struct, or union.
Douglas Gregor6ae4c522010-01-14 03:21:49 +00003567 Results.allowNestedNameSpecifiers();
Douglas Gregor09bbc652010-01-14 15:47:35 +00003568 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00003569 LookupVisibleDecls(Record->getDecl(), LookupMemberName, Consumer,
3570 CodeCompleter->includeGlobals());
Daniel Dunbar242ea9a2009-11-13 08:58:20 +00003571
David Blaikiebbafb8a2012-03-11 07:00:24 +00003572 if (getLangOpts().CPlusPlus) {
Douglas Gregor9291bad2009-11-18 01:29:26 +00003573 if (!Results.empty()) {
3574 // The "template" keyword can follow "->" or "." in the grammar.
3575 // However, we only want to suggest the template keyword if something
3576 // is dependent.
3577 bool IsDependent = BaseType->isDependentType();
3578 if (!IsDependent) {
3579 for (Scope *DepScope = S; DepScope; DepScope = DepScope->getParent())
3580 if (DeclContext *Ctx = (DeclContext *)DepScope->getEntity()) {
3581 IsDependent = Ctx->isDependentContext();
3582 break;
3583 }
3584 }
Daniel Dunbar242ea9a2009-11-13 08:58:20 +00003585
Douglas Gregor9291bad2009-11-18 01:29:26 +00003586 if (IsDependent)
Douglas Gregor78a21012010-01-14 16:01:26 +00003587 Results.AddResult(Result("template"));
Daniel Dunbar242ea9a2009-11-13 08:58:20 +00003588 }
Daniel Dunbar242ea9a2009-11-13 08:58:20 +00003589 }
Douglas Gregor9291bad2009-11-18 01:29:26 +00003590 } else if (!IsArrow && BaseType->getAsObjCInterfacePointerType()) {
3591 // Objective-C property reference.
Douglas Gregorb888acf2010-12-09 23:01:55 +00003592 AddedPropertiesSet AddedProperties;
Douglas Gregor9291bad2009-11-18 01:29:26 +00003593
3594 // Add property results based on our interface.
3595 const ObjCObjectPointerType *ObjCPtr
3596 = BaseType->getAsObjCInterfacePointerType();
3597 assert(ObjCPtr && "Non-NULL pointer guaranteed above!");
Douglas Gregor95147142011-05-05 15:50:42 +00003598 AddObjCProperties(ObjCPtr->getInterfaceDecl(), true,
3599 /*AllowNullaryMethods=*/true, CurContext,
Douglas Gregorb888acf2010-12-09 23:01:55 +00003600 AddedProperties, Results);
Douglas Gregor9291bad2009-11-18 01:29:26 +00003601
3602 // Add properties from the protocols in a qualified interface.
3603 for (ObjCObjectPointerType::qual_iterator I = ObjCPtr->qual_begin(),
3604 E = ObjCPtr->qual_end();
3605 I != E; ++I)
Douglas Gregor95147142011-05-05 15:50:42 +00003606 AddObjCProperties(*I, true, /*AllowNullaryMethods=*/true, CurContext,
3607 AddedProperties, Results);
Douglas Gregor9291bad2009-11-18 01:29:26 +00003608 } else if ((IsArrow && BaseType->isObjCObjectPointerType()) ||
John McCall8b07ec22010-05-15 11:32:37 +00003609 (!IsArrow && BaseType->isObjCObjectType())) {
Douglas Gregor9291bad2009-11-18 01:29:26 +00003610 // Objective-C instance variable access.
3611 ObjCInterfaceDecl *Class = 0;
3612 if (const ObjCObjectPointerType *ObjCPtr
3613 = BaseType->getAs<ObjCObjectPointerType>())
3614 Class = ObjCPtr->getInterfaceDecl();
3615 else
John McCall8b07ec22010-05-15 11:32:37 +00003616 Class = BaseType->getAs<ObjCObjectType>()->getInterface();
Douglas Gregor9291bad2009-11-18 01:29:26 +00003617
3618 // Add all ivars from this class and its superclasses.
Douglas Gregor2b8162b2010-01-14 16:08:12 +00003619 if (Class) {
3620 CodeCompletionDeclConsumer Consumer(Results, CurContext);
3621 Results.setFilter(&ResultBuilder::IsObjCIvar);
Douglas Gregor39982192010-08-15 06:18:01 +00003622 LookupVisibleDecls(Class, LookupMemberName, Consumer,
3623 CodeCompleter->includeGlobals());
Douglas Gregor9291bad2009-11-18 01:29:26 +00003624 }
Douglas Gregor3545ff42009-09-21 16:56:56 +00003625 }
Douglas Gregor9291bad2009-11-18 01:29:26 +00003626
3627 // FIXME: How do we cope with isa?
3628
3629 Results.ExitScope();
Daniel Dunbar242ea9a2009-11-13 08:58:20 +00003630
Daniel Dunbar242ea9a2009-11-13 08:58:20 +00003631 // Hand off the results found for code completion.
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003632 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0ac41382010-09-23 23:01:17 +00003633 Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003634 Results.data(),Results.size());
Douglas Gregor2436e712009-09-17 21:32:03 +00003635}
3636
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00003637void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) {
3638 if (!CodeCompleter)
3639 return;
3640
Douglas Gregor3545ff42009-09-21 16:56:56 +00003641 ResultBuilder::LookupFilter Filter = 0;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003642 enum CodeCompletionContext::Kind ContextKind
3643 = CodeCompletionContext::CCC_Other;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00003644 switch ((DeclSpec::TST)TagSpec) {
3645 case DeclSpec::TST_enum:
Douglas Gregor3545ff42009-09-21 16:56:56 +00003646 Filter = &ResultBuilder::IsEnum;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003647 ContextKind = CodeCompletionContext::CCC_EnumTag;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00003648 break;
3649
3650 case DeclSpec::TST_union:
Douglas Gregor3545ff42009-09-21 16:56:56 +00003651 Filter = &ResultBuilder::IsUnion;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003652 ContextKind = CodeCompletionContext::CCC_UnionTag;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00003653 break;
3654
3655 case DeclSpec::TST_struct:
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00003656 case DeclSpec::TST_class:
Joao Matosdc86f942012-08-31 18:45:21 +00003657 case DeclSpec::TST_interface:
Douglas Gregor3545ff42009-09-21 16:56:56 +00003658 Filter = &ResultBuilder::IsClassOrStruct;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003659 ContextKind = CodeCompletionContext::CCC_ClassOrStructTag;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00003660 break;
3661
3662 default:
David Blaikie83d382b2011-09-23 05:06:16 +00003663 llvm_unreachable("Unknown type specifier kind in CodeCompleteTag");
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00003664 }
Douglas Gregor3545ff42009-09-21 16:56:56 +00003665
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003666 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3667 CodeCompleter->getCodeCompletionTUInfo(), ContextKind);
Douglas Gregora6e2edc2010-01-14 03:27:13 +00003668 CodeCompletionDeclConsumer Consumer(Results, CurContext);
John McCalle87beb22010-04-23 18:46:30 +00003669
3670 // First pass: look for tags.
3671 Results.setFilter(Filter);
Douglas Gregor39982192010-08-15 06:18:01 +00003672 LookupVisibleDecls(S, LookupTagName, Consumer,
3673 CodeCompleter->includeGlobals());
John McCalle87beb22010-04-23 18:46:30 +00003674
Douglas Gregor39982192010-08-15 06:18:01 +00003675 if (CodeCompleter->includeGlobals()) {
3676 // Second pass: look for nested name specifiers.
3677 Results.setFilter(&ResultBuilder::IsNestedNameSpecifier);
3678 LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer);
3679 }
Douglas Gregor3545ff42009-09-21 16:56:56 +00003680
Douglas Gregor0ac41382010-09-23 23:01:17 +00003681 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003682 Results.data(),Results.size());
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00003683}
3684
Douglas Gregor28c78432010-08-27 17:35:51 +00003685void Sema::CodeCompleteTypeQualifiers(DeclSpec &DS) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003686 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003687 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003688 CodeCompletionContext::CCC_TypeQualifiers);
Douglas Gregor28c78432010-08-27 17:35:51 +00003689 Results.EnterNewScope();
3690 if (!(DS.getTypeQualifiers() & DeclSpec::TQ_const))
3691 Results.AddResult("const");
3692 if (!(DS.getTypeQualifiers() & DeclSpec::TQ_volatile))
3693 Results.AddResult("volatile");
David Blaikiebbafb8a2012-03-11 07:00:24 +00003694 if (getLangOpts().C99 &&
Douglas Gregor28c78432010-08-27 17:35:51 +00003695 !(DS.getTypeQualifiers() & DeclSpec::TQ_restrict))
3696 Results.AddResult("restrict");
3697 Results.ExitScope();
3698 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0ac41382010-09-23 23:01:17 +00003699 Results.getCompletionContext(),
Douglas Gregor28c78432010-08-27 17:35:51 +00003700 Results.data(), Results.size());
3701}
3702
Douglas Gregord328d572009-09-21 18:10:23 +00003703void Sema::CodeCompleteCase(Scope *S) {
John McCallaab3e412010-08-25 08:40:02 +00003704 if (getCurFunction()->SwitchStack.empty() || !CodeCompleter)
Douglas Gregord328d572009-09-21 18:10:23 +00003705 return;
John McCall5939b162011-08-06 07:30:58 +00003706
John McCallaab3e412010-08-25 08:40:02 +00003707 SwitchStmt *Switch = getCurFunction()->SwitchStack.back();
John McCall5939b162011-08-06 07:30:58 +00003708 QualType type = Switch->getCond()->IgnoreImplicit()->getType();
3709 if (!type->isEnumeralType()) {
3710 CodeCompleteExpressionData Data(type);
Douglas Gregor68762e72010-08-23 21:17:50 +00003711 Data.IntegralConstantExpression = true;
3712 CodeCompleteExpression(S, Data);
Douglas Gregord328d572009-09-21 18:10:23 +00003713 return;
Douglas Gregor85b50632010-07-28 21:50:18 +00003714 }
Douglas Gregord328d572009-09-21 18:10:23 +00003715
3716 // Code-complete the cases of a switch statement over an enumeration type
3717 // by providing the list of
John McCall5939b162011-08-06 07:30:58 +00003718 EnumDecl *Enum = type->castAs<EnumType>()->getDecl();
Douglas Gregor9b4f3702012-06-12 13:44:08 +00003719 if (EnumDecl *Def = Enum->getDefinition())
3720 Enum = Def;
Douglas Gregord328d572009-09-21 18:10:23 +00003721
3722 // Determine which enumerators we have already seen in the switch statement.
3723 // FIXME: Ideally, we would also be able to look *past* the code-completion
3724 // token, in case we are code-completing in the middle of the switch and not
3725 // at the end. However, we aren't able to do so at the moment.
3726 llvm::SmallPtrSet<EnumConstantDecl *, 8> EnumeratorsSeen;
Douglas Gregorf2510672009-09-21 19:57:38 +00003727 NestedNameSpecifier *Qualifier = 0;
Douglas Gregord328d572009-09-21 18:10:23 +00003728 for (SwitchCase *SC = Switch->getSwitchCaseList(); SC;
3729 SC = SC->getNextSwitchCase()) {
3730 CaseStmt *Case = dyn_cast<CaseStmt>(SC);
3731 if (!Case)
3732 continue;
3733
3734 Expr *CaseVal = Case->getLHS()->IgnoreParenCasts();
3735 if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CaseVal))
3736 if (EnumConstantDecl *Enumerator
3737 = dyn_cast<EnumConstantDecl>(DRE->getDecl())) {
3738 // We look into the AST of the case statement to determine which
3739 // enumerator was named. Alternatively, we could compute the value of
3740 // the integral constant expression, then compare it against the
3741 // values of each enumerator. However, value-based approach would not
3742 // work as well with C++ templates where enumerators declared within a
3743 // template are type- and value-dependent.
3744 EnumeratorsSeen.insert(Enumerator);
3745
Douglas Gregorf2510672009-09-21 19:57:38 +00003746 // If this is a qualified-id, keep track of the nested-name-specifier
3747 // so that we can reproduce it as part of code completion, e.g.,
Douglas Gregord328d572009-09-21 18:10:23 +00003748 //
3749 // switch (TagD.getKind()) {
3750 // case TagDecl::TK_enum:
3751 // break;
3752 // case XXX
3753 //
Douglas Gregorf2510672009-09-21 19:57:38 +00003754 // At the XXX, our completions are TagDecl::TK_union,
Douglas Gregord328d572009-09-21 18:10:23 +00003755 // TagDecl::TK_struct, and TagDecl::TK_class, rather than TK_union,
3756 // TK_struct, and TK_class.
Douglas Gregor4bd90e52009-10-23 18:54:35 +00003757 Qualifier = DRE->getQualifier();
Douglas Gregord328d572009-09-21 18:10:23 +00003758 }
3759 }
3760
David Blaikiebbafb8a2012-03-11 07:00:24 +00003761 if (getLangOpts().CPlusPlus && !Qualifier && EnumeratorsSeen.empty()) {
Douglas Gregorf2510672009-09-21 19:57:38 +00003762 // If there are no prior enumerators in C++, check whether we have to
3763 // qualify the names of the enumerators that we suggest, because they
3764 // may not be visible in this scope.
Douglas Gregord3cebdb2012-02-01 05:02:47 +00003765 Qualifier = getRequiredQualification(Context, CurContext, Enum);
Douglas Gregorf2510672009-09-21 19:57:38 +00003766 }
3767
Douglas Gregord328d572009-09-21 18:10:23 +00003768 // Add any enumerators that have not yet been mentioned.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003769 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003770 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003771 CodeCompletionContext::CCC_Expression);
Douglas Gregord328d572009-09-21 18:10:23 +00003772 Results.EnterNewScope();
3773 for (EnumDecl::enumerator_iterator E = Enum->enumerator_begin(),
3774 EEnd = Enum->enumerator_end();
3775 E != EEnd; ++E) {
David Blaikie40ed2972012-06-06 20:45:41 +00003776 if (EnumeratorsSeen.count(*E))
Douglas Gregord328d572009-09-21 18:10:23 +00003777 continue;
3778
Douglas Gregor0a0e2b32013-01-31 04:52:16 +00003779 CodeCompletionResult R(*E, CCP_EnumInCase, Qualifier);
Douglas Gregor3a69eaf2011-02-18 23:30:37 +00003780 Results.AddResult(R, CurContext, 0, false);
Douglas Gregord328d572009-09-21 18:10:23 +00003781 }
3782 Results.ExitScope();
Douglas Gregor285560922010-04-06 20:02:15 +00003783
Douglas Gregor21325842011-07-07 16:03:39 +00003784 //We need to make sure we're setting the right context,
3785 //so only say we include macros if the code completer says we do
3786 enum CodeCompletionContext::Kind kind = CodeCompletionContext::CCC_Other;
3787 if (CodeCompleter->includeMacros()) {
Douglas Gregor8cb17462012-10-09 16:01:50 +00003788 AddMacroResults(PP, Results, false);
Douglas Gregor21325842011-07-07 16:03:39 +00003789 kind = CodeCompletionContext::CCC_OtherWithMacros;
3790 }
3791
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003792 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor21325842011-07-07 16:03:39 +00003793 kind,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003794 Results.data(),Results.size());
Douglas Gregord328d572009-09-21 18:10:23 +00003795}
3796
Douglas Gregorcabea402009-09-22 15:41:20 +00003797namespace {
3798 struct IsBetterOverloadCandidate {
3799 Sema &S;
John McCallbc077cf2010-02-08 23:07:23 +00003800 SourceLocation Loc;
Douglas Gregorcabea402009-09-22 15:41:20 +00003801
3802 public:
John McCallbc077cf2010-02-08 23:07:23 +00003803 explicit IsBetterOverloadCandidate(Sema &S, SourceLocation Loc)
3804 : S(S), Loc(Loc) { }
Douglas Gregorcabea402009-09-22 15:41:20 +00003805
3806 bool
3807 operator()(const OverloadCandidate &X, const OverloadCandidate &Y) const {
John McCall5c32be02010-08-24 20:38:10 +00003808 return isBetterOverloadCandidate(S, X, Y, Loc);
Douglas Gregorcabea402009-09-22 15:41:20 +00003809 }
3810 };
3811}
3812
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00003813static bool anyNullArguments(llvm::ArrayRef<Expr*> Args) {
3814 if (Args.size() && !Args.data())
Douglas Gregor6ed3eb82010-05-30 06:10:08 +00003815 return true;
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00003816
3817 for (unsigned I = 0; I != Args.size(); ++I)
Douglas Gregor6ed3eb82010-05-30 06:10:08 +00003818 if (!Args[I])
3819 return true;
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00003820
Douglas Gregor6ed3eb82010-05-30 06:10:08 +00003821 return false;
3822}
3823
Richard Trieu2bd04012011-09-09 02:00:50 +00003824void Sema::CodeCompleteCall(Scope *S, Expr *FnIn,
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00003825 llvm::ArrayRef<Expr *> Args) {
Douglas Gregorcabea402009-09-22 15:41:20 +00003826 if (!CodeCompleter)
3827 return;
Douglas Gregor3ef59522009-12-11 19:06:04 +00003828
3829 // When we're code-completing for a call, we fall back to ordinary
3830 // name code-completion whenever we can't produce specific
3831 // results. We may want to revisit this strategy in the future,
3832 // e.g., by merging the two kinds of results.
3833
Douglas Gregorcabea402009-09-22 15:41:20 +00003834 Expr *Fn = (Expr *)FnIn;
Douglas Gregor3ef59522009-12-11 19:06:04 +00003835
Douglas Gregorcabea402009-09-22 15:41:20 +00003836 // Ignore type-dependent call expressions entirely.
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00003837 if (!Fn || Fn->isTypeDependent() || anyNullArguments(Args) ||
3838 Expr::hasAnyTypeDependentArguments(Args)) {
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003839 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregorcabea402009-09-22 15:41:20 +00003840 return;
Douglas Gregor3ef59522009-12-11 19:06:04 +00003841 }
Douglas Gregorcabea402009-09-22 15:41:20 +00003842
John McCall57500772009-12-16 12:17:52 +00003843 // Build an overload candidate set based on the functions we find.
John McCallbc077cf2010-02-08 23:07:23 +00003844 SourceLocation Loc = Fn->getExprLoc();
3845 OverloadCandidateSet CandidateSet(Loc);
John McCall57500772009-12-16 12:17:52 +00003846
Douglas Gregorcabea402009-09-22 15:41:20 +00003847 // FIXME: What if we're calling something that isn't a function declaration?
3848 // FIXME: What if we're calling a pseudo-destructor?
3849 // FIXME: What if we're calling a member function?
3850
Douglas Gregorff59f672010-01-21 15:46:19 +00003851 typedef CodeCompleteConsumer::OverloadCandidate ResultCandidate;
Chris Lattner0e62c1c2011-07-23 10:55:15 +00003852 SmallVector<ResultCandidate, 8> Results;
Douglas Gregorff59f672010-01-21 15:46:19 +00003853
John McCall57500772009-12-16 12:17:52 +00003854 Expr *NakedFn = Fn->IgnoreParenCasts();
3855 if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(NakedFn))
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00003856 AddOverloadedCallCandidates(ULE, Args, CandidateSet,
John McCall57500772009-12-16 12:17:52 +00003857 /*PartialOverloading=*/ true);
3858 else if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(NakedFn)) {
3859 FunctionDecl *FDecl = dyn_cast<FunctionDecl>(DRE->getDecl());
Douglas Gregorff59f672010-01-21 15:46:19 +00003860 if (FDecl) {
David Blaikiebbafb8a2012-03-11 07:00:24 +00003861 if (!getLangOpts().CPlusPlus ||
Douglas Gregor6ed3eb82010-05-30 06:10:08 +00003862 !FDecl->getType()->getAs<FunctionProtoType>())
Douglas Gregorff59f672010-01-21 15:46:19 +00003863 Results.push_back(ResultCandidate(FDecl));
3864 else
John McCallb89836b2010-01-26 01:37:31 +00003865 // FIXME: access?
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00003866 AddOverloadCandidate(FDecl, DeclAccessPair::make(FDecl, AS_none), Args,
3867 CandidateSet, false, /*PartialOverloading*/true);
Douglas Gregorff59f672010-01-21 15:46:19 +00003868 }
John McCall57500772009-12-16 12:17:52 +00003869 }
Douglas Gregorcabea402009-09-22 15:41:20 +00003870
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003871 QualType ParamType;
3872
Douglas Gregorff59f672010-01-21 15:46:19 +00003873 if (!CandidateSet.empty()) {
3874 // Sort the overload candidate set by placing the best overloads first.
3875 std::stable_sort(CandidateSet.begin(), CandidateSet.end(),
John McCallbc077cf2010-02-08 23:07:23 +00003876 IsBetterOverloadCandidate(*this, Loc));
Douglas Gregorcabea402009-09-22 15:41:20 +00003877
Douglas Gregorff59f672010-01-21 15:46:19 +00003878 // Add the remaining viable overload candidates as code-completion reslults.
3879 for (OverloadCandidateSet::iterator Cand = CandidateSet.begin(),
3880 CandEnd = CandidateSet.end();
3881 Cand != CandEnd; ++Cand) {
3882 if (Cand->Viable)
3883 Results.push_back(ResultCandidate(Cand->Function));
3884 }
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003885
3886 // From the viable candidates, try to determine the type of this parameter.
3887 for (unsigned I = 0, N = Results.size(); I != N; ++I) {
3888 if (const FunctionType *FType = Results[I].getFunctionType())
3889 if (const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FType))
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00003890 if (Args.size() < Proto->getNumArgs()) {
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003891 if (ParamType.isNull())
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00003892 ParamType = Proto->getArgType(Args.size());
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003893 else if (!Context.hasSameUnqualifiedType(
3894 ParamType.getNonReferenceType(),
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00003895 Proto->getArgType(Args.size()).getNonReferenceType())) {
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003896 ParamType = QualType();
3897 break;
3898 }
3899 }
3900 }
3901 } else {
3902 // Try to determine the parameter type from the type of the expression
3903 // being called.
3904 QualType FunctionType = Fn->getType();
3905 if (const PointerType *Ptr = FunctionType->getAs<PointerType>())
3906 FunctionType = Ptr->getPointeeType();
3907 else if (const BlockPointerType *BlockPtr
3908 = FunctionType->getAs<BlockPointerType>())
3909 FunctionType = BlockPtr->getPointeeType();
3910 else if (const MemberPointerType *MemPtr
3911 = FunctionType->getAs<MemberPointerType>())
3912 FunctionType = MemPtr->getPointeeType();
3913
3914 if (const FunctionProtoType *Proto
3915 = FunctionType->getAs<FunctionProtoType>()) {
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00003916 if (Args.size() < Proto->getNumArgs())
3917 ParamType = Proto->getArgType(Args.size());
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003918 }
Douglas Gregorcabea402009-09-22 15:41:20 +00003919 }
Douglas Gregor3ef59522009-12-11 19:06:04 +00003920
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003921 if (ParamType.isNull())
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003922 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003923 else
3924 CodeCompleteExpression(S, ParamType);
3925
Douglas Gregorc01890e2010-04-06 20:19:47 +00003926 if (!Results.empty())
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00003927 CodeCompleter->ProcessOverloadCandidates(*this, Args.size(), Results.data(),
Douglas Gregor3ef59522009-12-11 19:06:04 +00003928 Results.size());
Douglas Gregorcabea402009-09-22 15:41:20 +00003929}
3930
John McCall48871652010-08-21 09:40:31 +00003931void Sema::CodeCompleteInitializer(Scope *S, Decl *D) {
3932 ValueDecl *VD = dyn_cast_or_null<ValueDecl>(D);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003933 if (!VD) {
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003934 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003935 return;
3936 }
3937
3938 CodeCompleteExpression(S, VD->getType());
3939}
3940
3941void Sema::CodeCompleteReturn(Scope *S) {
3942 QualType ResultType;
3943 if (isa<BlockDecl>(CurContext)) {
3944 if (BlockScopeInfo *BSI = getCurBlock())
3945 ResultType = BSI->ReturnType;
3946 } else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(CurContext))
3947 ResultType = Function->getResultType();
3948 else if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(CurContext))
3949 ResultType = Method->getResultType();
3950
3951 if (ResultType.isNull())
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003952 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003953 else
3954 CodeCompleteExpression(S, ResultType);
3955}
3956
Douglas Gregor4ecb7202011-07-30 08:36:53 +00003957void Sema::CodeCompleteAfterIf(Scope *S) {
Douglas Gregor4ecb7202011-07-30 08:36:53 +00003958 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003959 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor4ecb7202011-07-30 08:36:53 +00003960 mapCodeCompletionContext(*this, PCC_Statement));
3961 Results.setFilter(&ResultBuilder::IsOrdinaryName);
3962 Results.EnterNewScope();
3963
3964 CodeCompletionDeclConsumer Consumer(Results, CurContext);
3965 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3966 CodeCompleter->includeGlobals());
3967
3968 AddOrdinaryNameResults(PCC_Statement, S, *this, Results);
3969
3970 // "else" block
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003971 CodeCompletionBuilder Builder(Results.getAllocator(),
3972 Results.getCodeCompletionTUInfo());
Douglas Gregor4ecb7202011-07-30 08:36:53 +00003973 Builder.AddTypedTextChunk("else");
Douglas Gregor3a5d6c22012-02-16 17:49:04 +00003974 if (Results.includeCodePatterns()) {
3975 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3976 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
3977 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
3978 Builder.AddPlaceholderChunk("statements");
3979 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
3980 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
3981 }
Douglas Gregor4ecb7202011-07-30 08:36:53 +00003982 Results.AddResult(Builder.TakeString());
3983
3984 // "else if" block
3985 Builder.AddTypedTextChunk("else");
3986 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3987 Builder.AddTextChunk("if");
3988 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3989 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00003990 if (getLangOpts().CPlusPlus)
Douglas Gregor4ecb7202011-07-30 08:36:53 +00003991 Builder.AddPlaceholderChunk("condition");
3992 else
3993 Builder.AddPlaceholderChunk("expression");
3994 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor3a5d6c22012-02-16 17:49:04 +00003995 if (Results.includeCodePatterns()) {
3996 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3997 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
3998 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
3999 Builder.AddPlaceholderChunk("statements");
4000 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
4001 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4002 }
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004003 Results.AddResult(Builder.TakeString());
4004
4005 Results.ExitScope();
4006
4007 if (S->getFnParent())
David Blaikiebbafb8a2012-03-11 07:00:24 +00004008 AddPrettyFunctionResults(PP.getLangOpts(), Results);
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004009
4010 if (CodeCompleter->includeMacros())
Douglas Gregor8cb17462012-10-09 16:01:50 +00004011 AddMacroResults(PP, Results, false);
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004012
4013 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4014 Results.data(),Results.size());
4015}
4016
Richard Trieu2bd04012011-09-09 02:00:50 +00004017void Sema::CodeCompleteAssignmentRHS(Scope *S, Expr *LHS) {
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004018 if (LHS)
4019 CodeCompleteExpression(S, static_cast<Expr *>(LHS)->getType());
4020 else
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004021 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004022}
4023
Jeffrey Yasskinc76498d2010-04-08 16:38:48 +00004024void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS,
Douglas Gregor2436e712009-09-17 21:32:03 +00004025 bool EnteringContext) {
4026 if (!SS.getScopeRep() || !CodeCompleter)
4027 return;
4028
Douglas Gregor3545ff42009-09-21 16:56:56 +00004029 DeclContext *Ctx = computeDeclContext(SS, EnteringContext);
4030 if (!Ctx)
4031 return;
Douglas Gregor800f2f02009-12-11 18:28:39 +00004032
4033 // Try to instantiate any non-dependent declaration contexts before
4034 // we look in them.
John McCall0b66eb32010-05-01 00:40:08 +00004035 if (!isDependentScopeSpecifier(SS) && RequireCompleteDeclContext(SS, Ctx))
Douglas Gregor800f2f02009-12-11 18:28:39 +00004036 return;
4037
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004038 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004039 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004040 CodeCompletionContext::CCC_Name);
Douglas Gregorac322ec2010-08-27 21:18:54 +00004041 Results.EnterNewScope();
Douglas Gregor0ac41382010-09-23 23:01:17 +00004042
Douglas Gregor3545ff42009-09-21 16:56:56 +00004043 // The "template" keyword can follow "::" in the grammar, but only
4044 // put it into the grammar if the nested-name-specifier is dependent.
4045 NestedNameSpecifier *NNS = (NestedNameSpecifier *)SS.getScopeRep();
4046 if (!Results.empty() && NNS->isDependent())
Douglas Gregor78a21012010-01-14 16:01:26 +00004047 Results.AddResult("template");
Douglas Gregorac322ec2010-08-27 21:18:54 +00004048
4049 // Add calls to overridden virtual functions, if there are any.
4050 //
4051 // FIXME: This isn't wonderful, because we don't know whether we're actually
4052 // in a context that permits expressions. This is a general issue with
4053 // qualified-id completions.
4054 if (!EnteringContext)
4055 MaybeAddOverrideCalls(*this, Ctx, Results);
4056 Results.ExitScope();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004057
Douglas Gregorac322ec2010-08-27 21:18:54 +00004058 CodeCompletionDeclConsumer Consumer(Results, CurContext);
4059 LookupVisibleDecls(Ctx, LookupOrdinaryName, Consumer);
4060
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004061 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregorc1679ec2011-07-25 17:48:11 +00004062 Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004063 Results.data(),Results.size());
Douglas Gregor2436e712009-09-17 21:32:03 +00004064}
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00004065
4066void Sema::CodeCompleteUsing(Scope *S) {
4067 if (!CodeCompleter)
4068 return;
4069
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004070 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004071 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00004072 CodeCompletionContext::CCC_PotentiallyQualifiedName,
4073 &ResultBuilder::IsNestedNameSpecifier);
Douglas Gregor64b12b52009-09-22 23:31:26 +00004074 Results.EnterNewScope();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004075
4076 // If we aren't in class scope, we could see the "namespace" keyword.
4077 if (!S->isClassScope())
John McCall276321a2010-08-25 06:19:51 +00004078 Results.AddResult(CodeCompletionResult("namespace"));
Douglas Gregor3545ff42009-09-21 16:56:56 +00004079
4080 // After "using", we can see anything that would start a
4081 // nested-name-specifier.
Douglas Gregora6e2edc2010-01-14 03:27:13 +00004082 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00004083 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4084 CodeCompleter->includeGlobals());
Douglas Gregor64b12b52009-09-22 23:31:26 +00004085 Results.ExitScope();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004086
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004087 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004088 CodeCompletionContext::CCC_PotentiallyQualifiedName,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004089 Results.data(),Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00004090}
4091
4092void Sema::CodeCompleteUsingDirective(Scope *S) {
4093 if (!CodeCompleter)
4094 return;
4095
Douglas Gregor3545ff42009-09-21 16:56:56 +00004096 // After "using namespace", we expect to see a namespace name or namespace
4097 // alias.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004098 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004099 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004100 CodeCompletionContext::CCC_Namespace,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004101 &ResultBuilder::IsNamespaceOrAlias);
Douglas Gregor64b12b52009-09-22 23:31:26 +00004102 Results.EnterNewScope();
Douglas Gregora6e2edc2010-01-14 03:27:13 +00004103 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00004104 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4105 CodeCompleter->includeGlobals());
Douglas Gregor64b12b52009-09-22 23:31:26 +00004106 Results.ExitScope();
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004107 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor39982192010-08-15 06:18:01 +00004108 CodeCompletionContext::CCC_Namespace,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004109 Results.data(),Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00004110}
4111
4112void Sema::CodeCompleteNamespaceDecl(Scope *S) {
4113 if (!CodeCompleter)
4114 return;
4115
Douglas Gregor3545ff42009-09-21 16:56:56 +00004116 DeclContext *Ctx = (DeclContext *)S->getEntity();
4117 if (!S->getParent())
4118 Ctx = Context.getTranslationUnitDecl();
4119
Douglas Gregor0ac41382010-09-23 23:01:17 +00004120 bool SuppressedGlobalResults
4121 = Ctx && !CodeCompleter->includeGlobals() && isa<TranslationUnitDecl>(Ctx);
4122
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004123 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004124 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00004125 SuppressedGlobalResults
4126 ? CodeCompletionContext::CCC_Namespace
4127 : CodeCompletionContext::CCC_Other,
4128 &ResultBuilder::IsNamespace);
4129
4130 if (Ctx && Ctx->isFileContext() && !SuppressedGlobalResults) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00004131 // We only want to see those namespaces that have already been defined
4132 // within this scope, because its likely that the user is creating an
4133 // extended namespace declaration. Keep track of the most recent
4134 // definition of each namespace.
4135 std::map<NamespaceDecl *, NamespaceDecl *> OrigToLatest;
4136 for (DeclContext::specific_decl_iterator<NamespaceDecl>
4137 NS(Ctx->decls_begin()), NSEnd(Ctx->decls_end());
4138 NS != NSEnd; ++NS)
David Blaikie40ed2972012-06-06 20:45:41 +00004139 OrigToLatest[NS->getOriginalNamespace()] = *NS;
Douglas Gregor3545ff42009-09-21 16:56:56 +00004140
4141 // Add the most recent definition (or extended definition) of each
4142 // namespace to the list of results.
Douglas Gregor64b12b52009-09-22 23:31:26 +00004143 Results.EnterNewScope();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004144 for (std::map<NamespaceDecl *, NamespaceDecl *>::iterator
Douglas Gregor78254c82012-03-27 23:34:16 +00004145 NS = OrigToLatest.begin(),
4146 NSEnd = OrigToLatest.end();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004147 NS != NSEnd; ++NS)
Douglas Gregor0a0e2b32013-01-31 04:52:16 +00004148 Results.AddResult(CodeCompletionResult(
4149 NS->second, Results.getBasePriority(NS->second), 0),
Douglas Gregorfc59ce12010-01-14 16:14:35 +00004150 CurContext, 0, false);
Douglas Gregor64b12b52009-09-22 23:31:26 +00004151 Results.ExitScope();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004152 }
4153
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004154 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004155 Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004156 Results.data(),Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00004157}
4158
4159void Sema::CodeCompleteNamespaceAliasDecl(Scope *S) {
4160 if (!CodeCompleter)
4161 return;
4162
Douglas Gregor3545ff42009-09-21 16:56:56 +00004163 // After "namespace", we expect to see a namespace or alias.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004164 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004165 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004166 CodeCompletionContext::CCC_Namespace,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004167 &ResultBuilder::IsNamespaceOrAlias);
Douglas Gregora6e2edc2010-01-14 03:27:13 +00004168 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00004169 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4170 CodeCompleter->includeGlobals());
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004171 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004172 Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004173 Results.data(),Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00004174}
4175
Douglas Gregorc811ede2009-09-18 20:05:18 +00004176void Sema::CodeCompleteOperatorName(Scope *S) {
4177 if (!CodeCompleter)
4178 return;
Douglas Gregor3545ff42009-09-21 16:56:56 +00004179
John McCall276321a2010-08-25 06:19:51 +00004180 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004181 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004182 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004183 CodeCompletionContext::CCC_Type,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004184 &ResultBuilder::IsType);
Douglas Gregor64b12b52009-09-22 23:31:26 +00004185 Results.EnterNewScope();
Douglas Gregorc811ede2009-09-18 20:05:18 +00004186
Douglas Gregor3545ff42009-09-21 16:56:56 +00004187 // Add the names of overloadable operators.
4188#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
4189 if (std::strcmp(Spelling, "?")) \
Douglas Gregor78a21012010-01-14 16:01:26 +00004190 Results.AddResult(Result(Spelling));
Douglas Gregor3545ff42009-09-21 16:56:56 +00004191#include "clang/Basic/OperatorKinds.def"
4192
4193 // Add any type names visible from the current scope
Douglas Gregor6ae4c522010-01-14 03:21:49 +00004194 Results.allowNestedNameSpecifiers();
Douglas Gregora6e2edc2010-01-14 03:27:13 +00004195 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00004196 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4197 CodeCompleter->includeGlobals());
Douglas Gregor3545ff42009-09-21 16:56:56 +00004198
4199 // Add any type specifiers
David Blaikiebbafb8a2012-03-11 07:00:24 +00004200 AddTypeSpecifierResults(getLangOpts(), Results);
Douglas Gregor64b12b52009-09-22 23:31:26 +00004201 Results.ExitScope();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004202
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004203 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor39982192010-08-15 06:18:01 +00004204 CodeCompletionContext::CCC_Type,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004205 Results.data(),Results.size());
Douglas Gregorc811ede2009-09-18 20:05:18 +00004206}
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00004207
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004208void Sema::CodeCompleteConstructorInitializer(Decl *ConstructorD,
Alexis Hunt1d792652011-01-08 20:30:50 +00004209 CXXCtorInitializer** Initializers,
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004210 unsigned NumInitializers) {
Douglas Gregor75acd922011-09-27 23:30:47 +00004211 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004212 CXXConstructorDecl *Constructor
4213 = static_cast<CXXConstructorDecl *>(ConstructorD);
4214 if (!Constructor)
4215 return;
4216
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004217 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004218 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00004219 CodeCompletionContext::CCC_PotentiallyQualifiedName);
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004220 Results.EnterNewScope();
4221
4222 // Fill in any already-initialized fields or base classes.
4223 llvm::SmallPtrSet<FieldDecl *, 4> InitializedFields;
4224 llvm::SmallPtrSet<CanQualType, 4> InitializedBases;
4225 for (unsigned I = 0; I != NumInitializers; ++I) {
4226 if (Initializers[I]->isBaseInitializer())
4227 InitializedBases.insert(
4228 Context.getCanonicalType(QualType(Initializers[I]->getBaseClass(), 0)));
4229 else
Francois Pichetd583da02010-12-04 09:14:42 +00004230 InitializedFields.insert(cast<FieldDecl>(
4231 Initializers[I]->getAnyMember()));
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004232 }
4233
4234 // Add completions for base classes.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004235 CodeCompletionBuilder Builder(Results.getAllocator(),
4236 Results.getCodeCompletionTUInfo());
Douglas Gregor99129ef2010-08-29 19:27:27 +00004237 bool SawLastInitializer = (NumInitializers == 0);
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004238 CXXRecordDecl *ClassDecl = Constructor->getParent();
4239 for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),
4240 BaseEnd = ClassDecl->bases_end();
4241 Base != BaseEnd; ++Base) {
Douglas Gregor99129ef2010-08-29 19:27:27 +00004242 if (!InitializedBases.insert(Context.getCanonicalType(Base->getType()))) {
4243 SawLastInitializer
4244 = NumInitializers > 0 &&
4245 Initializers[NumInitializers - 1]->isBaseInitializer() &&
4246 Context.hasSameUnqualifiedType(Base->getType(),
4247 QualType(Initializers[NumInitializers - 1]->getBaseClass(), 0));
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004248 continue;
Douglas Gregor99129ef2010-08-29 19:27:27 +00004249 }
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004250
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004251 Builder.AddTypedTextChunk(
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00004252 Results.getAllocator().CopyString(
John McCall31168b02011-06-15 23:02:42 +00004253 Base->getType().getAsString(Policy)));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004254 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4255 Builder.AddPlaceholderChunk("args");
4256 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4257 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor99129ef2010-08-29 19:27:27 +00004258 SawLastInitializer? CCP_NextInitializer
4259 : CCP_MemberDeclaration));
4260 SawLastInitializer = false;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004261 }
4262
4263 // Add completions for virtual base classes.
4264 for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(),
4265 BaseEnd = ClassDecl->vbases_end();
4266 Base != BaseEnd; ++Base) {
Douglas Gregor99129ef2010-08-29 19:27:27 +00004267 if (!InitializedBases.insert(Context.getCanonicalType(Base->getType()))) {
4268 SawLastInitializer
4269 = NumInitializers > 0 &&
4270 Initializers[NumInitializers - 1]->isBaseInitializer() &&
4271 Context.hasSameUnqualifiedType(Base->getType(),
4272 QualType(Initializers[NumInitializers - 1]->getBaseClass(), 0));
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004273 continue;
Douglas Gregor99129ef2010-08-29 19:27:27 +00004274 }
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004275
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004276 Builder.AddTypedTextChunk(
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00004277 Builder.getAllocator().CopyString(
John McCall31168b02011-06-15 23:02:42 +00004278 Base->getType().getAsString(Policy)));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004279 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4280 Builder.AddPlaceholderChunk("args");
4281 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4282 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor99129ef2010-08-29 19:27:27 +00004283 SawLastInitializer? CCP_NextInitializer
4284 : CCP_MemberDeclaration));
4285 SawLastInitializer = false;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004286 }
4287
4288 // Add completions for members.
4289 for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
4290 FieldEnd = ClassDecl->field_end();
4291 Field != FieldEnd; ++Field) {
Douglas Gregor99129ef2010-08-29 19:27:27 +00004292 if (!InitializedFields.insert(cast<FieldDecl>(Field->getCanonicalDecl()))) {
4293 SawLastInitializer
4294 = NumInitializers > 0 &&
Francois Pichetd583da02010-12-04 09:14:42 +00004295 Initializers[NumInitializers - 1]->isAnyMemberInitializer() &&
David Blaikie40ed2972012-06-06 20:45:41 +00004296 Initializers[NumInitializers - 1]->getAnyMember() == *Field;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004297 continue;
Douglas Gregor99129ef2010-08-29 19:27:27 +00004298 }
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004299
4300 if (!Field->getDeclName())
4301 continue;
4302
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00004303 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004304 Field->getIdentifier()->getName()));
4305 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4306 Builder.AddPlaceholderChunk("args");
4307 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4308 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor99129ef2010-08-29 19:27:27 +00004309 SawLastInitializer? CCP_NextInitializer
Douglas Gregorf3af3112010-09-09 21:42:20 +00004310 : CCP_MemberDeclaration,
Douglas Gregor78254c82012-03-27 23:34:16 +00004311 CXCursor_MemberRef,
4312 CXAvailability_Available,
David Blaikie40ed2972012-06-06 20:45:41 +00004313 *Field));
Douglas Gregor99129ef2010-08-29 19:27:27 +00004314 SawLastInitializer = false;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004315 }
4316 Results.ExitScope();
4317
Douglas Gregor0ac41382010-09-23 23:01:17 +00004318 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004319 Results.data(), Results.size());
4320}
4321
Douglas Gregord8c61782012-02-15 15:34:24 +00004322/// \brief Determine whether this scope denotes a namespace.
4323static bool isNamespaceScope(Scope *S) {
4324 DeclContext *DC = static_cast<DeclContext *>(S->getEntity());
4325 if (!DC)
4326 return false;
4327
4328 return DC->isFileContext();
4329}
4330
4331void Sema::CodeCompleteLambdaIntroducer(Scope *S, LambdaIntroducer &Intro,
4332 bool AfterAmpersand) {
4333 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004334 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregord8c61782012-02-15 15:34:24 +00004335 CodeCompletionContext::CCC_Other);
4336 Results.EnterNewScope();
4337
4338 // Note what has already been captured.
4339 llvm::SmallPtrSet<IdentifierInfo *, 4> Known;
4340 bool IncludedThis = false;
4341 for (SmallVectorImpl<LambdaCapture>::iterator C = Intro.Captures.begin(),
4342 CEnd = Intro.Captures.end();
4343 C != CEnd; ++C) {
4344 if (C->Kind == LCK_This) {
4345 IncludedThis = true;
4346 continue;
4347 }
4348
4349 Known.insert(C->Id);
4350 }
4351
4352 // Look for other capturable variables.
4353 for (; S && !isNamespaceScope(S); S = S->getParent()) {
4354 for (Scope::decl_iterator D = S->decl_begin(), DEnd = S->decl_end();
4355 D != DEnd; ++D) {
4356 VarDecl *Var = dyn_cast<VarDecl>(*D);
4357 if (!Var ||
4358 !Var->hasLocalStorage() ||
4359 Var->hasAttr<BlocksAttr>())
4360 continue;
4361
4362 if (Known.insert(Var->getIdentifier()))
Douglas Gregor0a0e2b32013-01-31 04:52:16 +00004363 Results.AddResult(CodeCompletionResult(Var, CCP_LocalDeclaration),
4364 CurContext, 0, false);
Douglas Gregord8c61782012-02-15 15:34:24 +00004365 }
4366 }
4367
4368 // Add 'this', if it would be valid.
4369 if (!IncludedThis && !AfterAmpersand && Intro.Default != LCD_ByCopy)
4370 addThisCompletion(*this, Results);
4371
4372 Results.ExitScope();
4373
4374 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4375 Results.data(), Results.size());
4376}
4377
James Dennett596e4752012-06-14 03:11:41 +00004378/// Macro that optionally prepends an "@" to the string literal passed in via
4379/// Keyword, depending on whether NeedAt is true or false.
4380#define OBJC_AT_KEYWORD_NAME(NeedAt,Keyword) ((NeedAt)? "@" Keyword : Keyword)
4381
Douglas Gregorf98e6a22010-01-13 23:51:12 +00004382static void AddObjCImplementationResults(const LangOptions &LangOpts,
Douglas Gregorf1934162010-01-13 21:24:21 +00004383 ResultBuilder &Results,
4384 bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00004385 typedef CodeCompletionResult Result;
Douglas Gregorf1934162010-01-13 21:24:21 +00004386 // Since we have an implementation, we can end it.
James Dennett596e4752012-06-14 03:11:41 +00004387 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"end")));
Douglas Gregorf1934162010-01-13 21:24:21 +00004388
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004389 CodeCompletionBuilder Builder(Results.getAllocator(),
4390 Results.getCodeCompletionTUInfo());
Douglas Gregorf1934162010-01-13 21:24:21 +00004391 if (LangOpts.ObjC2) {
4392 // @dynamic
James Dennett596e4752012-06-14 03:11:41 +00004393 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"dynamic"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004394 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4395 Builder.AddPlaceholderChunk("property");
4396 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf1934162010-01-13 21:24:21 +00004397
4398 // @synthesize
James Dennett596e4752012-06-14 03:11:41 +00004399 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"synthesize"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004400 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4401 Builder.AddPlaceholderChunk("property");
4402 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf1934162010-01-13 21:24:21 +00004403 }
4404}
4405
Douglas Gregorf98e6a22010-01-13 23:51:12 +00004406static void AddObjCInterfaceResults(const LangOptions &LangOpts,
Douglas Gregorf1934162010-01-13 21:24:21 +00004407 ResultBuilder &Results,
4408 bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00004409 typedef CodeCompletionResult Result;
Douglas Gregorf1934162010-01-13 21:24:21 +00004410
4411 // Since we have an interface or protocol, we can end it.
James Dennett596e4752012-06-14 03:11:41 +00004412 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"end")));
Douglas Gregorf1934162010-01-13 21:24:21 +00004413
4414 if (LangOpts.ObjC2) {
4415 // @property
James Dennett596e4752012-06-14 03:11:41 +00004416 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"property")));
Douglas Gregorf1934162010-01-13 21:24:21 +00004417
4418 // @required
James Dennett596e4752012-06-14 03:11:41 +00004419 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"required")));
Douglas Gregorf1934162010-01-13 21:24:21 +00004420
4421 // @optional
James Dennett596e4752012-06-14 03:11:41 +00004422 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"optional")));
Douglas Gregorf1934162010-01-13 21:24:21 +00004423 }
4424}
4425
Douglas Gregorf98e6a22010-01-13 23:51:12 +00004426static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00004427 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004428 CodeCompletionBuilder Builder(Results.getAllocator(),
4429 Results.getCodeCompletionTUInfo());
Douglas Gregorf1934162010-01-13 21:24:21 +00004430
4431 // @class name ;
James Dennett596e4752012-06-14 03:11:41 +00004432 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"class"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004433 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4434 Builder.AddPlaceholderChunk("name");
4435 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf1934162010-01-13 21:24:21 +00004436
Douglas Gregorf4c33342010-05-28 00:22:41 +00004437 if (Results.includeCodePatterns()) {
4438 // @interface name
4439 // FIXME: Could introduce the whole pattern, including superclasses and
4440 // such.
James Dennett596e4752012-06-14 03:11:41 +00004441 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"interface"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004442 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4443 Builder.AddPlaceholderChunk("class");
4444 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf1934162010-01-13 21:24:21 +00004445
Douglas Gregorf4c33342010-05-28 00:22:41 +00004446 // @protocol name
James Dennett596e4752012-06-14 03:11:41 +00004447 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"protocol"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004448 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4449 Builder.AddPlaceholderChunk("protocol");
4450 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00004451
4452 // @implementation name
James Dennett596e4752012-06-14 03:11:41 +00004453 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"implementation"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004454 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4455 Builder.AddPlaceholderChunk("class");
4456 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00004457 }
Douglas Gregorf1934162010-01-13 21:24:21 +00004458
4459 // @compatibility_alias name
James Dennett596e4752012-06-14 03:11:41 +00004460 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"compatibility_alias"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004461 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4462 Builder.AddPlaceholderChunk("alias");
4463 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4464 Builder.AddPlaceholderChunk("class");
4465 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf1934162010-01-13 21:24:21 +00004466}
4467
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00004468void Sema::CodeCompleteObjCAtDirective(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004469 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004470 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004471 CodeCompletionContext::CCC_Other);
Douglas Gregorf48706c2009-12-07 09:27:33 +00004472 Results.EnterNewScope();
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00004473 if (isa<ObjCImplDecl>(CurContext))
David Blaikiebbafb8a2012-03-11 07:00:24 +00004474 AddObjCImplementationResults(getLangOpts(), Results, false);
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00004475 else if (CurContext->isObjCContainer())
David Blaikiebbafb8a2012-03-11 07:00:24 +00004476 AddObjCInterfaceResults(getLangOpts(), Results, false);
Douglas Gregorf1934162010-01-13 21:24:21 +00004477 else
Douglas Gregorf98e6a22010-01-13 23:51:12 +00004478 AddObjCTopLevelResults(Results, false);
Douglas Gregorf48706c2009-12-07 09:27:33 +00004479 Results.ExitScope();
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004480 HandleCodeCompleteResults(this, CodeCompleter,
4481 CodeCompletionContext::CCC_Other,
4482 Results.data(),Results.size());
Douglas Gregorf48706c2009-12-07 09:27:33 +00004483}
4484
Douglas Gregorf98e6a22010-01-13 23:51:12 +00004485static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00004486 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004487 CodeCompletionBuilder Builder(Results.getAllocator(),
4488 Results.getCodeCompletionTUInfo());
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00004489
4490 // @encode ( type-name )
Douglas Gregore5c79d52011-10-18 21:20:17 +00004491 const char *EncodeType = "char[]";
David Blaikiebbafb8a2012-03-11 07:00:24 +00004492 if (Results.getSema().getLangOpts().CPlusPlus ||
4493 Results.getSema().getLangOpts().ConstStrings)
Jordan Rose9da05852012-06-15 18:19:56 +00004494 EncodeType = "const char[]";
Douglas Gregore5c79d52011-10-18 21:20:17 +00004495 Builder.AddResultTypeChunk(EncodeType);
James Dennett596e4752012-06-14 03:11:41 +00004496 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"encode"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004497 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4498 Builder.AddPlaceholderChunk("type-name");
4499 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4500 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00004501
4502 // @protocol ( protocol-name )
Douglas Gregore5c79d52011-10-18 21:20:17 +00004503 Builder.AddResultTypeChunk("Protocol *");
James Dennett596e4752012-06-14 03:11:41 +00004504 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"protocol"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004505 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4506 Builder.AddPlaceholderChunk("protocol-name");
4507 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4508 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00004509
4510 // @selector ( selector )
Douglas Gregore5c79d52011-10-18 21:20:17 +00004511 Builder.AddResultTypeChunk("SEL");
James Dennett596e4752012-06-14 03:11:41 +00004512 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"selector"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004513 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4514 Builder.AddPlaceholderChunk("selector");
4515 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4516 Results.AddResult(Result(Builder.TakeString()));
Jordan Rose9da05852012-06-15 18:19:56 +00004517
4518 // @"string"
4519 Builder.AddResultTypeChunk("NSString *");
4520 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"\""));
4521 Builder.AddPlaceholderChunk("string");
4522 Builder.AddTextChunk("\"");
4523 Results.AddResult(Result(Builder.TakeString()));
4524
Douglas Gregor951de302012-07-17 23:24:47 +00004525 // @[objects, ...]
Jordan Rose9da05852012-06-15 18:19:56 +00004526 Builder.AddResultTypeChunk("NSArray *");
James Dennett596e4752012-06-14 03:11:41 +00004527 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"["));
Ted Kremeneke65b0862012-03-06 20:05:56 +00004528 Builder.AddPlaceholderChunk("objects, ...");
Ted Kremeneke65b0862012-03-06 20:05:56 +00004529 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
4530 Results.AddResult(Result(Builder.TakeString()));
4531
Douglas Gregor951de302012-07-17 23:24:47 +00004532 // @{key : object, ...}
Jordan Rose9da05852012-06-15 18:19:56 +00004533 Builder.AddResultTypeChunk("NSDictionary *");
James Dennett596e4752012-06-14 03:11:41 +00004534 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"{"));
Ted Kremeneke65b0862012-03-06 20:05:56 +00004535 Builder.AddPlaceholderChunk("key");
Ted Kremeneke65b0862012-03-06 20:05:56 +00004536 Builder.AddChunk(CodeCompletionString::CK_Colon);
4537 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4538 Builder.AddPlaceholderChunk("object, ...");
Ted Kremeneke65b0862012-03-06 20:05:56 +00004539 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4540 Results.AddResult(Result(Builder.TakeString()));
Jordan Rose9da05852012-06-15 18:19:56 +00004541
Douglas Gregor951de302012-07-17 23:24:47 +00004542 // @(expression)
Jordan Rose9da05852012-06-15 18:19:56 +00004543 Builder.AddResultTypeChunk("id");
4544 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "("));
Jordan Rose9da05852012-06-15 18:19:56 +00004545 Builder.AddPlaceholderChunk("expression");
Jordan Rose9da05852012-06-15 18:19:56 +00004546 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4547 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00004548}
4549
Douglas Gregorf98e6a22010-01-13 23:51:12 +00004550static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00004551 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004552 CodeCompletionBuilder Builder(Results.getAllocator(),
4553 Results.getCodeCompletionTUInfo());
Douglas Gregorf1934162010-01-13 21:24:21 +00004554
Douglas Gregorf4c33342010-05-28 00:22:41 +00004555 if (Results.includeCodePatterns()) {
4556 // @try { statements } @catch ( declaration ) { statements } @finally
4557 // { statements }
James Dennett596e4752012-06-14 03:11:41 +00004558 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"try"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004559 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4560 Builder.AddPlaceholderChunk("statements");
4561 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4562 Builder.AddTextChunk("@catch");
4563 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4564 Builder.AddPlaceholderChunk("parameter");
4565 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4566 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4567 Builder.AddPlaceholderChunk("statements");
4568 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4569 Builder.AddTextChunk("@finally");
4570 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4571 Builder.AddPlaceholderChunk("statements");
4572 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4573 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00004574 }
Douglas Gregorf1934162010-01-13 21:24:21 +00004575
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00004576 // @throw
James Dennett596e4752012-06-14 03:11:41 +00004577 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"throw"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004578 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4579 Builder.AddPlaceholderChunk("expression");
4580 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf1934162010-01-13 21:24:21 +00004581
Douglas Gregorf4c33342010-05-28 00:22:41 +00004582 if (Results.includeCodePatterns()) {
4583 // @synchronized ( expression ) { statements }
James Dennett596e4752012-06-14 03:11:41 +00004584 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"synchronized"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004585 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4586 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4587 Builder.AddPlaceholderChunk("expression");
4588 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4589 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4590 Builder.AddPlaceholderChunk("statements");
4591 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4592 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00004593 }
Douglas Gregorf1934162010-01-13 21:24:21 +00004594}
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00004595
Douglas Gregorf98e6a22010-01-13 23:51:12 +00004596static void AddObjCVisibilityResults(const LangOptions &LangOpts,
Douglas Gregor48d46252010-01-13 21:54:15 +00004597 ResultBuilder &Results,
4598 bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00004599 typedef CodeCompletionResult Result;
James Dennett596e4752012-06-14 03:11:41 +00004600 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"private")));
4601 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"protected")));
4602 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"public")));
Douglas Gregor48d46252010-01-13 21:54:15 +00004603 if (LangOpts.ObjC2)
James Dennett596e4752012-06-14 03:11:41 +00004604 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"package")));
Douglas Gregor48d46252010-01-13 21:54:15 +00004605}
4606
4607void Sema::CodeCompleteObjCAtVisibility(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004608 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004609 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004610 CodeCompletionContext::CCC_Other);
Douglas Gregor48d46252010-01-13 21:54:15 +00004611 Results.EnterNewScope();
David Blaikiebbafb8a2012-03-11 07:00:24 +00004612 AddObjCVisibilityResults(getLangOpts(), Results, false);
Douglas Gregor48d46252010-01-13 21:54:15 +00004613 Results.ExitScope();
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004614 HandleCodeCompleteResults(this, CodeCompleter,
4615 CodeCompletionContext::CCC_Other,
4616 Results.data(),Results.size());
Douglas Gregor48d46252010-01-13 21:54:15 +00004617}
4618
4619void Sema::CodeCompleteObjCAtStatement(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004620 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004621 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004622 CodeCompletionContext::CCC_Other);
Douglas Gregorf1934162010-01-13 21:24:21 +00004623 Results.EnterNewScope();
Douglas Gregorf98e6a22010-01-13 23:51:12 +00004624 AddObjCStatementResults(Results, false);
4625 AddObjCExpressionResults(Results, false);
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00004626 Results.ExitScope();
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004627 HandleCodeCompleteResults(this, CodeCompleter,
4628 CodeCompletionContext::CCC_Other,
4629 Results.data(),Results.size());
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00004630}
4631
4632void Sema::CodeCompleteObjCAtExpression(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004633 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004634 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004635 CodeCompletionContext::CCC_Other);
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00004636 Results.EnterNewScope();
Douglas Gregorf98e6a22010-01-13 23:51:12 +00004637 AddObjCExpressionResults(Results, false);
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00004638 Results.ExitScope();
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004639 HandleCodeCompleteResults(this, CodeCompleter,
4640 CodeCompletionContext::CCC_Other,
4641 Results.data(),Results.size());
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00004642}
4643
Douglas Gregore6078da2009-11-19 00:14:45 +00004644/// \brief Determine whether the addition of the given flag to an Objective-C
4645/// property's attributes will cause a conflict.
Bill Wendling44426052012-12-20 19:22:21 +00004646static bool ObjCPropertyFlagConflicts(unsigned Attributes, unsigned NewFlag) {
Douglas Gregore6078da2009-11-19 00:14:45 +00004647 // Check if we've already added this flag.
Bill Wendling44426052012-12-20 19:22:21 +00004648 if (Attributes & NewFlag)
Douglas Gregore6078da2009-11-19 00:14:45 +00004649 return true;
4650
Bill Wendling44426052012-12-20 19:22:21 +00004651 Attributes |= NewFlag;
Douglas Gregore6078da2009-11-19 00:14:45 +00004652
4653 // Check for collisions with "readonly".
Bill Wendling44426052012-12-20 19:22:21 +00004654 if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) &&
4655 (Attributes & ObjCDeclSpec::DQ_PR_readwrite))
Douglas Gregore6078da2009-11-19 00:14:45 +00004656 return true;
4657
Jordan Rose53cb2f32012-08-20 20:01:13 +00004658 // Check for more than one of { assign, copy, retain, strong, weak }.
Bill Wendling44426052012-12-20 19:22:21 +00004659 unsigned AssignCopyRetMask = Attributes & (ObjCDeclSpec::DQ_PR_assign |
John McCall31168b02011-06-15 23:02:42 +00004660 ObjCDeclSpec::DQ_PR_unsafe_unretained |
Douglas Gregore6078da2009-11-19 00:14:45 +00004661 ObjCDeclSpec::DQ_PR_copy |
Jordan Rose53cb2f32012-08-20 20:01:13 +00004662 ObjCDeclSpec::DQ_PR_retain |
4663 ObjCDeclSpec::DQ_PR_strong |
4664 ObjCDeclSpec::DQ_PR_weak);
Douglas Gregore6078da2009-11-19 00:14:45 +00004665 if (AssignCopyRetMask &&
4666 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_assign &&
John McCall31168b02011-06-15 23:02:42 +00004667 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_unsafe_unretained &&
Douglas Gregore6078da2009-11-19 00:14:45 +00004668 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_copy &&
John McCall31168b02011-06-15 23:02:42 +00004669 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_retain &&
Jordan Rose53cb2f32012-08-20 20:01:13 +00004670 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_strong &&
4671 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_weak)
Douglas Gregore6078da2009-11-19 00:14:45 +00004672 return true;
4673
4674 return false;
4675}
4676
Douglas Gregor36029f42009-11-18 23:08:07 +00004677void Sema::CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS) {
Steve Naroff936354c2009-10-08 21:55:05 +00004678 if (!CodeCompleter)
4679 return;
Douglas Gregor1b605f72009-11-19 01:08:35 +00004680
Bill Wendling44426052012-12-20 19:22:21 +00004681 unsigned Attributes = ODS.getPropertyAttributes();
Steve Naroff936354c2009-10-08 21:55:05 +00004682
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004683 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004684 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004685 CodeCompletionContext::CCC_Other);
Steve Naroff936354c2009-10-08 21:55:05 +00004686 Results.EnterNewScope();
Bill Wendling44426052012-12-20 19:22:21 +00004687 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readonly))
John McCall276321a2010-08-25 06:19:51 +00004688 Results.AddResult(CodeCompletionResult("readonly"));
Bill Wendling44426052012-12-20 19:22:21 +00004689 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_assign))
John McCall276321a2010-08-25 06:19:51 +00004690 Results.AddResult(CodeCompletionResult("assign"));
Bill Wendling44426052012-12-20 19:22:21 +00004691 if (!ObjCPropertyFlagConflicts(Attributes,
John McCall31168b02011-06-15 23:02:42 +00004692 ObjCDeclSpec::DQ_PR_unsafe_unretained))
4693 Results.AddResult(CodeCompletionResult("unsafe_unretained"));
Bill Wendling44426052012-12-20 19:22:21 +00004694 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readwrite))
John McCall276321a2010-08-25 06:19:51 +00004695 Results.AddResult(CodeCompletionResult("readwrite"));
Bill Wendling44426052012-12-20 19:22:21 +00004696 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_retain))
John McCall276321a2010-08-25 06:19:51 +00004697 Results.AddResult(CodeCompletionResult("retain"));
Bill Wendling44426052012-12-20 19:22:21 +00004698 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_strong))
John McCall31168b02011-06-15 23:02:42 +00004699 Results.AddResult(CodeCompletionResult("strong"));
Bill Wendling44426052012-12-20 19:22:21 +00004700 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_copy))
John McCall276321a2010-08-25 06:19:51 +00004701 Results.AddResult(CodeCompletionResult("copy"));
Bill Wendling44426052012-12-20 19:22:21 +00004702 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_nonatomic))
John McCall276321a2010-08-25 06:19:51 +00004703 Results.AddResult(CodeCompletionResult("nonatomic"));
Bill Wendling44426052012-12-20 19:22:21 +00004704 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_atomic))
Fariborz Jahanian1c2d29e2011-06-11 17:14:27 +00004705 Results.AddResult(CodeCompletionResult("atomic"));
Jordan Rose53cb2f32012-08-20 20:01:13 +00004706
4707 // Only suggest "weak" if we're compiling for ARC-with-weak-references or GC.
John McCall3deb1ad2012-08-21 02:47:43 +00004708 if (getLangOpts().ObjCARCWeak || getLangOpts().getGC() != LangOptions::NonGC)
Bill Wendling44426052012-12-20 19:22:21 +00004709 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_weak))
Jordan Rose53cb2f32012-08-20 20:01:13 +00004710 Results.AddResult(CodeCompletionResult("weak"));
4711
Bill Wendling44426052012-12-20 19:22:21 +00004712 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_setter)) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004713 CodeCompletionBuilder Setter(Results.getAllocator(),
4714 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004715 Setter.AddTypedTextChunk("setter");
4716 Setter.AddTextChunk(" = ");
4717 Setter.AddPlaceholderChunk("method");
4718 Results.AddResult(CodeCompletionResult(Setter.TakeString()));
Douglas Gregor45f83ee2009-11-19 00:01:57 +00004719 }
Bill Wendling44426052012-12-20 19:22:21 +00004720 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_getter)) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004721 CodeCompletionBuilder Getter(Results.getAllocator(),
4722 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004723 Getter.AddTypedTextChunk("getter");
4724 Getter.AddTextChunk(" = ");
4725 Getter.AddPlaceholderChunk("method");
4726 Results.AddResult(CodeCompletionResult(Getter.TakeString()));
Douglas Gregor45f83ee2009-11-19 00:01:57 +00004727 }
Steve Naroff936354c2009-10-08 21:55:05 +00004728 Results.ExitScope();
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004729 HandleCodeCompleteResults(this, CodeCompleter,
4730 CodeCompletionContext::CCC_Other,
4731 Results.data(),Results.size());
Steve Naroff936354c2009-10-08 21:55:05 +00004732}
Steve Naroffeae65032009-11-07 02:08:14 +00004733
James Dennettf1243872012-06-17 05:33:25 +00004734/// \brief Describes the kind of Objective-C method that we want to find
Douglas Gregorc8537c52009-11-19 07:41:15 +00004735/// via code completion.
4736enum ObjCMethodKind {
Dmitri Gribenko4280e5c2012-06-08 23:13:42 +00004737 MK_Any, ///< Any kind of method, provided it means other specified criteria.
4738 MK_ZeroArgSelector, ///< Zero-argument (unary) selector.
4739 MK_OneArgSelector ///< One-argument selector.
Douglas Gregorc8537c52009-11-19 07:41:15 +00004740};
4741
Douglas Gregor67c692c2010-08-26 15:07:07 +00004742static bool isAcceptableObjCSelector(Selector Sel,
4743 ObjCMethodKind WantKind,
4744 IdentifierInfo **SelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00004745 unsigned NumSelIdents,
4746 bool AllowSameLength = true) {
Douglas Gregor67c692c2010-08-26 15:07:07 +00004747 if (NumSelIdents > Sel.getNumArgs())
4748 return false;
4749
4750 switch (WantKind) {
4751 case MK_Any: break;
4752 case MK_ZeroArgSelector: return Sel.isUnarySelector();
4753 case MK_OneArgSelector: return Sel.getNumArgs() == 1;
4754 }
4755
Douglas Gregorb4a7c032010-11-17 21:36:08 +00004756 if (!AllowSameLength && NumSelIdents && NumSelIdents == Sel.getNumArgs())
4757 return false;
4758
Douglas Gregor67c692c2010-08-26 15:07:07 +00004759 for (unsigned I = 0; I != NumSelIdents; ++I)
4760 if (SelIdents[I] != Sel.getIdentifierInfoForSlot(I))
4761 return false;
4762
4763 return true;
4764}
4765
Douglas Gregorc8537c52009-11-19 07:41:15 +00004766static bool isAcceptableObjCMethod(ObjCMethodDecl *Method,
4767 ObjCMethodKind WantKind,
4768 IdentifierInfo **SelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00004769 unsigned NumSelIdents,
4770 bool AllowSameLength = true) {
Douglas Gregor67c692c2010-08-26 15:07:07 +00004771 return isAcceptableObjCSelector(Method->getSelector(), WantKind, SelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00004772 NumSelIdents, AllowSameLength);
Douglas Gregorc8537c52009-11-19 07:41:15 +00004773}
Douglas Gregor1154e272010-09-16 16:06:31 +00004774
4775namespace {
4776 /// \brief A set of selectors, which is used to avoid introducing multiple
4777 /// completions with the same selector into the result set.
4778 typedef llvm::SmallPtrSet<Selector, 16> VisitedSelectorSet;
4779}
4780
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00004781/// \brief Add all of the Objective-C methods in the given Objective-C
4782/// container to the set of results.
4783///
4784/// The container will be a class, protocol, category, or implementation of
4785/// any of the above. This mether will recurse to include methods from
4786/// the superclasses of classes along with their categories, protocols, and
4787/// implementations.
4788///
4789/// \param Container the container in which we'll look to find methods.
4790///
James Dennett596e4752012-06-14 03:11:41 +00004791/// \param WantInstanceMethods Whether to add instance methods (only); if
4792/// false, this routine will add factory methods (only).
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00004793///
4794/// \param CurContext the context in which we're performing the lookup that
4795/// finds methods.
4796///
Douglas Gregorb4a7c032010-11-17 21:36:08 +00004797/// \param AllowSameLength Whether we allow a method to be added to the list
4798/// when it has the same number of parameters as we have selector identifiers.
4799///
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00004800/// \param Results the structure into which we'll add results.
4801static void AddObjCMethods(ObjCContainerDecl *Container,
4802 bool WantInstanceMethods,
Douglas Gregorc8537c52009-11-19 07:41:15 +00004803 ObjCMethodKind WantKind,
Douglas Gregor1b605f72009-11-19 01:08:35 +00004804 IdentifierInfo **SelIdents,
4805 unsigned NumSelIdents,
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00004806 DeclContext *CurContext,
Douglas Gregor1154e272010-09-16 16:06:31 +00004807 VisitedSelectorSet &Selectors,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00004808 bool AllowSameLength,
Douglas Gregor416b5752010-08-25 01:08:01 +00004809 ResultBuilder &Results,
4810 bool InOriginalClass = true) {
John McCall276321a2010-08-25 06:19:51 +00004811 typedef CodeCompletionResult Result;
Douglas Gregor9b4f3702012-06-12 13:44:08 +00004812 Container = getContainerDef(Container);
Douglas Gregor41778c32013-01-30 06:58:39 +00004813 ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container);
4814 bool isRootClass = IFace && !IFace->getSuperClass();
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00004815 for (ObjCContainerDecl::method_iterator M = Container->meth_begin(),
4816 MEnd = Container->meth_end();
4817 M != MEnd; ++M) {
Douglas Gregor41778c32013-01-30 06:58:39 +00004818 // The instance methods on the root class can be messaged via the
4819 // metaclass.
4820 if (M->isInstanceMethod() == WantInstanceMethods ||
4821 (isRootClass && !WantInstanceMethods)) {
Douglas Gregor1b605f72009-11-19 01:08:35 +00004822 // Check whether the selector identifiers we've been given are a
4823 // subset of the identifiers for this particular method.
David Blaikie40ed2972012-06-06 20:45:41 +00004824 if (!isAcceptableObjCMethod(*M, WantKind, SelIdents, NumSelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00004825 AllowSameLength))
Douglas Gregor1b605f72009-11-19 01:08:35 +00004826 continue;
Douglas Gregorc8537c52009-11-19 07:41:15 +00004827
David Blaikie2d7c57e2012-04-30 02:36:29 +00004828 if (!Selectors.insert(M->getSelector()))
Douglas Gregor1154e272010-09-16 16:06:31 +00004829 continue;
4830
Douglas Gregor0a0e2b32013-01-31 04:52:16 +00004831 Result R = Result(*M, Results.getBasePriority(*M), 0);
Douglas Gregor1b605f72009-11-19 01:08:35 +00004832 R.StartParameter = NumSelIdents;
Douglas Gregorc8537c52009-11-19 07:41:15 +00004833 R.AllParametersAreInformative = (WantKind != MK_Any);
Douglas Gregor416b5752010-08-25 01:08:01 +00004834 if (!InOriginalClass)
4835 R.Priority += CCD_InBaseClass;
Douglas Gregor1b605f72009-11-19 01:08:35 +00004836 Results.MaybeAddResult(R, CurContext);
4837 }
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00004838 }
4839
Douglas Gregorf37c9492010-09-16 15:34:59 +00004840 // Visit the protocols of protocols.
4841 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Douglas Gregore6e48b12012-01-01 19:29:29 +00004842 if (Protocol->hasDefinition()) {
4843 const ObjCList<ObjCProtocolDecl> &Protocols
4844 = Protocol->getReferencedProtocols();
4845 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
4846 E = Protocols.end();
4847 I != E; ++I)
4848 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents,
4849 NumSelIdents, CurContext, Selectors, AllowSameLength,
4850 Results, false);
4851 }
Douglas Gregorf37c9492010-09-16 15:34:59 +00004852 }
4853
Douglas Gregorc0ac7d62011-12-15 05:27:12 +00004854 if (!IFace || !IFace->hasDefinition())
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00004855 return;
4856
4857 // Add methods in protocols.
Argyrios Kyrtzidise7f3ef32012-03-13 01:09:41 +00004858 for (ObjCInterfaceDecl::protocol_iterator I = IFace->protocol_begin(),
4859 E = IFace->protocol_end();
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00004860 I != E; ++I)
Douglas Gregorc8537c52009-11-19 07:41:15 +00004861 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, NumSelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00004862 CurContext, Selectors, AllowSameLength, Results, false);
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00004863
4864 // Add methods in categories.
Douglas Gregor048fbfa2013-01-16 23:00:23 +00004865 for (ObjCInterfaceDecl::known_categories_iterator
4866 Cat = IFace->known_categories_begin(),
4867 CatEnd = IFace->known_categories_end();
4868 Cat != CatEnd; ++Cat) {
4869 ObjCCategoryDecl *CatDecl = *Cat;
4870
4871 AddObjCMethods(CatDecl, WantInstanceMethods, WantKind, SelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00004872 NumSelIdents, CurContext, Selectors, AllowSameLength,
4873 Results, InOriginalClass);
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00004874
4875 // Add a categories protocol methods.
4876 const ObjCList<ObjCProtocolDecl> &Protocols
4877 = CatDecl->getReferencedProtocols();
4878 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
4879 E = Protocols.end();
4880 I != E; ++I)
Douglas Gregorc8537c52009-11-19 07:41:15 +00004881 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00004882 NumSelIdents, CurContext, Selectors, AllowSameLength,
4883 Results, false);
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00004884
4885 // Add methods in category implementations.
4886 if (ObjCCategoryImplDecl *Impl = CatDecl->getImplementation())
Douglas Gregorc8537c52009-11-19 07:41:15 +00004887 AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00004888 NumSelIdents, CurContext, Selectors, AllowSameLength,
4889 Results, InOriginalClass);
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00004890 }
4891
4892 // Add methods in superclass.
4893 if (IFace->getSuperClass())
Douglas Gregorc8537c52009-11-19 07:41:15 +00004894 AddObjCMethods(IFace->getSuperClass(), WantInstanceMethods, WantKind,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00004895 SelIdents, NumSelIdents, CurContext, Selectors,
4896 AllowSameLength, Results, false);
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00004897
4898 // Add methods in our implementation, if any.
4899 if (ObjCImplementationDecl *Impl = IFace->getImplementation())
Douglas Gregorc8537c52009-11-19 07:41:15 +00004900 AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00004901 NumSelIdents, CurContext, Selectors, AllowSameLength,
4902 Results, InOriginalClass);
Douglas Gregorc8537c52009-11-19 07:41:15 +00004903}
4904
4905
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00004906void Sema::CodeCompleteObjCPropertyGetter(Scope *S) {
Douglas Gregorc8537c52009-11-19 07:41:15 +00004907 // Try to find the interface where getters might live.
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00004908 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext);
Douglas Gregorc8537c52009-11-19 07:41:15 +00004909 if (!Class) {
4910 if (ObjCCategoryDecl *Category
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00004911 = dyn_cast_or_null<ObjCCategoryDecl>(CurContext))
Douglas Gregorc8537c52009-11-19 07:41:15 +00004912 Class = Category->getClassInterface();
4913
4914 if (!Class)
4915 return;
4916 }
4917
4918 // Find all of the potential getters.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004919 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004920 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004921 CodeCompletionContext::CCC_Other);
Douglas Gregorc8537c52009-11-19 07:41:15 +00004922 Results.EnterNewScope();
4923
Douglas Gregor1154e272010-09-16 16:06:31 +00004924 VisitedSelectorSet Selectors;
4925 AddObjCMethods(Class, true, MK_ZeroArgSelector, 0, 0, CurContext, Selectors,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00004926 /*AllowSameLength=*/true, Results);
Douglas Gregorc8537c52009-11-19 07:41:15 +00004927 Results.ExitScope();
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004928 HandleCodeCompleteResults(this, CodeCompleter,
4929 CodeCompletionContext::CCC_Other,
4930 Results.data(),Results.size());
Douglas Gregorc8537c52009-11-19 07:41:15 +00004931}
4932
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00004933void Sema::CodeCompleteObjCPropertySetter(Scope *S) {
Douglas Gregorc8537c52009-11-19 07:41:15 +00004934 // Try to find the interface where setters might live.
4935 ObjCInterfaceDecl *Class
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00004936 = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext);
Douglas Gregorc8537c52009-11-19 07:41:15 +00004937 if (!Class) {
4938 if (ObjCCategoryDecl *Category
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00004939 = dyn_cast_or_null<ObjCCategoryDecl>(CurContext))
Douglas Gregorc8537c52009-11-19 07:41:15 +00004940 Class = Category->getClassInterface();
4941
4942 if (!Class)
4943 return;
4944 }
4945
4946 // Find all of the potential getters.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004947 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004948 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004949 CodeCompletionContext::CCC_Other);
Douglas Gregorc8537c52009-11-19 07:41:15 +00004950 Results.EnterNewScope();
4951
Douglas Gregor1154e272010-09-16 16:06:31 +00004952 VisitedSelectorSet Selectors;
4953 AddObjCMethods(Class, true, MK_OneArgSelector, 0, 0, CurContext,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00004954 Selectors, /*AllowSameLength=*/true, Results);
Douglas Gregorc8537c52009-11-19 07:41:15 +00004955
4956 Results.ExitScope();
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004957 HandleCodeCompleteResults(this, CodeCompleter,
4958 CodeCompletionContext::CCC_Other,
4959 Results.data(),Results.size());
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00004960}
4961
Douglas Gregorf34a6f02011-02-15 22:19:42 +00004962void Sema::CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS,
4963 bool IsParameter) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004964 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004965 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004966 CodeCompletionContext::CCC_Type);
Douglas Gregor99fa2642010-08-24 01:06:58 +00004967 Results.EnterNewScope();
4968
4969 // Add context-sensitive, Objective-C parameter-passing keywords.
4970 bool AddedInOut = false;
4971 if ((DS.getObjCDeclQualifier() &
4972 (ObjCDeclSpec::DQ_In | ObjCDeclSpec::DQ_Inout)) == 0) {
4973 Results.AddResult("in");
4974 Results.AddResult("inout");
4975 AddedInOut = true;
4976 }
4977 if ((DS.getObjCDeclQualifier() &
4978 (ObjCDeclSpec::DQ_Out | ObjCDeclSpec::DQ_Inout)) == 0) {
4979 Results.AddResult("out");
4980 if (!AddedInOut)
4981 Results.AddResult("inout");
4982 }
4983 if ((DS.getObjCDeclQualifier() &
4984 (ObjCDeclSpec::DQ_Bycopy | ObjCDeclSpec::DQ_Byref |
4985 ObjCDeclSpec::DQ_Oneway)) == 0) {
4986 Results.AddResult("bycopy");
4987 Results.AddResult("byref");
4988 Results.AddResult("oneway");
4989 }
4990
Douglas Gregorf34a6f02011-02-15 22:19:42 +00004991 // If we're completing the return type of an Objective-C method and the
4992 // identifier IBAction refers to a macro, provide a completion item for
4993 // an action, e.g.,
4994 // IBAction)<#selector#>:(id)sender
4995 if (DS.getObjCDeclQualifier() == 0 && !IsParameter &&
4996 Context.Idents.get("IBAction").hasMacroDefinition()) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004997 CodeCompletionBuilder Builder(Results.getAllocator(),
4998 Results.getCodeCompletionTUInfo(),
4999 CCP_CodePattern, CXAvailability_Available);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00005000 Builder.AddTypedTextChunk("IBAction");
Benjamin Kramerdb534a42012-03-26 16:57:36 +00005001 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00005002 Builder.AddPlaceholderChunk("selector");
Benjamin Kramerdb534a42012-03-26 16:57:36 +00005003 Builder.AddChunk(CodeCompletionString::CK_Colon);
5004 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00005005 Builder.AddTextChunk("id");
Benjamin Kramerdb534a42012-03-26 16:57:36 +00005006 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00005007 Builder.AddTextChunk("sender");
5008 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
5009 }
Douglas Gregored1f5972013-01-30 07:11:43 +00005010
5011 // If we're completing the return type, provide 'instancetype'.
5012 if (!IsParameter) {
5013 Results.AddResult(CodeCompletionResult("instancetype"));
5014 }
Douglas Gregorf34a6f02011-02-15 22:19:42 +00005015
Douglas Gregor99fa2642010-08-24 01:06:58 +00005016 // Add various builtin type names and specifiers.
5017 AddOrdinaryNameResults(PCC_Type, S, *this, Results);
5018 Results.ExitScope();
5019
5020 // Add the various type names
5021 Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
5022 CodeCompletionDeclConsumer Consumer(Results, CurContext);
5023 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
5024 CodeCompleter->includeGlobals());
5025
5026 if (CodeCompleter->includeMacros())
Douglas Gregor8cb17462012-10-09 16:01:50 +00005027 AddMacroResults(PP, Results, false);
Douglas Gregor99fa2642010-08-24 01:06:58 +00005028
5029 HandleCodeCompleteResults(this, CodeCompleter,
5030 CodeCompletionContext::CCC_Type,
5031 Results.data(), Results.size());
5032}
5033
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005034/// \brief When we have an expression with type "id", we may assume
5035/// that it has some more-specific class type based on knowledge of
5036/// common uses of Objective-C. This routine returns that class type,
5037/// or NULL if no better result could be determined.
5038static ObjCInterfaceDecl *GetAssumedMessageSendExprType(Expr *E) {
Douglas Gregored0b69d2010-09-15 16:23:04 +00005039 ObjCMessageExpr *Msg = dyn_cast_or_null<ObjCMessageExpr>(E);
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005040 if (!Msg)
5041 return 0;
5042
5043 Selector Sel = Msg->getSelector();
5044 if (Sel.isNull())
5045 return 0;
5046
5047 IdentifierInfo *Id = Sel.getIdentifierInfoForSlot(0);
5048 if (!Id)
5049 return 0;
5050
5051 ObjCMethodDecl *Method = Msg->getMethodDecl();
5052 if (!Method)
5053 return 0;
5054
5055 // Determine the class that we're sending the message to.
Douglas Gregor9a129192010-04-21 00:45:42 +00005056 ObjCInterfaceDecl *IFace = 0;
5057 switch (Msg->getReceiverKind()) {
5058 case ObjCMessageExpr::Class:
John McCall8b07ec22010-05-15 11:32:37 +00005059 if (const ObjCObjectType *ObjType
5060 = Msg->getClassReceiver()->getAs<ObjCObjectType>())
5061 IFace = ObjType->getInterface();
Douglas Gregor9a129192010-04-21 00:45:42 +00005062 break;
5063
5064 case ObjCMessageExpr::Instance: {
5065 QualType T = Msg->getInstanceReceiver()->getType();
5066 if (const ObjCObjectPointerType *Ptr = T->getAs<ObjCObjectPointerType>())
5067 IFace = Ptr->getInterfaceDecl();
5068 break;
5069 }
5070
5071 case ObjCMessageExpr::SuperInstance:
5072 case ObjCMessageExpr::SuperClass:
5073 break;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005074 }
5075
5076 if (!IFace)
5077 return 0;
5078
5079 ObjCInterfaceDecl *Super = IFace->getSuperClass();
5080 if (Method->isInstanceMethod())
5081 return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
5082 .Case("retain", IFace)
John McCall31168b02011-06-15 23:02:42 +00005083 .Case("strong", IFace)
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005084 .Case("autorelease", IFace)
5085 .Case("copy", IFace)
5086 .Case("copyWithZone", IFace)
5087 .Case("mutableCopy", IFace)
5088 .Case("mutableCopyWithZone", IFace)
5089 .Case("awakeFromCoder", IFace)
5090 .Case("replacementObjectFromCoder", IFace)
5091 .Case("class", IFace)
5092 .Case("classForCoder", IFace)
5093 .Case("superclass", Super)
5094 .Default(0);
5095
5096 return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
5097 .Case("new", IFace)
5098 .Case("alloc", IFace)
5099 .Case("allocWithZone", IFace)
5100 .Case("class", IFace)
5101 .Case("superclass", Super)
5102 .Default(0);
5103}
5104
Douglas Gregor6fc04132010-08-27 15:10:57 +00005105// Add a special completion for a message send to "super", which fills in the
5106// most likely case of forwarding all of our arguments to the superclass
5107// function.
5108///
5109/// \param S The semantic analysis object.
5110///
Dmitri Gribenkoadba9be2012-08-23 17:58:28 +00005111/// \param NeedSuperKeyword Whether we need to prefix this completion with
Douglas Gregor6fc04132010-08-27 15:10:57 +00005112/// the "super" keyword. Otherwise, we just need to provide the arguments.
5113///
5114/// \param SelIdents The identifiers in the selector that have already been
5115/// provided as arguments for a send to "super".
5116///
5117/// \param NumSelIdents The number of identifiers in \p SelIdents.
5118///
5119/// \param Results The set of results to augment.
5120///
5121/// \returns the Objective-C method declaration that would be invoked by
5122/// this "super" completion. If NULL, no completion was added.
5123static ObjCMethodDecl *AddSuperSendCompletion(Sema &S, bool NeedSuperKeyword,
5124 IdentifierInfo **SelIdents,
5125 unsigned NumSelIdents,
5126 ResultBuilder &Results) {
5127 ObjCMethodDecl *CurMethod = S.getCurMethodDecl();
5128 if (!CurMethod)
5129 return 0;
5130
5131 ObjCInterfaceDecl *Class = CurMethod->getClassInterface();
5132 if (!Class)
5133 return 0;
5134
5135 // Try to find a superclass method with the same selector.
5136 ObjCMethodDecl *SuperMethod = 0;
Douglas Gregorb5f1e462011-02-16 00:51:18 +00005137 while ((Class = Class->getSuperClass()) && !SuperMethod) {
5138 // Check in the class
Douglas Gregor6fc04132010-08-27 15:10:57 +00005139 SuperMethod = Class->getMethod(CurMethod->getSelector(),
5140 CurMethod->isInstanceMethod());
5141
Douglas Gregorb5f1e462011-02-16 00:51:18 +00005142 // Check in categories or class extensions.
5143 if (!SuperMethod) {
Douglas Gregor048fbfa2013-01-16 23:00:23 +00005144 for (ObjCInterfaceDecl::known_categories_iterator
5145 Cat = Class->known_categories_begin(),
5146 CatEnd = Class->known_categories_end();
5147 Cat != CatEnd; ++Cat) {
5148 if ((SuperMethod = Cat->getMethod(CurMethod->getSelector(),
Douglas Gregorb5f1e462011-02-16 00:51:18 +00005149 CurMethod->isInstanceMethod())))
5150 break;
Douglas Gregor048fbfa2013-01-16 23:00:23 +00005151 }
Douglas Gregorb5f1e462011-02-16 00:51:18 +00005152 }
5153 }
5154
Douglas Gregor6fc04132010-08-27 15:10:57 +00005155 if (!SuperMethod)
5156 return 0;
5157
5158 // Check whether the superclass method has the same signature.
5159 if (CurMethod->param_size() != SuperMethod->param_size() ||
5160 CurMethod->isVariadic() != SuperMethod->isVariadic())
5161 return 0;
5162
5163 for (ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin(),
5164 CurPEnd = CurMethod->param_end(),
5165 SuperP = SuperMethod->param_begin();
5166 CurP != CurPEnd; ++CurP, ++SuperP) {
5167 // Make sure the parameter types are compatible.
5168 if (!S.Context.hasSameUnqualifiedType((*CurP)->getType(),
5169 (*SuperP)->getType()))
5170 return 0;
5171
5172 // Make sure we have a parameter name to forward!
5173 if (!(*CurP)->getIdentifier())
5174 return 0;
5175 }
5176
5177 // We have a superclass method. Now, form the send-to-super completion.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005178 CodeCompletionBuilder Builder(Results.getAllocator(),
5179 Results.getCodeCompletionTUInfo());
Douglas Gregor6fc04132010-08-27 15:10:57 +00005180
5181 // Give this completion a return type.
Douglas Gregor75acd922011-09-27 23:30:47 +00005182 AddResultTypeChunk(S.Context, getCompletionPrintingPolicy(S), SuperMethod,
5183 Builder);
Douglas Gregor6fc04132010-08-27 15:10:57 +00005184
5185 // If we need the "super" keyword, add it (plus some spacing).
5186 if (NeedSuperKeyword) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005187 Builder.AddTypedTextChunk("super");
5188 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregor6fc04132010-08-27 15:10:57 +00005189 }
5190
5191 Selector Sel = CurMethod->getSelector();
5192 if (Sel.isUnarySelector()) {
5193 if (NeedSuperKeyword)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005194 Builder.AddTextChunk(Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00005195 Sel.getNameForSlot(0)));
Douglas Gregor6fc04132010-08-27 15:10:57 +00005196 else
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005197 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00005198 Sel.getNameForSlot(0)));
Douglas Gregor6fc04132010-08-27 15:10:57 +00005199 } else {
5200 ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin();
5201 for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I, ++CurP) {
5202 if (I > NumSelIdents)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005203 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregor6fc04132010-08-27 15:10:57 +00005204
5205 if (I < NumSelIdents)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005206 Builder.AddInformativeChunk(
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005207 Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00005208 Sel.getNameForSlot(I) + ":"));
Douglas Gregor6fc04132010-08-27 15:10:57 +00005209 else if (NeedSuperKeyword || I > NumSelIdents) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005210 Builder.AddTextChunk(
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005211 Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00005212 Sel.getNameForSlot(I) + ":"));
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005213 Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005214 (*CurP)->getIdentifier()->getName()));
Douglas Gregor6fc04132010-08-27 15:10:57 +00005215 } else {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005216 Builder.AddTypedTextChunk(
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005217 Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00005218 Sel.getNameForSlot(I) + ":"));
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005219 Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005220 (*CurP)->getIdentifier()->getName()));
Douglas Gregor6fc04132010-08-27 15:10:57 +00005221 }
5222 }
5223 }
5224
Douglas Gregor78254c82012-03-27 23:34:16 +00005225 Results.AddResult(CodeCompletionResult(Builder.TakeString(), SuperMethod,
5226 CCP_SuperCompletion));
Douglas Gregor6fc04132010-08-27 15:10:57 +00005227 return SuperMethod;
5228}
5229
Douglas Gregora817a192010-05-27 23:06:34 +00005230void Sema::CodeCompleteObjCMessageReceiver(Scope *S) {
John McCall276321a2010-08-25 06:19:51 +00005231 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005232 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005233 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005234 CodeCompletionContext::CCC_ObjCMessageReceiver,
Richard Smith2bf7fdb2013-01-02 11:42:31 +00005235 getLangOpts().CPlusPlus11
Douglas Gregord8c61782012-02-15 15:34:24 +00005236 ? &ResultBuilder::IsObjCMessageReceiverOrLambdaCapture
5237 : &ResultBuilder::IsObjCMessageReceiver);
Douglas Gregora817a192010-05-27 23:06:34 +00005238
Douglas Gregora817a192010-05-27 23:06:34 +00005239 CodeCompletionDeclConsumer Consumer(Results, CurContext);
5240 Results.EnterNewScope();
Douglas Gregor39982192010-08-15 06:18:01 +00005241 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
5242 CodeCompleter->includeGlobals());
Douglas Gregora817a192010-05-27 23:06:34 +00005243
5244 // If we are in an Objective-C method inside a class that has a superclass,
5245 // add "super" as an option.
5246 if (ObjCMethodDecl *Method = getCurMethodDecl())
5247 if (ObjCInterfaceDecl *Iface = Method->getClassInterface())
Douglas Gregor6fc04132010-08-27 15:10:57 +00005248 if (Iface->getSuperClass()) {
Douglas Gregora817a192010-05-27 23:06:34 +00005249 Results.AddResult(Result("super"));
Douglas Gregor6fc04132010-08-27 15:10:57 +00005250
5251 AddSuperSendCompletion(*this, /*NeedSuperKeyword=*/true, 0, 0, Results);
5252 }
Douglas Gregora817a192010-05-27 23:06:34 +00005253
Richard Smith2bf7fdb2013-01-02 11:42:31 +00005254 if (getLangOpts().CPlusPlus11)
Douglas Gregord8c61782012-02-15 15:34:24 +00005255 addThisCompletion(*this, Results);
5256
Douglas Gregora817a192010-05-27 23:06:34 +00005257 Results.ExitScope();
5258
5259 if (CodeCompleter->includeMacros())
Douglas Gregor8cb17462012-10-09 16:01:50 +00005260 AddMacroResults(PP, Results, false);
Douglas Gregor50832e02010-09-20 22:39:41 +00005261 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005262 Results.data(), Results.size());
Douglas Gregora817a192010-05-27 23:06:34 +00005263
5264}
5265
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005266void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc,
5267 IdentifierInfo **SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00005268 unsigned NumSelIdents,
5269 bool AtArgumentExpression) {
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005270 ObjCInterfaceDecl *CDecl = 0;
5271 if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
5272 // Figure out which interface we're in.
5273 CDecl = CurMethod->getClassInterface();
5274 if (!CDecl)
5275 return;
5276
5277 // Find the superclass of this class.
5278 CDecl = CDecl->getSuperClass();
5279 if (!CDecl)
5280 return;
5281
5282 if (CurMethod->isInstanceMethod()) {
5283 // We are inside an instance method, which means that the message
5284 // send [super ...] is actually calling an instance method on the
Douglas Gregor392a84b2010-10-13 21:24:53 +00005285 // current object.
5286 return CodeCompleteObjCInstanceMessage(S, 0,
Douglas Gregor6fc04132010-08-27 15:10:57 +00005287 SelIdents, NumSelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00005288 AtArgumentExpression,
Douglas Gregor392a84b2010-10-13 21:24:53 +00005289 CDecl);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005290 }
5291
5292 // Fall through to send to the superclass in CDecl.
5293 } else {
5294 // "super" may be the name of a type or variable. Figure out which
5295 // it is.
5296 IdentifierInfo *Super = &Context.Idents.get("super");
5297 NamedDecl *ND = LookupSingleName(S, Super, SuperLoc,
5298 LookupOrdinaryName);
5299 if ((CDecl = dyn_cast_or_null<ObjCInterfaceDecl>(ND))) {
5300 // "super" names an interface. Use it.
5301 } else if (TypeDecl *TD = dyn_cast_or_null<TypeDecl>(ND)) {
John McCall8b07ec22010-05-15 11:32:37 +00005302 if (const ObjCObjectType *Iface
5303 = Context.getTypeDeclType(TD)->getAs<ObjCObjectType>())
5304 CDecl = Iface->getInterface();
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005305 } else if (ND && isa<UnresolvedUsingTypenameDecl>(ND)) {
5306 // "super" names an unresolved type; we can't be more specific.
5307 } else {
5308 // Assume that "super" names some kind of value and parse that way.
5309 CXXScopeSpec SS;
Abramo Bagnara7945c982012-01-27 09:46:47 +00005310 SourceLocation TemplateKWLoc;
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005311 UnqualifiedId id;
5312 id.setIdentifier(Super, SuperLoc);
Abramo Bagnara7945c982012-01-27 09:46:47 +00005313 ExprResult SuperExpr = ActOnIdExpression(S, SS, TemplateKWLoc, id,
5314 false, false);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005315 return CodeCompleteObjCInstanceMessage(S, (Expr *)SuperExpr.get(),
Douglas Gregorf86e4da2010-09-20 23:34:21 +00005316 SelIdents, NumSelIdents,
5317 AtArgumentExpression);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005318 }
5319
5320 // Fall through
5321 }
5322
John McCallba7bf592010-08-24 05:47:05 +00005323 ParsedType Receiver;
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005324 if (CDecl)
John McCallba7bf592010-08-24 05:47:05 +00005325 Receiver = ParsedType::make(Context.getObjCInterfaceType(CDecl));
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005326 return CodeCompleteObjCClassMessage(S, Receiver, SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00005327 NumSelIdents, AtArgumentExpression,
5328 /*IsSuper=*/true);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005329}
5330
Douglas Gregor74661272010-09-21 00:03:25 +00005331/// \brief Given a set of code-completion results for the argument of a message
5332/// send, determine the preferred type (if any) for that argument expression.
5333static QualType getPreferredArgumentTypeForMessageSend(ResultBuilder &Results,
5334 unsigned NumSelIdents) {
5335 typedef CodeCompletionResult Result;
5336 ASTContext &Context = Results.getSema().Context;
5337
5338 QualType PreferredType;
5339 unsigned BestPriority = CCP_Unlikely * 2;
5340 Result *ResultsData = Results.data();
5341 for (unsigned I = 0, N = Results.size(); I != N; ++I) {
5342 Result &R = ResultsData[I];
5343 if (R.Kind == Result::RK_Declaration &&
5344 isa<ObjCMethodDecl>(R.Declaration)) {
5345 if (R.Priority <= BestPriority) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00005346 const ObjCMethodDecl *Method = cast<ObjCMethodDecl>(R.Declaration);
Douglas Gregor74661272010-09-21 00:03:25 +00005347 if (NumSelIdents <= Method->param_size()) {
5348 QualType MyPreferredType = Method->param_begin()[NumSelIdents - 1]
5349 ->getType();
5350 if (R.Priority < BestPriority || PreferredType.isNull()) {
5351 BestPriority = R.Priority;
5352 PreferredType = MyPreferredType;
5353 } else if (!Context.hasSameUnqualifiedType(PreferredType,
5354 MyPreferredType)) {
5355 PreferredType = QualType();
5356 }
5357 }
5358 }
5359 }
5360 }
5361
5362 return PreferredType;
5363}
5364
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005365static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
5366 ParsedType Receiver,
5367 IdentifierInfo **SelIdents,
5368 unsigned NumSelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00005369 bool AtArgumentExpression,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005370 bool IsSuper,
5371 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00005372 typedef CodeCompletionResult Result;
Douglas Gregor8ce33212009-11-17 17:59:40 +00005373 ObjCInterfaceDecl *CDecl = 0;
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005374
Douglas Gregor8ce33212009-11-17 17:59:40 +00005375 // If the given name refers to an interface type, retrieve the
5376 // corresponding declaration.
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005377 if (Receiver) {
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005378 QualType T = SemaRef.GetTypeFromParser(Receiver, 0);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005379 if (!T.isNull())
John McCall8b07ec22010-05-15 11:32:37 +00005380 if (const ObjCObjectType *Interface = T->getAs<ObjCObjectType>())
5381 CDecl = Interface->getInterface();
Douglas Gregor8ce33212009-11-17 17:59:40 +00005382 }
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005383
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005384 // Add all of the factory methods in this Objective-C class, its protocols,
5385 // superclasses, categories, implementation, etc.
Steve Naroffeae65032009-11-07 02:08:14 +00005386 Results.EnterNewScope();
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005387
Douglas Gregor6fc04132010-08-27 15:10:57 +00005388 // If this is a send-to-super, try to add the special "super" send
5389 // completion.
5390 if (IsSuper) {
5391 if (ObjCMethodDecl *SuperMethod
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005392 = AddSuperSendCompletion(SemaRef, false, SelIdents, NumSelIdents,
5393 Results))
Douglas Gregor6fc04132010-08-27 15:10:57 +00005394 Results.Ignore(SuperMethod);
5395 }
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005396
Douglas Gregorc2cb2e22010-08-27 15:29:55 +00005397 // If we're inside an Objective-C method definition, prefer its selector to
5398 // others.
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005399 if (ObjCMethodDecl *CurMethod = SemaRef.getCurMethodDecl())
Douglas Gregorc2cb2e22010-08-27 15:29:55 +00005400 Results.setPreferredSelector(CurMethod->getSelector());
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005401
Douglas Gregor1154e272010-09-16 16:06:31 +00005402 VisitedSelectorSet Selectors;
Douglas Gregor6285f752010-04-06 16:40:00 +00005403 if (CDecl)
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005404 AddObjCMethods(CDecl, false, MK_Any, SelIdents, NumSelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005405 SemaRef.CurContext, Selectors, AtArgumentExpression,
5406 Results);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005407 else {
Douglas Gregor6285f752010-04-06 16:40:00 +00005408 // We're messaging "id" as a type; provide all class/factory methods.
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005409
Douglas Gregord720daf2010-04-06 17:30:22 +00005410 // If we have an external source, load the entire class method
Sebastian Redld44cd6a2010-08-18 23:57:06 +00005411 // pool from the AST file.
Axel Naumanndd433f02012-10-18 19:05:02 +00005412 if (SemaRef.getExternalSource()) {
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005413 for (uint32_t I = 0,
Axel Naumanndd433f02012-10-18 19:05:02 +00005414 N = SemaRef.getExternalSource()->GetNumExternalSelectors();
John McCall75b960e2010-06-01 09:23:16 +00005415 I != N; ++I) {
Axel Naumanndd433f02012-10-18 19:05:02 +00005416 Selector Sel = SemaRef.getExternalSource()->GetExternalSelector(I);
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005417 if (Sel.isNull() || SemaRef.MethodPool.count(Sel))
Douglas Gregord720daf2010-04-06 17:30:22 +00005418 continue;
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005419
5420 SemaRef.ReadMethodPool(Sel);
Douglas Gregord720daf2010-04-06 17:30:22 +00005421 }
5422 }
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005423
5424 for (Sema::GlobalMethodPool::iterator M = SemaRef.MethodPool.begin(),
5425 MEnd = SemaRef.MethodPool.end();
Sebastian Redl75d8a322010-08-02 23:18:59 +00005426 M != MEnd; ++M) {
5427 for (ObjCMethodList *MethList = &M->second.second;
5428 MethList && MethList->Method;
Douglas Gregor6285f752010-04-06 16:40:00 +00005429 MethList = MethList->Next) {
5430 if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents,
5431 NumSelIdents))
5432 continue;
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005433
Douglas Gregor0a0e2b32013-01-31 04:52:16 +00005434 Result R(MethList->Method, Results.getBasePriority(MethList->Method),0);
Douglas Gregor6285f752010-04-06 16:40:00 +00005435 R.StartParameter = NumSelIdents;
5436 R.AllParametersAreInformative = false;
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005437 Results.MaybeAddResult(R, SemaRef.CurContext);
Douglas Gregor6285f752010-04-06 16:40:00 +00005438 }
5439 }
5440 }
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005441
5442 Results.ExitScope();
5443}
Douglas Gregor6285f752010-04-06 16:40:00 +00005444
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005445void Sema::CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver,
5446 IdentifierInfo **SelIdents,
5447 unsigned NumSelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00005448 bool AtArgumentExpression,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005449 bool IsSuper) {
Douglas Gregor63745d52011-07-21 01:05:26 +00005450
5451 QualType T = this->GetTypeFromParser(Receiver);
5452
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005453 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005454 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor63745d52011-07-21 01:05:26 +00005455 CodeCompletionContext(CodeCompletionContext::CCC_ObjCClassMessage,
Douglas Gregorea777402011-07-26 15:24:30 +00005456 T, SelIdents, NumSelIdents));
Douglas Gregor63745d52011-07-21 01:05:26 +00005457
Douglas Gregorf86e4da2010-09-20 23:34:21 +00005458 AddClassMessageCompletions(*this, S, Receiver, SelIdents, NumSelIdents,
5459 AtArgumentExpression, IsSuper, Results);
Douglas Gregor74661272010-09-21 00:03:25 +00005460
5461 // If we're actually at the argument expression (rather than prior to the
5462 // selector), we're actually performing code completion for an expression.
5463 // Determine whether we have a single, best method. If so, we can
5464 // code-complete the expression using the corresponding parameter type as
5465 // our preferred type, improving completion results.
5466 if (AtArgumentExpression) {
5467 QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results,
Douglas Gregor63745d52011-07-21 01:05:26 +00005468 NumSelIdents);
Douglas Gregor74661272010-09-21 00:03:25 +00005469 if (PreferredType.isNull())
5470 CodeCompleteOrdinaryName(S, PCC_Expression);
5471 else
5472 CodeCompleteExpression(S, PreferredType);
5473 return;
5474 }
5475
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005476 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor63745d52011-07-21 01:05:26 +00005477 Results.getCompletionContext(),
Douglas Gregor6fc04132010-08-27 15:10:57 +00005478 Results.data(), Results.size());
Steve Naroffeae65032009-11-07 02:08:14 +00005479}
5480
Richard Trieu2bd04012011-09-09 02:00:50 +00005481void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver,
Douglas Gregor1b605f72009-11-19 01:08:35 +00005482 IdentifierInfo **SelIdents,
Douglas Gregor6fc04132010-08-27 15:10:57 +00005483 unsigned NumSelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00005484 bool AtArgumentExpression,
Douglas Gregor392a84b2010-10-13 21:24:53 +00005485 ObjCInterfaceDecl *Super) {
John McCall276321a2010-08-25 06:19:51 +00005486 typedef CodeCompletionResult Result;
Steve Naroffeae65032009-11-07 02:08:14 +00005487
5488 Expr *RecExpr = static_cast<Expr *>(Receiver);
Steve Naroffeae65032009-11-07 02:08:14 +00005489
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005490 // If necessary, apply function/array conversion to the receiver.
5491 // C99 6.7.5.3p[7,8].
John Wiegley01296292011-04-08 18:41:53 +00005492 if (RecExpr) {
5493 ExprResult Conv = DefaultFunctionArrayLvalueConversion(RecExpr);
5494 if (Conv.isInvalid()) // conversion failed. bail.
5495 return;
5496 RecExpr = Conv.take();
5497 }
Douglas Gregor392a84b2010-10-13 21:24:53 +00005498 QualType ReceiverType = RecExpr? RecExpr->getType()
5499 : Super? Context.getObjCObjectPointerType(
5500 Context.getObjCInterfaceType(Super))
5501 : Context.getObjCIdType();
Steve Naroffeae65032009-11-07 02:08:14 +00005502
Douglas Gregordc520b02010-11-08 21:12:30 +00005503 // If we're messaging an expression with type "id" or "Class", check
5504 // whether we know something special about the receiver that allows
5505 // us to assume a more-specific receiver type.
5506 if (ReceiverType->isObjCIdType() || ReceiverType->isObjCClassType())
5507 if (ObjCInterfaceDecl *IFace = GetAssumedMessageSendExprType(RecExpr)) {
5508 if (ReceiverType->isObjCClassType())
5509 return CodeCompleteObjCClassMessage(S,
5510 ParsedType::make(Context.getObjCInterfaceType(IFace)),
5511 SelIdents, NumSelIdents,
5512 AtArgumentExpression, Super);
5513
5514 ReceiverType = Context.getObjCObjectPointerType(
5515 Context.getObjCInterfaceType(IFace));
5516 }
5517
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005518 // Build the set of methods we can see.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005519 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005520 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor63745d52011-07-21 01:05:26 +00005521 CodeCompletionContext(CodeCompletionContext::CCC_ObjCInstanceMessage,
Douglas Gregorea777402011-07-26 15:24:30 +00005522 ReceiverType, SelIdents, NumSelIdents));
Douglas Gregor63745d52011-07-21 01:05:26 +00005523
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005524 Results.EnterNewScope();
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005525
Douglas Gregor6fc04132010-08-27 15:10:57 +00005526 // If this is a send-to-super, try to add the special "super" send
5527 // completion.
Douglas Gregor392a84b2010-10-13 21:24:53 +00005528 if (Super) {
Douglas Gregor6fc04132010-08-27 15:10:57 +00005529 if (ObjCMethodDecl *SuperMethod
5530 = AddSuperSendCompletion(*this, false, SelIdents, NumSelIdents,
5531 Results))
5532 Results.Ignore(SuperMethod);
5533 }
5534
Douglas Gregorc2cb2e22010-08-27 15:29:55 +00005535 // If we're inside an Objective-C method definition, prefer its selector to
5536 // others.
5537 if (ObjCMethodDecl *CurMethod = getCurMethodDecl())
5538 Results.setPreferredSelector(CurMethod->getSelector());
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005539
Douglas Gregor1154e272010-09-16 16:06:31 +00005540 // Keep track of the selectors we've already added.
5541 VisitedSelectorSet Selectors;
5542
Douglas Gregora3329fa2009-11-18 00:06:18 +00005543 // Handle messages to Class. This really isn't a message to an instance
5544 // method, so we treat it the same way we would treat a message send to a
5545 // class method.
5546 if (ReceiverType->isObjCClassType() ||
5547 ReceiverType->isObjCQualifiedClassType()) {
5548 if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
5549 if (ObjCInterfaceDecl *ClassDecl = CurMethod->getClassInterface())
Douglas Gregorc8537c52009-11-19 07:41:15 +00005550 AddObjCMethods(ClassDecl, false, MK_Any, SelIdents, NumSelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005551 CurContext, Selectors, AtArgumentExpression, Results);
Douglas Gregora3329fa2009-11-18 00:06:18 +00005552 }
5553 }
5554 // Handle messages to a qualified ID ("id<foo>").
5555 else if (const ObjCObjectPointerType *QualID
5556 = ReceiverType->getAsObjCQualifiedIdType()) {
5557 // Search protocols for instance methods.
5558 for (ObjCObjectPointerType::qual_iterator I = QualID->qual_begin(),
5559 E = QualID->qual_end();
5560 I != E; ++I)
Douglas Gregorc8537c52009-11-19 07:41:15 +00005561 AddObjCMethods(*I, true, MK_Any, SelIdents, NumSelIdents, CurContext,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005562 Selectors, AtArgumentExpression, Results);
Douglas Gregora3329fa2009-11-18 00:06:18 +00005563 }
5564 // Handle messages to a pointer to interface type.
5565 else if (const ObjCObjectPointerType *IFacePtr
5566 = ReceiverType->getAsObjCInterfacePointerType()) {
5567 // Search the class, its superclasses, etc., for instance methods.
Douglas Gregorc8537c52009-11-19 07:41:15 +00005568 AddObjCMethods(IFacePtr->getInterfaceDecl(), true, MK_Any, SelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005569 NumSelIdents, CurContext, Selectors, AtArgumentExpression,
5570 Results);
Douglas Gregora3329fa2009-11-18 00:06:18 +00005571
5572 // Search protocols for instance methods.
5573 for (ObjCObjectPointerType::qual_iterator I = IFacePtr->qual_begin(),
5574 E = IFacePtr->qual_end();
5575 I != E; ++I)
Douglas Gregorc8537c52009-11-19 07:41:15 +00005576 AddObjCMethods(*I, true, MK_Any, SelIdents, NumSelIdents, CurContext,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005577 Selectors, AtArgumentExpression, Results);
Douglas Gregora3329fa2009-11-18 00:06:18 +00005578 }
Douglas Gregor6285f752010-04-06 16:40:00 +00005579 // Handle messages to "id".
5580 else if (ReceiverType->isObjCIdType()) {
Douglas Gregord720daf2010-04-06 17:30:22 +00005581 // We're messaging "id", so provide all instance methods we know
5582 // about as code-completion results.
5583
5584 // If we have an external source, load the entire class method
Sebastian Redld44cd6a2010-08-18 23:57:06 +00005585 // pool from the AST file.
Douglas Gregord720daf2010-04-06 17:30:22 +00005586 if (ExternalSource) {
John McCall75b960e2010-06-01 09:23:16 +00005587 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
5588 I != N; ++I) {
5589 Selector Sel = ExternalSource->GetExternalSelector(I);
Sebastian Redl75d8a322010-08-02 23:18:59 +00005590 if (Sel.isNull() || MethodPool.count(Sel))
Douglas Gregord720daf2010-04-06 17:30:22 +00005591 continue;
5592
Sebastian Redl75d8a322010-08-02 23:18:59 +00005593 ReadMethodPool(Sel);
Douglas Gregord720daf2010-04-06 17:30:22 +00005594 }
5595 }
5596
Sebastian Redl75d8a322010-08-02 23:18:59 +00005597 for (GlobalMethodPool::iterator M = MethodPool.begin(),
5598 MEnd = MethodPool.end();
5599 M != MEnd; ++M) {
5600 for (ObjCMethodList *MethList = &M->second.first;
5601 MethList && MethList->Method;
Douglas Gregor6285f752010-04-06 16:40:00 +00005602 MethList = MethList->Next) {
5603 if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents,
5604 NumSelIdents))
5605 continue;
Douglas Gregor1154e272010-09-16 16:06:31 +00005606
5607 if (!Selectors.insert(MethList->Method->getSelector()))
5608 continue;
5609
Douglas Gregor0a0e2b32013-01-31 04:52:16 +00005610 Result R(MethList->Method, Results.getBasePriority(MethList->Method),0);
Douglas Gregor6285f752010-04-06 16:40:00 +00005611 R.StartParameter = NumSelIdents;
5612 R.AllParametersAreInformative = false;
5613 Results.MaybeAddResult(R, CurContext);
5614 }
5615 }
5616 }
Steve Naroffeae65032009-11-07 02:08:14 +00005617 Results.ExitScope();
Douglas Gregor74661272010-09-21 00:03:25 +00005618
5619
5620 // If we're actually at the argument expression (rather than prior to the
5621 // selector), we're actually performing code completion for an expression.
5622 // Determine whether we have a single, best method. If so, we can
5623 // code-complete the expression using the corresponding parameter type as
5624 // our preferred type, improving completion results.
5625 if (AtArgumentExpression) {
5626 QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results,
5627 NumSelIdents);
5628 if (PreferredType.isNull())
5629 CodeCompleteOrdinaryName(S, PCC_Expression);
5630 else
5631 CodeCompleteExpression(S, PreferredType);
5632 return;
5633 }
5634
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005635 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor63745d52011-07-21 01:05:26 +00005636 Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005637 Results.data(),Results.size());
Steve Naroffeae65032009-11-07 02:08:14 +00005638}
Douglas Gregorbaf69612009-11-18 04:19:12 +00005639
Douglas Gregor68762e72010-08-23 21:17:50 +00005640void Sema::CodeCompleteObjCForCollection(Scope *S,
5641 DeclGroupPtrTy IterationVar) {
5642 CodeCompleteExpressionData Data;
5643 Data.ObjCCollection = true;
5644
5645 if (IterationVar.getAsOpaquePtr()) {
5646 DeclGroupRef DG = IterationVar.getAsVal<DeclGroupRef>();
5647 for (DeclGroupRef::iterator I = DG.begin(), End = DG.end(); I != End; ++I) {
5648 if (*I)
5649 Data.IgnoreDecls.push_back(*I);
5650 }
5651 }
5652
5653 CodeCompleteExpression(S, Data);
5654}
5655
Douglas Gregor67c692c2010-08-26 15:07:07 +00005656void Sema::CodeCompleteObjCSelector(Scope *S, IdentifierInfo **SelIdents,
5657 unsigned NumSelIdents) {
5658 // If we have an external source, load the entire class method
5659 // pool from the AST file.
5660 if (ExternalSource) {
5661 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
5662 I != N; ++I) {
5663 Selector Sel = ExternalSource->GetExternalSelector(I);
5664 if (Sel.isNull() || MethodPool.count(Sel))
5665 continue;
5666
5667 ReadMethodPool(Sel);
5668 }
5669 }
5670
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005671 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005672 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005673 CodeCompletionContext::CCC_SelectorName);
Douglas Gregor67c692c2010-08-26 15:07:07 +00005674 Results.EnterNewScope();
5675 for (GlobalMethodPool::iterator M = MethodPool.begin(),
5676 MEnd = MethodPool.end();
5677 M != MEnd; ++M) {
5678
5679 Selector Sel = M->first;
5680 if (!isAcceptableObjCSelector(Sel, MK_Any, SelIdents, NumSelIdents))
5681 continue;
5682
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005683 CodeCompletionBuilder Builder(Results.getAllocator(),
5684 Results.getCodeCompletionTUInfo());
Douglas Gregor67c692c2010-08-26 15:07:07 +00005685 if (Sel.isUnarySelector()) {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005686 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00005687 Sel.getNameForSlot(0)));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005688 Results.AddResult(Builder.TakeString());
Douglas Gregor67c692c2010-08-26 15:07:07 +00005689 continue;
5690 }
5691
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00005692 std::string Accumulator;
Douglas Gregor67c692c2010-08-26 15:07:07 +00005693 for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I) {
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00005694 if (I == NumSelIdents) {
5695 if (!Accumulator.empty()) {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005696 Builder.AddInformativeChunk(Builder.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005697 Accumulator));
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00005698 Accumulator.clear();
5699 }
5700 }
5701
Benjamin Kramer632500c2011-07-26 16:59:25 +00005702 Accumulator += Sel.getNameForSlot(I);
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00005703 Accumulator += ':';
Douglas Gregor67c692c2010-08-26 15:07:07 +00005704 }
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005705 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString( Accumulator));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005706 Results.AddResult(Builder.TakeString());
Douglas Gregor67c692c2010-08-26 15:07:07 +00005707 }
5708 Results.ExitScope();
5709
5710 HandleCodeCompleteResults(this, CodeCompleter,
5711 CodeCompletionContext::CCC_SelectorName,
5712 Results.data(), Results.size());
5713}
5714
Douglas Gregorbaf69612009-11-18 04:19:12 +00005715/// \brief Add all of the protocol declarations that we find in the given
5716/// (translation unit) context.
5717static void AddProtocolResults(DeclContext *Ctx, DeclContext *CurContext,
Douglas Gregor5b4671c2009-11-18 04:49:41 +00005718 bool OnlyForwardDeclarations,
Douglas Gregorbaf69612009-11-18 04:19:12 +00005719 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00005720 typedef CodeCompletionResult Result;
Douglas Gregorbaf69612009-11-18 04:19:12 +00005721
5722 for (DeclContext::decl_iterator D = Ctx->decls_begin(),
5723 DEnd = Ctx->decls_end();
5724 D != DEnd; ++D) {
5725 // Record any protocols we find.
5726 if (ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>(*D))
Douglas Gregore6e48b12012-01-01 19:29:29 +00005727 if (!OnlyForwardDeclarations || !Proto->hasDefinition())
Douglas Gregor0a0e2b32013-01-31 04:52:16 +00005728 Results.AddResult(Result(Proto, Results.getBasePriority(Proto), 0),
5729 CurContext, 0, false);
Douglas Gregorbaf69612009-11-18 04:19:12 +00005730 }
5731}
5732
5733void Sema::CodeCompleteObjCProtocolReferences(IdentifierLocPair *Protocols,
5734 unsigned NumProtocols) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005735 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005736 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005737 CodeCompletionContext::CCC_ObjCProtocolName);
Douglas Gregorbaf69612009-11-18 04:19:12 +00005738
Douglas Gregora3b23b02010-12-09 21:44:02 +00005739 if (CodeCompleter && CodeCompleter->includeGlobals()) {
5740 Results.EnterNewScope();
5741
5742 // Tell the result set to ignore all of the protocols we have
5743 // already seen.
5744 // FIXME: This doesn't work when caching code-completion results.
5745 for (unsigned I = 0; I != NumProtocols; ++I)
5746 if (ObjCProtocolDecl *Protocol = LookupProtocol(Protocols[I].first,
5747 Protocols[I].second))
5748 Results.Ignore(Protocol);
Douglas Gregorbaf69612009-11-18 04:19:12 +00005749
Douglas Gregora3b23b02010-12-09 21:44:02 +00005750 // Add all protocols.
5751 AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, false,
5752 Results);
Douglas Gregor5b4671c2009-11-18 04:49:41 +00005753
Douglas Gregora3b23b02010-12-09 21:44:02 +00005754 Results.ExitScope();
5755 }
5756
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005757 HandleCodeCompleteResults(this, CodeCompleter,
5758 CodeCompletionContext::CCC_ObjCProtocolName,
5759 Results.data(),Results.size());
Douglas Gregor5b4671c2009-11-18 04:49:41 +00005760}
5761
5762void Sema::CodeCompleteObjCProtocolDecl(Scope *) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005763 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005764 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005765 CodeCompletionContext::CCC_ObjCProtocolName);
Douglas Gregor5b4671c2009-11-18 04:49:41 +00005766
Douglas Gregora3b23b02010-12-09 21:44:02 +00005767 if (CodeCompleter && CodeCompleter->includeGlobals()) {
5768 Results.EnterNewScope();
5769
5770 // Add all protocols.
5771 AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, true,
5772 Results);
Douglas Gregorbaf69612009-11-18 04:19:12 +00005773
Douglas Gregora3b23b02010-12-09 21:44:02 +00005774 Results.ExitScope();
5775 }
5776
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005777 HandleCodeCompleteResults(this, CodeCompleter,
5778 CodeCompletionContext::CCC_ObjCProtocolName,
5779 Results.data(),Results.size());
Douglas Gregorbaf69612009-11-18 04:19:12 +00005780}
Douglas Gregor49c22a72009-11-18 16:26:39 +00005781
5782/// \brief Add all of the Objective-C interface declarations that we find in
5783/// the given (translation unit) context.
5784static void AddInterfaceResults(DeclContext *Ctx, DeclContext *CurContext,
5785 bool OnlyForwardDeclarations,
5786 bool OnlyUnimplemented,
5787 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00005788 typedef CodeCompletionResult Result;
Douglas Gregor49c22a72009-11-18 16:26:39 +00005789
5790 for (DeclContext::decl_iterator D = Ctx->decls_begin(),
5791 DEnd = Ctx->decls_end();
5792 D != DEnd; ++D) {
Douglas Gregor1c283312010-08-11 12:19:30 +00005793 // Record any interfaces we find.
5794 if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(*D))
Douglas Gregordc9166c2011-12-15 20:29:51 +00005795 if ((!OnlyForwardDeclarations || !Class->hasDefinition()) &&
Douglas Gregor1c283312010-08-11 12:19:30 +00005796 (!OnlyUnimplemented || !Class->getImplementation()))
Douglas Gregor0a0e2b32013-01-31 04:52:16 +00005797 Results.AddResult(Result(Class, Results.getBasePriority(Class), 0),
5798 CurContext, 0, false);
Douglas Gregor49c22a72009-11-18 16:26:39 +00005799 }
5800}
5801
5802void Sema::CodeCompleteObjCInterfaceDecl(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005803 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005804 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005805 CodeCompletionContext::CCC_Other);
Douglas Gregor49c22a72009-11-18 16:26:39 +00005806 Results.EnterNewScope();
5807
Douglas Gregor2c595ad2011-07-30 06:55:39 +00005808 if (CodeCompleter->includeGlobals()) {
5809 // Add all classes.
5810 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
5811 false, Results);
5812 }
5813
Douglas Gregor49c22a72009-11-18 16:26:39 +00005814 Results.ExitScope();
Douglas Gregor2c595ad2011-07-30 06:55:39 +00005815
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005816 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor2c595ad2011-07-30 06:55:39 +00005817 CodeCompletionContext::CCC_ObjCInterfaceName,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005818 Results.data(),Results.size());
Douglas Gregor49c22a72009-11-18 16:26:39 +00005819}
5820
Douglas Gregorb2ccf012010-04-15 22:33:43 +00005821void Sema::CodeCompleteObjCSuperclass(Scope *S, IdentifierInfo *ClassName,
5822 SourceLocation ClassNameLoc) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005823 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005824 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor2c595ad2011-07-30 06:55:39 +00005825 CodeCompletionContext::CCC_ObjCInterfaceName);
Douglas Gregor49c22a72009-11-18 16:26:39 +00005826 Results.EnterNewScope();
5827
5828 // Make sure that we ignore the class we're currently defining.
5829 NamedDecl *CurClass
Douglas Gregorb2ccf012010-04-15 22:33:43 +00005830 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00005831 if (CurClass && isa<ObjCInterfaceDecl>(CurClass))
Douglas Gregor49c22a72009-11-18 16:26:39 +00005832 Results.Ignore(CurClass);
5833
Douglas Gregor2c595ad2011-07-30 06:55:39 +00005834 if (CodeCompleter->includeGlobals()) {
5835 // Add all classes.
5836 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
5837 false, Results);
5838 }
5839
Douglas Gregor49c22a72009-11-18 16:26:39 +00005840 Results.ExitScope();
Douglas Gregor2c595ad2011-07-30 06:55:39 +00005841
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005842 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor2c595ad2011-07-30 06:55:39 +00005843 CodeCompletionContext::CCC_ObjCInterfaceName,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005844 Results.data(),Results.size());
Douglas Gregor49c22a72009-11-18 16:26:39 +00005845}
5846
5847void Sema::CodeCompleteObjCImplementationDecl(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005848 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005849 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005850 CodeCompletionContext::CCC_Other);
Douglas Gregor49c22a72009-11-18 16:26:39 +00005851 Results.EnterNewScope();
5852
Douglas Gregor2c595ad2011-07-30 06:55:39 +00005853 if (CodeCompleter->includeGlobals()) {
5854 // Add all unimplemented classes.
5855 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
5856 true, Results);
5857 }
5858
Douglas Gregor49c22a72009-11-18 16:26:39 +00005859 Results.ExitScope();
Douglas Gregor2c595ad2011-07-30 06:55:39 +00005860
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005861 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor2c595ad2011-07-30 06:55:39 +00005862 CodeCompletionContext::CCC_ObjCInterfaceName,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005863 Results.data(),Results.size());
Douglas Gregor49c22a72009-11-18 16:26:39 +00005864}
Douglas Gregor5d34fd32009-11-18 19:08:43 +00005865
5866void Sema::CodeCompleteObjCInterfaceCategory(Scope *S,
Douglas Gregorb2ccf012010-04-15 22:33:43 +00005867 IdentifierInfo *ClassName,
5868 SourceLocation ClassNameLoc) {
John McCall276321a2010-08-25 06:19:51 +00005869 typedef CodeCompletionResult Result;
Douglas Gregor5d34fd32009-11-18 19:08:43 +00005870
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005871 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005872 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor21325842011-07-07 16:03:39 +00005873 CodeCompletionContext::CCC_ObjCCategoryName);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00005874
5875 // Ignore any categories we find that have already been implemented by this
5876 // interface.
5877 llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
5878 NamedDecl *CurClass
Douglas Gregorb2ccf012010-04-15 22:33:43 +00005879 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor048fbfa2013-01-16 23:00:23 +00005880 if (ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass)){
5881 for (ObjCInterfaceDecl::visible_categories_iterator
5882 Cat = Class->visible_categories_begin(),
5883 CatEnd = Class->visible_categories_end();
5884 Cat != CatEnd; ++Cat) {
5885 CategoryNames.insert(Cat->getIdentifier());
5886 }
5887 }
5888
Douglas Gregor5d34fd32009-11-18 19:08:43 +00005889 // Add all of the categories we know about.
5890 Results.EnterNewScope();
5891 TranslationUnitDecl *TU = Context.getTranslationUnitDecl();
5892 for (DeclContext::decl_iterator D = TU->decls_begin(),
5893 DEnd = TU->decls_end();
5894 D != DEnd; ++D)
5895 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(*D))
5896 if (CategoryNames.insert(Category->getIdentifier()))
Douglas Gregor0a0e2b32013-01-31 04:52:16 +00005897 Results.AddResult(Result(Category, Results.getBasePriority(Category),0),
5898 CurContext, 0, false);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00005899 Results.ExitScope();
5900
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005901 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor21325842011-07-07 16:03:39 +00005902 CodeCompletionContext::CCC_ObjCCategoryName,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005903 Results.data(),Results.size());
Douglas Gregor5d34fd32009-11-18 19:08:43 +00005904}
5905
5906void Sema::CodeCompleteObjCImplementationCategory(Scope *S,
Douglas Gregorb2ccf012010-04-15 22:33:43 +00005907 IdentifierInfo *ClassName,
5908 SourceLocation ClassNameLoc) {
John McCall276321a2010-08-25 06:19:51 +00005909 typedef CodeCompletionResult Result;
Douglas Gregor5d34fd32009-11-18 19:08:43 +00005910
5911 // Find the corresponding interface. If we couldn't find the interface, the
5912 // program itself is ill-formed. However, we'll try to be helpful still by
5913 // providing the list of all of the categories we know about.
5914 NamedDecl *CurClass
Douglas Gregorb2ccf012010-04-15 22:33:43 +00005915 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00005916 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass);
5917 if (!Class)
Douglas Gregorb2ccf012010-04-15 22:33:43 +00005918 return CodeCompleteObjCInterfaceCategory(S, ClassName, ClassNameLoc);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00005919
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005920 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005921 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor21325842011-07-07 16:03:39 +00005922 CodeCompletionContext::CCC_ObjCCategoryName);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00005923
5924 // Add all of the categories that have have corresponding interface
5925 // declarations in this class and any of its superclasses, except for
5926 // already-implemented categories in the class itself.
5927 llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
5928 Results.EnterNewScope();
5929 bool IgnoreImplemented = true;
5930 while (Class) {
Douglas Gregor048fbfa2013-01-16 23:00:23 +00005931 for (ObjCInterfaceDecl::visible_categories_iterator
5932 Cat = Class->visible_categories_begin(),
5933 CatEnd = Class->visible_categories_end();
5934 Cat != CatEnd; ++Cat) {
5935 if ((!IgnoreImplemented || !Cat->getImplementation()) &&
5936 CategoryNames.insert(Cat->getIdentifier()))
Douglas Gregor0a0e2b32013-01-31 04:52:16 +00005937 Results.AddResult(Result(*Cat, Results.getBasePriority(*Cat), 0),
5938 CurContext, 0, false);
Douglas Gregor048fbfa2013-01-16 23:00:23 +00005939 }
Douglas Gregor5d34fd32009-11-18 19:08:43 +00005940
5941 Class = Class->getSuperClass();
5942 IgnoreImplemented = false;
5943 }
5944 Results.ExitScope();
5945
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005946 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor21325842011-07-07 16:03:39 +00005947 CodeCompletionContext::CCC_ObjCCategoryName,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005948 Results.data(),Results.size());
Douglas Gregor5d34fd32009-11-18 19:08:43 +00005949}
Douglas Gregor5d649882009-11-18 22:32:06 +00005950
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005951void Sema::CodeCompleteObjCPropertyDefinition(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005952 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005953 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005954 CodeCompletionContext::CCC_Other);
Douglas Gregor5d649882009-11-18 22:32:06 +00005955
5956 // Figure out where this @synthesize lives.
5957 ObjCContainerDecl *Container
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005958 = dyn_cast_or_null<ObjCContainerDecl>(CurContext);
Douglas Gregor5d649882009-11-18 22:32:06 +00005959 if (!Container ||
5960 (!isa<ObjCImplementationDecl>(Container) &&
5961 !isa<ObjCCategoryImplDecl>(Container)))
5962 return;
5963
5964 // Ignore any properties that have already been implemented.
Douglas Gregor9b4f3702012-06-12 13:44:08 +00005965 Container = getContainerDef(Container);
5966 for (DeclContext::decl_iterator D = Container->decls_begin(),
Douglas Gregor5d649882009-11-18 22:32:06 +00005967 DEnd = Container->decls_end();
5968 D != DEnd; ++D)
5969 if (ObjCPropertyImplDecl *PropertyImpl = dyn_cast<ObjCPropertyImplDecl>(*D))
5970 Results.Ignore(PropertyImpl->getPropertyDecl());
5971
5972 // Add any properties that we find.
Douglas Gregorb888acf2010-12-09 23:01:55 +00005973 AddedPropertiesSet AddedProperties;
Douglas Gregor5d649882009-11-18 22:32:06 +00005974 Results.EnterNewScope();
5975 if (ObjCImplementationDecl *ClassImpl
5976 = dyn_cast<ObjCImplementationDecl>(Container))
Douglas Gregor95147142011-05-05 15:50:42 +00005977 AddObjCProperties(ClassImpl->getClassInterface(), false,
5978 /*AllowNullaryMethods=*/false, CurContext,
Douglas Gregorb888acf2010-12-09 23:01:55 +00005979 AddedProperties, Results);
Douglas Gregor5d649882009-11-18 22:32:06 +00005980 else
5981 AddObjCProperties(cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl(),
Douglas Gregor95147142011-05-05 15:50:42 +00005982 false, /*AllowNullaryMethods=*/false, CurContext,
5983 AddedProperties, Results);
Douglas Gregor5d649882009-11-18 22:32:06 +00005984 Results.ExitScope();
5985
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005986 HandleCodeCompleteResults(this, CodeCompleter,
5987 CodeCompletionContext::CCC_Other,
5988 Results.data(),Results.size());
Douglas Gregor5d649882009-11-18 22:32:06 +00005989}
5990
5991void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S,
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005992 IdentifierInfo *PropertyName) {
John McCall276321a2010-08-25 06:19:51 +00005993 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005994 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005995 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005996 CodeCompletionContext::CCC_Other);
Douglas Gregor5d649882009-11-18 22:32:06 +00005997
5998 // Figure out where this @synthesize lives.
5999 ObjCContainerDecl *Container
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00006000 = dyn_cast_or_null<ObjCContainerDecl>(CurContext);
Douglas Gregor5d649882009-11-18 22:32:06 +00006001 if (!Container ||
6002 (!isa<ObjCImplementationDecl>(Container) &&
6003 !isa<ObjCCategoryImplDecl>(Container)))
6004 return;
6005
6006 // Figure out which interface we're looking into.
6007 ObjCInterfaceDecl *Class = 0;
6008 if (ObjCImplementationDecl *ClassImpl
6009 = dyn_cast<ObjCImplementationDecl>(Container))
6010 Class = ClassImpl->getClassInterface();
6011 else
6012 Class = cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl()
6013 ->getClassInterface();
6014
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006015 // Determine the type of the property we're synthesizing.
6016 QualType PropertyType = Context.getObjCIdType();
6017 if (Class) {
6018 if (ObjCPropertyDecl *Property
6019 = Class->FindPropertyDeclaration(PropertyName)) {
6020 PropertyType
6021 = Property->getType().getNonReferenceType().getUnqualifiedType();
6022
6023 // Give preference to ivars
6024 Results.setPreferredType(PropertyType);
6025 }
6026 }
6027
Douglas Gregor5d649882009-11-18 22:32:06 +00006028 // Add all of the instance variables in this class and its superclasses.
6029 Results.EnterNewScope();
Douglas Gregor331faa02011-04-18 14:13:53 +00006030 bool SawSimilarlyNamedIvar = false;
6031 std::string NameWithPrefix;
6032 NameWithPrefix += '_';
Benjamin Kramer632500c2011-07-26 16:59:25 +00006033 NameWithPrefix += PropertyName->getName();
Douglas Gregor331faa02011-04-18 14:13:53 +00006034 std::string NameWithSuffix = PropertyName->getName().str();
6035 NameWithSuffix += '_';
Douglas Gregor5d649882009-11-18 22:32:06 +00006036 for(; Class; Class = Class->getSuperClass()) {
Douglas Gregor331faa02011-04-18 14:13:53 +00006037 for (ObjCIvarDecl *Ivar = Class->all_declared_ivar_begin(); Ivar;
6038 Ivar = Ivar->getNextIvar()) {
Douglas Gregor0a0e2b32013-01-31 04:52:16 +00006039 Results.AddResult(Result(Ivar, Results.getBasePriority(Ivar), 0),
6040 CurContext, 0, false);
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006041
Douglas Gregor331faa02011-04-18 14:13:53 +00006042 // Determine whether we've seen an ivar with a name similar to the
6043 // property.
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006044 if ((PropertyName == Ivar->getIdentifier() ||
Douglas Gregor331faa02011-04-18 14:13:53 +00006045 NameWithPrefix == Ivar->getName() ||
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006046 NameWithSuffix == Ivar->getName())) {
Douglas Gregor331faa02011-04-18 14:13:53 +00006047 SawSimilarlyNamedIvar = true;
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006048
6049 // Reduce the priority of this result by one, to give it a slight
6050 // advantage over other results whose names don't match so closely.
6051 if (Results.size() &&
6052 Results.data()[Results.size() - 1].Kind
6053 == CodeCompletionResult::RK_Declaration &&
6054 Results.data()[Results.size() - 1].Declaration == Ivar)
6055 Results.data()[Results.size() - 1].Priority--;
6056 }
Douglas Gregor331faa02011-04-18 14:13:53 +00006057 }
Douglas Gregor5d649882009-11-18 22:32:06 +00006058 }
Douglas Gregor331faa02011-04-18 14:13:53 +00006059
6060 if (!SawSimilarlyNamedIvar) {
6061 // Create ivar result _propName, that the user can use to synthesize
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006062 // an ivar of the appropriate type.
6063 unsigned Priority = CCP_MemberDeclaration + 1;
Douglas Gregor331faa02011-04-18 14:13:53 +00006064 typedef CodeCompletionResult Result;
6065 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006066 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo(),
6067 Priority,CXAvailability_Available);
Douglas Gregor331faa02011-04-18 14:13:53 +00006068
Douglas Gregor75acd922011-09-27 23:30:47 +00006069 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006070 Builder.AddResultTypeChunk(GetCompletionTypeString(PropertyType, Context,
Douglas Gregor75acd922011-09-27 23:30:47 +00006071 Policy, Allocator));
Douglas Gregor331faa02011-04-18 14:13:53 +00006072 Builder.AddTypedTextChunk(Allocator.CopyString(NameWithPrefix));
6073 Results.AddResult(Result(Builder.TakeString(), Priority,
6074 CXCursor_ObjCIvarDecl));
6075 }
6076
Douglas Gregor5d649882009-11-18 22:32:06 +00006077 Results.ExitScope();
6078
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006079 HandleCodeCompleteResults(this, CodeCompleter,
6080 CodeCompletionContext::CCC_Other,
6081 Results.data(),Results.size());
Douglas Gregor5d649882009-11-18 22:32:06 +00006082}
Douglas Gregor636a61e2010-04-07 00:21:17 +00006083
Douglas Gregor416b5752010-08-25 01:08:01 +00006084// Mapping from selectors to the methods that implement that selector, along
6085// with the "in original class" flag.
6086typedef llvm::DenseMap<Selector, std::pair<ObjCMethodDecl *, bool> >
6087 KnownMethodsMap;
Douglas Gregor636a61e2010-04-07 00:21:17 +00006088
6089/// \brief Find all of the methods that reside in the given container
6090/// (and its superclasses, protocols, etc.) that meet the given
6091/// criteria. Insert those methods into the map of known methods,
6092/// indexed by selector so they can be easily found.
6093static void FindImplementableMethods(ASTContext &Context,
6094 ObjCContainerDecl *Container,
6095 bool WantInstanceMethods,
6096 QualType ReturnType,
Douglas Gregor416b5752010-08-25 01:08:01 +00006097 KnownMethodsMap &KnownMethods,
6098 bool InOriginalClass = true) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00006099 if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)) {
Douglas Gregor9b4f3702012-06-12 13:44:08 +00006100 // Make sure we have a definition; that's what we'll walk.
Douglas Gregorc0ac7d62011-12-15 05:27:12 +00006101 if (!IFace->hasDefinition())
6102 return;
Douglas Gregor9b4f3702012-06-12 13:44:08 +00006103
6104 IFace = IFace->getDefinition();
6105 Container = IFace;
Douglas Gregorc0ac7d62011-12-15 05:27:12 +00006106
Douglas Gregor636a61e2010-04-07 00:21:17 +00006107 const ObjCList<ObjCProtocolDecl> &Protocols
6108 = IFace->getReferencedProtocols();
6109 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006110 E = Protocols.end();
Douglas Gregor636a61e2010-04-07 00:21:17 +00006111 I != E; ++I)
6112 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006113 KnownMethods, InOriginalClass);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006114
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006115 // Add methods from any class extensions and categories.
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006116 for (ObjCInterfaceDecl::visible_categories_iterator
6117 Cat = IFace->visible_categories_begin(),
6118 CatEnd = IFace->visible_categories_end();
6119 Cat != CatEnd; ++Cat) {
6120 FindImplementableMethods(Context, *Cat, WantInstanceMethods, ReturnType,
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006121 KnownMethods, false);
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006122 }
6123
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006124 // Visit the superclass.
6125 if (IFace->getSuperClass())
6126 FindImplementableMethods(Context, IFace->getSuperClass(),
6127 WantInstanceMethods, ReturnType,
6128 KnownMethods, false);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006129 }
6130
6131 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(Container)) {
6132 // Recurse into protocols.
6133 const ObjCList<ObjCProtocolDecl> &Protocols
6134 = Category->getReferencedProtocols();
6135 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006136 E = Protocols.end();
Douglas Gregor636a61e2010-04-07 00:21:17 +00006137 I != E; ++I)
6138 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006139 KnownMethods, InOriginalClass);
6140
6141 // If this category is the original class, jump to the interface.
6142 if (InOriginalClass && Category->getClassInterface())
6143 FindImplementableMethods(Context, Category->getClassInterface(),
6144 WantInstanceMethods, ReturnType, KnownMethods,
6145 false);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006146 }
6147
6148 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Douglas Gregor9b4f3702012-06-12 13:44:08 +00006149 // Make sure we have a definition; that's what we'll walk.
6150 if (!Protocol->hasDefinition())
6151 return;
6152 Protocol = Protocol->getDefinition();
6153 Container = Protocol;
6154
6155 // Recurse into protocols.
6156 const ObjCList<ObjCProtocolDecl> &Protocols
6157 = Protocol->getReferencedProtocols();
6158 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
6159 E = Protocols.end();
6160 I != E; ++I)
6161 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
6162 KnownMethods, false);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006163 }
6164
6165 // Add methods in this container. This operation occurs last because
6166 // we want the methods from this container to override any methods
6167 // we've previously seen with the same selector.
6168 for (ObjCContainerDecl::method_iterator M = Container->meth_begin(),
6169 MEnd = Container->meth_end();
6170 M != MEnd; ++M) {
David Blaikie2d7c57e2012-04-30 02:36:29 +00006171 if (M->isInstanceMethod() == WantInstanceMethods) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00006172 if (!ReturnType.isNull() &&
David Blaikie2d7c57e2012-04-30 02:36:29 +00006173 !Context.hasSameUnqualifiedType(ReturnType, M->getResultType()))
Douglas Gregor636a61e2010-04-07 00:21:17 +00006174 continue;
6175
David Blaikie40ed2972012-06-06 20:45:41 +00006176 KnownMethods[M->getSelector()] = std::make_pair(*M, InOriginalClass);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006177 }
6178 }
6179}
6180
Douglas Gregor669a25a2011-02-17 00:22:45 +00006181/// \brief Add the parenthesized return or parameter type chunk to a code
6182/// completion string.
6183static void AddObjCPassingTypeChunk(QualType Type,
Douglas Gregor29979142012-04-10 18:35:07 +00006184 unsigned ObjCDeclQuals,
Douglas Gregor669a25a2011-02-17 00:22:45 +00006185 ASTContext &Context,
Douglas Gregor75acd922011-09-27 23:30:47 +00006186 const PrintingPolicy &Policy,
Douglas Gregor669a25a2011-02-17 00:22:45 +00006187 CodeCompletionBuilder &Builder) {
6188 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregor29979142012-04-10 18:35:07 +00006189 std::string Quals = formatObjCParamQualifiers(ObjCDeclQuals);
6190 if (!Quals.empty())
6191 Builder.AddTextChunk(Builder.getAllocator().CopyString(Quals));
Douglas Gregor75acd922011-09-27 23:30:47 +00006192 Builder.AddTextChunk(GetCompletionTypeString(Type, Context, Policy,
Douglas Gregor669a25a2011-02-17 00:22:45 +00006193 Builder.getAllocator()));
6194 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6195}
6196
6197/// \brief Determine whether the given class is or inherits from a class by
6198/// the given name.
6199static bool InheritsFromClassNamed(ObjCInterfaceDecl *Class,
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006200 StringRef Name) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006201 if (!Class)
6202 return false;
6203
6204 if (Class->getIdentifier() && Class->getIdentifier()->getName() == Name)
6205 return true;
6206
6207 return InheritsFromClassNamed(Class->getSuperClass(), Name);
6208}
6209
6210/// \brief Add code completions for Objective-C Key-Value Coding (KVC) and
6211/// Key-Value Observing (KVO).
6212static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
6213 bool IsInstanceMethod,
6214 QualType ReturnType,
6215 ASTContext &Context,
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006216 VisitedSelectorSet &KnownSelectors,
Douglas Gregor669a25a2011-02-17 00:22:45 +00006217 ResultBuilder &Results) {
6218 IdentifierInfo *PropName = Property->getIdentifier();
6219 if (!PropName || PropName->getLength() == 0)
6220 return;
6221
Douglas Gregor75acd922011-09-27 23:30:47 +00006222 PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema());
6223
Douglas Gregor669a25a2011-02-17 00:22:45 +00006224 // Builder that will create each code completion.
6225 typedef CodeCompletionResult Result;
6226 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006227 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Douglas Gregor669a25a2011-02-17 00:22:45 +00006228
6229 // The selector table.
6230 SelectorTable &Selectors = Context.Selectors;
6231
6232 // The property name, copied into the code completion allocation region
6233 // on demand.
6234 struct KeyHolder {
6235 CodeCompletionAllocator &Allocator;
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006236 StringRef Key;
Douglas Gregor669a25a2011-02-17 00:22:45 +00006237 const char *CopiedKey;
6238
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006239 KeyHolder(CodeCompletionAllocator &Allocator, StringRef Key)
Douglas Gregor669a25a2011-02-17 00:22:45 +00006240 : Allocator(Allocator), Key(Key), CopiedKey(0) { }
6241
6242 operator const char *() {
6243 if (CopiedKey)
6244 return CopiedKey;
6245
6246 return CopiedKey = Allocator.CopyString(Key);
6247 }
6248 } Key(Allocator, PropName->getName());
6249
6250 // The uppercased name of the property name.
6251 std::string UpperKey = PropName->getName();
6252 if (!UpperKey.empty())
6253 UpperKey[0] = toupper(UpperKey[0]);
6254
6255 bool ReturnTypeMatchesProperty = ReturnType.isNull() ||
6256 Context.hasSameUnqualifiedType(ReturnType.getNonReferenceType(),
6257 Property->getType());
6258 bool ReturnTypeMatchesVoid
6259 = ReturnType.isNull() || ReturnType->isVoidType();
6260
6261 // Add the normal accessor -(type)key.
6262 if (IsInstanceMethod &&
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006263 KnownSelectors.insert(Selectors.getNullarySelector(PropName)) &&
Douglas Gregor669a25a2011-02-17 00:22:45 +00006264 ReturnTypeMatchesProperty && !Property->getGetterMethodDecl()) {
6265 if (ReturnType.isNull())
Douglas Gregor29979142012-04-10 18:35:07 +00006266 AddObjCPassingTypeChunk(Property->getType(), /*Quals=*/0,
6267 Context, Policy, Builder);
Douglas Gregor669a25a2011-02-17 00:22:45 +00006268
6269 Builder.AddTypedTextChunk(Key);
6270 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
6271 CXCursor_ObjCInstanceMethodDecl));
6272 }
6273
6274 // If we have an integral or boolean property (or the user has provided
6275 // an integral or boolean return type), add the accessor -(type)isKey.
6276 if (IsInstanceMethod &&
6277 ((!ReturnType.isNull() &&
6278 (ReturnType->isIntegerType() || ReturnType->isBooleanType())) ||
6279 (ReturnType.isNull() &&
6280 (Property->getType()->isIntegerType() ||
6281 Property->getType()->isBooleanType())))) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006282 std::string SelectorName = (Twine("is") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006283 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006284 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006285 if (ReturnType.isNull()) {
6286 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6287 Builder.AddTextChunk("BOOL");
6288 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6289 }
6290
6291 Builder.AddTypedTextChunk(
6292 Allocator.CopyString(SelectorId->getName()));
6293 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
6294 CXCursor_ObjCInstanceMethodDecl));
6295 }
6296 }
6297
6298 // Add the normal mutator.
6299 if (IsInstanceMethod && ReturnTypeMatchesVoid &&
6300 !Property->getSetterMethodDecl()) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006301 std::string SelectorName = (Twine("set") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006302 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006303 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006304 if (ReturnType.isNull()) {
6305 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6306 Builder.AddTextChunk("void");
6307 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6308 }
6309
6310 Builder.AddTypedTextChunk(
6311 Allocator.CopyString(SelectorId->getName()));
6312 Builder.AddTypedTextChunk(":");
Douglas Gregor29979142012-04-10 18:35:07 +00006313 AddObjCPassingTypeChunk(Property->getType(), /*Quals=*/0,
6314 Context, Policy, Builder);
Douglas Gregor669a25a2011-02-17 00:22:45 +00006315 Builder.AddTextChunk(Key);
6316 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
6317 CXCursor_ObjCInstanceMethodDecl));
6318 }
6319 }
6320
6321 // Indexed and unordered accessors
6322 unsigned IndexedGetterPriority = CCP_CodePattern;
6323 unsigned IndexedSetterPriority = CCP_CodePattern;
6324 unsigned UnorderedGetterPriority = CCP_CodePattern;
6325 unsigned UnorderedSetterPriority = CCP_CodePattern;
6326 if (const ObjCObjectPointerType *ObjCPointer
6327 = Property->getType()->getAs<ObjCObjectPointerType>()) {
6328 if (ObjCInterfaceDecl *IFace = ObjCPointer->getInterfaceDecl()) {
6329 // If this interface type is not provably derived from a known
6330 // collection, penalize the corresponding completions.
6331 if (!InheritsFromClassNamed(IFace, "NSMutableArray")) {
6332 IndexedSetterPriority += CCD_ProbablyNotObjCCollection;
6333 if (!InheritsFromClassNamed(IFace, "NSArray"))
6334 IndexedGetterPriority += CCD_ProbablyNotObjCCollection;
6335 }
6336
6337 if (!InheritsFromClassNamed(IFace, "NSMutableSet")) {
6338 UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;
6339 if (!InheritsFromClassNamed(IFace, "NSSet"))
6340 UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;
6341 }
6342 }
6343 } else {
6344 IndexedGetterPriority += CCD_ProbablyNotObjCCollection;
6345 IndexedSetterPriority += CCD_ProbablyNotObjCCollection;
6346 UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;
6347 UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;
6348 }
6349
6350 // Add -(NSUInteger)countOf<key>
6351 if (IsInstanceMethod &&
6352 (ReturnType.isNull() || ReturnType->isIntegerType())) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006353 std::string SelectorName = (Twine("countOf") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006354 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006355 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006356 if (ReturnType.isNull()) {
6357 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6358 Builder.AddTextChunk("NSUInteger");
6359 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6360 }
6361
6362 Builder.AddTypedTextChunk(
6363 Allocator.CopyString(SelectorId->getName()));
6364 Results.AddResult(Result(Builder.TakeString(),
6365 std::min(IndexedGetterPriority,
6366 UnorderedGetterPriority),
6367 CXCursor_ObjCInstanceMethodDecl));
6368 }
6369 }
6370
6371 // Indexed getters
6372 // Add -(id)objectInKeyAtIndex:(NSUInteger)index
6373 if (IsInstanceMethod &&
6374 (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006375 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006376 = (Twine("objectIn") + UpperKey + "AtIndex").str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006377 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006378 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006379 if (ReturnType.isNull()) {
6380 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6381 Builder.AddTextChunk("id");
6382 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6383 }
6384
6385 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6386 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6387 Builder.AddTextChunk("NSUInteger");
6388 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6389 Builder.AddTextChunk("index");
6390 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
6391 CXCursor_ObjCInstanceMethodDecl));
6392 }
6393 }
6394
6395 // Add -(NSArray *)keyAtIndexes:(NSIndexSet *)indexes
6396 if (IsInstanceMethod &&
6397 (ReturnType.isNull() ||
6398 (ReturnType->isObjCObjectPointerType() &&
6399 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
6400 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
6401 ->getName() == "NSArray"))) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006402 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006403 = (Twine(Property->getName()) + "AtIndexes").str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006404 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006405 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006406 if (ReturnType.isNull()) {
6407 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6408 Builder.AddTextChunk("NSArray *");
6409 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6410 }
6411
6412 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6413 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6414 Builder.AddTextChunk("NSIndexSet *");
6415 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6416 Builder.AddTextChunk("indexes");
6417 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
6418 CXCursor_ObjCInstanceMethodDecl));
6419 }
6420 }
6421
6422 // Add -(void)getKey:(type **)buffer range:(NSRange)inRange
6423 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006424 std::string SelectorName = (Twine("get") + UpperKey).str();
Douglas Gregor669a25a2011-02-17 00:22:45 +00006425 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006426 &Context.Idents.get(SelectorName),
Douglas Gregor669a25a2011-02-17 00:22:45 +00006427 &Context.Idents.get("range")
6428 };
6429
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006430 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006431 if (ReturnType.isNull()) {
6432 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6433 Builder.AddTextChunk("void");
6434 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6435 }
6436
6437 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6438 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6439 Builder.AddPlaceholderChunk("object-type");
6440 Builder.AddTextChunk(" **");
6441 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6442 Builder.AddTextChunk("buffer");
6443 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6444 Builder.AddTypedTextChunk("range:");
6445 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6446 Builder.AddTextChunk("NSRange");
6447 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6448 Builder.AddTextChunk("inRange");
6449 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
6450 CXCursor_ObjCInstanceMethodDecl));
6451 }
6452 }
6453
6454 // Mutable indexed accessors
6455
6456 // - (void)insertObject:(type *)object inKeyAtIndex:(NSUInteger)index
6457 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006458 std::string SelectorName = (Twine("in") + UpperKey + "AtIndex").str();
Douglas Gregor669a25a2011-02-17 00:22:45 +00006459 IdentifierInfo *SelectorIds[2] = {
6460 &Context.Idents.get("insertObject"),
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006461 &Context.Idents.get(SelectorName)
Douglas Gregor669a25a2011-02-17 00:22:45 +00006462 };
6463
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006464 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006465 if (ReturnType.isNull()) {
6466 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6467 Builder.AddTextChunk("void");
6468 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6469 }
6470
6471 Builder.AddTypedTextChunk("insertObject:");
6472 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6473 Builder.AddPlaceholderChunk("object-type");
6474 Builder.AddTextChunk(" *");
6475 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6476 Builder.AddTextChunk("object");
6477 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6478 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6479 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6480 Builder.AddPlaceholderChunk("NSUInteger");
6481 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6482 Builder.AddTextChunk("index");
6483 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6484 CXCursor_ObjCInstanceMethodDecl));
6485 }
6486 }
6487
6488 // - (void)insertKey:(NSArray *)array atIndexes:(NSIndexSet *)indexes
6489 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006490 std::string SelectorName = (Twine("insert") + UpperKey).str();
Douglas Gregor669a25a2011-02-17 00:22:45 +00006491 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006492 &Context.Idents.get(SelectorName),
Douglas Gregor669a25a2011-02-17 00:22:45 +00006493 &Context.Idents.get("atIndexes")
6494 };
6495
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006496 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006497 if (ReturnType.isNull()) {
6498 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6499 Builder.AddTextChunk("void");
6500 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6501 }
6502
6503 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6504 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6505 Builder.AddTextChunk("NSArray *");
6506 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6507 Builder.AddTextChunk("array");
6508 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6509 Builder.AddTypedTextChunk("atIndexes:");
6510 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6511 Builder.AddPlaceholderChunk("NSIndexSet *");
6512 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6513 Builder.AddTextChunk("indexes");
6514 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6515 CXCursor_ObjCInstanceMethodDecl));
6516 }
6517 }
6518
6519 // -(void)removeObjectFromKeyAtIndex:(NSUInteger)index
6520 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006521 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006522 = (Twine("removeObjectFrom") + UpperKey + "AtIndex").str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006523 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006524 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006525 if (ReturnType.isNull()) {
6526 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6527 Builder.AddTextChunk("void");
6528 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6529 }
6530
6531 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6532 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6533 Builder.AddTextChunk("NSUInteger");
6534 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6535 Builder.AddTextChunk("index");
6536 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6537 CXCursor_ObjCInstanceMethodDecl));
6538 }
6539 }
6540
6541 // -(void)removeKeyAtIndexes:(NSIndexSet *)indexes
6542 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006543 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006544 = (Twine("remove") + UpperKey + "AtIndexes").str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006545 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006546 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006547 if (ReturnType.isNull()) {
6548 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6549 Builder.AddTextChunk("void");
6550 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6551 }
6552
6553 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6554 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6555 Builder.AddTextChunk("NSIndexSet *");
6556 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6557 Builder.AddTextChunk("indexes");
6558 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6559 CXCursor_ObjCInstanceMethodDecl));
6560 }
6561 }
6562
6563 // - (void)replaceObjectInKeyAtIndex:(NSUInteger)index withObject:(id)object
6564 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006565 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006566 = (Twine("replaceObjectIn") + UpperKey + "AtIndex").str();
Douglas Gregor669a25a2011-02-17 00:22:45 +00006567 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006568 &Context.Idents.get(SelectorName),
Douglas Gregor669a25a2011-02-17 00:22:45 +00006569 &Context.Idents.get("withObject")
6570 };
6571
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006572 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006573 if (ReturnType.isNull()) {
6574 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6575 Builder.AddTextChunk("void");
6576 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6577 }
6578
6579 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6580 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6581 Builder.AddPlaceholderChunk("NSUInteger");
6582 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6583 Builder.AddTextChunk("index");
6584 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6585 Builder.AddTypedTextChunk("withObject:");
6586 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6587 Builder.AddTextChunk("id");
6588 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6589 Builder.AddTextChunk("object");
6590 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6591 CXCursor_ObjCInstanceMethodDecl));
6592 }
6593 }
6594
6595 // - (void)replaceKeyAtIndexes:(NSIndexSet *)indexes withKey:(NSArray *)array
6596 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006597 std::string SelectorName1
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006598 = (Twine("replace") + UpperKey + "AtIndexes").str();
6599 std::string SelectorName2 = (Twine("with") + UpperKey).str();
Douglas Gregor669a25a2011-02-17 00:22:45 +00006600 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006601 &Context.Idents.get(SelectorName1),
6602 &Context.Idents.get(SelectorName2)
Douglas Gregor669a25a2011-02-17 00:22:45 +00006603 };
6604
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006605 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006606 if (ReturnType.isNull()) {
6607 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6608 Builder.AddTextChunk("void");
6609 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6610 }
6611
6612 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName1 + ":"));
6613 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6614 Builder.AddPlaceholderChunk("NSIndexSet *");
6615 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6616 Builder.AddTextChunk("indexes");
6617 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6618 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName2 + ":"));
6619 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6620 Builder.AddTextChunk("NSArray *");
6621 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6622 Builder.AddTextChunk("array");
6623 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6624 CXCursor_ObjCInstanceMethodDecl));
6625 }
6626 }
6627
6628 // Unordered getters
6629 // - (NSEnumerator *)enumeratorOfKey
6630 if (IsInstanceMethod &&
6631 (ReturnType.isNull() ||
6632 (ReturnType->isObjCObjectPointerType() &&
6633 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
6634 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
6635 ->getName() == "NSEnumerator"))) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006636 std::string SelectorName = (Twine("enumeratorOf") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006637 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006638 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006639 if (ReturnType.isNull()) {
6640 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6641 Builder.AddTextChunk("NSEnumerator *");
6642 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6643 }
6644
6645 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
6646 Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
6647 CXCursor_ObjCInstanceMethodDecl));
6648 }
6649 }
6650
6651 // - (type *)memberOfKey:(type *)object
6652 if (IsInstanceMethod &&
6653 (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006654 std::string SelectorName = (Twine("memberOf") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006655 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006656 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006657 if (ReturnType.isNull()) {
6658 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6659 Builder.AddPlaceholderChunk("object-type");
6660 Builder.AddTextChunk(" *");
6661 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6662 }
6663
6664 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6665 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6666 if (ReturnType.isNull()) {
6667 Builder.AddPlaceholderChunk("object-type");
6668 Builder.AddTextChunk(" *");
6669 } else {
6670 Builder.AddTextChunk(GetCompletionTypeString(ReturnType, Context,
Douglas Gregor75acd922011-09-27 23:30:47 +00006671 Policy,
Douglas Gregor669a25a2011-02-17 00:22:45 +00006672 Builder.getAllocator()));
6673 }
6674 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6675 Builder.AddTextChunk("object");
6676 Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
6677 CXCursor_ObjCInstanceMethodDecl));
6678 }
6679 }
6680
6681 // Mutable unordered accessors
6682 // - (void)addKeyObject:(type *)object
6683 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006684 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006685 = (Twine("add") + UpperKey + Twine("Object")).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006686 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006687 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006688 if (ReturnType.isNull()) {
6689 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6690 Builder.AddTextChunk("void");
6691 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6692 }
6693
6694 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6695 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6696 Builder.AddPlaceholderChunk("object-type");
6697 Builder.AddTextChunk(" *");
6698 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6699 Builder.AddTextChunk("object");
6700 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6701 CXCursor_ObjCInstanceMethodDecl));
6702 }
6703 }
6704
6705 // - (void)addKey:(NSSet *)objects
6706 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006707 std::string SelectorName = (Twine("add") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006708 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006709 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006710 if (ReturnType.isNull()) {
6711 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6712 Builder.AddTextChunk("void");
6713 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6714 }
6715
6716 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6717 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6718 Builder.AddTextChunk("NSSet *");
6719 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6720 Builder.AddTextChunk("objects");
6721 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6722 CXCursor_ObjCInstanceMethodDecl));
6723 }
6724 }
6725
6726 // - (void)removeKeyObject:(type *)object
6727 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006728 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006729 = (Twine("remove") + UpperKey + Twine("Object")).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006730 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006731 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006732 if (ReturnType.isNull()) {
6733 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6734 Builder.AddTextChunk("void");
6735 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6736 }
6737
6738 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6739 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6740 Builder.AddPlaceholderChunk("object-type");
6741 Builder.AddTextChunk(" *");
6742 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6743 Builder.AddTextChunk("object");
6744 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6745 CXCursor_ObjCInstanceMethodDecl));
6746 }
6747 }
6748
6749 // - (void)removeKey:(NSSet *)objects
6750 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006751 std::string SelectorName = (Twine("remove") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006752 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006753 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006754 if (ReturnType.isNull()) {
6755 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6756 Builder.AddTextChunk("void");
6757 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6758 }
6759
6760 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6761 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6762 Builder.AddTextChunk("NSSet *");
6763 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6764 Builder.AddTextChunk("objects");
6765 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6766 CXCursor_ObjCInstanceMethodDecl));
6767 }
6768 }
6769
6770 // - (void)intersectKey:(NSSet *)objects
6771 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006772 std::string SelectorName = (Twine("intersect") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006773 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006774 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006775 if (ReturnType.isNull()) {
6776 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6777 Builder.AddTextChunk("void");
6778 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6779 }
6780
6781 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6782 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6783 Builder.AddTextChunk("NSSet *");
6784 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6785 Builder.AddTextChunk("objects");
6786 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6787 CXCursor_ObjCInstanceMethodDecl));
6788 }
6789 }
6790
6791 // Key-Value Observing
6792 // + (NSSet *)keyPathsForValuesAffectingKey
6793 if (!IsInstanceMethod &&
6794 (ReturnType.isNull() ||
6795 (ReturnType->isObjCObjectPointerType() &&
6796 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
6797 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
6798 ->getName() == "NSSet"))) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006799 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006800 = (Twine("keyPathsForValuesAffecting") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006801 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006802 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006803 if (ReturnType.isNull()) {
6804 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6805 Builder.AddTextChunk("NSSet *");
6806 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6807 }
6808
6809 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
6810 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Douglas Gregor857bcda2011-06-02 04:02:27 +00006811 CXCursor_ObjCClassMethodDecl));
6812 }
6813 }
6814
6815 // + (BOOL)automaticallyNotifiesObserversForKey
6816 if (!IsInstanceMethod &&
6817 (ReturnType.isNull() ||
6818 ReturnType->isIntegerType() ||
6819 ReturnType->isBooleanType())) {
6820 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006821 = (Twine("automaticallyNotifiesObserversOf") + UpperKey).str();
Douglas Gregor857bcda2011-06-02 04:02:27 +00006822 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
6823 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
6824 if (ReturnType.isNull()) {
6825 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6826 Builder.AddTextChunk("BOOL");
6827 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6828 }
6829
6830 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
6831 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
6832 CXCursor_ObjCClassMethodDecl));
Douglas Gregor669a25a2011-02-17 00:22:45 +00006833 }
6834 }
6835}
6836
Douglas Gregor636a61e2010-04-07 00:21:17 +00006837void Sema::CodeCompleteObjCMethodDecl(Scope *S,
6838 bool IsInstanceMethod,
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00006839 ParsedType ReturnTy) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00006840 // Determine the return type of the method we're declaring, if
6841 // provided.
6842 QualType ReturnType = GetTypeFromParser(ReturnTy);
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00006843 Decl *IDecl = 0;
6844 if (CurContext->isObjCContainer()) {
6845 ObjCContainerDecl *OCD = dyn_cast<ObjCContainerDecl>(CurContext);
6846 IDecl = cast<Decl>(OCD);
6847 }
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006848 // Determine where we should start searching for methods.
6849 ObjCContainerDecl *SearchDecl = 0;
Douglas Gregor636a61e2010-04-07 00:21:17 +00006850 bool IsInImplementation = false;
John McCall48871652010-08-21 09:40:31 +00006851 if (Decl *D = IDecl) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00006852 if (ObjCImplementationDecl *Impl = dyn_cast<ObjCImplementationDecl>(D)) {
6853 SearchDecl = Impl->getClassInterface();
Douglas Gregor636a61e2010-04-07 00:21:17 +00006854 IsInImplementation = true;
6855 } else if (ObjCCategoryImplDecl *CatImpl
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006856 = dyn_cast<ObjCCategoryImplDecl>(D)) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00006857 SearchDecl = CatImpl->getCategoryDecl();
Douglas Gregor636a61e2010-04-07 00:21:17 +00006858 IsInImplementation = true;
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006859 } else
Douglas Gregor636a61e2010-04-07 00:21:17 +00006860 SearchDecl = dyn_cast<ObjCContainerDecl>(D);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006861 }
6862
6863 if (!SearchDecl && S) {
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006864 if (DeclContext *DC = static_cast<DeclContext *>(S->getEntity()))
Douglas Gregor636a61e2010-04-07 00:21:17 +00006865 SearchDecl = dyn_cast<ObjCContainerDecl>(DC);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006866 }
6867
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006868 if (!SearchDecl) {
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006869 HandleCodeCompleteResults(this, CodeCompleter,
6870 CodeCompletionContext::CCC_Other,
6871 0, 0);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006872 return;
6873 }
6874
6875 // Find all of the methods that we could declare/implement here.
6876 KnownMethodsMap KnownMethods;
6877 FindImplementableMethods(Context, SearchDecl, IsInstanceMethod,
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006878 ReturnType, KnownMethods);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006879
Douglas Gregor636a61e2010-04-07 00:21:17 +00006880 // Add declarations or definitions for each of the known methods.
John McCall276321a2010-08-25 06:19:51 +00006881 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006882 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006883 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006884 CodeCompletionContext::CCC_Other);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006885 Results.EnterNewScope();
Douglas Gregor75acd922011-09-27 23:30:47 +00006886 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006887 for (KnownMethodsMap::iterator M = KnownMethods.begin(),
6888 MEnd = KnownMethods.end();
6889 M != MEnd; ++M) {
Douglas Gregor416b5752010-08-25 01:08:01 +00006890 ObjCMethodDecl *Method = M->second.first;
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006891 CodeCompletionBuilder Builder(Results.getAllocator(),
6892 Results.getCodeCompletionTUInfo());
Douglas Gregor636a61e2010-04-07 00:21:17 +00006893
6894 // If the result type was not already provided, add it to the
6895 // pattern as (type).
Douglas Gregor669a25a2011-02-17 00:22:45 +00006896 if (ReturnType.isNull())
Douglas Gregor29979142012-04-10 18:35:07 +00006897 AddObjCPassingTypeChunk(Method->getResultType(),
6898 Method->getObjCDeclQualifier(),
6899 Context, Policy,
6900 Builder);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006901
6902 Selector Sel = Method->getSelector();
6903
6904 // Add the first part of the selector to the pattern.
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00006905 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00006906 Sel.getNameForSlot(0)));
Douglas Gregor636a61e2010-04-07 00:21:17 +00006907
6908 // Add parameters to the pattern.
6909 unsigned I = 0;
6910 for (ObjCMethodDecl::param_iterator P = Method->param_begin(),
6911 PEnd = Method->param_end();
6912 P != PEnd; (void)++P, ++I) {
6913 // Add the part of the selector name.
6914 if (I == 0)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006915 Builder.AddTypedTextChunk(":");
Douglas Gregor636a61e2010-04-07 00:21:17 +00006916 else if (I < Sel.getNumArgs()) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006917 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6918 Builder.AddTypedTextChunk(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00006919 Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":"));
Douglas Gregor636a61e2010-04-07 00:21:17 +00006920 } else
6921 break;
6922
6923 // Add the parameter type.
Douglas Gregor29979142012-04-10 18:35:07 +00006924 AddObjCPassingTypeChunk((*P)->getOriginalType(),
6925 (*P)->getObjCDeclQualifier(),
6926 Context, Policy,
Douglas Gregor75acd922011-09-27 23:30:47 +00006927 Builder);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006928
6929 if (IdentifierInfo *Id = (*P)->getIdentifier())
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00006930 Builder.AddTextChunk(Builder.getAllocator().CopyString( Id->getName()));
Douglas Gregor636a61e2010-04-07 00:21:17 +00006931 }
6932
6933 if (Method->isVariadic()) {
6934 if (Method->param_size() > 0)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006935 Builder.AddChunk(CodeCompletionString::CK_Comma);
6936 Builder.AddTextChunk("...");
Douglas Gregor400f5972010-08-31 05:13:43 +00006937 }
Douglas Gregor636a61e2010-04-07 00:21:17 +00006938
Douglas Gregord37c59d2010-05-28 00:57:46 +00006939 if (IsInImplementation && Results.includeCodePatterns()) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00006940 // We will be defining the method here, so add a compound statement.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006941 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6942 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
6943 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006944 if (!Method->getResultType()->isVoidType()) {
6945 // If the result type is not void, add a return clause.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006946 Builder.AddTextChunk("return");
6947 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6948 Builder.AddPlaceholderChunk("expression");
6949 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006950 } else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006951 Builder.AddPlaceholderChunk("statements");
Douglas Gregor636a61e2010-04-07 00:21:17 +00006952
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006953 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
6954 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006955 }
6956
Douglas Gregor416b5752010-08-25 01:08:01 +00006957 unsigned Priority = CCP_CodePattern;
6958 if (!M->second.second)
6959 Priority += CCD_InBaseClass;
6960
Douglas Gregor78254c82012-03-27 23:34:16 +00006961 Results.AddResult(Result(Builder.TakeString(), Method, Priority));
Douglas Gregor636a61e2010-04-07 00:21:17 +00006962 }
6963
Douglas Gregor669a25a2011-02-17 00:22:45 +00006964 // Add Key-Value-Coding and Key-Value-Observing accessor methods for all of
6965 // the properties in this class and its categories.
David Blaikiebbafb8a2012-03-11 07:00:24 +00006966 if (Context.getLangOpts().ObjC2) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006967 SmallVector<ObjCContainerDecl *, 4> Containers;
Douglas Gregor669a25a2011-02-17 00:22:45 +00006968 Containers.push_back(SearchDecl);
6969
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006970 VisitedSelectorSet KnownSelectors;
6971 for (KnownMethodsMap::iterator M = KnownMethods.begin(),
6972 MEnd = KnownMethods.end();
6973 M != MEnd; ++M)
6974 KnownSelectors.insert(M->first);
6975
6976
Douglas Gregor669a25a2011-02-17 00:22:45 +00006977 ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(SearchDecl);
6978 if (!IFace)
6979 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(SearchDecl))
6980 IFace = Category->getClassInterface();
6981
6982 if (IFace) {
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006983 for (ObjCInterfaceDecl::visible_categories_iterator
6984 Cat = IFace->visible_categories_begin(),
6985 CatEnd = IFace->visible_categories_end();
6986 Cat != CatEnd; ++Cat) {
6987 Containers.push_back(*Cat);
6988 }
Douglas Gregor669a25a2011-02-17 00:22:45 +00006989 }
6990
6991 for (unsigned I = 0, N = Containers.size(); I != N; ++I) {
6992 for (ObjCContainerDecl::prop_iterator P = Containers[I]->prop_begin(),
6993 PEnd = Containers[I]->prop_end();
6994 P != PEnd; ++P) {
David Blaikie40ed2972012-06-06 20:45:41 +00006995 AddObjCKeyValueCompletions(*P, IsInstanceMethod, ReturnType, Context,
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006996 KnownSelectors, Results);
Douglas Gregor669a25a2011-02-17 00:22:45 +00006997 }
6998 }
6999 }
7000
Douglas Gregor636a61e2010-04-07 00:21:17 +00007001 Results.ExitScope();
7002
Douglas Gregor00c37ef2010-08-11 21:23:17 +00007003 HandleCodeCompleteResults(this, CodeCompleter,
7004 CodeCompletionContext::CCC_Other,
7005 Results.data(),Results.size());
Douglas Gregor636a61e2010-04-07 00:21:17 +00007006}
Douglas Gregor95887f92010-07-08 23:20:03 +00007007
7008void Sema::CodeCompleteObjCMethodDeclSelector(Scope *S,
7009 bool IsInstanceMethod,
Douglas Gregor45879692010-07-08 23:37:41 +00007010 bool AtParameterName,
John McCallba7bf592010-08-24 05:47:05 +00007011 ParsedType ReturnTy,
Douglas Gregor95887f92010-07-08 23:20:03 +00007012 IdentifierInfo **SelIdents,
7013 unsigned NumSelIdents) {
Douglas Gregor95887f92010-07-08 23:20:03 +00007014 // If we have an external source, load the entire class method
Sebastian Redld44cd6a2010-08-18 23:57:06 +00007015 // pool from the AST file.
Douglas Gregor95887f92010-07-08 23:20:03 +00007016 if (ExternalSource) {
7017 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
7018 I != N; ++I) {
7019 Selector Sel = ExternalSource->GetExternalSelector(I);
Sebastian Redl75d8a322010-08-02 23:18:59 +00007020 if (Sel.isNull() || MethodPool.count(Sel))
Douglas Gregor95887f92010-07-08 23:20:03 +00007021 continue;
Sebastian Redl75d8a322010-08-02 23:18:59 +00007022
7023 ReadMethodPool(Sel);
Douglas Gregor95887f92010-07-08 23:20:03 +00007024 }
7025 }
7026
7027 // Build the set of methods we can see.
John McCall276321a2010-08-25 06:19:51 +00007028 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007029 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007030 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007031 CodeCompletionContext::CCC_Other);
Douglas Gregor95887f92010-07-08 23:20:03 +00007032
7033 if (ReturnTy)
7034 Results.setPreferredType(GetTypeFromParser(ReturnTy).getNonReferenceType());
Sebastian Redl75d8a322010-08-02 23:18:59 +00007035
Douglas Gregor95887f92010-07-08 23:20:03 +00007036 Results.EnterNewScope();
Sebastian Redl75d8a322010-08-02 23:18:59 +00007037 for (GlobalMethodPool::iterator M = MethodPool.begin(),
7038 MEnd = MethodPool.end();
7039 M != MEnd; ++M) {
7040 for (ObjCMethodList *MethList = IsInstanceMethod ? &M->second.first :
7041 &M->second.second;
7042 MethList && MethList->Method;
Douglas Gregor95887f92010-07-08 23:20:03 +00007043 MethList = MethList->Next) {
7044 if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents,
7045 NumSelIdents))
7046 continue;
7047
Douglas Gregor45879692010-07-08 23:37:41 +00007048 if (AtParameterName) {
7049 // Suggest parameter names we've seen before.
7050 if (NumSelIdents && NumSelIdents <= MethList->Method->param_size()) {
7051 ParmVarDecl *Param = MethList->Method->param_begin()[NumSelIdents-1];
7052 if (Param->getIdentifier()) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007053 CodeCompletionBuilder Builder(Results.getAllocator(),
7054 Results.getCodeCompletionTUInfo());
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00007055 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007056 Param->getIdentifier()->getName()));
7057 Results.AddResult(Builder.TakeString());
Douglas Gregor45879692010-07-08 23:37:41 +00007058 }
7059 }
7060
7061 continue;
7062 }
7063
Douglas Gregor0a0e2b32013-01-31 04:52:16 +00007064 Result R(MethList->Method, Results.getBasePriority(MethList->Method), 0);
Douglas Gregor95887f92010-07-08 23:20:03 +00007065 R.StartParameter = NumSelIdents;
7066 R.AllParametersAreInformative = false;
7067 R.DeclaringEntity = true;
7068 Results.MaybeAddResult(R, CurContext);
7069 }
7070 }
7071
7072 Results.ExitScope();
Douglas Gregor00c37ef2010-08-11 21:23:17 +00007073 HandleCodeCompleteResults(this, CodeCompleter,
7074 CodeCompletionContext::CCC_Other,
7075 Results.data(),Results.size());
Douglas Gregor95887f92010-07-08 23:20:03 +00007076}
Douglas Gregorb14904c2010-08-13 22:48:40 +00007077
Douglas Gregorec00a262010-08-24 22:20:20 +00007078void Sema::CodeCompletePreprocessorDirective(bool InConditional) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007079 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007080 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00007081 CodeCompletionContext::CCC_PreprocessorDirective);
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007082 Results.EnterNewScope();
7083
7084 // #if <condition>
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007085 CodeCompletionBuilder Builder(Results.getAllocator(),
7086 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007087 Builder.AddTypedTextChunk("if");
7088 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7089 Builder.AddPlaceholderChunk("condition");
7090 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007091
7092 // #ifdef <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007093 Builder.AddTypedTextChunk("ifdef");
7094 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7095 Builder.AddPlaceholderChunk("macro");
7096 Results.AddResult(Builder.TakeString());
7097
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007098 // #ifndef <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007099 Builder.AddTypedTextChunk("ifndef");
7100 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7101 Builder.AddPlaceholderChunk("macro");
7102 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007103
7104 if (InConditional) {
7105 // #elif <condition>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007106 Builder.AddTypedTextChunk("elif");
7107 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7108 Builder.AddPlaceholderChunk("condition");
7109 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007110
7111 // #else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007112 Builder.AddTypedTextChunk("else");
7113 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007114
7115 // #endif
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007116 Builder.AddTypedTextChunk("endif");
7117 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007118 }
7119
7120 // #include "header"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007121 Builder.AddTypedTextChunk("include");
7122 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7123 Builder.AddTextChunk("\"");
7124 Builder.AddPlaceholderChunk("header");
7125 Builder.AddTextChunk("\"");
7126 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007127
7128 // #include <header>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007129 Builder.AddTypedTextChunk("include");
7130 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7131 Builder.AddTextChunk("<");
7132 Builder.AddPlaceholderChunk("header");
7133 Builder.AddTextChunk(">");
7134 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007135
7136 // #define <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007137 Builder.AddTypedTextChunk("define");
7138 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7139 Builder.AddPlaceholderChunk("macro");
7140 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007141
7142 // #define <macro>(<args>)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007143 Builder.AddTypedTextChunk("define");
7144 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7145 Builder.AddPlaceholderChunk("macro");
7146 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7147 Builder.AddPlaceholderChunk("args");
7148 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7149 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007150
7151 // #undef <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007152 Builder.AddTypedTextChunk("undef");
7153 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7154 Builder.AddPlaceholderChunk("macro");
7155 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007156
7157 // #line <number>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007158 Builder.AddTypedTextChunk("line");
7159 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7160 Builder.AddPlaceholderChunk("number");
7161 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007162
7163 // #line <number> "filename"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007164 Builder.AddTypedTextChunk("line");
7165 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7166 Builder.AddPlaceholderChunk("number");
7167 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7168 Builder.AddTextChunk("\"");
7169 Builder.AddPlaceholderChunk("filename");
7170 Builder.AddTextChunk("\"");
7171 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007172
7173 // #error <message>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007174 Builder.AddTypedTextChunk("error");
7175 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7176 Builder.AddPlaceholderChunk("message");
7177 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007178
7179 // #pragma <arguments>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007180 Builder.AddTypedTextChunk("pragma");
7181 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7182 Builder.AddPlaceholderChunk("arguments");
7183 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007184
David Blaikiebbafb8a2012-03-11 07:00:24 +00007185 if (getLangOpts().ObjC1) {
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007186 // #import "header"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007187 Builder.AddTypedTextChunk("import");
7188 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7189 Builder.AddTextChunk("\"");
7190 Builder.AddPlaceholderChunk("header");
7191 Builder.AddTextChunk("\"");
7192 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007193
7194 // #import <header>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007195 Builder.AddTypedTextChunk("import");
7196 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7197 Builder.AddTextChunk("<");
7198 Builder.AddPlaceholderChunk("header");
7199 Builder.AddTextChunk(">");
7200 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007201 }
7202
7203 // #include_next "header"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007204 Builder.AddTypedTextChunk("include_next");
7205 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7206 Builder.AddTextChunk("\"");
7207 Builder.AddPlaceholderChunk("header");
7208 Builder.AddTextChunk("\"");
7209 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007210
7211 // #include_next <header>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007212 Builder.AddTypedTextChunk("include_next");
7213 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7214 Builder.AddTextChunk("<");
7215 Builder.AddPlaceholderChunk("header");
7216 Builder.AddTextChunk(">");
7217 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007218
7219 // #warning <message>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007220 Builder.AddTypedTextChunk("warning");
7221 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7222 Builder.AddPlaceholderChunk("message");
7223 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007224
7225 // Note: #ident and #sccs are such crazy anachronisms that we don't provide
7226 // completions for them. And __include_macros is a Clang-internal extension
7227 // that we don't want to encourage anyone to use.
7228
7229 // FIXME: we don't support #assert or #unassert, so don't suggest them.
7230 Results.ExitScope();
7231
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007232 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0de55ce2010-08-25 18:41:16 +00007233 CodeCompletionContext::CCC_PreprocessorDirective,
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007234 Results.data(), Results.size());
7235}
7236
7237void Sema::CodeCompleteInPreprocessorConditionalExclusion(Scope *S) {
Douglas Gregorec00a262010-08-24 22:20:20 +00007238 CodeCompleteOrdinaryName(S,
John McCallfaf5fb42010-08-26 23:41:50 +00007239 S->getFnParent()? Sema::PCC_RecoveryInFunction
7240 : Sema::PCC_Namespace);
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007241}
7242
Douglas Gregorec00a262010-08-24 22:20:20 +00007243void Sema::CodeCompletePreprocessorMacroName(bool IsDefinition) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007244 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007245 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00007246 IsDefinition? CodeCompletionContext::CCC_MacroName
7247 : CodeCompletionContext::CCC_MacroNameUse);
Douglas Gregor12785102010-08-24 20:21:13 +00007248 if (!IsDefinition && (!CodeCompleter || CodeCompleter->includeMacros())) {
7249 // Add just the names of macros, not their arguments.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007250 CodeCompletionBuilder Builder(Results.getAllocator(),
7251 Results.getCodeCompletionTUInfo());
Douglas Gregor12785102010-08-24 20:21:13 +00007252 Results.EnterNewScope();
7253 for (Preprocessor::macro_iterator M = PP.macro_begin(),
7254 MEnd = PP.macro_end();
7255 M != MEnd; ++M) {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00007256 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007257 M->first->getName()));
Argyrios Kyrtzidis5c8b1cd2012-09-27 00:24:09 +00007258 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
7259 CCP_CodePattern,
7260 CXCursor_MacroDefinition));
Douglas Gregor12785102010-08-24 20:21:13 +00007261 }
7262 Results.ExitScope();
7263 } else if (IsDefinition) {
7264 // FIXME: Can we detect when the user just wrote an include guard above?
7265 }
7266
Douglas Gregor0ac41382010-09-23 23:01:17 +00007267 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor12785102010-08-24 20:21:13 +00007268 Results.data(), Results.size());
7269}
7270
Douglas Gregorec00a262010-08-24 22:20:20 +00007271void Sema::CodeCompletePreprocessorExpression() {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007272 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007273 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00007274 CodeCompletionContext::CCC_PreprocessorExpression);
Douglas Gregorec00a262010-08-24 22:20:20 +00007275
7276 if (!CodeCompleter || CodeCompleter->includeMacros())
Douglas Gregor8cb17462012-10-09 16:01:50 +00007277 AddMacroResults(PP, Results, true);
Douglas Gregorec00a262010-08-24 22:20:20 +00007278
7279 // defined (<macro>)
7280 Results.EnterNewScope();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007281 CodeCompletionBuilder Builder(Results.getAllocator(),
7282 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007283 Builder.AddTypedTextChunk("defined");
7284 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7285 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7286 Builder.AddPlaceholderChunk("macro");
7287 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7288 Results.AddResult(Builder.TakeString());
Douglas Gregorec00a262010-08-24 22:20:20 +00007289 Results.ExitScope();
7290
7291 HandleCodeCompleteResults(this, CodeCompleter,
7292 CodeCompletionContext::CCC_PreprocessorExpression,
7293 Results.data(), Results.size());
7294}
7295
7296void Sema::CodeCompletePreprocessorMacroArgument(Scope *S,
7297 IdentifierInfo *Macro,
7298 MacroInfo *MacroInfo,
7299 unsigned Argument) {
7300 // FIXME: In the future, we could provide "overload" results, much like we
7301 // do for function calls.
7302
Argyrios Kyrtzidis75f6cd22011-08-18 19:41:28 +00007303 // Now just ignore this. There will be another code-completion callback
7304 // for the expanded tokens.
Douglas Gregorec00a262010-08-24 22:20:20 +00007305}
7306
Douglas Gregor11583702010-08-25 17:04:25 +00007307void Sema::CodeCompleteNaturalLanguage() {
Douglas Gregor11583702010-08-25 17:04:25 +00007308 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregorea736372010-08-25 17:10:00 +00007309 CodeCompletionContext::CCC_NaturalLanguage,
Douglas Gregor11583702010-08-25 17:04:25 +00007310 0, 0);
7311}
7312
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00007313void Sema::GatherGlobalCodeCompletions(CodeCompletionAllocator &Allocator,
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007314 CodeCompletionTUInfo &CCTUInfo,
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007315 SmallVectorImpl<CodeCompletionResult> &Results) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007316 ResultBuilder Builder(*this, Allocator, CCTUInfo,
7317 CodeCompletionContext::CCC_Recovery);
Douglas Gregor39982192010-08-15 06:18:01 +00007318 if (!CodeCompleter || CodeCompleter->includeGlobals()) {
7319 CodeCompletionDeclConsumer Consumer(Builder,
7320 Context.getTranslationUnitDecl());
7321 LookupVisibleDecls(Context.getTranslationUnitDecl(), LookupAnyName,
7322 Consumer);
7323 }
Douglas Gregorb14904c2010-08-13 22:48:40 +00007324
7325 if (!CodeCompleter || CodeCompleter->includeMacros())
Douglas Gregor8cb17462012-10-09 16:01:50 +00007326 AddMacroResults(PP, Builder, true);
Douglas Gregorb14904c2010-08-13 22:48:40 +00007327
7328 Results.clear();
7329 Results.insert(Results.end(),
7330 Builder.data(), Builder.data() + Builder.size());
7331}