blob: ce580ceea30544e867783e67e6a6462d0f6b29ad [file] [log] [blame]
Douglas Gregor81b747b2009-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 McCall2d887082010-08-25 22:03:47 +000013#include "clang/Sema/SemaInternal.h"
John McCall7cd088e2010-08-24 07:21:54 +000014#include "clang/AST/DeclObjC.h"
Douglas Gregorb9d0ef72009-09-21 19:57:38 +000015#include "clang/AST/ExprCXX.h"
Douglas Gregor24a069f2009-11-17 17:59:40 +000016#include "clang/AST/ExprObjC.h"
Douglas Gregorc5b2e582012-01-29 18:15:03 +000017#include "clang/Lex/HeaderSearch.h"
Douglas Gregor3f7c7f42009-10-30 16:50:04 +000018#include "clang/Lex/MacroInfo.h"
19#include "clang/Lex/Preprocessor.h"
Chandler Carruth55fc8732012-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 Gregord36adf52010-09-16 16:06:31 +000026#include "llvm/ADT/DenseSet.h"
Benjamin Kramer013b3662012-01-30 16:17:39 +000027#include "llvm/ADT/SmallBitVector.h"
Douglas Gregor86d9a522009-09-21 16:56:56 +000028#include "llvm/ADT/SmallPtrSet.h"
Benjamin Kramer8fe83e12012-02-04 13:45:25 +000029#include "llvm/ADT/SmallString.h"
Douglas Gregor6a684032009-09-28 03:51:44 +000030#include "llvm/ADT/StringExtras.h"
Douglas Gregor22f56992010-04-06 19:22:33 +000031#include "llvm/ADT/StringSwitch.h"
Douglas Gregor458433d2010-08-26 15:07:07 +000032#include "llvm/ADT/Twine.h"
Douglas Gregor86d9a522009-09-21 16:56:56 +000033#include <list>
34#include <map>
35#include <vector>
Douglas Gregor81b747b2009-09-17 21:32:03 +000036
37using namespace clang;
John McCall781472f2010-08-25 08:40:02 +000038using namespace sema;
Douglas Gregor81b747b2009-09-17 21:32:03 +000039
Douglas Gregor86d9a522009-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 Gribenko89cf4252013-01-23 17:21:11 +000048 typedef bool (ResultBuilder::*LookupFilter)(const NamedDecl *) const;
Douglas Gregor86d9a522009-09-21 16:56:56 +000049
John McCall0a2c5e22010-08-25 06:19:51 +000050 typedef CodeCompletionResult Result;
Douglas Gregor86d9a522009-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 Gribenko89cf4252013-01-23 17:21:11 +000059 llvm::SmallPtrSet<const Decl*, 16> AllDeclsFound;
Douglas Gregor86d9a522009-09-21 16:56:56 +000060
Dmitri Gribenko89cf4252013-01-23 17:21:11 +000061 typedef std::pair<const NamedDecl *, unsigned> DeclIndexPair;
Douglas Gregorfbcb5d62009-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 Lattner5f9e2722011-07-23 10:55:15 +000067 typedef SmallVector<DeclIndexPair, 4> DeclIndexPairVector;
Douglas Gregorfbcb5d62009-12-06 20:23:50 +000068
69 /// \brief Contains either the solitary NamedDecl * or a vector
70 /// of (declaration, index) pairs.
Dmitri Gribenko89cf4252013-01-23 17:21:11 +000071 llvm::PointerUnion<const NamedDecl *, DeclIndexPairVector*> DeclOrVector;
Douglas Gregorfbcb5d62009-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 Gribenko89cf4252013-01-23 17:21:11 +000080 void Add(const NamedDecl *ND, unsigned Index) {
Douglas Gregorfbcb5d62009-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 Gribenko89cf4252013-01-23 17:21:11 +000088 if (const NamedDecl *PrevND =
89 DeclOrVector.dyn_cast<const NamedDecl *>()) {
Douglas Gregorfbcb5d62009-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 Gregor86d9a522009-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 Gregorfbcb5d62009-12-06 20:23:50 +0000119 typedef llvm::DenseMap<DeclarationName, ShadowMapEntry> ShadowMap;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000120
121 /// \brief The semantic analysis object for which results are being
122 /// produced.
123 Sema &SemaRef;
Douglas Gregor218937c2011-02-01 19:23:04 +0000124
125 /// \brief The allocator used to allocate new code-completion strings.
Douglas Gregordae68752011-02-01 22:57:45 +0000126 CodeCompletionAllocator &Allocator;
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +0000127
128 CodeCompletionTUInfo &CCTUInfo;
Douglas Gregor86d9a522009-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 Gregor45bcd432010-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 Gregor5ac3bdb2010-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 Gregor86d9a522009-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 Gregor3cdee122010-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 Gregor265f7492010-08-27 15:29:55 +0000156 /// \brief The selector that we prefer.
157 Selector PreferredSelector;
158
Douglas Gregorca45da02010-11-02 20:36:02 +0000159 /// \brief The completion context in which we are gathering results.
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000160 CodeCompletionContext CompletionContext;
161
James Dennetta40f7922012-06-14 03:11:41 +0000162 /// \brief If we are in an instance method definition, the \@implementation
Douglas Gregorca45da02010-11-02 20:36:02 +0000163 /// object.
164 ObjCImplementationDecl *ObjCImplementation;
165
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000166 void AdjustResultPriorityForDecl(Result &R);
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000167
Douglas Gregor6f942b22010-09-21 16:06:22 +0000168 void MaybeAddConstructorResults(Result R);
169
Douglas Gregor86d9a522009-09-21 16:56:56 +0000170 public:
Douglas Gregordae68752011-02-01 22:57:45 +0000171 explicit ResultBuilder(Sema &SemaRef, CodeCompletionAllocator &Allocator,
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +0000172 CodeCompletionTUInfo &CCTUInfo,
Douglas Gregor52779fb2010-09-23 23:01:17 +0000173 const CodeCompletionContext &CompletionContext,
174 LookupFilter Filter = 0)
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +0000175 : SemaRef(SemaRef), Allocator(Allocator), CCTUInfo(CCTUInfo),
176 Filter(Filter),
Douglas Gregor218937c2011-02-01 19:23:04 +0000177 AllowNestedNameSpecifiers(false), HasObjectTypeQualifiers(false),
Douglas Gregorca45da02010-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 Gregor86d9a522009-09-21 16:56:56 +0000199
Douglas Gregord8e8a582010-05-25 21:41:55 +0000200 /// \brief Whether we should include code patterns in the completion
201 /// results.
202 bool includeCodePatterns() const {
203 return SemaRef.CodeCompleter &&
Douglas Gregorf6961522010-08-27 21:18:54 +0000204 SemaRef.CodeCompleter->includeCodePatterns();
Douglas Gregord8e8a582010-05-25 21:41:55 +0000205 }
206
Douglas Gregor86d9a522009-09-21 16:56:56 +0000207 /// \brief Set the filter used for code-completion results.
208 void setFilter(LookupFilter Filter) {
209 this->Filter = Filter;
210 }
211
Douglas Gregor86d9a522009-09-21 16:56:56 +0000212 Result *data() { return Results.empty()? 0 : &Results.front(); }
213 unsigned size() const { return Results.size(); }
214 bool empty() const { return Results.empty(); }
215
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +0000216 /// \brief Specify the preferred type.
217 void setPreferredType(QualType T) {
218 PreferredType = SemaRef.Context.getCanonicalType(T);
219 }
220
Douglas Gregor3cdee122010-08-26 16:36:48 +0000221 /// \brief Set the cv-qualifiers on the object type, for us in filtering
222 /// calls to member functions.
223 ///
224 /// When there are qualifiers in this set, they will be used to filter
225 /// out member functions that aren't available (because there will be a
226 /// cv-qualifier mismatch) or prefer functions with an exact qualifier
227 /// match.
228 void setObjectTypeQualifiers(Qualifiers Quals) {
229 ObjectTypeQualifiers = Quals;
230 HasObjectTypeQualifiers = true;
231 }
232
Douglas Gregor265f7492010-08-27 15:29:55 +0000233 /// \brief Set the preferred selector.
234 ///
235 /// When an Objective-C method declaration result is added, and that
236 /// method's selector matches this preferred selector, we give that method
237 /// a slight priority boost.
238 void setPreferredSelector(Selector Sel) {
239 PreferredSelector = Sel;
240 }
Douglas Gregorca45da02010-11-02 20:36:02 +0000241
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000242 /// \brief Retrieve the code-completion context for which results are
243 /// being collected.
244 const CodeCompletionContext &getCompletionContext() const {
245 return CompletionContext;
246 }
247
Douglas Gregor45bcd432010-01-14 03:21:49 +0000248 /// \brief Specify whether nested-name-specifiers are allowed.
249 void allowNestedNameSpecifiers(bool Allow = true) {
250 AllowNestedNameSpecifiers = Allow;
251 }
252
Douglas Gregorb9d77572010-09-21 00:03:25 +0000253 /// \brief Return the semantic analysis object for which we are collecting
254 /// code completion results.
255 Sema &getSema() const { return SemaRef; }
256
Douglas Gregor218937c2011-02-01 19:23:04 +0000257 /// \brief Retrieve the allocator used to allocate code completion strings.
Douglas Gregordae68752011-02-01 22:57:45 +0000258 CodeCompletionAllocator &getAllocator() const { return Allocator; }
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +0000259
260 CodeCompletionTUInfo &getCodeCompletionTUInfo() const { return CCTUInfo; }
Douglas Gregor218937c2011-02-01 19:23:04 +0000261
Douglas Gregore495b7f2010-01-14 00:20:49 +0000262 /// \brief Determine whether the given declaration is at all interesting
263 /// as a code-completion result.
Douglas Gregor45bcd432010-01-14 03:21:49 +0000264 ///
265 /// \param ND the declaration that we are inspecting.
266 ///
267 /// \param AsNestedNameSpecifier will be set true if this declaration is
268 /// only interesting when it is a nested-name-specifier.
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000269 bool isInterestingDecl(const NamedDecl *ND,
270 bool &AsNestedNameSpecifier) const;
Douglas Gregor6660d842010-01-14 00:41:07 +0000271
272 /// \brief Check whether the result is hidden by the Hiding declaration.
273 ///
274 /// \returns true if the result is hidden and cannot be found, false if
275 /// the hidden result could still be found. When false, \p R may be
276 /// modified to describe how the result can be found (e.g., via extra
277 /// qualification).
278 bool CheckHiddenResult(Result &R, DeclContext *CurContext,
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000279 const NamedDecl *Hiding);
Douglas Gregor6660d842010-01-14 00:41:07 +0000280
Douglas Gregor86d9a522009-09-21 16:56:56 +0000281 /// \brief Add a new result to this result set (if it isn't already in one
282 /// of the shadow maps), or replace an existing result (for, e.g., a
283 /// redeclaration).
Douglas Gregor456c4a12009-09-21 20:12:40 +0000284 ///
Douglas Gregor81f3bff2012-02-15 15:34:24 +0000285 /// \param R the result to add (if it is unique).
Douglas Gregor456c4a12009-09-21 20:12:40 +0000286 ///
Douglas Gregor81f3bff2012-02-15 15:34:24 +0000287 /// \param CurContext the context in which this result will be named.
Douglas Gregor456c4a12009-09-21 20:12:40 +0000288 void MaybeAddResult(Result R, DeclContext *CurContext = 0);
Douglas Gregor86d9a522009-09-21 16:56:56 +0000289
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000290 /// \brief Add a new result to this result set, where we already know
291 /// the hiding declation (if any).
292 ///
293 /// \param R the result to add (if it is unique).
294 ///
295 /// \param CurContext the context in which this result will be named.
296 ///
297 /// \param Hiding the declaration that hides the result.
Douglas Gregor0cc84042010-01-14 15:47:35 +0000298 ///
299 /// \param InBaseClass whether the result was found in a base
300 /// class of the searched context.
301 void AddResult(Result R, DeclContext *CurContext, NamedDecl *Hiding,
302 bool InBaseClass);
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000303
Douglas Gregora4477812010-01-14 16:01:26 +0000304 /// \brief Add a new non-declaration result to this result set.
305 void AddResult(Result R);
306
Douglas Gregor86d9a522009-09-21 16:56:56 +0000307 /// \brief Enter into a new scope.
308 void EnterNewScope();
309
310 /// \brief Exit from the current scope.
311 void ExitScope();
312
Douglas Gregor55385fe2009-11-18 04:19:12 +0000313 /// \brief Ignore this declaration, if it is seen again.
314 void Ignore(Decl *D) { AllDeclsFound.insert(D->getCanonicalDecl()); }
315
Douglas Gregor86d9a522009-09-21 16:56:56 +0000316 /// \name Name lookup predicates
317 ///
318 /// These predicates can be passed to the name lookup functions to filter the
319 /// results of name lookup. All of the predicates have the same type, so that
320 ///
321 //@{
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000322 bool IsOrdinaryName(const NamedDecl *ND) const;
323 bool IsOrdinaryNonTypeName(const NamedDecl *ND) const;
324 bool IsIntegralConstantValue(const NamedDecl *ND) const;
325 bool IsOrdinaryNonValueName(const NamedDecl *ND) const;
326 bool IsNestedNameSpecifier(const NamedDecl *ND) const;
327 bool IsEnum(const NamedDecl *ND) const;
328 bool IsClassOrStruct(const NamedDecl *ND) const;
329 bool IsUnion(const NamedDecl *ND) const;
330 bool IsNamespace(const NamedDecl *ND) const;
331 bool IsNamespaceOrAlias(const NamedDecl *ND) const;
332 bool IsType(const NamedDecl *ND) const;
333 bool IsMember(const NamedDecl *ND) const;
334 bool IsObjCIvar(const NamedDecl *ND) const;
335 bool IsObjCMessageReceiver(const NamedDecl *ND) const;
336 bool IsObjCMessageReceiverOrLambdaCapture(const NamedDecl *ND) const;
337 bool IsObjCCollection(const NamedDecl *ND) const;
338 bool IsImpossibleToSatisfy(const NamedDecl *ND) const;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000339 //@}
340 };
341}
342
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000343class ResultBuilder::ShadowMapEntry::iterator {
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000344 llvm::PointerUnion<const NamedDecl *, const DeclIndexPair *> DeclOrIterator;
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000345 unsigned SingleDeclIndex;
346
347public:
348 typedef DeclIndexPair value_type;
349 typedef value_type reference;
350 typedef std::ptrdiff_t difference_type;
351 typedef std::input_iterator_tag iterator_category;
352
353 class pointer {
354 DeclIndexPair Value;
355
356 public:
357 pointer(const DeclIndexPair &Value) : Value(Value) { }
358
359 const DeclIndexPair *operator->() const {
360 return &Value;
361 }
362 };
363
364 iterator() : DeclOrIterator((NamedDecl *)0), SingleDeclIndex(0) { }
365
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000366 iterator(const NamedDecl *SingleDecl, unsigned Index)
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000367 : DeclOrIterator(SingleDecl), SingleDeclIndex(Index) { }
368
369 iterator(const DeclIndexPair *Iterator)
370 : DeclOrIterator(Iterator), SingleDeclIndex(0) { }
371
372 iterator &operator++() {
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000373 if (DeclOrIterator.is<const NamedDecl *>()) {
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000374 DeclOrIterator = (NamedDecl *)0;
375 SingleDeclIndex = 0;
376 return *this;
377 }
378
379 const DeclIndexPair *I = DeclOrIterator.get<const DeclIndexPair*>();
380 ++I;
381 DeclOrIterator = I;
382 return *this;
383 }
384
Chris Lattner66392d42010-09-04 18:12:20 +0000385 /*iterator operator++(int) {
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000386 iterator tmp(*this);
387 ++(*this);
388 return tmp;
Chris Lattner66392d42010-09-04 18:12:20 +0000389 }*/
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000390
391 reference operator*() const {
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000392 if (const NamedDecl *ND = DeclOrIterator.dyn_cast<const NamedDecl *>())
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000393 return reference(ND, SingleDeclIndex);
394
Douglas Gregord490f952009-12-06 21:27:58 +0000395 return *DeclOrIterator.get<const DeclIndexPair*>();
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000396 }
397
398 pointer operator->() const {
399 return pointer(**this);
400 }
401
402 friend bool operator==(const iterator &X, const iterator &Y) {
Douglas Gregord490f952009-12-06 21:27:58 +0000403 return X.DeclOrIterator.getOpaqueValue()
404 == Y.DeclOrIterator.getOpaqueValue() &&
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000405 X.SingleDeclIndex == Y.SingleDeclIndex;
406 }
407
408 friend bool operator!=(const iterator &X, const iterator &Y) {
Douglas Gregord490f952009-12-06 21:27:58 +0000409 return !(X == Y);
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000410 }
411};
412
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000413ResultBuilder::ShadowMapEntry::iterator
414ResultBuilder::ShadowMapEntry::begin() const {
415 if (DeclOrVector.isNull())
416 return iterator();
417
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000418 if (const NamedDecl *ND = DeclOrVector.dyn_cast<const NamedDecl *>())
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000419 return iterator(ND, SingleDeclIndex);
420
421 return iterator(DeclOrVector.get<DeclIndexPairVector *>()->begin());
422}
423
424ResultBuilder::ShadowMapEntry::iterator
425ResultBuilder::ShadowMapEntry::end() const {
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000426 if (DeclOrVector.is<const NamedDecl *>() || DeclOrVector.isNull())
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000427 return iterator();
428
429 return iterator(DeclOrVector.get<DeclIndexPairVector *>()->end());
430}
431
Douglas Gregor456c4a12009-09-21 20:12:40 +0000432/// \brief Compute the qualification required to get from the current context
433/// (\p CurContext) to the target context (\p TargetContext).
434///
435/// \param Context the AST context in which the qualification will be used.
436///
437/// \param CurContext the context where an entity is being named, which is
438/// typically based on the current scope.
439///
440/// \param TargetContext the context in which the named entity actually
441/// resides.
442///
443/// \returns a nested name specifier that refers into the target context, or
444/// NULL if no qualification is needed.
445static NestedNameSpecifier *
446getRequiredQualification(ASTContext &Context,
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000447 const DeclContext *CurContext,
448 const DeclContext *TargetContext) {
449 SmallVector<const DeclContext *, 4> TargetParents;
Douglas Gregor456c4a12009-09-21 20:12:40 +0000450
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000451 for (const DeclContext *CommonAncestor = TargetContext;
Douglas Gregor456c4a12009-09-21 20:12:40 +0000452 CommonAncestor && !CommonAncestor->Encloses(CurContext);
453 CommonAncestor = CommonAncestor->getLookupParent()) {
454 if (CommonAncestor->isTransparentContext() ||
455 CommonAncestor->isFunctionOrMethod())
456 continue;
457
458 TargetParents.push_back(CommonAncestor);
459 }
460
461 NestedNameSpecifier *Result = 0;
462 while (!TargetParents.empty()) {
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000463 const DeclContext *Parent = TargetParents.back();
Douglas Gregor456c4a12009-09-21 20:12:40 +0000464 TargetParents.pop_back();
465
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000466 if (const NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Parent)) {
Douglas Gregorfb629412010-08-23 21:17:50 +0000467 if (!Namespace->getIdentifier())
468 continue;
469
Douglas Gregor456c4a12009-09-21 20:12:40 +0000470 Result = NestedNameSpecifier::Create(Context, Result, Namespace);
Douglas Gregorfb629412010-08-23 21:17:50 +0000471 }
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000472 else if (const TagDecl *TD = dyn_cast<TagDecl>(Parent))
Douglas Gregor456c4a12009-09-21 20:12:40 +0000473 Result = NestedNameSpecifier::Create(Context, Result,
474 false,
475 Context.getTypeDeclType(TD).getTypePtr());
Douglas Gregor0c8296d2009-11-07 00:00:49 +0000476 }
Douglas Gregor456c4a12009-09-21 20:12:40 +0000477 return Result;
478}
479
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000480bool ResultBuilder::isInterestingDecl(const NamedDecl *ND,
Douglas Gregor45bcd432010-01-14 03:21:49 +0000481 bool &AsNestedNameSpecifier) const {
482 AsNestedNameSpecifier = false;
483
Douglas Gregore495b7f2010-01-14 00:20:49 +0000484 ND = ND->getUnderlyingDecl();
485 unsigned IDNS = ND->getIdentifierNamespace();
Douglas Gregorf52cede2009-10-09 22:16:47 +0000486
487 // Skip unnamed entities.
Douglas Gregore495b7f2010-01-14 00:20:49 +0000488 if (!ND->getDeclName())
489 return false;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000490
491 // Friend declarations and declarations introduced due to friends are never
492 // added as results.
John McCall92b7f702010-03-11 07:50:04 +0000493 if (IDNS & (Decl::IDNS_OrdinaryFriend | Decl::IDNS_TagFriend))
Douglas Gregore495b7f2010-01-14 00:20:49 +0000494 return false;
495
Douglas Gregor76282942009-12-11 17:31:05 +0000496 // Class template (partial) specializations are never added as results.
Douglas Gregore495b7f2010-01-14 00:20:49 +0000497 if (isa<ClassTemplateSpecializationDecl>(ND) ||
498 isa<ClassTemplatePartialSpecializationDecl>(ND))
499 return false;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000500
Douglas Gregor76282942009-12-11 17:31:05 +0000501 // Using declarations themselves are never added as results.
Douglas Gregore495b7f2010-01-14 00:20:49 +0000502 if (isa<UsingDecl>(ND))
503 return false;
504
505 // Some declarations have reserved names that we don't want to ever show.
506 if (const IdentifierInfo *Id = ND->getIdentifier()) {
Douglas Gregor86d9a522009-09-21 16:56:56 +0000507 // __va_list_tag is a freak of nature. Find it and skip it.
508 if (Id->isStr("__va_list_tag") || Id->isStr("__builtin_va_list"))
Douglas Gregore495b7f2010-01-14 00:20:49 +0000509 return false;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000510
Douglas Gregorf52cede2009-10-09 22:16:47 +0000511 // Filter out names reserved for the implementation (C99 7.1.3,
Douglas Gregor797efb52010-07-14 17:44:04 +0000512 // C++ [lib.global.names]) if they come from a system header.
Daniel Dunbare013d682009-10-18 20:26:12 +0000513 //
514 // FIXME: Add predicate for this.
Douglas Gregorf52cede2009-10-09 22:16:47 +0000515 if (Id->getLength() >= 2) {
Daniel Dunbare013d682009-10-18 20:26:12 +0000516 const char *Name = Id->getNameStart();
Douglas Gregorf52cede2009-10-09 22:16:47 +0000517 if (Name[0] == '_' &&
Douglas Gregor797efb52010-07-14 17:44:04 +0000518 (Name[1] == '_' || (Name[1] >= 'A' && Name[1] <= 'Z')) &&
519 (ND->getLocation().isInvalid() ||
520 SemaRef.SourceMgr.isInSystemHeader(
521 SemaRef.SourceMgr.getSpellingLoc(ND->getLocation()))))
Douglas Gregore495b7f2010-01-14 00:20:49 +0000522 return false;
Douglas Gregorf52cede2009-10-09 22:16:47 +0000523 }
Douglas Gregor86d9a522009-09-21 16:56:56 +0000524 }
Douglas Gregor9b0ba872010-11-09 03:59:40 +0000525
Douglas Gregora5fb7c32010-08-16 23:05:20 +0000526 if (Filter == &ResultBuilder::IsNestedNameSpecifier ||
527 ((isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND)) &&
528 Filter != &ResultBuilder::IsNamespace &&
Douglas Gregor52779fb2010-09-23 23:01:17 +0000529 Filter != &ResultBuilder::IsNamespaceOrAlias &&
530 Filter != 0))
Douglas Gregora5fb7c32010-08-16 23:05:20 +0000531 AsNestedNameSpecifier = true;
532
Douglas Gregor86d9a522009-09-21 16:56:56 +0000533 // Filter out any unwanted results.
Douglas Gregor45bcd432010-01-14 03:21:49 +0000534 if (Filter && !(this->*Filter)(ND)) {
535 // Check whether it is interesting as a nested-name-specifier.
David Blaikie4e4d0842012-03-11 07:00:24 +0000536 if (AllowNestedNameSpecifiers && SemaRef.getLangOpts().CPlusPlus &&
Douglas Gregor45bcd432010-01-14 03:21:49 +0000537 IsNestedNameSpecifier(ND) &&
538 (Filter != &ResultBuilder::IsMember ||
539 (isa<CXXRecordDecl>(ND) &&
540 cast<CXXRecordDecl>(ND)->isInjectedClassName()))) {
541 AsNestedNameSpecifier = true;
542 return true;
543 }
544
Douglas Gregore495b7f2010-01-14 00:20:49 +0000545 return false;
Douglas Gregora5fb7c32010-08-16 23:05:20 +0000546 }
Douglas Gregore495b7f2010-01-14 00:20:49 +0000547 // ... then it must be interesting!
548 return true;
549}
550
Douglas Gregor6660d842010-01-14 00:41:07 +0000551bool ResultBuilder::CheckHiddenResult(Result &R, DeclContext *CurContext,
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000552 const NamedDecl *Hiding) {
Douglas Gregor6660d842010-01-14 00:41:07 +0000553 // In C, there is no way to refer to a hidden name.
554 // FIXME: This isn't true; we can find a tag name hidden by an ordinary
555 // name if we introduce the tag type.
David Blaikie4e4d0842012-03-11 07:00:24 +0000556 if (!SemaRef.getLangOpts().CPlusPlus)
Douglas Gregor6660d842010-01-14 00:41:07 +0000557 return true;
558
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000559 const DeclContext *HiddenCtx =
560 R.Declaration->getDeclContext()->getRedeclContext();
Douglas Gregor6660d842010-01-14 00:41:07 +0000561
562 // There is no way to qualify a name declared in a function or method.
563 if (HiddenCtx->isFunctionOrMethod())
564 return true;
565
Sebastian Redl7a126a42010-08-31 00:36:30 +0000566 if (HiddenCtx == Hiding->getDeclContext()->getRedeclContext())
Douglas Gregor6660d842010-01-14 00:41:07 +0000567 return true;
568
569 // We can refer to the result with the appropriate qualification. Do it.
570 R.Hidden = true;
571 R.QualifierIsInformative = false;
572
573 if (!R.Qualifier)
574 R.Qualifier = getRequiredQualification(SemaRef.Context,
575 CurContext,
576 R.Declaration->getDeclContext());
577 return false;
578}
579
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000580/// \brief A simplified classification of types used to determine whether two
581/// types are "similar enough" when adjusting priorities.
Douglas Gregor1827e102010-08-16 16:18:59 +0000582SimplifiedTypeClass clang::getSimplifiedTypeClass(CanQualType T) {
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000583 switch (T->getTypeClass()) {
584 case Type::Builtin:
585 switch (cast<BuiltinType>(T)->getKind()) {
586 case BuiltinType::Void:
587 return STC_Void;
588
589 case BuiltinType::NullPtr:
590 return STC_Pointer;
591
592 case BuiltinType::Overload:
593 case BuiltinType::Dependent:
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000594 return STC_Other;
595
596 case BuiltinType::ObjCId:
597 case BuiltinType::ObjCClass:
598 case BuiltinType::ObjCSel:
599 return STC_ObjectiveC;
600
601 default:
602 return STC_Arithmetic;
603 }
David Blaikie7530c032012-01-17 06:56:22 +0000604
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000605 case Type::Complex:
606 return STC_Arithmetic;
607
608 case Type::Pointer:
609 return STC_Pointer;
610
611 case Type::BlockPointer:
612 return STC_Block;
613
614 case Type::LValueReference:
615 case Type::RValueReference:
616 return getSimplifiedTypeClass(T->getAs<ReferenceType>()->getPointeeType());
617
618 case Type::ConstantArray:
619 case Type::IncompleteArray:
620 case Type::VariableArray:
621 case Type::DependentSizedArray:
622 return STC_Array;
623
624 case Type::DependentSizedExtVector:
625 case Type::Vector:
626 case Type::ExtVector:
627 return STC_Arithmetic;
628
629 case Type::FunctionProto:
630 case Type::FunctionNoProto:
631 return STC_Function;
632
633 case Type::Record:
634 return STC_Record;
635
636 case Type::Enum:
637 return STC_Arithmetic;
638
639 case Type::ObjCObject:
640 case Type::ObjCInterface:
641 case Type::ObjCObjectPointer:
642 return STC_ObjectiveC;
643
644 default:
645 return STC_Other;
646 }
647}
648
649/// \brief Get the type that a given expression will have if this declaration
650/// is used as an expression in its "typical" code-completion form.
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000651QualType clang::getDeclUsageType(ASTContext &C, const NamedDecl *ND) {
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000652 ND = cast<NamedDecl>(ND->getUnderlyingDecl());
653
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000654 if (const TypeDecl *Type = dyn_cast<TypeDecl>(ND))
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000655 return C.getTypeDeclType(Type);
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000656 if (const ObjCInterfaceDecl *Iface = dyn_cast<ObjCInterfaceDecl>(ND))
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000657 return C.getObjCInterfaceType(Iface);
658
659 QualType T;
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000660 if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(ND))
Douglas Gregor5291c3c2010-07-13 08:18:22 +0000661 T = Function->getCallResultType();
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000662 else if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND))
Douglas Gregor5291c3c2010-07-13 08:18:22 +0000663 T = Method->getSendResultType();
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000664 else if (const FunctionTemplateDecl *FunTmpl =
665 dyn_cast<FunctionTemplateDecl>(ND))
Douglas Gregor5291c3c2010-07-13 08:18:22 +0000666 T = FunTmpl->getTemplatedDecl()->getCallResultType();
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000667 else if (const EnumConstantDecl *Enumerator = dyn_cast<EnumConstantDecl>(ND))
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000668 T = C.getTypeDeclType(cast<EnumDecl>(Enumerator->getDeclContext()));
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000669 else if (const ObjCPropertyDecl *Property = dyn_cast<ObjCPropertyDecl>(ND))
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000670 T = Property->getType();
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000671 else if (const ValueDecl *Value = dyn_cast<ValueDecl>(ND))
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000672 T = Value->getType();
673 else
674 return QualType();
Douglas Gregor3e64d562011-04-14 20:33:34 +0000675
676 // Dig through references, function pointers, and block pointers to
677 // get down to the likely type of an expression when the entity is
678 // used.
679 do {
680 if (const ReferenceType *Ref = T->getAs<ReferenceType>()) {
681 T = Ref->getPointeeType();
682 continue;
683 }
684
685 if (const PointerType *Pointer = T->getAs<PointerType>()) {
686 if (Pointer->getPointeeType()->isFunctionType()) {
687 T = Pointer->getPointeeType();
688 continue;
689 }
690
691 break;
692 }
693
694 if (const BlockPointerType *Block = T->getAs<BlockPointerType>()) {
695 T = Block->getPointeeType();
696 continue;
697 }
698
699 if (const FunctionType *Function = T->getAs<FunctionType>()) {
700 T = Function->getResultType();
701 continue;
702 }
703
704 break;
705 } while (true);
706
707 return T;
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000708}
709
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000710void ResultBuilder::AdjustResultPriorityForDecl(Result &R) {
711 // If this is an Objective-C method declaration whose selector matches our
712 // preferred selector, give it a priority boost.
713 if (!PreferredSelector.isNull())
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000714 if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(R.Declaration))
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000715 if (PreferredSelector == Method->getSelector())
716 R.Priority += CCD_SelectorMatch;
Douglas Gregor08f43cd2010-09-20 23:11:55 +0000717
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000718 // If we have a preferred type, adjust the priority for results with exactly-
719 // matching or nearly-matching types.
720 if (!PreferredType.isNull()) {
721 QualType T = getDeclUsageType(SemaRef.Context, R.Declaration);
722 if (!T.isNull()) {
723 CanQualType TC = SemaRef.Context.getCanonicalType(T);
724 // Check for exactly-matching types (modulo qualifiers).
725 if (SemaRef.Context.hasSameUnqualifiedType(PreferredType, TC))
726 R.Priority /= CCF_ExactTypeMatch;
727 // Check for nearly-matching types, based on classification of each.
728 else if ((getSimplifiedTypeClass(PreferredType)
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000729 == getSimplifiedTypeClass(TC)) &&
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000730 !(PreferredType->isEnumeralType() && TC->isEnumeralType()))
731 R.Priority /= CCF_SimilarTypeMatch;
732 }
733 }
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000734}
735
Douglas Gregor6f942b22010-09-21 16:06:22 +0000736void ResultBuilder::MaybeAddConstructorResults(Result R) {
David Blaikie4e4d0842012-03-11 07:00:24 +0000737 if (!SemaRef.getLangOpts().CPlusPlus || !R.Declaration ||
Douglas Gregor6f942b22010-09-21 16:06:22 +0000738 !CompletionContext.wantConstructorResults())
739 return;
740
741 ASTContext &Context = SemaRef.Context;
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000742 const NamedDecl *D = R.Declaration;
743 const CXXRecordDecl *Record = 0;
744 if (const ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(D))
Douglas Gregor6f942b22010-09-21 16:06:22 +0000745 Record = ClassTemplate->getTemplatedDecl();
746 else if ((Record = dyn_cast<CXXRecordDecl>(D))) {
747 // Skip specializations and partial specializations.
748 if (isa<ClassTemplateSpecializationDecl>(Record))
749 return;
750 } else {
751 // There are no constructors here.
752 return;
753 }
754
755 Record = Record->getDefinition();
756 if (!Record)
757 return;
758
759
760 QualType RecordTy = Context.getTypeDeclType(Record);
761 DeclarationName ConstructorName
762 = Context.DeclarationNames.getCXXConstructorName(
763 Context.getCanonicalType(RecordTy));
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000764 DeclContext::lookup_const_result Ctors = Record->lookup(ConstructorName);
765 for (DeclContext::lookup_const_iterator I = Ctors.begin(),
766 E = Ctors.end();
767 I != E; ++I) {
David Blaikie3bc93e32012-12-19 00:45:41 +0000768 R.Declaration = *I;
Douglas Gregor6f942b22010-09-21 16:06:22 +0000769 R.CursorKind = getCursorKindForDecl(R.Declaration);
770 Results.push_back(R);
771 }
772}
773
Douglas Gregore495b7f2010-01-14 00:20:49 +0000774void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) {
775 assert(!ShadowMaps.empty() && "Must enter into a results scope");
776
777 if (R.Kind != Result::RK_Declaration) {
778 // For non-declaration results, just add the result.
779 Results.push_back(R);
780 return;
781 }
782
783 // Look through using declarations.
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000784 if (const UsingShadowDecl *Using =
785 dyn_cast<UsingShadowDecl>(R.Declaration)) {
Douglas Gregore495b7f2010-01-14 00:20:49 +0000786 MaybeAddResult(Result(Using->getTargetDecl(), R.Qualifier), CurContext);
787 return;
788 }
789
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000790 const Decl *CanonDecl = R.Declaration->getCanonicalDecl();
Douglas Gregore495b7f2010-01-14 00:20:49 +0000791 unsigned IDNS = CanonDecl->getIdentifierNamespace();
792
Douglas Gregor45bcd432010-01-14 03:21:49 +0000793 bool AsNestedNameSpecifier = false;
794 if (!isInterestingDecl(R.Declaration, AsNestedNameSpecifier))
Douglas Gregore495b7f2010-01-14 00:20:49 +0000795 return;
796
Douglas Gregor6f942b22010-09-21 16:06:22 +0000797 // C++ constructors are never found by name lookup.
798 if (isa<CXXConstructorDecl>(R.Declaration))
799 return;
800
Douglas Gregor86d9a522009-09-21 16:56:56 +0000801 ShadowMap &SMap = ShadowMaps.back();
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000802 ShadowMapEntry::iterator I, IEnd;
803 ShadowMap::iterator NamePos = SMap.find(R.Declaration->getDeclName());
804 if (NamePos != SMap.end()) {
805 I = NamePos->second.begin();
806 IEnd = NamePos->second.end();
807 }
808
809 for (; I != IEnd; ++I) {
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000810 const NamedDecl *ND = I->first;
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000811 unsigned Index = I->second;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000812 if (ND->getCanonicalDecl() == CanonDecl) {
813 // This is a redeclaration. Always pick the newer declaration.
Douglas Gregor86d9a522009-09-21 16:56:56 +0000814 Results[Index].Declaration = R.Declaration;
815
Douglas Gregor86d9a522009-09-21 16:56:56 +0000816 // We're done.
817 return;
818 }
819 }
820
821 // This is a new declaration in this scope. However, check whether this
822 // declaration name is hidden by a similarly-named declaration in an outer
823 // scope.
824 std::list<ShadowMap>::iterator SM, SMEnd = ShadowMaps.end();
825 --SMEnd;
826 for (SM = ShadowMaps.begin(); SM != SMEnd; ++SM) {
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000827 ShadowMapEntry::iterator I, IEnd;
828 ShadowMap::iterator NamePos = SM->find(R.Declaration->getDeclName());
829 if (NamePos != SM->end()) {
830 I = NamePos->second.begin();
831 IEnd = NamePos->second.end();
832 }
833 for (; I != IEnd; ++I) {
Douglas Gregor86d9a522009-09-21 16:56:56 +0000834 // A tag declaration does not hide a non-tag declaration.
John McCall0d6b1642010-04-23 18:46:30 +0000835 if (I->first->hasTagIdentifierNamespace() &&
Douglas Gregor86d9a522009-09-21 16:56:56 +0000836 (IDNS & (Decl::IDNS_Member | Decl::IDNS_Ordinary |
837 Decl::IDNS_ObjCProtocol)))
838 continue;
839
840 // Protocols are in distinct namespaces from everything else.
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000841 if (((I->first->getIdentifierNamespace() & Decl::IDNS_ObjCProtocol)
Douglas Gregor86d9a522009-09-21 16:56:56 +0000842 || (IDNS & Decl::IDNS_ObjCProtocol)) &&
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000843 I->first->getIdentifierNamespace() != IDNS)
Douglas Gregor86d9a522009-09-21 16:56:56 +0000844 continue;
845
846 // The newly-added result is hidden by an entry in the shadow map.
Douglas Gregor6660d842010-01-14 00:41:07 +0000847 if (CheckHiddenResult(R, CurContext, I->first))
Douglas Gregor86d9a522009-09-21 16:56:56 +0000848 return;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000849
850 break;
851 }
852 }
853
854 // Make sure that any given declaration only shows up in the result set once.
855 if (!AllDeclsFound.insert(CanonDecl))
856 return;
Douglas Gregor265f7492010-08-27 15:29:55 +0000857
Douglas Gregoreb5758b2009-09-23 22:26:46 +0000858 // If the filter is for nested-name-specifiers, then this result starts a
859 // nested-name-specifier.
Douglas Gregor12e13132010-05-26 22:00:08 +0000860 if (AsNestedNameSpecifier) {
Douglas Gregoreb5758b2009-09-23 22:26:46 +0000861 R.StartsNestedNameSpecifier = true;
Douglas Gregor12e13132010-05-26 22:00:08 +0000862 R.Priority = CCP_NestedNameSpecifier;
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000863 } else
864 AdjustResultPriorityForDecl(R);
Douglas Gregor265f7492010-08-27 15:29:55 +0000865
Douglas Gregor0563c262009-09-22 23:15:58 +0000866 // If this result is supposed to have an informative qualifier, add one.
Douglas Gregoreb5758b2009-09-23 22:26:46 +0000867 if (R.QualifierIsInformative && !R.Qualifier &&
868 !R.StartsNestedNameSpecifier) {
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000869 const DeclContext *Ctx = R.Declaration->getDeclContext();
870 if (const NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Ctx))
Douglas Gregor0563c262009-09-22 23:15:58 +0000871 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, Namespace);
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000872 else if (const TagDecl *Tag = dyn_cast<TagDecl>(Ctx))
Douglas Gregor0563c262009-09-22 23:15:58 +0000873 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, false,
874 SemaRef.Context.getTypeDeclType(Tag).getTypePtr());
875 else
876 R.QualifierIsInformative = false;
877 }
Douglas Gregoreb5758b2009-09-23 22:26:46 +0000878
Douglas Gregor86d9a522009-09-21 16:56:56 +0000879 // Insert this result into the set of results and into the current shadow
880 // map.
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000881 SMap[R.Declaration->getDeclName()].Add(R.Declaration, Results.size());
Douglas Gregor86d9a522009-09-21 16:56:56 +0000882 Results.push_back(R);
Douglas Gregor6f942b22010-09-21 16:06:22 +0000883
884 if (!AsNestedNameSpecifier)
885 MaybeAddConstructorResults(R);
Douglas Gregor86d9a522009-09-21 16:56:56 +0000886}
887
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000888void ResultBuilder::AddResult(Result R, DeclContext *CurContext,
Douglas Gregor0cc84042010-01-14 15:47:35 +0000889 NamedDecl *Hiding, bool InBaseClass = false) {
Douglas Gregora4477812010-01-14 16:01:26 +0000890 if (R.Kind != Result::RK_Declaration) {
891 // For non-declaration results, just add the result.
892 Results.push_back(R);
893 return;
894 }
895
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000896 // Look through using declarations.
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000897 if (const UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(R.Declaration)) {
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000898 AddResult(Result(Using->getTargetDecl(), R.Qualifier), CurContext, Hiding);
899 return;
900 }
901
Douglas Gregor45bcd432010-01-14 03:21:49 +0000902 bool AsNestedNameSpecifier = false;
903 if (!isInterestingDecl(R.Declaration, AsNestedNameSpecifier))
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000904 return;
905
Douglas Gregor6f942b22010-09-21 16:06:22 +0000906 // C++ constructors are never found by name lookup.
907 if (isa<CXXConstructorDecl>(R.Declaration))
908 return;
909
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000910 if (Hiding && CheckHiddenResult(R, CurContext, Hiding))
911 return;
Nick Lewycky173a37a2012-04-03 21:44:08 +0000912
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000913 // Make sure that any given declaration only shows up in the result set once.
914 if (!AllDeclsFound.insert(R.Declaration->getCanonicalDecl()))
915 return;
916
917 // If the filter is for nested-name-specifiers, then this result starts a
918 // nested-name-specifier.
Douglas Gregor12e13132010-05-26 22:00:08 +0000919 if (AsNestedNameSpecifier) {
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000920 R.StartsNestedNameSpecifier = true;
Douglas Gregor12e13132010-05-26 22:00:08 +0000921 R.Priority = CCP_NestedNameSpecifier;
922 }
Douglas Gregor0cc84042010-01-14 15:47:35 +0000923 else if (Filter == &ResultBuilder::IsMember && !R.Qualifier && InBaseClass &&
924 isa<CXXRecordDecl>(R.Declaration->getDeclContext()
Sebastian Redl7a126a42010-08-31 00:36:30 +0000925 ->getRedeclContext()))
Douglas Gregor0cc84042010-01-14 15:47:35 +0000926 R.QualifierIsInformative = true;
927
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000928 // If this result is supposed to have an informative qualifier, add one.
929 if (R.QualifierIsInformative && !R.Qualifier &&
930 !R.StartsNestedNameSpecifier) {
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000931 const DeclContext *Ctx = R.Declaration->getDeclContext();
932 if (const NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Ctx))
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000933 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, Namespace);
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000934 else if (const TagDecl *Tag = dyn_cast<TagDecl>(Ctx))
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000935 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, false,
Douglas Gregor45bcd432010-01-14 03:21:49 +0000936 SemaRef.Context.getTypeDeclType(Tag).getTypePtr());
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000937 else
938 R.QualifierIsInformative = false;
939 }
940
Douglas Gregor12e13132010-05-26 22:00:08 +0000941 // Adjust the priority if this result comes from a base class.
942 if (InBaseClass)
943 R.Priority += CCD_InBaseClass;
944
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000945 AdjustResultPriorityForDecl(R);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +0000946
Douglas Gregor3cdee122010-08-26 16:36:48 +0000947 if (HasObjectTypeQualifiers)
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000948 if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(R.Declaration))
Douglas Gregor3cdee122010-08-26 16:36:48 +0000949 if (Method->isInstance()) {
950 Qualifiers MethodQuals
951 = Qualifiers::fromCVRMask(Method->getTypeQualifiers());
952 if (ObjectTypeQualifiers == MethodQuals)
953 R.Priority += CCD_ObjectQualifierMatch;
954 else if (ObjectTypeQualifiers - MethodQuals) {
955 // The method cannot be invoked, because doing so would drop
956 // qualifiers.
957 return;
958 }
959 }
960
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000961 // Insert this result into the set of results.
962 Results.push_back(R);
Douglas Gregor6f942b22010-09-21 16:06:22 +0000963
964 if (!AsNestedNameSpecifier)
965 MaybeAddConstructorResults(R);
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000966}
967
Douglas Gregora4477812010-01-14 16:01:26 +0000968void ResultBuilder::AddResult(Result R) {
969 assert(R.Kind != Result::RK_Declaration &&
970 "Declaration results need more context");
971 Results.push_back(R);
972}
973
Douglas Gregor86d9a522009-09-21 16:56:56 +0000974/// \brief Enter into a new scope.
975void ResultBuilder::EnterNewScope() {
976 ShadowMaps.push_back(ShadowMap());
977}
978
979/// \brief Exit from the current scope.
980void ResultBuilder::ExitScope() {
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000981 for (ShadowMap::iterator E = ShadowMaps.back().begin(),
982 EEnd = ShadowMaps.back().end();
983 E != EEnd;
984 ++E)
985 E->second.Destroy();
986
Douglas Gregor86d9a522009-09-21 16:56:56 +0000987 ShadowMaps.pop_back();
988}
989
Douglas Gregor791215b2009-09-21 20:51:25 +0000990/// \brief Determines whether this given declaration will be found by
991/// ordinary name lookup.
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000992bool ResultBuilder::IsOrdinaryName(const NamedDecl *ND) const {
Douglas Gregor4710e5b2010-05-28 00:49:12 +0000993 ND = cast<NamedDecl>(ND->getUnderlyingDecl());
994
Douglas Gregor791215b2009-09-21 20:51:25 +0000995 unsigned IDNS = Decl::IDNS_Ordinary;
David Blaikie4e4d0842012-03-11 07:00:24 +0000996 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregor9b30b262010-06-15 20:26:51 +0000997 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member;
David Blaikie4e4d0842012-03-11 07:00:24 +0000998 else if (SemaRef.getLangOpts().ObjC1) {
Douglas Gregorca45da02010-11-02 20:36:02 +0000999 if (isa<ObjCIvarDecl>(ND))
1000 return true;
Douglas Gregorca45da02010-11-02 20:36:02 +00001001 }
1002
Douglas Gregor791215b2009-09-21 20:51:25 +00001003 return ND->getIdentifierNamespace() & IDNS;
1004}
1005
Douglas Gregor01dfea02010-01-10 23:08:15 +00001006/// \brief Determines whether this given declaration will be found by
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001007/// ordinary name lookup but is not a type name.
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00001008bool ResultBuilder::IsOrdinaryNonTypeName(const NamedDecl *ND) const {
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001009 ND = cast<NamedDecl>(ND->getUnderlyingDecl());
1010 if (isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND))
1011 return false;
1012
1013 unsigned IDNS = Decl::IDNS_Ordinary;
David Blaikie4e4d0842012-03-11 07:00:24 +00001014 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregor9b30b262010-06-15 20:26:51 +00001015 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member;
David Blaikie4e4d0842012-03-11 07:00:24 +00001016 else if (SemaRef.getLangOpts().ObjC1) {
Douglas Gregorca45da02010-11-02 20:36:02 +00001017 if (isa<ObjCIvarDecl>(ND))
1018 return true;
Douglas Gregorca45da02010-11-02 20:36:02 +00001019 }
1020
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001021 return ND->getIdentifierNamespace() & IDNS;
1022}
1023
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00001024bool ResultBuilder::IsIntegralConstantValue(const NamedDecl *ND) const {
Douglas Gregorf9578432010-07-28 21:50:18 +00001025 if (!IsOrdinaryNonTypeName(ND))
1026 return 0;
1027
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00001028 if (const ValueDecl *VD = dyn_cast<ValueDecl>(ND->getUnderlyingDecl()))
Douglas Gregorf9578432010-07-28 21:50:18 +00001029 if (VD->getType()->isIntegralOrEnumerationType())
1030 return true;
1031
1032 return false;
1033}
1034
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001035/// \brief Determines whether this given declaration will be found by
Douglas Gregor01dfea02010-01-10 23:08:15 +00001036/// ordinary name lookup.
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00001037bool ResultBuilder::IsOrdinaryNonValueName(const NamedDecl *ND) const {
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001038 ND = cast<NamedDecl>(ND->getUnderlyingDecl());
1039
Douglas Gregor01dfea02010-01-10 23:08:15 +00001040 unsigned IDNS = Decl::IDNS_Ordinary;
David Blaikie4e4d0842012-03-11 07:00:24 +00001041 if (SemaRef.getLangOpts().CPlusPlus)
John McCall0d6b1642010-04-23 18:46:30 +00001042 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace;
Douglas Gregor01dfea02010-01-10 23:08:15 +00001043
1044 return (ND->getIdentifierNamespace() & IDNS) &&
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001045 !isa<ValueDecl>(ND) && !isa<FunctionTemplateDecl>(ND) &&
1046 !isa<ObjCPropertyDecl>(ND);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001047}
1048
Douglas Gregor86d9a522009-09-21 16:56:56 +00001049/// \brief Determines whether the given declaration is suitable as the
1050/// start of a C++ nested-name-specifier, e.g., a class or namespace.
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00001051bool ResultBuilder::IsNestedNameSpecifier(const NamedDecl *ND) const {
Douglas Gregor86d9a522009-09-21 16:56:56 +00001052 // Allow us to find class templates, too.
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00001053 if (const ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
Douglas Gregor86d9a522009-09-21 16:56:56 +00001054 ND = ClassTemplate->getTemplatedDecl();
1055
1056 return SemaRef.isAcceptableNestedNameSpecifier(ND);
1057}
1058
1059/// \brief Determines whether the given declaration is an enumeration.
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00001060bool ResultBuilder::IsEnum(const NamedDecl *ND) const {
Douglas Gregor86d9a522009-09-21 16:56:56 +00001061 return isa<EnumDecl>(ND);
1062}
1063
1064/// \brief Determines whether the given declaration is a class or struct.
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00001065bool ResultBuilder::IsClassOrStruct(const NamedDecl *ND) const {
Douglas Gregor86d9a522009-09-21 16:56:56 +00001066 // Allow us to find class templates, too.
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00001067 if (const ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
Douglas Gregor86d9a522009-09-21 16:56:56 +00001068 ND = ClassTemplate->getTemplatedDecl();
Joao Matos6666ed42012-08-31 18:45:21 +00001069
1070 // For purposes of this check, interfaces match too.
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00001071 if (const RecordDecl *RD = dyn_cast<RecordDecl>(ND))
Abramo Bagnara465d41b2010-05-11 21:36:43 +00001072 return RD->getTagKind() == TTK_Class ||
Joao Matos6666ed42012-08-31 18:45:21 +00001073 RD->getTagKind() == TTK_Struct ||
1074 RD->getTagKind() == TTK_Interface;
Douglas Gregor86d9a522009-09-21 16:56:56 +00001075
1076 return false;
1077}
1078
1079/// \brief Determines whether the given declaration is a union.
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00001080bool ResultBuilder::IsUnion(const NamedDecl *ND) const {
Douglas Gregor86d9a522009-09-21 16:56:56 +00001081 // Allow us to find class templates, too.
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00001082 if (const ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
Douglas Gregor86d9a522009-09-21 16:56:56 +00001083 ND = ClassTemplate->getTemplatedDecl();
1084
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00001085 if (const RecordDecl *RD = dyn_cast<RecordDecl>(ND))
Abramo Bagnara465d41b2010-05-11 21:36:43 +00001086 return RD->getTagKind() == TTK_Union;
Douglas Gregor86d9a522009-09-21 16:56:56 +00001087
1088 return false;
1089}
1090
1091/// \brief Determines whether the given declaration is a namespace.
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00001092bool ResultBuilder::IsNamespace(const NamedDecl *ND) const {
Douglas Gregor86d9a522009-09-21 16:56:56 +00001093 return isa<NamespaceDecl>(ND);
1094}
1095
1096/// \brief Determines whether the given declaration is a namespace or
1097/// namespace alias.
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00001098bool ResultBuilder::IsNamespaceOrAlias(const NamedDecl *ND) const {
Douglas Gregor86d9a522009-09-21 16:56:56 +00001099 return isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND);
1100}
1101
Douglas Gregor76282942009-12-11 17:31:05 +00001102/// \brief Determines whether the given declaration is a type.
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00001103bool ResultBuilder::IsType(const NamedDecl *ND) const {
1104 if (const UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(ND))
Douglas Gregord32b0222010-08-24 01:06:58 +00001105 ND = Using->getTargetDecl();
1106
1107 return isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND);
Douglas Gregor86d9a522009-09-21 16:56:56 +00001108}
1109
Douglas Gregor76282942009-12-11 17:31:05 +00001110/// \brief Determines which members of a class should be visible via
1111/// "." or "->". Only value declarations, nested name specifiers, and
1112/// using declarations thereof should show up.
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00001113bool ResultBuilder::IsMember(const NamedDecl *ND) const {
1114 if (const UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(ND))
Douglas Gregor76282942009-12-11 17:31:05 +00001115 ND = Using->getTargetDecl();
1116
Douglas Gregorce821962009-12-11 18:14:22 +00001117 return isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND) ||
1118 isa<ObjCPropertyDecl>(ND);
Douglas Gregoreb5758b2009-09-23 22:26:46 +00001119}
1120
Douglas Gregor8e254cf2010-05-27 23:06:34 +00001121static bool isObjCReceiverType(ASTContext &C, QualType T) {
1122 T = C.getCanonicalType(T);
1123 switch (T->getTypeClass()) {
1124 case Type::ObjCObject:
1125 case Type::ObjCInterface:
1126 case Type::ObjCObjectPointer:
1127 return true;
1128
1129 case Type::Builtin:
1130 switch (cast<BuiltinType>(T)->getKind()) {
1131 case BuiltinType::ObjCId:
1132 case BuiltinType::ObjCClass:
1133 case BuiltinType::ObjCSel:
1134 return true;
1135
1136 default:
1137 break;
1138 }
1139 return false;
1140
1141 default:
1142 break;
1143 }
1144
David Blaikie4e4d0842012-03-11 07:00:24 +00001145 if (!C.getLangOpts().CPlusPlus)
Douglas Gregor8e254cf2010-05-27 23:06:34 +00001146 return false;
1147
1148 // FIXME: We could perform more analysis here to determine whether a
1149 // particular class type has any conversions to Objective-C types. For now,
1150 // just accept all class types.
1151 return T->isDependentType() || T->isRecordType();
1152}
1153
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00001154bool ResultBuilder::IsObjCMessageReceiver(const NamedDecl *ND) const {
Douglas Gregor8e254cf2010-05-27 23:06:34 +00001155 QualType T = getDeclUsageType(SemaRef.Context, ND);
1156 if (T.isNull())
1157 return false;
1158
1159 T = SemaRef.Context.getBaseElementType(T);
1160 return isObjCReceiverType(SemaRef.Context, T);
1161}
1162
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00001163bool ResultBuilder::IsObjCMessageReceiverOrLambdaCapture(const NamedDecl *ND) const {
Douglas Gregor81f3bff2012-02-15 15:34:24 +00001164 if (IsObjCMessageReceiver(ND))
1165 return true;
1166
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00001167 const VarDecl *Var = dyn_cast<VarDecl>(ND);
Douglas Gregor81f3bff2012-02-15 15:34:24 +00001168 if (!Var)
1169 return false;
1170
1171 return Var->hasLocalStorage() && !Var->hasAttr<BlocksAttr>();
1172}
1173
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00001174bool ResultBuilder::IsObjCCollection(const NamedDecl *ND) const {
David Blaikie4e4d0842012-03-11 07:00:24 +00001175 if ((SemaRef.getLangOpts().CPlusPlus && !IsOrdinaryName(ND)) ||
1176 (!SemaRef.getLangOpts().CPlusPlus && !IsOrdinaryNonTypeName(ND)))
Douglas Gregorfb629412010-08-23 21:17:50 +00001177 return false;
1178
1179 QualType T = getDeclUsageType(SemaRef.Context, ND);
1180 if (T.isNull())
1181 return false;
1182
1183 T = SemaRef.Context.getBaseElementType(T);
1184 return T->isObjCObjectType() || T->isObjCObjectPointerType() ||
1185 T->isObjCIdType() ||
David Blaikie4e4d0842012-03-11 07:00:24 +00001186 (SemaRef.getLangOpts().CPlusPlus && T->isRecordType());
Douglas Gregorfb629412010-08-23 21:17:50 +00001187}
Douglas Gregor8e254cf2010-05-27 23:06:34 +00001188
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00001189bool ResultBuilder::IsImpossibleToSatisfy(const NamedDecl *ND) const {
Douglas Gregor52779fb2010-09-23 23:01:17 +00001190 return false;
1191}
1192
James Dennettde23c7e2012-06-17 05:33:25 +00001193/// \brief Determines whether the given declaration is an Objective-C
Douglas Gregor80f4f4c2010-01-14 16:08:12 +00001194/// instance variable.
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00001195bool ResultBuilder::IsObjCIvar(const NamedDecl *ND) const {
Douglas Gregor80f4f4c2010-01-14 16:08:12 +00001196 return isa<ObjCIvarDecl>(ND);
1197}
1198
Douglas Gregor1ca6ae82010-01-14 01:09:38 +00001199namespace {
1200 /// \brief Visible declaration consumer that adds a code-completion result
1201 /// for each visible declaration.
1202 class CodeCompletionDeclConsumer : public VisibleDeclConsumer {
1203 ResultBuilder &Results;
1204 DeclContext *CurContext;
1205
1206 public:
1207 CodeCompletionDeclConsumer(ResultBuilder &Results, DeclContext *CurContext)
1208 : Results(Results), CurContext(CurContext) { }
1209
Erik Verbruggend1205962011-10-06 07:27:49 +00001210 virtual void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx,
1211 bool InBaseClass) {
1212 bool Accessible = true;
Douglas Gregor17015ef2011-11-03 16:51:37 +00001213 if (Ctx)
1214 Accessible = Results.getSema().IsSimplyAccessible(ND, Ctx);
1215
Erik Verbruggend1205962011-10-06 07:27:49 +00001216 ResultBuilder::Result Result(ND, 0, false, Accessible);
1217 Results.AddResult(Result, CurContext, Hiding, InBaseClass);
Douglas Gregor1ca6ae82010-01-14 01:09:38 +00001218 }
1219 };
1220}
1221
Douglas Gregor86d9a522009-09-21 16:56:56 +00001222/// \brief Add type specifiers for the current language as keyword results.
Douglas Gregorbca403c2010-01-13 23:51:12 +00001223static void AddTypeSpecifierResults(const LangOptions &LangOpts,
Douglas Gregor86d9a522009-09-21 16:56:56 +00001224 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00001225 typedef CodeCompletionResult Result;
Douglas Gregor12e13132010-05-26 22:00:08 +00001226 Results.AddResult(Result("short", CCP_Type));
1227 Results.AddResult(Result("long", CCP_Type));
1228 Results.AddResult(Result("signed", CCP_Type));
1229 Results.AddResult(Result("unsigned", CCP_Type));
1230 Results.AddResult(Result("void", CCP_Type));
1231 Results.AddResult(Result("char", CCP_Type));
1232 Results.AddResult(Result("int", CCP_Type));
1233 Results.AddResult(Result("float", CCP_Type));
1234 Results.AddResult(Result("double", CCP_Type));
1235 Results.AddResult(Result("enum", CCP_Type));
1236 Results.AddResult(Result("struct", CCP_Type));
1237 Results.AddResult(Result("union", CCP_Type));
1238 Results.AddResult(Result("const", CCP_Type));
1239 Results.AddResult(Result("volatile", CCP_Type));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001240
Douglas Gregor86d9a522009-09-21 16:56:56 +00001241 if (LangOpts.C99) {
1242 // C99-specific
Douglas Gregor12e13132010-05-26 22:00:08 +00001243 Results.AddResult(Result("_Complex", CCP_Type));
1244 Results.AddResult(Result("_Imaginary", CCP_Type));
1245 Results.AddResult(Result("_Bool", CCP_Type));
1246 Results.AddResult(Result("restrict", CCP_Type));
Douglas Gregor86d9a522009-09-21 16:56:56 +00001247 }
1248
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00001249 CodeCompletionBuilder Builder(Results.getAllocator(),
1250 Results.getCodeCompletionTUInfo());
Douglas Gregor86d9a522009-09-21 16:56:56 +00001251 if (LangOpts.CPlusPlus) {
1252 // C++-specific
Douglas Gregorb05496d2010-09-20 21:11:48 +00001253 Results.AddResult(Result("bool", CCP_Type +
1254 (LangOpts.ObjC1? CCD_bool_in_ObjC : 0)));
Douglas Gregor12e13132010-05-26 22:00:08 +00001255 Results.AddResult(Result("class", CCP_Type));
1256 Results.AddResult(Result("wchar_t", CCP_Type));
Douglas Gregor86d9a522009-09-21 16:56:56 +00001257
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001258 // typename qualified-id
Douglas Gregor218937c2011-02-01 19:23:04 +00001259 Builder.AddTypedTextChunk("typename");
1260 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1261 Builder.AddPlaceholderChunk("qualifier");
1262 Builder.AddTextChunk("::");
1263 Builder.AddPlaceholderChunk("name");
1264 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregord8e8a582010-05-25 21:41:55 +00001265
Richard Smith80ad52f2013-01-02 11:42:31 +00001266 if (LangOpts.CPlusPlus11) {
Douglas Gregor12e13132010-05-26 22:00:08 +00001267 Results.AddResult(Result("auto", CCP_Type));
1268 Results.AddResult(Result("char16_t", CCP_Type));
1269 Results.AddResult(Result("char32_t", CCP_Type));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001270
Douglas Gregor218937c2011-02-01 19:23:04 +00001271 Builder.AddTypedTextChunk("decltype");
1272 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1273 Builder.AddPlaceholderChunk("expression");
1274 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1275 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor86d9a522009-09-21 16:56:56 +00001276 }
1277 }
1278
1279 // GNU extensions
1280 if (LangOpts.GNUMode) {
1281 // FIXME: Enable when we actually support decimal floating point.
Douglas Gregora4477812010-01-14 16:01:26 +00001282 // Results.AddResult(Result("_Decimal32"));
1283 // Results.AddResult(Result("_Decimal64"));
1284 // Results.AddResult(Result("_Decimal128"));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001285
Douglas Gregor218937c2011-02-01 19:23:04 +00001286 Builder.AddTypedTextChunk("typeof");
1287 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1288 Builder.AddPlaceholderChunk("expression");
1289 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001290
Douglas Gregor218937c2011-02-01 19:23:04 +00001291 Builder.AddTypedTextChunk("typeof");
1292 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1293 Builder.AddPlaceholderChunk("type");
1294 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1295 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor86d9a522009-09-21 16:56:56 +00001296 }
1297}
1298
John McCallf312b1e2010-08-26 23:41:50 +00001299static void AddStorageSpecifiers(Sema::ParserCompletionContext CCC,
Douglas Gregor01dfea02010-01-10 23:08:15 +00001300 const LangOptions &LangOpts,
Douglas Gregor01dfea02010-01-10 23:08:15 +00001301 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00001302 typedef CodeCompletionResult Result;
Douglas Gregor01dfea02010-01-10 23:08:15 +00001303 // Note: we don't suggest either "auto" or "register", because both
1304 // are pointless as storage specifiers. Elsewhere, we suggest "auto"
1305 // in C++0x as a type specifier.
Douglas Gregora4477812010-01-14 16:01:26 +00001306 Results.AddResult(Result("extern"));
1307 Results.AddResult(Result("static"));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001308}
1309
John McCallf312b1e2010-08-26 23:41:50 +00001310static void AddFunctionSpecifiers(Sema::ParserCompletionContext CCC,
Douglas Gregor01dfea02010-01-10 23:08:15 +00001311 const LangOptions &LangOpts,
Douglas Gregor01dfea02010-01-10 23:08:15 +00001312 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00001313 typedef CodeCompletionResult Result;
Douglas Gregor01dfea02010-01-10 23:08:15 +00001314 switch (CCC) {
John McCallf312b1e2010-08-26 23:41:50 +00001315 case Sema::PCC_Class:
1316 case Sema::PCC_MemberTemplate:
Douglas Gregor01dfea02010-01-10 23:08:15 +00001317 if (LangOpts.CPlusPlus) {
Douglas Gregora4477812010-01-14 16:01:26 +00001318 Results.AddResult(Result("explicit"));
1319 Results.AddResult(Result("friend"));
1320 Results.AddResult(Result("mutable"));
1321 Results.AddResult(Result("virtual"));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001322 }
1323 // Fall through
1324
John McCallf312b1e2010-08-26 23:41:50 +00001325 case Sema::PCC_ObjCInterface:
1326 case Sema::PCC_ObjCImplementation:
1327 case Sema::PCC_Namespace:
1328 case Sema::PCC_Template:
Douglas Gregor01dfea02010-01-10 23:08:15 +00001329 if (LangOpts.CPlusPlus || LangOpts.C99)
Douglas Gregora4477812010-01-14 16:01:26 +00001330 Results.AddResult(Result("inline"));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001331 break;
1332
John McCallf312b1e2010-08-26 23:41:50 +00001333 case Sema::PCC_ObjCInstanceVariableList:
1334 case Sema::PCC_Expression:
1335 case Sema::PCC_Statement:
1336 case Sema::PCC_ForInit:
1337 case Sema::PCC_Condition:
1338 case Sema::PCC_RecoveryInFunction:
1339 case Sema::PCC_Type:
Douglas Gregor02688102010-09-14 23:59:36 +00001340 case Sema::PCC_ParenthesizedExpression:
Douglas Gregor68e3c2e2011-02-15 20:33:25 +00001341 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregor01dfea02010-01-10 23:08:15 +00001342 break;
1343 }
1344}
1345
Douglas Gregorbca403c2010-01-13 23:51:12 +00001346static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt);
1347static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt);
1348static void AddObjCVisibilityResults(const LangOptions &LangOpts,
Douglas Gregorc38c3e12010-01-13 21:54:15 +00001349 ResultBuilder &Results,
1350 bool NeedAt);
Douglas Gregorbca403c2010-01-13 23:51:12 +00001351static void AddObjCImplementationResults(const LangOptions &LangOpts,
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001352 ResultBuilder &Results,
1353 bool NeedAt);
Douglas Gregorbca403c2010-01-13 23:51:12 +00001354static void AddObjCInterfaceResults(const LangOptions &LangOpts,
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001355 ResultBuilder &Results,
1356 bool NeedAt);
Douglas Gregorbca403c2010-01-13 23:51:12 +00001357static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001358
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001359static void AddTypedefResult(ResultBuilder &Results) {
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00001360 CodeCompletionBuilder Builder(Results.getAllocator(),
1361 Results.getCodeCompletionTUInfo());
Douglas Gregor218937c2011-02-01 19:23:04 +00001362 Builder.AddTypedTextChunk("typedef");
1363 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1364 Builder.AddPlaceholderChunk("type");
1365 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1366 Builder.AddPlaceholderChunk("name");
1367 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001368}
1369
John McCallf312b1e2010-08-26 23:41:50 +00001370static bool WantTypesInContext(Sema::ParserCompletionContext CCC,
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001371 const LangOptions &LangOpts) {
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001372 switch (CCC) {
John McCallf312b1e2010-08-26 23:41:50 +00001373 case Sema::PCC_Namespace:
1374 case Sema::PCC_Class:
1375 case Sema::PCC_ObjCInstanceVariableList:
1376 case Sema::PCC_Template:
1377 case Sema::PCC_MemberTemplate:
1378 case Sema::PCC_Statement:
1379 case Sema::PCC_RecoveryInFunction:
1380 case Sema::PCC_Type:
Douglas Gregor02688102010-09-14 23:59:36 +00001381 case Sema::PCC_ParenthesizedExpression:
Douglas Gregor68e3c2e2011-02-15 20:33:25 +00001382 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001383 return true;
1384
John McCallf312b1e2010-08-26 23:41:50 +00001385 case Sema::PCC_Expression:
1386 case Sema::PCC_Condition:
Douglas Gregor02688102010-09-14 23:59:36 +00001387 return LangOpts.CPlusPlus;
1388
1389 case Sema::PCC_ObjCInterface:
1390 case Sema::PCC_ObjCImplementation:
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001391 return false;
1392
John McCallf312b1e2010-08-26 23:41:50 +00001393 case Sema::PCC_ForInit:
Douglas Gregor02688102010-09-14 23:59:36 +00001394 return LangOpts.CPlusPlus || LangOpts.ObjC1 || LangOpts.C99;
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001395 }
David Blaikie7530c032012-01-17 06:56:22 +00001396
1397 llvm_unreachable("Invalid ParserCompletionContext!");
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001398}
1399
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00001400static PrintingPolicy getCompletionPrintingPolicy(const ASTContext &Context,
1401 const Preprocessor &PP) {
1402 PrintingPolicy Policy = Sema::getPrintingPolicy(Context, PP);
Douglas Gregor8ca72082011-10-18 21:20:17 +00001403 Policy.AnonymousTagLocations = false;
1404 Policy.SuppressStrongLifetime = true;
Douglas Gregor25270b62011-11-03 00:16:13 +00001405 Policy.SuppressUnwrittenScope = true;
Douglas Gregor8ca72082011-10-18 21:20:17 +00001406 return Policy;
1407}
1408
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00001409/// \brief Retrieve a printing policy suitable for code completion.
1410static PrintingPolicy getCompletionPrintingPolicy(Sema &S) {
1411 return getCompletionPrintingPolicy(S.Context, S.PP);
1412}
1413
Douglas Gregor8ca72082011-10-18 21:20:17 +00001414/// \brief Retrieve the string representation of the given type as a string
1415/// that has the appropriate lifetime for code completion.
1416///
1417/// This routine provides a fast path where we provide constant strings for
1418/// common type names.
1419static const char *GetCompletionTypeString(QualType T,
1420 ASTContext &Context,
1421 const PrintingPolicy &Policy,
1422 CodeCompletionAllocator &Allocator) {
1423 if (!T.getLocalQualifiers()) {
1424 // Built-in type names are constant strings.
1425 if (const BuiltinType *BT = dyn_cast<BuiltinType>(T))
Argyrios Kyrtzidis27a00972012-05-05 04:20:28 +00001426 return BT->getNameAsCString(Policy);
Douglas Gregor8ca72082011-10-18 21:20:17 +00001427
1428 // Anonymous tag types are constant strings.
1429 if (const TagType *TagT = dyn_cast<TagType>(T))
1430 if (TagDecl *Tag = TagT->getDecl())
1431 if (!Tag->getIdentifier() && !Tag->getTypedefNameForAnonDecl()) {
1432 switch (Tag->getTagKind()) {
1433 case TTK_Struct: return "struct <anonymous>";
Joao Matos6666ed42012-08-31 18:45:21 +00001434 case TTK_Interface: return "__interface <anonymous>";
1435 case TTK_Class: return "class <anonymous>";
Douglas Gregor8ca72082011-10-18 21:20:17 +00001436 case TTK_Union: return "union <anonymous>";
1437 case TTK_Enum: return "enum <anonymous>";
1438 }
1439 }
1440 }
1441
1442 // Slow path: format the type as a string.
1443 std::string Result;
1444 T.getAsStringInternal(Result, Policy);
1445 return Allocator.CopyString(Result);
1446}
1447
Douglas Gregor81f3bff2012-02-15 15:34:24 +00001448/// \brief Add a completion for "this", if we're in a member function.
1449static void addThisCompletion(Sema &S, ResultBuilder &Results) {
1450 QualType ThisTy = S.getCurrentThisType();
1451 if (ThisTy.isNull())
1452 return;
1453
1454 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00001455 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Douglas Gregor81f3bff2012-02-15 15:34:24 +00001456 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
1457 Builder.AddResultTypeChunk(GetCompletionTypeString(ThisTy,
1458 S.Context,
1459 Policy,
1460 Allocator));
1461 Builder.AddTypedTextChunk("this");
Joao Matos6666ed42012-08-31 18:45:21 +00001462 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
Douglas Gregor81f3bff2012-02-15 15:34:24 +00001463}
1464
Douglas Gregor01dfea02010-01-10 23:08:15 +00001465/// \brief Add language constructs that show up for "ordinary" names.
John McCallf312b1e2010-08-26 23:41:50 +00001466static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
Douglas Gregor01dfea02010-01-10 23:08:15 +00001467 Scope *S,
1468 Sema &SemaRef,
Douglas Gregor01dfea02010-01-10 23:08:15 +00001469 ResultBuilder &Results) {
Douglas Gregor8ca72082011-10-18 21:20:17 +00001470 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00001471 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Douglas Gregor8ca72082011-10-18 21:20:17 +00001472 PrintingPolicy Policy = getCompletionPrintingPolicy(SemaRef);
Douglas Gregor218937c2011-02-01 19:23:04 +00001473
John McCall0a2c5e22010-08-25 06:19:51 +00001474 typedef CodeCompletionResult Result;
Douglas Gregor01dfea02010-01-10 23:08:15 +00001475 switch (CCC) {
John McCallf312b1e2010-08-26 23:41:50 +00001476 case Sema::PCC_Namespace:
David Blaikie4e4d0842012-03-11 07:00:24 +00001477 if (SemaRef.getLangOpts().CPlusPlus) {
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001478 if (Results.includeCodePatterns()) {
1479 // namespace <identifier> { declarations }
Douglas Gregor218937c2011-02-01 19:23:04 +00001480 Builder.AddTypedTextChunk("namespace");
1481 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1482 Builder.AddPlaceholderChunk("identifier");
1483 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1484 Builder.AddPlaceholderChunk("declarations");
1485 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1486 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1487 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001488 }
1489
Douglas Gregor01dfea02010-01-10 23:08:15 +00001490 // namespace identifier = identifier ;
Douglas Gregor218937c2011-02-01 19:23:04 +00001491 Builder.AddTypedTextChunk("namespace");
1492 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1493 Builder.AddPlaceholderChunk("name");
1494 Builder.AddChunk(CodeCompletionString::CK_Equal);
1495 Builder.AddPlaceholderChunk("namespace");
1496 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001497
1498 // Using directives
Douglas Gregor218937c2011-02-01 19:23:04 +00001499 Builder.AddTypedTextChunk("using");
1500 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1501 Builder.AddTextChunk("namespace");
1502 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1503 Builder.AddPlaceholderChunk("identifier");
1504 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001505
1506 // asm(string-literal)
Douglas Gregor218937c2011-02-01 19:23:04 +00001507 Builder.AddTypedTextChunk("asm");
1508 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1509 Builder.AddPlaceholderChunk("string-literal");
1510 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1511 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001512
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001513 if (Results.includeCodePatterns()) {
1514 // Explicit template instantiation
Douglas Gregor218937c2011-02-01 19:23:04 +00001515 Builder.AddTypedTextChunk("template");
1516 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1517 Builder.AddPlaceholderChunk("declaration");
1518 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001519 }
Douglas Gregor01dfea02010-01-10 23:08:15 +00001520 }
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001521
David Blaikie4e4d0842012-03-11 07:00:24 +00001522 if (SemaRef.getLangOpts().ObjC1)
Douglas Gregorbca403c2010-01-13 23:51:12 +00001523 AddObjCTopLevelResults(Results, true);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001524
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001525 AddTypedefResult(Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001526 // Fall through
1527
John McCallf312b1e2010-08-26 23:41:50 +00001528 case Sema::PCC_Class:
David Blaikie4e4d0842012-03-11 07:00:24 +00001529 if (SemaRef.getLangOpts().CPlusPlus) {
Douglas Gregor01dfea02010-01-10 23:08:15 +00001530 // Using declaration
Douglas Gregor218937c2011-02-01 19:23:04 +00001531 Builder.AddTypedTextChunk("using");
1532 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1533 Builder.AddPlaceholderChunk("qualifier");
1534 Builder.AddTextChunk("::");
1535 Builder.AddPlaceholderChunk("name");
1536 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001537
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001538 // using typename qualifier::name (only in a dependent context)
Douglas Gregor01dfea02010-01-10 23:08:15 +00001539 if (SemaRef.CurContext->isDependentContext()) {
Douglas Gregor218937c2011-02-01 19:23:04 +00001540 Builder.AddTypedTextChunk("using");
1541 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1542 Builder.AddTextChunk("typename");
1543 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1544 Builder.AddPlaceholderChunk("qualifier");
1545 Builder.AddTextChunk("::");
1546 Builder.AddPlaceholderChunk("name");
1547 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001548 }
1549
John McCallf312b1e2010-08-26 23:41:50 +00001550 if (CCC == Sema::PCC_Class) {
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001551 AddTypedefResult(Results);
1552
Douglas Gregor01dfea02010-01-10 23:08:15 +00001553 // public:
Douglas Gregor218937c2011-02-01 19:23:04 +00001554 Builder.AddTypedTextChunk("public");
Douglas Gregor10ccf122012-04-10 17:56:28 +00001555 if (Results.includeCodePatterns())
1556 Builder.AddChunk(CodeCompletionString::CK_Colon);
Douglas Gregor218937c2011-02-01 19:23:04 +00001557 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001558
1559 // protected:
Douglas Gregor218937c2011-02-01 19:23:04 +00001560 Builder.AddTypedTextChunk("protected");
Douglas Gregor10ccf122012-04-10 17:56:28 +00001561 if (Results.includeCodePatterns())
1562 Builder.AddChunk(CodeCompletionString::CK_Colon);
Douglas Gregor218937c2011-02-01 19:23:04 +00001563 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001564
1565 // private:
Douglas Gregor218937c2011-02-01 19:23:04 +00001566 Builder.AddTypedTextChunk("private");
Douglas Gregor10ccf122012-04-10 17:56:28 +00001567 if (Results.includeCodePatterns())
1568 Builder.AddChunk(CodeCompletionString::CK_Colon);
Douglas Gregor218937c2011-02-01 19:23:04 +00001569 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001570 }
1571 }
1572 // Fall through
1573
John McCallf312b1e2010-08-26 23:41:50 +00001574 case Sema::PCC_Template:
1575 case Sema::PCC_MemberTemplate:
David Blaikie4e4d0842012-03-11 07:00:24 +00001576 if (SemaRef.getLangOpts().CPlusPlus && Results.includeCodePatterns()) {
Douglas Gregor01dfea02010-01-10 23:08:15 +00001577 // template < parameters >
Douglas Gregor218937c2011-02-01 19:23:04 +00001578 Builder.AddTypedTextChunk("template");
1579 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1580 Builder.AddPlaceholderChunk("parameters");
1581 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1582 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001583 }
1584
David Blaikie4e4d0842012-03-11 07:00:24 +00001585 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
1586 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001587 break;
1588
John McCallf312b1e2010-08-26 23:41:50 +00001589 case Sema::PCC_ObjCInterface:
David Blaikie4e4d0842012-03-11 07:00:24 +00001590 AddObjCInterfaceResults(SemaRef.getLangOpts(), Results, true);
1591 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
1592 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001593 break;
1594
John McCallf312b1e2010-08-26 23:41:50 +00001595 case Sema::PCC_ObjCImplementation:
David Blaikie4e4d0842012-03-11 07:00:24 +00001596 AddObjCImplementationResults(SemaRef.getLangOpts(), Results, true);
1597 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
1598 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001599 break;
1600
John McCallf312b1e2010-08-26 23:41:50 +00001601 case Sema::PCC_ObjCInstanceVariableList:
David Blaikie4e4d0842012-03-11 07:00:24 +00001602 AddObjCVisibilityResults(SemaRef.getLangOpts(), Results, true);
Douglas Gregorc38c3e12010-01-13 21:54:15 +00001603 break;
1604
John McCallf312b1e2010-08-26 23:41:50 +00001605 case Sema::PCC_RecoveryInFunction:
1606 case Sema::PCC_Statement: {
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001607 AddTypedefResult(Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001608
David Blaikie4e4d0842012-03-11 07:00:24 +00001609 if (SemaRef.getLangOpts().CPlusPlus && Results.includeCodePatterns() &&
1610 SemaRef.getLangOpts().CXXExceptions) {
Douglas Gregor218937c2011-02-01 19:23:04 +00001611 Builder.AddTypedTextChunk("try");
1612 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1613 Builder.AddPlaceholderChunk("statements");
1614 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1615 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1616 Builder.AddTextChunk("catch");
1617 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1618 Builder.AddPlaceholderChunk("declaration");
1619 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1620 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1621 Builder.AddPlaceholderChunk("statements");
1622 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1623 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1624 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001625 }
David Blaikie4e4d0842012-03-11 07:00:24 +00001626 if (SemaRef.getLangOpts().ObjC1)
Douglas Gregorbca403c2010-01-13 23:51:12 +00001627 AddObjCStatementResults(Results, true);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001628
Douglas Gregord8e8a582010-05-25 21:41:55 +00001629 if (Results.includeCodePatterns()) {
1630 // if (condition) { statements }
Douglas Gregor218937c2011-02-01 19:23:04 +00001631 Builder.AddTypedTextChunk("if");
1632 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikie4e4d0842012-03-11 07:00:24 +00001633 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregor218937c2011-02-01 19:23:04 +00001634 Builder.AddPlaceholderChunk("condition");
Douglas Gregord8e8a582010-05-25 21:41:55 +00001635 else
Douglas Gregor218937c2011-02-01 19:23:04 +00001636 Builder.AddPlaceholderChunk("expression");
1637 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1638 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1639 Builder.AddPlaceholderChunk("statements");
1640 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1641 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1642 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001643
Douglas Gregord8e8a582010-05-25 21:41:55 +00001644 // switch (condition) { }
Douglas Gregor218937c2011-02-01 19:23:04 +00001645 Builder.AddTypedTextChunk("switch");
1646 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikie4e4d0842012-03-11 07:00:24 +00001647 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregor218937c2011-02-01 19:23:04 +00001648 Builder.AddPlaceholderChunk("condition");
Douglas Gregord8e8a582010-05-25 21:41:55 +00001649 else
Douglas Gregor218937c2011-02-01 19:23:04 +00001650 Builder.AddPlaceholderChunk("expression");
1651 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1652 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1653 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1654 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1655 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregord8e8a582010-05-25 21:41:55 +00001656 }
1657
Douglas Gregor01dfea02010-01-10 23:08:15 +00001658 // Switch-specific statements.
John McCall781472f2010-08-25 08:40:02 +00001659 if (!SemaRef.getCurFunction()->SwitchStack.empty()) {
Douglas Gregor01dfea02010-01-10 23:08:15 +00001660 // case expression:
Douglas Gregor218937c2011-02-01 19:23:04 +00001661 Builder.AddTypedTextChunk("case");
1662 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1663 Builder.AddPlaceholderChunk("expression");
1664 Builder.AddChunk(CodeCompletionString::CK_Colon);
1665 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001666
1667 // default:
Douglas Gregor218937c2011-02-01 19:23:04 +00001668 Builder.AddTypedTextChunk("default");
1669 Builder.AddChunk(CodeCompletionString::CK_Colon);
1670 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001671 }
1672
Douglas Gregord8e8a582010-05-25 21:41:55 +00001673 if (Results.includeCodePatterns()) {
1674 /// while (condition) { statements }
Douglas Gregor218937c2011-02-01 19:23:04 +00001675 Builder.AddTypedTextChunk("while");
1676 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikie4e4d0842012-03-11 07:00:24 +00001677 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregor218937c2011-02-01 19:23:04 +00001678 Builder.AddPlaceholderChunk("condition");
Douglas Gregord8e8a582010-05-25 21:41:55 +00001679 else
Douglas Gregor218937c2011-02-01 19:23:04 +00001680 Builder.AddPlaceholderChunk("expression");
1681 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1682 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1683 Builder.AddPlaceholderChunk("statements");
1684 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1685 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1686 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregord8e8a582010-05-25 21:41:55 +00001687
1688 // do { statements } while ( expression );
Douglas Gregor218937c2011-02-01 19:23:04 +00001689 Builder.AddTypedTextChunk("do");
1690 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1691 Builder.AddPlaceholderChunk("statements");
1692 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1693 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1694 Builder.AddTextChunk("while");
1695 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1696 Builder.AddPlaceholderChunk("expression");
1697 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1698 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001699
Douglas Gregord8e8a582010-05-25 21:41:55 +00001700 // for ( for-init-statement ; condition ; expression ) { statements }
Douglas Gregor218937c2011-02-01 19:23:04 +00001701 Builder.AddTypedTextChunk("for");
1702 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikie4e4d0842012-03-11 07:00:24 +00001703 if (SemaRef.getLangOpts().CPlusPlus || SemaRef.getLangOpts().C99)
Douglas Gregor218937c2011-02-01 19:23:04 +00001704 Builder.AddPlaceholderChunk("init-statement");
Douglas Gregord8e8a582010-05-25 21:41:55 +00001705 else
Douglas Gregor218937c2011-02-01 19:23:04 +00001706 Builder.AddPlaceholderChunk("init-expression");
1707 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
1708 Builder.AddPlaceholderChunk("condition");
1709 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
1710 Builder.AddPlaceholderChunk("inc-expression");
1711 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1712 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1713 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1714 Builder.AddPlaceholderChunk("statements");
1715 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1716 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1717 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregord8e8a582010-05-25 21:41:55 +00001718 }
Douglas Gregor01dfea02010-01-10 23:08:15 +00001719
1720 if (S->getContinueParent()) {
1721 // continue ;
Douglas Gregor218937c2011-02-01 19:23:04 +00001722 Builder.AddTypedTextChunk("continue");
1723 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001724 }
1725
1726 if (S->getBreakParent()) {
1727 // break ;
Douglas Gregor218937c2011-02-01 19:23:04 +00001728 Builder.AddTypedTextChunk("break");
1729 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001730 }
1731
1732 // "return expression ;" or "return ;", depending on whether we
1733 // know the function is void or not.
1734 bool isVoid = false;
1735 if (FunctionDecl *Function = dyn_cast<FunctionDecl>(SemaRef.CurContext))
1736 isVoid = Function->getResultType()->isVoidType();
1737 else if (ObjCMethodDecl *Method
1738 = dyn_cast<ObjCMethodDecl>(SemaRef.CurContext))
1739 isVoid = Method->getResultType()->isVoidType();
Douglas Gregor9ea9bdb2010-03-01 23:15:13 +00001740 else if (SemaRef.getCurBlock() &&
1741 !SemaRef.getCurBlock()->ReturnType.isNull())
1742 isVoid = SemaRef.getCurBlock()->ReturnType->isVoidType();
Douglas Gregor218937c2011-02-01 19:23:04 +00001743 Builder.AddTypedTextChunk("return");
Douglas Gregor93298002010-02-18 04:06:48 +00001744 if (!isVoid) {
Douglas Gregor218937c2011-02-01 19:23:04 +00001745 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1746 Builder.AddPlaceholderChunk("expression");
Douglas Gregor93298002010-02-18 04:06:48 +00001747 }
Douglas Gregor218937c2011-02-01 19:23:04 +00001748 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001749
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001750 // goto identifier ;
Douglas Gregor218937c2011-02-01 19:23:04 +00001751 Builder.AddTypedTextChunk("goto");
1752 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1753 Builder.AddPlaceholderChunk("label");
1754 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001755
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001756 // Using directives
Douglas Gregor218937c2011-02-01 19:23:04 +00001757 Builder.AddTypedTextChunk("using");
1758 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1759 Builder.AddTextChunk("namespace");
1760 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1761 Builder.AddPlaceholderChunk("identifier");
1762 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001763 }
1764
1765 // Fall through (for statement expressions).
John McCallf312b1e2010-08-26 23:41:50 +00001766 case Sema::PCC_ForInit:
1767 case Sema::PCC_Condition:
David Blaikie4e4d0842012-03-11 07:00:24 +00001768 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001769 // Fall through: conditions and statements can have expressions.
1770
Douglas Gregor02688102010-09-14 23:59:36 +00001771 case Sema::PCC_ParenthesizedExpression:
David Blaikie4e4d0842012-03-11 07:00:24 +00001772 if (SemaRef.getLangOpts().ObjCAutoRefCount &&
John McCallf85e1932011-06-15 23:02:42 +00001773 CCC == Sema::PCC_ParenthesizedExpression) {
1774 // (__bridge <type>)<expression>
1775 Builder.AddTypedTextChunk("__bridge");
1776 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1777 Builder.AddPlaceholderChunk("type");
1778 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1779 Builder.AddPlaceholderChunk("expression");
1780 Results.AddResult(Result(Builder.TakeString()));
1781
1782 // (__bridge_transfer <Objective-C type>)<expression>
1783 Builder.AddTypedTextChunk("__bridge_transfer");
1784 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1785 Builder.AddPlaceholderChunk("Objective-C type");
1786 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1787 Builder.AddPlaceholderChunk("expression");
1788 Results.AddResult(Result(Builder.TakeString()));
1789
1790 // (__bridge_retained <CF type>)<expression>
1791 Builder.AddTypedTextChunk("__bridge_retained");
1792 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1793 Builder.AddPlaceholderChunk("CF type");
1794 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1795 Builder.AddPlaceholderChunk("expression");
1796 Results.AddResult(Result(Builder.TakeString()));
1797 }
1798 // Fall through
1799
John McCallf312b1e2010-08-26 23:41:50 +00001800 case Sema::PCC_Expression: {
David Blaikie4e4d0842012-03-11 07:00:24 +00001801 if (SemaRef.getLangOpts().CPlusPlus) {
Douglas Gregor01dfea02010-01-10 23:08:15 +00001802 // 'this', if we're in a non-static member function.
Douglas Gregor81f3bff2012-02-15 15:34:24 +00001803 addThisCompletion(SemaRef, Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001804
Douglas Gregor8ca72082011-10-18 21:20:17 +00001805 // true
1806 Builder.AddResultTypeChunk("bool");
1807 Builder.AddTypedTextChunk("true");
1808 Results.AddResult(Result(Builder.TakeString()));
1809
1810 // false
1811 Builder.AddResultTypeChunk("bool");
1812 Builder.AddTypedTextChunk("false");
1813 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001814
David Blaikie4e4d0842012-03-11 07:00:24 +00001815 if (SemaRef.getLangOpts().RTTI) {
Douglas Gregorec3310a2011-04-12 02:47:21 +00001816 // dynamic_cast < type-id > ( expression )
1817 Builder.AddTypedTextChunk("dynamic_cast");
1818 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1819 Builder.AddPlaceholderChunk("type");
1820 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1821 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1822 Builder.AddPlaceholderChunk("expression");
1823 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1824 Results.AddResult(Result(Builder.TakeString()));
1825 }
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001826
1827 // static_cast < type-id > ( expression )
Douglas Gregor218937c2011-02-01 19:23:04 +00001828 Builder.AddTypedTextChunk("static_cast");
1829 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1830 Builder.AddPlaceholderChunk("type");
1831 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1832 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1833 Builder.AddPlaceholderChunk("expression");
1834 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1835 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001836
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001837 // reinterpret_cast < type-id > ( expression )
Douglas Gregor218937c2011-02-01 19:23:04 +00001838 Builder.AddTypedTextChunk("reinterpret_cast");
1839 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1840 Builder.AddPlaceholderChunk("type");
1841 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1842 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1843 Builder.AddPlaceholderChunk("expression");
1844 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1845 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001846
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001847 // const_cast < type-id > ( expression )
Douglas Gregor218937c2011-02-01 19:23:04 +00001848 Builder.AddTypedTextChunk("const_cast");
1849 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1850 Builder.AddPlaceholderChunk("type");
1851 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1852 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1853 Builder.AddPlaceholderChunk("expression");
1854 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1855 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001856
David Blaikie4e4d0842012-03-11 07:00:24 +00001857 if (SemaRef.getLangOpts().RTTI) {
Douglas Gregorec3310a2011-04-12 02:47:21 +00001858 // typeid ( expression-or-type )
Douglas Gregor8ca72082011-10-18 21:20:17 +00001859 Builder.AddResultTypeChunk("std::type_info");
Douglas Gregorec3310a2011-04-12 02:47:21 +00001860 Builder.AddTypedTextChunk("typeid");
1861 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1862 Builder.AddPlaceholderChunk("expression-or-type");
1863 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1864 Results.AddResult(Result(Builder.TakeString()));
1865 }
1866
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001867 // new T ( ... )
Douglas Gregor218937c2011-02-01 19:23:04 +00001868 Builder.AddTypedTextChunk("new");
1869 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1870 Builder.AddPlaceholderChunk("type");
1871 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1872 Builder.AddPlaceholderChunk("expressions");
1873 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1874 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001875
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001876 // new T [ ] ( ... )
Douglas Gregor218937c2011-02-01 19:23:04 +00001877 Builder.AddTypedTextChunk("new");
1878 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1879 Builder.AddPlaceholderChunk("type");
1880 Builder.AddChunk(CodeCompletionString::CK_LeftBracket);
1881 Builder.AddPlaceholderChunk("size");
1882 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
1883 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1884 Builder.AddPlaceholderChunk("expressions");
1885 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1886 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001887
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001888 // delete expression
Douglas Gregor8ca72082011-10-18 21:20:17 +00001889 Builder.AddResultTypeChunk("void");
Douglas Gregor218937c2011-02-01 19:23:04 +00001890 Builder.AddTypedTextChunk("delete");
1891 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1892 Builder.AddPlaceholderChunk("expression");
1893 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001894
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001895 // delete [] expression
Douglas Gregor8ca72082011-10-18 21:20:17 +00001896 Builder.AddResultTypeChunk("void");
Douglas Gregor218937c2011-02-01 19:23:04 +00001897 Builder.AddTypedTextChunk("delete");
1898 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1899 Builder.AddChunk(CodeCompletionString::CK_LeftBracket);
1900 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
1901 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1902 Builder.AddPlaceholderChunk("expression");
1903 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001904
David Blaikie4e4d0842012-03-11 07:00:24 +00001905 if (SemaRef.getLangOpts().CXXExceptions) {
Douglas Gregorec3310a2011-04-12 02:47:21 +00001906 // throw expression
Douglas Gregor8ca72082011-10-18 21:20:17 +00001907 Builder.AddResultTypeChunk("void");
Douglas Gregorec3310a2011-04-12 02:47:21 +00001908 Builder.AddTypedTextChunk("throw");
1909 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1910 Builder.AddPlaceholderChunk("expression");
1911 Results.AddResult(Result(Builder.TakeString()));
1912 }
Douglas Gregora50216c2011-10-18 16:29:03 +00001913
Douglas Gregor12e13132010-05-26 22:00:08 +00001914 // FIXME: Rethrow?
Douglas Gregora50216c2011-10-18 16:29:03 +00001915
Richard Smith80ad52f2013-01-02 11:42:31 +00001916 if (SemaRef.getLangOpts().CPlusPlus11) {
Douglas Gregora50216c2011-10-18 16:29:03 +00001917 // nullptr
Douglas Gregor8ca72082011-10-18 21:20:17 +00001918 Builder.AddResultTypeChunk("std::nullptr_t");
Douglas Gregora50216c2011-10-18 16:29:03 +00001919 Builder.AddTypedTextChunk("nullptr");
1920 Results.AddResult(Result(Builder.TakeString()));
1921
1922 // alignof
Douglas Gregor8ca72082011-10-18 21:20:17 +00001923 Builder.AddResultTypeChunk("size_t");
Douglas Gregora50216c2011-10-18 16:29:03 +00001924 Builder.AddTypedTextChunk("alignof");
1925 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1926 Builder.AddPlaceholderChunk("type");
1927 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1928 Results.AddResult(Result(Builder.TakeString()));
1929
1930 // noexcept
Douglas Gregor8ca72082011-10-18 21:20:17 +00001931 Builder.AddResultTypeChunk("bool");
Douglas Gregora50216c2011-10-18 16:29:03 +00001932 Builder.AddTypedTextChunk("noexcept");
1933 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1934 Builder.AddPlaceholderChunk("expression");
1935 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1936 Results.AddResult(Result(Builder.TakeString()));
1937
1938 // sizeof... expression
Douglas Gregor8ca72082011-10-18 21:20:17 +00001939 Builder.AddResultTypeChunk("size_t");
Douglas Gregora50216c2011-10-18 16:29:03 +00001940 Builder.AddTypedTextChunk("sizeof...");
1941 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1942 Builder.AddPlaceholderChunk("parameter-pack");
1943 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1944 Results.AddResult(Result(Builder.TakeString()));
1945 }
Douglas Gregor01dfea02010-01-10 23:08:15 +00001946 }
1947
David Blaikie4e4d0842012-03-11 07:00:24 +00001948 if (SemaRef.getLangOpts().ObjC1) {
Douglas Gregor01dfea02010-01-10 23:08:15 +00001949 // Add "super", if we're in an Objective-C class with a superclass.
Ted Kremenek681e2562010-05-31 21:43:10 +00001950 if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl()) {
1951 // The interface can be NULL.
1952 if (ObjCInterfaceDecl *ID = Method->getClassInterface())
Douglas Gregor8ca72082011-10-18 21:20:17 +00001953 if (ID->getSuperClass()) {
1954 std::string SuperType;
1955 SuperType = ID->getSuperClass()->getNameAsString();
1956 if (Method->isInstanceMethod())
1957 SuperType += " *";
1958
1959 Builder.AddResultTypeChunk(Allocator.CopyString(SuperType));
1960 Builder.AddTypedTextChunk("super");
1961 Results.AddResult(Result(Builder.TakeString()));
1962 }
Ted Kremenek681e2562010-05-31 21:43:10 +00001963 }
1964
Douglas Gregorbca403c2010-01-13 23:51:12 +00001965 AddObjCExpressionResults(Results, true);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001966 }
1967
Jordan Rosef70a8862012-06-30 21:33:57 +00001968 if (SemaRef.getLangOpts().C11) {
1969 // _Alignof
1970 Builder.AddResultTypeChunk("size_t");
1971 if (SemaRef.getASTContext().Idents.get("alignof").hasMacroDefinition())
1972 Builder.AddTypedTextChunk("alignof");
1973 else
1974 Builder.AddTypedTextChunk("_Alignof");
1975 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1976 Builder.AddPlaceholderChunk("type");
1977 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1978 Results.AddResult(Result(Builder.TakeString()));
1979 }
1980
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001981 // sizeof expression
Douglas Gregor8ca72082011-10-18 21:20:17 +00001982 Builder.AddResultTypeChunk("size_t");
Douglas Gregor218937c2011-02-01 19:23:04 +00001983 Builder.AddTypedTextChunk("sizeof");
1984 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1985 Builder.AddPlaceholderChunk("expression-or-type");
1986 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1987 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001988 break;
1989 }
Douglas Gregord32b0222010-08-24 01:06:58 +00001990
John McCallf312b1e2010-08-26 23:41:50 +00001991 case Sema::PCC_Type:
Douglas Gregor68e3c2e2011-02-15 20:33:25 +00001992 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregord32b0222010-08-24 01:06:58 +00001993 break;
Douglas Gregor01dfea02010-01-10 23:08:15 +00001994 }
1995
David Blaikie4e4d0842012-03-11 07:00:24 +00001996 if (WantTypesInContext(CCC, SemaRef.getLangOpts()))
1997 AddTypeSpecifierResults(SemaRef.getLangOpts(), Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001998
David Blaikie4e4d0842012-03-11 07:00:24 +00001999 if (SemaRef.getLangOpts().CPlusPlus && CCC != Sema::PCC_Type)
Douglas Gregora4477812010-01-14 16:01:26 +00002000 Results.AddResult(Result("operator"));
Douglas Gregor01dfea02010-01-10 23:08:15 +00002001}
2002
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00002003/// \brief If the given declaration has an associated type, add it as a result
2004/// type chunk.
2005static void AddResultTypeChunk(ASTContext &Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00002006 const PrintingPolicy &Policy,
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00002007 const NamedDecl *ND,
Douglas Gregor218937c2011-02-01 19:23:04 +00002008 CodeCompletionBuilder &Result) {
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00002009 if (!ND)
2010 return;
Douglas Gregor6f942b22010-09-21 16:06:22 +00002011
2012 // Skip constructors and conversion functions, which have their return types
2013 // built into their names.
2014 if (isa<CXXConstructorDecl>(ND) || isa<CXXConversionDecl>(ND))
2015 return;
2016
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00002017 // Determine the type of the declaration (if it has a type).
Douglas Gregor6f942b22010-09-21 16:06:22 +00002018 QualType T;
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00002019 if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(ND))
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00002020 T = Function->getResultType();
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00002021 else if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND))
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00002022 T = Method->getResultType();
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00002023 else if (const FunctionTemplateDecl *FunTmpl =
2024 dyn_cast<FunctionTemplateDecl>(ND))
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00002025 T = FunTmpl->getTemplatedDecl()->getResultType();
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00002026 else if (const EnumConstantDecl *Enumerator = dyn_cast<EnumConstantDecl>(ND))
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00002027 T = Context.getTypeDeclType(cast<TypeDecl>(Enumerator->getDeclContext()));
2028 else if (isa<UnresolvedUsingValueDecl>(ND)) {
2029 /* Do nothing: ignore unresolved using declarations*/
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00002030 } else if (const ValueDecl *Value = dyn_cast<ValueDecl>(ND)) {
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00002031 T = Value->getType();
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00002032 } else if (const ObjCPropertyDecl *Property = dyn_cast<ObjCPropertyDecl>(ND))
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00002033 T = Property->getType();
2034
2035 if (T.isNull() || Context.hasSameType(T, Context.DependentTy))
2036 return;
2037
Douglas Gregor8987b232011-09-27 23:30:47 +00002038 Result.AddResultTypeChunk(GetCompletionTypeString(T, Context, Policy,
Douglas Gregora63f6de2011-02-01 21:15:40 +00002039 Result.getAllocator()));
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00002040}
2041
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00002042static void MaybeAddSentinel(ASTContext &Context,
2043 const NamedDecl *FunctionOrMethod,
Douglas Gregor218937c2011-02-01 19:23:04 +00002044 CodeCompletionBuilder &Result) {
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002045 if (SentinelAttr *Sentinel = FunctionOrMethod->getAttr<SentinelAttr>())
2046 if (Sentinel->getSentinel() == 0) {
David Blaikie4e4d0842012-03-11 07:00:24 +00002047 if (Context.getLangOpts().ObjC1 &&
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002048 Context.Idents.get("nil").hasMacroDefinition())
Douglas Gregor218937c2011-02-01 19:23:04 +00002049 Result.AddTextChunk(", nil");
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002050 else if (Context.Idents.get("NULL").hasMacroDefinition())
Douglas Gregor218937c2011-02-01 19:23:04 +00002051 Result.AddTextChunk(", NULL");
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002052 else
Douglas Gregor218937c2011-02-01 19:23:04 +00002053 Result.AddTextChunk(", (void*)0");
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002054 }
2055}
2056
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002057static std::string formatObjCParamQualifiers(unsigned ObjCQuals) {
2058 std::string Result;
2059 if (ObjCQuals & Decl::OBJC_TQ_In)
Douglas Gregor6ef92092011-11-09 02:13:45 +00002060 Result += "in ";
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002061 else if (ObjCQuals & Decl::OBJC_TQ_Inout)
Douglas Gregor6ef92092011-11-09 02:13:45 +00002062 Result += "inout ";
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002063 else if (ObjCQuals & Decl::OBJC_TQ_Out)
Douglas Gregor6ef92092011-11-09 02:13:45 +00002064 Result += "out ";
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002065 if (ObjCQuals & Decl::OBJC_TQ_Bycopy)
Douglas Gregor6ef92092011-11-09 02:13:45 +00002066 Result += "bycopy ";
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002067 else if (ObjCQuals & Decl::OBJC_TQ_Byref)
Douglas Gregor6ef92092011-11-09 02:13:45 +00002068 Result += "byref ";
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002069 if (ObjCQuals & Decl::OBJC_TQ_Oneway)
Douglas Gregor6ef92092011-11-09 02:13:45 +00002070 Result += "oneway ";
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002071 return Result;
2072}
2073
Douglas Gregor83482d12010-08-24 16:15:59 +00002074static std::string FormatFunctionParameter(ASTContext &Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00002075 const PrintingPolicy &Policy,
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00002076 const ParmVarDecl *Param,
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002077 bool SuppressName = false,
2078 bool SuppressBlock = false) {
Douglas Gregor83482d12010-08-24 16:15:59 +00002079 bool ObjCMethodParam = isa<ObjCMethodDecl>(Param->getDeclContext());
2080 if (Param->getType()->isDependentType() ||
2081 !Param->getType()->isBlockPointerType()) {
2082 // The argument for a dependent or non-block parameter is a placeholder
2083 // containing that parameter's type.
2084 std::string Result;
2085
Douglas Gregoraba48082010-08-29 19:47:46 +00002086 if (Param->getIdentifier() && !ObjCMethodParam && !SuppressName)
Douglas Gregor83482d12010-08-24 16:15:59 +00002087 Result = Param->getIdentifier()->getName();
2088
John McCallf85e1932011-06-15 23:02:42 +00002089 Param->getType().getAsStringInternal(Result, Policy);
Douglas Gregor83482d12010-08-24 16:15:59 +00002090
2091 if (ObjCMethodParam) {
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002092 Result = "(" + formatObjCParamQualifiers(Param->getObjCDeclQualifier())
2093 + Result + ")";
Douglas Gregoraba48082010-08-29 19:47:46 +00002094 if (Param->getIdentifier() && !SuppressName)
Douglas Gregor83482d12010-08-24 16:15:59 +00002095 Result += Param->getIdentifier()->getName();
2096 }
2097 return Result;
2098 }
2099
2100 // The argument for a block pointer parameter is a block literal with
2101 // the appropriate type.
Douglas Gregor830072c2011-02-15 22:37:09 +00002102 FunctionTypeLoc *Block = 0;
2103 FunctionProtoTypeLoc *BlockProto = 0;
Douglas Gregor83482d12010-08-24 16:15:59 +00002104 TypeLoc TL;
2105 if (TypeSourceInfo *TSInfo = Param->getTypeSourceInfo()) {
2106 TL = TSInfo->getTypeLoc().getUnqualifiedLoc();
2107 while (true) {
2108 // Look through typedefs.
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002109 if (!SuppressBlock) {
2110 if (TypedefTypeLoc *TypedefTL = dyn_cast<TypedefTypeLoc>(&TL)) {
2111 if (TypeSourceInfo *InnerTSInfo
2112 = TypedefTL->getTypedefNameDecl()->getTypeSourceInfo()) {
2113 TL = InnerTSInfo->getTypeLoc().getUnqualifiedLoc();
2114 continue;
2115 }
2116 }
2117
2118 // Look through qualified types
2119 if (QualifiedTypeLoc *QualifiedTL = dyn_cast<QualifiedTypeLoc>(&TL)) {
2120 TL = QualifiedTL->getUnqualifiedLoc();
Douglas Gregor83482d12010-08-24 16:15:59 +00002121 continue;
2122 }
2123 }
2124
Douglas Gregor83482d12010-08-24 16:15:59 +00002125 // Try to get the function prototype behind the block pointer type,
2126 // then we're done.
2127 if (BlockPointerTypeLoc *BlockPtr
2128 = dyn_cast<BlockPointerTypeLoc>(&TL)) {
Abramo Bagnara723df242010-12-14 22:11:44 +00002129 TL = BlockPtr->getPointeeLoc().IgnoreParens();
Douglas Gregor830072c2011-02-15 22:37:09 +00002130 Block = dyn_cast<FunctionTypeLoc>(&TL);
2131 BlockProto = dyn_cast<FunctionProtoTypeLoc>(&TL);
Douglas Gregor83482d12010-08-24 16:15:59 +00002132 }
2133 break;
2134 }
2135 }
2136
2137 if (!Block) {
2138 // We were unable to find a FunctionProtoTypeLoc with parameter names
2139 // for the block; just use the parameter type as a placeholder.
2140 std::string Result;
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002141 if (!ObjCMethodParam && Param->getIdentifier())
2142 Result = Param->getIdentifier()->getName();
2143
John McCallf85e1932011-06-15 23:02:42 +00002144 Param->getType().getUnqualifiedType().getAsStringInternal(Result, Policy);
Douglas Gregor83482d12010-08-24 16:15:59 +00002145
2146 if (ObjCMethodParam) {
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002147 Result = "(" + formatObjCParamQualifiers(Param->getObjCDeclQualifier())
2148 + Result + ")";
Douglas Gregor83482d12010-08-24 16:15:59 +00002149 if (Param->getIdentifier())
2150 Result += Param->getIdentifier()->getName();
2151 }
2152
2153 return Result;
2154 }
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002155
Douglas Gregor83482d12010-08-24 16:15:59 +00002156 // We have the function prototype behind the block pointer type, as it was
2157 // written in the source.
Douglas Gregor38276252010-09-08 22:47:51 +00002158 std::string Result;
2159 QualType ResultType = Block->getTypePtr()->getResultType();
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002160 if (!ResultType->isVoidType() || SuppressBlock)
John McCallf85e1932011-06-15 23:02:42 +00002161 ResultType.getAsStringInternal(Result, Policy);
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002162
2163 // Format the parameter list.
2164 std::string Params;
Douglas Gregor830072c2011-02-15 22:37:09 +00002165 if (!BlockProto || Block->getNumArgs() == 0) {
2166 if (BlockProto && BlockProto->getTypePtr()->isVariadic())
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002167 Params = "(...)";
Douglas Gregorc2760bc2010-10-02 23:49:58 +00002168 else
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002169 Params = "(void)";
Douglas Gregor38276252010-09-08 22:47:51 +00002170 } else {
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002171 Params += "(";
Douglas Gregor38276252010-09-08 22:47:51 +00002172 for (unsigned I = 0, N = Block->getNumArgs(); I != N; ++I) {
2173 if (I)
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002174 Params += ", ";
2175 Params += FormatFunctionParameter(Context, Policy, Block->getArg(I),
2176 /*SuppressName=*/false,
2177 /*SuppressBlock=*/true);
Douglas Gregor38276252010-09-08 22:47:51 +00002178
Douglas Gregor830072c2011-02-15 22:37:09 +00002179 if (I == N - 1 && BlockProto->getTypePtr()->isVariadic())
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002180 Params += ", ...";
Douglas Gregor38276252010-09-08 22:47:51 +00002181 }
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002182 Params += ")";
Douglas Gregore17794f2010-08-31 05:13:43 +00002183 }
Douglas Gregor38276252010-09-08 22:47:51 +00002184
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002185 if (SuppressBlock) {
2186 // Format as a parameter.
2187 Result = Result + " (^";
2188 if (Param->getIdentifier())
2189 Result += Param->getIdentifier()->getName();
2190 Result += ")";
2191 Result += Params;
2192 } else {
2193 // Format as a block literal argument.
2194 Result = '^' + Result;
2195 Result += Params;
2196
2197 if (Param->getIdentifier())
2198 Result += Param->getIdentifier()->getName();
2199 }
2200
Douglas Gregor83482d12010-08-24 16:15:59 +00002201 return Result;
2202}
2203
Douglas Gregor86d9a522009-09-21 16:56:56 +00002204/// \brief Add function parameter chunks to the given code completion string.
2205static void AddFunctionParameterChunks(ASTContext &Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00002206 const PrintingPolicy &Policy,
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00002207 const FunctionDecl *Function,
Douglas Gregor218937c2011-02-01 19:23:04 +00002208 CodeCompletionBuilder &Result,
2209 unsigned Start = 0,
2210 bool InOptional = false) {
Douglas Gregor218937c2011-02-01 19:23:04 +00002211 bool FirstParameter = true;
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002212
Douglas Gregor218937c2011-02-01 19:23:04 +00002213 for (unsigned P = Start, N = Function->getNumParams(); P != N; ++P) {
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00002214 const ParmVarDecl *Param = Function->getParamDecl(P);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002215
Douglas Gregor218937c2011-02-01 19:23:04 +00002216 if (Param->hasDefaultArg() && !InOptional) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002217 // When we see an optional default argument, put that argument and
2218 // the remaining default arguments into a new, optional string.
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00002219 CodeCompletionBuilder Opt(Result.getAllocator(),
2220 Result.getCodeCompletionTUInfo());
Douglas Gregor218937c2011-02-01 19:23:04 +00002221 if (!FirstParameter)
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002222 Opt.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor8987b232011-09-27 23:30:47 +00002223 AddFunctionParameterChunks(Context, Policy, Function, Opt, P, true);
Douglas Gregor218937c2011-02-01 19:23:04 +00002224 Result.AddOptionalChunk(Opt.TakeString());
2225 break;
Douglas Gregor86d9a522009-09-21 16:56:56 +00002226 }
2227
Douglas Gregor218937c2011-02-01 19:23:04 +00002228 if (FirstParameter)
2229 FirstParameter = false;
2230 else
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002231 Result.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor218937c2011-02-01 19:23:04 +00002232
2233 InOptional = false;
Douglas Gregor86d9a522009-09-21 16:56:56 +00002234
2235 // Format the placeholder string.
Douglas Gregor8987b232011-09-27 23:30:47 +00002236 std::string PlaceholderStr = FormatFunctionParameter(Context, Policy,
2237 Param);
Douglas Gregor83482d12010-08-24 16:15:59 +00002238
Douglas Gregore17794f2010-08-31 05:13:43 +00002239 if (Function->isVariadic() && P == N - 1)
2240 PlaceholderStr += ", ...";
2241
Douglas Gregor86d9a522009-09-21 16:56:56 +00002242 // Add the placeholder string.
Douglas Gregordae68752011-02-01 22:57:45 +00002243 Result.AddPlaceholderChunk(
2244 Result.getAllocator().CopyString(PlaceholderStr));
Douglas Gregor86d9a522009-09-21 16:56:56 +00002245 }
Douglas Gregorb3d45252009-09-22 21:42:17 +00002246
2247 if (const FunctionProtoType *Proto
2248 = Function->getType()->getAs<FunctionProtoType>())
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002249 if (Proto->isVariadic()) {
Douglas Gregore17794f2010-08-31 05:13:43 +00002250 if (Proto->getNumArgs() == 0)
Douglas Gregor218937c2011-02-01 19:23:04 +00002251 Result.AddPlaceholderChunk("...");
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002252
Douglas Gregor218937c2011-02-01 19:23:04 +00002253 MaybeAddSentinel(Context, Function, Result);
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002254 }
Douglas Gregor86d9a522009-09-21 16:56:56 +00002255}
2256
2257/// \brief Add template parameter chunks to the given code completion string.
2258static void AddTemplateParameterChunks(ASTContext &Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00002259 const PrintingPolicy &Policy,
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00002260 const TemplateDecl *Template,
Douglas Gregor218937c2011-02-01 19:23:04 +00002261 CodeCompletionBuilder &Result,
2262 unsigned MaxParameters = 0,
2263 unsigned Start = 0,
2264 bool InDefaultArg = false) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002265 bool FirstParameter = true;
2266
2267 TemplateParameterList *Params = Template->getTemplateParameters();
2268 TemplateParameterList::iterator PEnd = Params->end();
2269 if (MaxParameters)
2270 PEnd = Params->begin() + MaxParameters;
Douglas Gregor218937c2011-02-01 19:23:04 +00002271 for (TemplateParameterList::iterator P = Params->begin() + Start;
2272 P != PEnd; ++P) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002273 bool HasDefaultArg = false;
2274 std::string PlaceholderStr;
2275 if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*P)) {
2276 if (TTP->wasDeclaredWithTypename())
2277 PlaceholderStr = "typename";
2278 else
2279 PlaceholderStr = "class";
2280
2281 if (TTP->getIdentifier()) {
2282 PlaceholderStr += ' ';
2283 PlaceholderStr += TTP->getIdentifier()->getName();
2284 }
2285
2286 HasDefaultArg = TTP->hasDefaultArgument();
2287 } else if (NonTypeTemplateParmDecl *NTTP
Douglas Gregor218937c2011-02-01 19:23:04 +00002288 = dyn_cast<NonTypeTemplateParmDecl>(*P)) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002289 if (NTTP->getIdentifier())
2290 PlaceholderStr = NTTP->getIdentifier()->getName();
John McCallf85e1932011-06-15 23:02:42 +00002291 NTTP->getType().getAsStringInternal(PlaceholderStr, Policy);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002292 HasDefaultArg = NTTP->hasDefaultArgument();
2293 } else {
2294 assert(isa<TemplateTemplateParmDecl>(*P));
2295 TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*P);
2296
2297 // Since putting the template argument list into the placeholder would
2298 // be very, very long, we just use an abbreviation.
2299 PlaceholderStr = "template<...> class";
2300 if (TTP->getIdentifier()) {
2301 PlaceholderStr += ' ';
2302 PlaceholderStr += TTP->getIdentifier()->getName();
2303 }
2304
2305 HasDefaultArg = TTP->hasDefaultArgument();
2306 }
2307
Douglas Gregor218937c2011-02-01 19:23:04 +00002308 if (HasDefaultArg && !InDefaultArg) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002309 // When we see an optional default argument, put that argument and
2310 // the remaining default arguments into a new, optional string.
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00002311 CodeCompletionBuilder Opt(Result.getAllocator(),
2312 Result.getCodeCompletionTUInfo());
Douglas Gregor218937c2011-02-01 19:23:04 +00002313 if (!FirstParameter)
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002314 Opt.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor8987b232011-09-27 23:30:47 +00002315 AddTemplateParameterChunks(Context, Policy, Template, Opt, MaxParameters,
Douglas Gregor218937c2011-02-01 19:23:04 +00002316 P - Params->begin(), true);
2317 Result.AddOptionalChunk(Opt.TakeString());
2318 break;
Douglas Gregor86d9a522009-09-21 16:56:56 +00002319 }
2320
Douglas Gregor218937c2011-02-01 19:23:04 +00002321 InDefaultArg = false;
2322
Douglas Gregor86d9a522009-09-21 16:56:56 +00002323 if (FirstParameter)
2324 FirstParameter = false;
2325 else
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002326 Result.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002327
2328 // Add the placeholder string.
Douglas Gregordae68752011-02-01 22:57:45 +00002329 Result.AddPlaceholderChunk(
2330 Result.getAllocator().CopyString(PlaceholderStr));
Douglas Gregor86d9a522009-09-21 16:56:56 +00002331 }
2332}
2333
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00002334/// \brief Add a qualifier to the given code-completion string, if the
2335/// provided nested-name-specifier is non-NULL.
Douglas Gregora61a8792009-12-11 18:44:16 +00002336static void
Douglas Gregor218937c2011-02-01 19:23:04 +00002337AddQualifierToCompletionString(CodeCompletionBuilder &Result,
Douglas Gregora61a8792009-12-11 18:44:16 +00002338 NestedNameSpecifier *Qualifier,
2339 bool QualifierIsInformative,
Douglas Gregor8987b232011-09-27 23:30:47 +00002340 ASTContext &Context,
2341 const PrintingPolicy &Policy) {
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00002342 if (!Qualifier)
2343 return;
2344
2345 std::string PrintedNNS;
2346 {
2347 llvm::raw_string_ostream OS(PrintedNNS);
Douglas Gregor8987b232011-09-27 23:30:47 +00002348 Qualifier->print(OS, Policy);
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00002349 }
Douglas Gregor0563c262009-09-22 23:15:58 +00002350 if (QualifierIsInformative)
Douglas Gregordae68752011-02-01 22:57:45 +00002351 Result.AddInformativeChunk(Result.getAllocator().CopyString(PrintedNNS));
Douglas Gregor0563c262009-09-22 23:15:58 +00002352 else
Douglas Gregordae68752011-02-01 22:57:45 +00002353 Result.AddTextChunk(Result.getAllocator().CopyString(PrintedNNS));
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00002354}
2355
Douglas Gregor218937c2011-02-01 19:23:04 +00002356static void
2357AddFunctionTypeQualsToCompletionString(CodeCompletionBuilder &Result,
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00002358 const FunctionDecl *Function) {
Douglas Gregora61a8792009-12-11 18:44:16 +00002359 const FunctionProtoType *Proto
2360 = Function->getType()->getAs<FunctionProtoType>();
2361 if (!Proto || !Proto->getTypeQuals())
2362 return;
2363
Douglas Gregora63f6de2011-02-01 21:15:40 +00002364 // FIXME: Add ref-qualifier!
2365
2366 // Handle single qualifiers without copying
2367 if (Proto->getTypeQuals() == Qualifiers::Const) {
2368 Result.AddInformativeChunk(" const");
2369 return;
2370 }
2371
2372 if (Proto->getTypeQuals() == Qualifiers::Volatile) {
2373 Result.AddInformativeChunk(" volatile");
2374 return;
2375 }
2376
2377 if (Proto->getTypeQuals() == Qualifiers::Restrict) {
2378 Result.AddInformativeChunk(" restrict");
2379 return;
2380 }
2381
2382 // Handle multiple qualifiers.
Douglas Gregora61a8792009-12-11 18:44:16 +00002383 std::string QualsStr;
David Blaikie4ef832f2012-08-10 00:55:35 +00002384 if (Proto->isConst())
Douglas Gregora61a8792009-12-11 18:44:16 +00002385 QualsStr += " const";
David Blaikie4ef832f2012-08-10 00:55:35 +00002386 if (Proto->isVolatile())
Douglas Gregora61a8792009-12-11 18:44:16 +00002387 QualsStr += " volatile";
David Blaikie4ef832f2012-08-10 00:55:35 +00002388 if (Proto->isRestrict())
Douglas Gregora61a8792009-12-11 18:44:16 +00002389 QualsStr += " restrict";
Douglas Gregordae68752011-02-01 22:57:45 +00002390 Result.AddInformativeChunk(Result.getAllocator().CopyString(QualsStr));
Douglas Gregora61a8792009-12-11 18:44:16 +00002391}
2392
Douglas Gregor6f942b22010-09-21 16:06:22 +00002393/// \brief Add the name of the given declaration
Douglas Gregor8987b232011-09-27 23:30:47 +00002394static void AddTypedNameChunk(ASTContext &Context, const PrintingPolicy &Policy,
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00002395 const NamedDecl *ND,
2396 CodeCompletionBuilder &Result) {
Douglas Gregor6f942b22010-09-21 16:06:22 +00002397 DeclarationName Name = ND->getDeclName();
2398 if (!Name)
2399 return;
2400
2401 switch (Name.getNameKind()) {
Douglas Gregora63f6de2011-02-01 21:15:40 +00002402 case DeclarationName::CXXOperatorName: {
2403 const char *OperatorName = 0;
2404 switch (Name.getCXXOverloadedOperator()) {
2405 case OO_None:
2406 case OO_Conditional:
2407 case NUM_OVERLOADED_OPERATORS:
2408 OperatorName = "operator";
2409 break;
2410
2411#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
2412 case OO_##Name: OperatorName = "operator" Spelling; break;
2413#define OVERLOADED_OPERATOR_MULTI(Name,Spelling,Unary,Binary,MemberOnly)
2414#include "clang/Basic/OperatorKinds.def"
2415
2416 case OO_New: OperatorName = "operator new"; break;
2417 case OO_Delete: OperatorName = "operator delete"; break;
2418 case OO_Array_New: OperatorName = "operator new[]"; break;
2419 case OO_Array_Delete: OperatorName = "operator delete[]"; break;
2420 case OO_Call: OperatorName = "operator()"; break;
2421 case OO_Subscript: OperatorName = "operator[]"; break;
2422 }
2423 Result.AddTypedTextChunk(OperatorName);
2424 break;
2425 }
2426
Douglas Gregor6f942b22010-09-21 16:06:22 +00002427 case DeclarationName::Identifier:
2428 case DeclarationName::CXXConversionFunctionName:
Douglas Gregor6f942b22010-09-21 16:06:22 +00002429 case DeclarationName::CXXDestructorName:
2430 case DeclarationName::CXXLiteralOperatorName:
Douglas Gregordae68752011-02-01 22:57:45 +00002431 Result.AddTypedTextChunk(
2432 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor6f942b22010-09-21 16:06:22 +00002433 break;
2434
2435 case DeclarationName::CXXUsingDirective:
2436 case DeclarationName::ObjCZeroArgSelector:
2437 case DeclarationName::ObjCOneArgSelector:
2438 case DeclarationName::ObjCMultiArgSelector:
2439 break;
2440
2441 case DeclarationName::CXXConstructorName: {
2442 CXXRecordDecl *Record = 0;
2443 QualType Ty = Name.getCXXNameType();
2444 if (const RecordType *RecordTy = Ty->getAs<RecordType>())
2445 Record = cast<CXXRecordDecl>(RecordTy->getDecl());
2446 else if (const InjectedClassNameType *InjectedTy
2447 = Ty->getAs<InjectedClassNameType>())
2448 Record = InjectedTy->getDecl();
2449 else {
Douglas Gregordae68752011-02-01 22:57:45 +00002450 Result.AddTypedTextChunk(
2451 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor6f942b22010-09-21 16:06:22 +00002452 break;
2453 }
2454
Douglas Gregordae68752011-02-01 22:57:45 +00002455 Result.AddTypedTextChunk(
2456 Result.getAllocator().CopyString(Record->getNameAsString()));
Douglas Gregor6f942b22010-09-21 16:06:22 +00002457 if (ClassTemplateDecl *Template = Record->getDescribedClassTemplate()) {
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002458 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Douglas Gregor8987b232011-09-27 23:30:47 +00002459 AddTemplateParameterChunks(Context, Policy, Template, Result);
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002460 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregor6f942b22010-09-21 16:06:22 +00002461 }
2462 break;
2463 }
2464 }
2465}
2466
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002467CodeCompletionString *CodeCompletionResult::CreateCodeCompletionString(Sema &S,
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00002468 CodeCompletionAllocator &Allocator,
Dmitri Gribenkod99ef532012-07-02 17:35:10 +00002469 CodeCompletionTUInfo &CCTUInfo,
2470 bool IncludeBriefComments) {
2471 return CreateCodeCompletionString(S.Context, S.PP, Allocator, CCTUInfo,
2472 IncludeBriefComments);
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002473}
2474
Douglas Gregor86d9a522009-09-21 16:56:56 +00002475/// \brief If possible, create a new code completion string for the given
2476/// result.
2477///
2478/// \returns Either a new, heap-allocated code completion string describing
2479/// how to use this result, or NULL to indicate that the string or name of the
2480/// result is all that is needed.
2481CodeCompletionString *
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002482CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx,
2483 Preprocessor &PP,
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00002484 CodeCompletionAllocator &Allocator,
Dmitri Gribenkod99ef532012-07-02 17:35:10 +00002485 CodeCompletionTUInfo &CCTUInfo,
2486 bool IncludeBriefComments) {
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00002487 CodeCompletionBuilder Result(Allocator, CCTUInfo, Priority, Availability);
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002488
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002489 PrintingPolicy Policy = getCompletionPrintingPolicy(Ctx, PP);
Douglas Gregor218937c2011-02-01 19:23:04 +00002490 if (Kind == RK_Pattern) {
2491 Pattern->Priority = Priority;
2492 Pattern->Availability = Availability;
Douglas Gregorba103062012-03-27 23:34:16 +00002493
2494 if (Declaration) {
2495 Result.addParentContext(Declaration->getDeclContext());
Douglas Gregorba103062012-03-27 23:34:16 +00002496 Pattern->ParentName = Result.getParentName();
2497 }
2498
Douglas Gregor218937c2011-02-01 19:23:04 +00002499 return Pattern;
2500 }
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002501
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002502 if (Kind == RK_Keyword) {
Douglas Gregor218937c2011-02-01 19:23:04 +00002503 Result.AddTypedTextChunk(Keyword);
2504 return Result.TakeString();
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002505 }
Douglas Gregor86d9a522009-09-21 16:56:56 +00002506
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002507 if (Kind == RK_Macro) {
Douglas Gregor3644d972012-10-09 16:01:50 +00002508 MacroInfo *MI = PP.getMacroInfoHistory(Macro);
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002509 assert(MI && "Not a macro?");
2510
Douglas Gregordae68752011-02-01 22:57:45 +00002511 Result.AddTypedTextChunk(
2512 Result.getAllocator().CopyString(Macro->getName()));
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002513
2514 if (!MI->isFunctionLike())
Douglas Gregor218937c2011-02-01 19:23:04 +00002515 return Result.TakeString();
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002516
2517 // Format a function-like macro with placeholders for the arguments.
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002518 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregore4244702011-07-30 08:17:44 +00002519 MacroInfo::arg_iterator A = MI->arg_begin(), AEnd = MI->arg_end();
Douglas Gregorc8dc1352012-01-21 00:43:38 +00002520
2521 // C99 variadic macros add __VA_ARGS__ at the end. Skip it.
2522 if (MI->isC99Varargs()) {
2523 --AEnd;
2524
2525 if (A == AEnd) {
2526 Result.AddPlaceholderChunk("...");
2527 }
Douglas Gregore4244702011-07-30 08:17:44 +00002528 }
Douglas Gregorc8dc1352012-01-21 00:43:38 +00002529
Douglas Gregore4244702011-07-30 08:17:44 +00002530 for (MacroInfo::arg_iterator A = MI->arg_begin(); A != AEnd; ++A) {
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002531 if (A != MI->arg_begin())
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002532 Result.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregorc8dc1352012-01-21 00:43:38 +00002533
2534 if (MI->isVariadic() && (A+1) == AEnd) {
Dylan Noblesmithf7ccbad2012-02-05 02:13:05 +00002535 SmallString<32> Arg = (*A)->getName();
Douglas Gregorc8dc1352012-01-21 00:43:38 +00002536 if (MI->isC99Varargs())
2537 Arg += ", ...";
2538 else
2539 Arg += "...";
Douglas Gregordae68752011-02-01 22:57:45 +00002540 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregorc8dc1352012-01-21 00:43:38 +00002541 break;
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002542 }
Douglas Gregorc8dc1352012-01-21 00:43:38 +00002543
2544 // Non-variadic macros are simple.
2545 Result.AddPlaceholderChunk(
2546 Result.getAllocator().CopyString((*A)->getName()));
Douglas Gregore4244702011-07-30 08:17:44 +00002547 }
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002548 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor218937c2011-02-01 19:23:04 +00002549 return Result.TakeString();
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002550 }
2551
Douglas Gregord8e8a582010-05-25 21:41:55 +00002552 assert(Kind == RK_Declaration && "Missed a result kind?");
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00002553 const NamedDecl *ND = Declaration;
Douglas Gregorba103062012-03-27 23:34:16 +00002554 Result.addParentContext(ND->getDeclContext());
Dmitri Gribenkod99ef532012-07-02 17:35:10 +00002555
2556 if (IncludeBriefComments) {
2557 // Add documentation comment, if it exists.
Dmitri Gribenkof50555e2012-08-11 00:51:43 +00002558 if (const RawComment *RC = Ctx.getRawCommentForAnyRedecl(ND)) {
Dmitri Gribenkod99ef532012-07-02 17:35:10 +00002559 Result.addBriefComment(RC->getBriefText(Ctx));
2560 }
2561 }
2562
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002563 if (StartsNestedNameSpecifier) {
Douglas Gregordae68752011-02-01 22:57:45 +00002564 Result.AddTypedTextChunk(
2565 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor218937c2011-02-01 19:23:04 +00002566 Result.AddTextChunk("::");
2567 return Result.TakeString();
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002568 }
Erik Verbruggen6164ea12011-10-14 15:31:08 +00002569
2570 for (Decl::attr_iterator i = ND->attr_begin(); i != ND->attr_end(); ++i) {
2571 if (AnnotateAttr *Attr = dyn_cast_or_null<AnnotateAttr>(*i)) {
2572 Result.AddAnnotation(Result.getAllocator().CopyString(Attr->getAnnotation()));
2573 }
2574 }
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002575
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002576 AddResultTypeChunk(Ctx, Policy, ND, Result);
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00002577
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00002578 if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(ND)) {
Douglas Gregor0563c262009-09-22 23:15:58 +00002579 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002580 Ctx, Policy);
2581 AddTypedNameChunk(Ctx, Policy, ND, Result);
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002582 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002583 AddFunctionParameterChunks(Ctx, Policy, Function, Result);
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002584 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregora61a8792009-12-11 18:44:16 +00002585 AddFunctionTypeQualsToCompletionString(Result, Function);
Douglas Gregor218937c2011-02-01 19:23:04 +00002586 return Result.TakeString();
Douglas Gregor86d9a522009-09-21 16:56:56 +00002587 }
2588
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00002589 if (const FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND)) {
Douglas Gregor0563c262009-09-22 23:15:58 +00002590 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002591 Ctx, Policy);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002592 FunctionDecl *Function = FunTmpl->getTemplatedDecl();
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002593 AddTypedNameChunk(Ctx, Policy, Function, Result);
Douglas Gregor6f942b22010-09-21 16:06:22 +00002594
Douglas Gregor86d9a522009-09-21 16:56:56 +00002595 // Figure out which template parameters are deduced (or have default
2596 // arguments).
Benjamin Kramer013b3662012-01-30 16:17:39 +00002597 llvm::SmallBitVector Deduced;
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002598 Sema::MarkDeducedTemplateParameters(Ctx, FunTmpl, Deduced);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002599 unsigned LastDeducibleArgument;
2600 for (LastDeducibleArgument = Deduced.size(); LastDeducibleArgument > 0;
2601 --LastDeducibleArgument) {
2602 if (!Deduced[LastDeducibleArgument - 1]) {
2603 // C++0x: Figure out if the template argument has a default. If so,
2604 // the user doesn't need to type this argument.
2605 // FIXME: We need to abstract template parameters better!
2606 bool HasDefaultArg = false;
2607 NamedDecl *Param = FunTmpl->getTemplateParameters()->getParam(
Douglas Gregor218937c2011-02-01 19:23:04 +00002608 LastDeducibleArgument - 1);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002609 if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param))
2610 HasDefaultArg = TTP->hasDefaultArgument();
2611 else if (NonTypeTemplateParmDecl *NTTP
2612 = dyn_cast<NonTypeTemplateParmDecl>(Param))
2613 HasDefaultArg = NTTP->hasDefaultArgument();
2614 else {
2615 assert(isa<TemplateTemplateParmDecl>(Param));
2616 HasDefaultArg
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002617 = cast<TemplateTemplateParmDecl>(Param)->hasDefaultArgument();
Douglas Gregor86d9a522009-09-21 16:56:56 +00002618 }
2619
2620 if (!HasDefaultArg)
2621 break;
2622 }
2623 }
2624
2625 if (LastDeducibleArgument) {
2626 // Some of the function template arguments cannot be deduced from a
2627 // function call, so we introduce an explicit template argument list
2628 // containing all of the arguments up to the first deducible argument.
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002629 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002630 AddTemplateParameterChunks(Ctx, Policy, FunTmpl, Result,
Douglas Gregor86d9a522009-09-21 16:56:56 +00002631 LastDeducibleArgument);
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002632 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002633 }
2634
2635 // Add the function parameters
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002636 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002637 AddFunctionParameterChunks(Ctx, Policy, Function, Result);
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002638 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregora61a8792009-12-11 18:44:16 +00002639 AddFunctionTypeQualsToCompletionString(Result, Function);
Douglas Gregor218937c2011-02-01 19:23:04 +00002640 return Result.TakeString();
Douglas Gregor86d9a522009-09-21 16:56:56 +00002641 }
2642
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00002643 if (const TemplateDecl *Template = dyn_cast<TemplateDecl>(ND)) {
Douglas Gregor0563c262009-09-22 23:15:58 +00002644 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002645 Ctx, Policy);
Douglas Gregordae68752011-02-01 22:57:45 +00002646 Result.AddTypedTextChunk(
2647 Result.getAllocator().CopyString(Template->getNameAsString()));
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002648 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002649 AddTemplateParameterChunks(Ctx, Policy, Template, Result);
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002650 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregor218937c2011-02-01 19:23:04 +00002651 return Result.TakeString();
Douglas Gregor86d9a522009-09-21 16:56:56 +00002652 }
2653
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00002654 if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND)) {
Douglas Gregor9630eb62009-11-17 16:44:22 +00002655 Selector Sel = Method->getSelector();
2656 if (Sel.isUnarySelector()) {
Douglas Gregordae68752011-02-01 22:57:45 +00002657 Result.AddTypedTextChunk(Result.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00002658 Sel.getNameForSlot(0)));
Douglas Gregor218937c2011-02-01 19:23:04 +00002659 return Result.TakeString();
Douglas Gregor9630eb62009-11-17 16:44:22 +00002660 }
2661
Douglas Gregor813d8342011-02-18 22:29:55 +00002662 std::string SelName = Sel.getNameForSlot(0).str();
Douglas Gregord3c68542009-11-19 01:08:35 +00002663 SelName += ':';
2664 if (StartParameter == 0)
Douglas Gregordae68752011-02-01 22:57:45 +00002665 Result.AddTypedTextChunk(Result.getAllocator().CopyString(SelName));
Douglas Gregord3c68542009-11-19 01:08:35 +00002666 else {
Douglas Gregordae68752011-02-01 22:57:45 +00002667 Result.AddInformativeChunk(Result.getAllocator().CopyString(SelName));
Douglas Gregord3c68542009-11-19 01:08:35 +00002668
2669 // If there is only one parameter, and we're past it, add an empty
2670 // typed-text chunk since there is nothing to type.
2671 if (Method->param_size() == 1)
Douglas Gregor218937c2011-02-01 19:23:04 +00002672 Result.AddTypedTextChunk("");
Douglas Gregord3c68542009-11-19 01:08:35 +00002673 }
Douglas Gregor9630eb62009-11-17 16:44:22 +00002674 unsigned Idx = 0;
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00002675 for (ObjCMethodDecl::param_const_iterator P = Method->param_begin(),
2676 PEnd = Method->param_end();
Douglas Gregor9630eb62009-11-17 16:44:22 +00002677 P != PEnd; (void)++P, ++Idx) {
2678 if (Idx > 0) {
Douglas Gregord3c68542009-11-19 01:08:35 +00002679 std::string Keyword;
2680 if (Idx > StartParameter)
Douglas Gregor218937c2011-02-01 19:23:04 +00002681 Result.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregor9630eb62009-11-17 16:44:22 +00002682 if (IdentifierInfo *II = Sel.getIdentifierInfoForSlot(Idx))
Benjamin Kramera0651c52011-07-26 16:59:25 +00002683 Keyword += II->getName();
Douglas Gregor9630eb62009-11-17 16:44:22 +00002684 Keyword += ":";
Douglas Gregor1f5537a2010-07-08 23:20:03 +00002685 if (Idx < StartParameter || AllParametersAreInformative)
Douglas Gregordae68752011-02-01 22:57:45 +00002686 Result.AddInformativeChunk(Result.getAllocator().CopyString(Keyword));
Douglas Gregorc7b7b7a2010-10-18 21:05:04 +00002687 else
Douglas Gregordae68752011-02-01 22:57:45 +00002688 Result.AddTypedTextChunk(Result.getAllocator().CopyString(Keyword));
Douglas Gregor9630eb62009-11-17 16:44:22 +00002689 }
Douglas Gregord3c68542009-11-19 01:08:35 +00002690
2691 // If we're before the starting parameter, skip the placeholder.
2692 if (Idx < StartParameter)
2693 continue;
Douglas Gregor9630eb62009-11-17 16:44:22 +00002694
2695 std::string Arg;
Douglas Gregor83482d12010-08-24 16:15:59 +00002696
2697 if ((*P)->getType()->isBlockPointerType() && !DeclaringEntity)
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002698 Arg = FormatFunctionParameter(Ctx, Policy, *P, true);
Douglas Gregor83482d12010-08-24 16:15:59 +00002699 else {
John McCallf85e1932011-06-15 23:02:42 +00002700 (*P)->getType().getAsStringInternal(Arg, Policy);
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002701 Arg = "(" + formatObjCParamQualifiers((*P)->getObjCDeclQualifier())
2702 + Arg + ")";
Douglas Gregor83482d12010-08-24 16:15:59 +00002703 if (IdentifierInfo *II = (*P)->getIdentifier())
Douglas Gregoraba48082010-08-29 19:47:46 +00002704 if (DeclaringEntity || AllParametersAreInformative)
Benjamin Kramera0651c52011-07-26 16:59:25 +00002705 Arg += II->getName();
Douglas Gregor83482d12010-08-24 16:15:59 +00002706 }
2707
Douglas Gregore17794f2010-08-31 05:13:43 +00002708 if (Method->isVariadic() && (P + 1) == PEnd)
2709 Arg += ", ...";
2710
Douglas Gregor1f5537a2010-07-08 23:20:03 +00002711 if (DeclaringEntity)
Douglas Gregordae68752011-02-01 22:57:45 +00002712 Result.AddTextChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregor1f5537a2010-07-08 23:20:03 +00002713 else if (AllParametersAreInformative)
Douglas Gregordae68752011-02-01 22:57:45 +00002714 Result.AddInformativeChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregor4ad96852009-11-19 07:41:15 +00002715 else
Douglas Gregordae68752011-02-01 22:57:45 +00002716 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregor9630eb62009-11-17 16:44:22 +00002717 }
2718
Douglas Gregor2a17af02009-12-23 00:21:46 +00002719 if (Method->isVariadic()) {
Douglas Gregore17794f2010-08-31 05:13:43 +00002720 if (Method->param_size() == 0) {
2721 if (DeclaringEntity)
Douglas Gregor218937c2011-02-01 19:23:04 +00002722 Result.AddTextChunk(", ...");
Douglas Gregore17794f2010-08-31 05:13:43 +00002723 else if (AllParametersAreInformative)
Douglas Gregor218937c2011-02-01 19:23:04 +00002724 Result.AddInformativeChunk(", ...");
Douglas Gregore17794f2010-08-31 05:13:43 +00002725 else
Douglas Gregor218937c2011-02-01 19:23:04 +00002726 Result.AddPlaceholderChunk(", ...");
Douglas Gregore17794f2010-08-31 05:13:43 +00002727 }
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002728
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002729 MaybeAddSentinel(Ctx, Method, Result);
Douglas Gregor2a17af02009-12-23 00:21:46 +00002730 }
2731
Douglas Gregor218937c2011-02-01 19:23:04 +00002732 return Result.TakeString();
Douglas Gregor9630eb62009-11-17 16:44:22 +00002733 }
2734
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002735 if (Qualifier)
Douglas Gregor0563c262009-09-22 23:15:58 +00002736 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002737 Ctx, Policy);
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002738
Douglas Gregordae68752011-02-01 22:57:45 +00002739 Result.AddTypedTextChunk(
2740 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor218937c2011-02-01 19:23:04 +00002741 return Result.TakeString();
Douglas Gregor86d9a522009-09-21 16:56:56 +00002742}
2743
Douglas Gregor86d802e2009-09-23 00:34:09 +00002744CodeCompletionString *
2745CodeCompleteConsumer::OverloadCandidate::CreateSignatureString(
2746 unsigned CurrentArg,
Douglas Gregor32be4a52010-10-11 21:37:58 +00002747 Sema &S,
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00002748 CodeCompletionAllocator &Allocator,
2749 CodeCompletionTUInfo &CCTUInfo) const {
Douglas Gregor8987b232011-09-27 23:30:47 +00002750 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
John McCallf85e1932011-06-15 23:02:42 +00002751
Douglas Gregor218937c2011-02-01 19:23:04 +00002752 // FIXME: Set priority, availability appropriately.
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00002753 CodeCompletionBuilder Result(Allocator,CCTUInfo, 1, CXAvailability_Available);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002754 FunctionDecl *FDecl = getFunction();
Douglas Gregor8987b232011-09-27 23:30:47 +00002755 AddResultTypeChunk(S.Context, Policy, FDecl, Result);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002756 const FunctionProtoType *Proto
2757 = dyn_cast<FunctionProtoType>(getFunctionType());
2758 if (!FDecl && !Proto) {
2759 // Function without a prototype. Just give the return type and a
2760 // highlighted ellipsis.
2761 const FunctionType *FT = getFunctionType();
Douglas Gregora63f6de2011-02-01 21:15:40 +00002762 Result.AddTextChunk(GetCompletionTypeString(FT->getResultType(),
Douglas Gregor8987b232011-09-27 23:30:47 +00002763 S.Context, Policy,
Douglas Gregora63f6de2011-02-01 21:15:40 +00002764 Result.getAllocator()));
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002765 Result.AddChunk(CodeCompletionString::CK_LeftParen);
2766 Result.AddChunk(CodeCompletionString::CK_CurrentParameter, "...");
2767 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor218937c2011-02-01 19:23:04 +00002768 return Result.TakeString();
Douglas Gregor86d802e2009-09-23 00:34:09 +00002769 }
2770
2771 if (FDecl)
Douglas Gregordae68752011-02-01 22:57:45 +00002772 Result.AddTextChunk(
2773 Result.getAllocator().CopyString(FDecl->getNameAsString()));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002774 else
Douglas Gregor218937c2011-02-01 19:23:04 +00002775 Result.AddTextChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00002776 Result.getAllocator().CopyString(
John McCallf85e1932011-06-15 23:02:42 +00002777 Proto->getResultType().getAsString(Policy)));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002778
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002779 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002780 unsigned NumParams = FDecl? FDecl->getNumParams() : Proto->getNumArgs();
2781 for (unsigned I = 0; I != NumParams; ++I) {
2782 if (I)
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002783 Result.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002784
2785 std::string ArgString;
2786 QualType ArgType;
2787
2788 if (FDecl) {
2789 ArgString = FDecl->getParamDecl(I)->getNameAsString();
2790 ArgType = FDecl->getParamDecl(I)->getOriginalType();
2791 } else {
2792 ArgType = Proto->getArgType(I);
2793 }
2794
John McCallf85e1932011-06-15 23:02:42 +00002795 ArgType.getAsStringInternal(ArgString, Policy);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002796
2797 if (I == CurrentArg)
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002798 Result.AddChunk(CodeCompletionString::CK_CurrentParameter,
2799 Result.getAllocator().CopyString(ArgString));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002800 else
Douglas Gregordae68752011-02-01 22:57:45 +00002801 Result.AddTextChunk(Result.getAllocator().CopyString(ArgString));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002802 }
2803
2804 if (Proto && Proto->isVariadic()) {
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002805 Result.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002806 if (CurrentArg < NumParams)
Douglas Gregor218937c2011-02-01 19:23:04 +00002807 Result.AddTextChunk("...");
Douglas Gregor86d802e2009-09-23 00:34:09 +00002808 else
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002809 Result.AddChunk(CodeCompletionString::CK_CurrentParameter, "...");
Douglas Gregor86d802e2009-09-23 00:34:09 +00002810 }
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002811 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002812
Douglas Gregor218937c2011-02-01 19:23:04 +00002813 return Result.TakeString();
Douglas Gregor86d802e2009-09-23 00:34:09 +00002814}
2815
Chris Lattner5f9e2722011-07-23 10:55:15 +00002816unsigned clang::getMacroUsagePriority(StringRef MacroName,
Douglas Gregorb05496d2010-09-20 21:11:48 +00002817 const LangOptions &LangOpts,
Douglas Gregor1827e102010-08-16 16:18:59 +00002818 bool PreferredTypeIsPointer) {
2819 unsigned Priority = CCP_Macro;
2820
Douglas Gregorb05496d2010-09-20 21:11:48 +00002821 // Treat the "nil", "Nil" and "NULL" macros as null pointer constants.
2822 if (MacroName.equals("nil") || MacroName.equals("NULL") ||
2823 MacroName.equals("Nil")) {
Douglas Gregor1827e102010-08-16 16:18:59 +00002824 Priority = CCP_Constant;
2825 if (PreferredTypeIsPointer)
2826 Priority = Priority / CCF_SimilarTypeMatch;
Douglas Gregorb05496d2010-09-20 21:11:48 +00002827 }
2828 // Treat "YES", "NO", "true", and "false" as constants.
2829 else if (MacroName.equals("YES") || MacroName.equals("NO") ||
2830 MacroName.equals("true") || MacroName.equals("false"))
2831 Priority = CCP_Constant;
2832 // Treat "bool" as a type.
2833 else if (MacroName.equals("bool"))
2834 Priority = CCP_Type + (LangOpts.ObjC1? CCD_bool_in_ObjC : 0);
2835
Douglas Gregor1827e102010-08-16 16:18:59 +00002836
2837 return Priority;
2838}
2839
Dmitri Gribenko06d8c602013-01-11 20:32:41 +00002840CXCursorKind clang::getCursorKindForDecl(const Decl *D) {
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002841 if (!D)
2842 return CXCursor_UnexposedDecl;
2843
2844 switch (D->getKind()) {
2845 case Decl::Enum: return CXCursor_EnumDecl;
2846 case Decl::EnumConstant: return CXCursor_EnumConstantDecl;
2847 case Decl::Field: return CXCursor_FieldDecl;
2848 case Decl::Function:
2849 return CXCursor_FunctionDecl;
2850 case Decl::ObjCCategory: return CXCursor_ObjCCategoryDecl;
2851 case Decl::ObjCCategoryImpl: return CXCursor_ObjCCategoryImplDecl;
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002852 case Decl::ObjCImplementation: return CXCursor_ObjCImplementationDecl;
Douglas Gregor375bb142011-12-27 22:43:10 +00002853
Argyrios Kyrtzidisc15707d2012-01-24 21:39:26 +00002854 case Decl::ObjCInterface: return CXCursor_ObjCInterfaceDecl;
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002855 case Decl::ObjCIvar: return CXCursor_ObjCIvarDecl;
2856 case Decl::ObjCMethod:
2857 return cast<ObjCMethodDecl>(D)->isInstanceMethod()
2858 ? CXCursor_ObjCInstanceMethodDecl : CXCursor_ObjCClassMethodDecl;
2859 case Decl::CXXMethod: return CXCursor_CXXMethod;
2860 case Decl::CXXConstructor: return CXCursor_Constructor;
2861 case Decl::CXXDestructor: return CXCursor_Destructor;
2862 case Decl::CXXConversion: return CXCursor_ConversionFunction;
2863 case Decl::ObjCProperty: return CXCursor_ObjCPropertyDecl;
Argyrios Kyrtzidisc15707d2012-01-24 21:39:26 +00002864 case Decl::ObjCProtocol: return CXCursor_ObjCProtocolDecl;
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002865 case Decl::ParmVar: return CXCursor_ParmDecl;
2866 case Decl::Typedef: return CXCursor_TypedefDecl;
Richard Smith162e1c12011-04-15 14:24:37 +00002867 case Decl::TypeAlias: return CXCursor_TypeAliasDecl;
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002868 case Decl::Var: return CXCursor_VarDecl;
2869 case Decl::Namespace: return CXCursor_Namespace;
2870 case Decl::NamespaceAlias: return CXCursor_NamespaceAlias;
2871 case Decl::TemplateTypeParm: return CXCursor_TemplateTypeParameter;
2872 case Decl::NonTypeTemplateParm:return CXCursor_NonTypeTemplateParameter;
2873 case Decl::TemplateTemplateParm:return CXCursor_TemplateTemplateParameter;
2874 case Decl::FunctionTemplate: return CXCursor_FunctionTemplate;
2875 case Decl::ClassTemplate: return CXCursor_ClassTemplate;
Argyrios Kyrtzidis2dfdb942011-09-30 17:58:23 +00002876 case Decl::AccessSpec: return CXCursor_CXXAccessSpecifier;
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002877 case Decl::ClassTemplatePartialSpecialization:
2878 return CXCursor_ClassTemplatePartialSpecialization;
2879 case Decl::UsingDirective: return CXCursor_UsingDirective;
Douglas Gregor8e5900c2012-04-30 23:41:16 +00002880 case Decl::TranslationUnit: return CXCursor_TranslationUnit;
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002881
2882 case Decl::Using:
2883 case Decl::UnresolvedUsingValue:
2884 case Decl::UnresolvedUsingTypename:
2885 return CXCursor_UsingDeclaration;
2886
Douglas Gregor352697a2011-06-03 23:08:58 +00002887 case Decl::ObjCPropertyImpl:
2888 switch (cast<ObjCPropertyImplDecl>(D)->getPropertyImplementation()) {
2889 case ObjCPropertyImplDecl::Dynamic:
2890 return CXCursor_ObjCDynamicDecl;
2891
2892 case ObjCPropertyImplDecl::Synthesize:
2893 return CXCursor_ObjCSynthesizeDecl;
2894 }
Argyrios Kyrtzidis6a010122012-10-05 00:22:24 +00002895
2896 case Decl::Import:
2897 return CXCursor_ModuleImportDecl;
Douglas Gregor352697a2011-06-03 23:08:58 +00002898
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002899 default:
Dmitri Gribenko06d8c602013-01-11 20:32:41 +00002900 if (const TagDecl *TD = dyn_cast<TagDecl>(D)) {
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002901 switch (TD->getTagKind()) {
Joao Matos6666ed42012-08-31 18:45:21 +00002902 case TTK_Interface: // fall through
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002903 case TTK_Struct: return CXCursor_StructDecl;
2904 case TTK_Class: return CXCursor_ClassDecl;
2905 case TTK_Union: return CXCursor_UnionDecl;
2906 case TTK_Enum: return CXCursor_EnumDecl;
2907 }
2908 }
2909 }
2910
2911 return CXCursor_UnexposedDecl;
2912}
2913
Douglas Gregor590c7d52010-07-08 20:55:51 +00002914static void AddMacroResults(Preprocessor &PP, ResultBuilder &Results,
Douglas Gregor3644d972012-10-09 16:01:50 +00002915 bool IncludeUndefined,
Douglas Gregor590c7d52010-07-08 20:55:51 +00002916 bool TargetTypeIsPointer = false) {
John McCall0a2c5e22010-08-25 06:19:51 +00002917 typedef CodeCompletionResult Result;
Douglas Gregor590c7d52010-07-08 20:55:51 +00002918
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002919 Results.EnterNewScope();
Douglas Gregorc7b7b7a2010-10-18 21:05:04 +00002920
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002921 for (Preprocessor::macro_iterator M = PP.macro_begin(),
2922 MEnd = PP.macro_end();
Douglas Gregor590c7d52010-07-08 20:55:51 +00002923 M != MEnd; ++M) {
Douglas Gregor3644d972012-10-09 16:01:50 +00002924 if (IncludeUndefined || M->first->hasMacroDefinition())
2925 Results.AddResult(Result(M->first,
Douglas Gregor1827e102010-08-16 16:18:59 +00002926 getMacroUsagePriority(M->first->getName(),
David Blaikie4e4d0842012-03-11 07:00:24 +00002927 PP.getLangOpts(),
Douglas Gregor1827e102010-08-16 16:18:59 +00002928 TargetTypeIsPointer)));
Douglas Gregor590c7d52010-07-08 20:55:51 +00002929 }
Douglas Gregorc7b7b7a2010-10-18 21:05:04 +00002930
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002931 Results.ExitScope();
Douglas Gregorc7b7b7a2010-10-18 21:05:04 +00002932
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002933}
2934
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00002935static void AddPrettyFunctionResults(const LangOptions &LangOpts,
2936 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00002937 typedef CodeCompletionResult Result;
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00002938
2939 Results.EnterNewScope();
Douglas Gregorc7b7b7a2010-10-18 21:05:04 +00002940
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00002941 Results.AddResult(Result("__PRETTY_FUNCTION__", CCP_Constant));
2942 Results.AddResult(Result("__FUNCTION__", CCP_Constant));
Richard Smith80ad52f2013-01-02 11:42:31 +00002943 if (LangOpts.C99 || LangOpts.CPlusPlus11)
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00002944 Results.AddResult(Result("__func__", CCP_Constant));
2945 Results.ExitScope();
2946}
2947
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00002948static void HandleCodeCompleteResults(Sema *S,
2949 CodeCompleteConsumer *CodeCompleter,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002950 CodeCompletionContext Context,
John McCall0a2c5e22010-08-25 06:19:51 +00002951 CodeCompletionResult *Results,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002952 unsigned NumResults) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002953 if (CodeCompleter)
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002954 CodeCompleter->ProcessCodeCompleteResults(*S, Context, Results, NumResults);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002955}
2956
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002957static enum CodeCompletionContext::Kind mapCodeCompletionContext(Sema &S,
2958 Sema::ParserCompletionContext PCC) {
2959 switch (PCC) {
John McCallf312b1e2010-08-26 23:41:50 +00002960 case Sema::PCC_Namespace:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002961 return CodeCompletionContext::CCC_TopLevel;
2962
John McCallf312b1e2010-08-26 23:41:50 +00002963 case Sema::PCC_Class:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002964 return CodeCompletionContext::CCC_ClassStructUnion;
2965
John McCallf312b1e2010-08-26 23:41:50 +00002966 case Sema::PCC_ObjCInterface:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002967 return CodeCompletionContext::CCC_ObjCInterface;
2968
John McCallf312b1e2010-08-26 23:41:50 +00002969 case Sema::PCC_ObjCImplementation:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002970 return CodeCompletionContext::CCC_ObjCImplementation;
2971
John McCallf312b1e2010-08-26 23:41:50 +00002972 case Sema::PCC_ObjCInstanceVariableList:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002973 return CodeCompletionContext::CCC_ObjCIvarList;
2974
John McCallf312b1e2010-08-26 23:41:50 +00002975 case Sema::PCC_Template:
2976 case Sema::PCC_MemberTemplate:
Douglas Gregor52779fb2010-09-23 23:01:17 +00002977 if (S.CurContext->isFileContext())
2978 return CodeCompletionContext::CCC_TopLevel;
David Blaikie7530c032012-01-17 06:56:22 +00002979 if (S.CurContext->isRecord())
Douglas Gregor52779fb2010-09-23 23:01:17 +00002980 return CodeCompletionContext::CCC_ClassStructUnion;
David Blaikie7530c032012-01-17 06:56:22 +00002981 return CodeCompletionContext::CCC_Other;
Douglas Gregor52779fb2010-09-23 23:01:17 +00002982
John McCallf312b1e2010-08-26 23:41:50 +00002983 case Sema::PCC_RecoveryInFunction:
Douglas Gregor52779fb2010-09-23 23:01:17 +00002984 return CodeCompletionContext::CCC_Recovery;
Douglas Gregora5450a02010-10-18 22:01:46 +00002985
John McCallf312b1e2010-08-26 23:41:50 +00002986 case Sema::PCC_ForInit:
David Blaikie4e4d0842012-03-11 07:00:24 +00002987 if (S.getLangOpts().CPlusPlus || S.getLangOpts().C99 ||
2988 S.getLangOpts().ObjC1)
Douglas Gregora5450a02010-10-18 22:01:46 +00002989 return CodeCompletionContext::CCC_ParenthesizedExpression;
2990 else
2991 return CodeCompletionContext::CCC_Expression;
2992
2993 case Sema::PCC_Expression:
John McCallf312b1e2010-08-26 23:41:50 +00002994 case Sema::PCC_Condition:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002995 return CodeCompletionContext::CCC_Expression;
2996
John McCallf312b1e2010-08-26 23:41:50 +00002997 case Sema::PCC_Statement:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002998 return CodeCompletionContext::CCC_Statement;
Douglas Gregor72db1082010-08-24 01:11:00 +00002999
John McCallf312b1e2010-08-26 23:41:50 +00003000 case Sema::PCC_Type:
Douglas Gregor72db1082010-08-24 01:11:00 +00003001 return CodeCompletionContext::CCC_Type;
Douglas Gregor02688102010-09-14 23:59:36 +00003002
3003 case Sema::PCC_ParenthesizedExpression:
3004 return CodeCompletionContext::CCC_ParenthesizedExpression;
Douglas Gregor68e3c2e2011-02-15 20:33:25 +00003005
3006 case Sema::PCC_LocalDeclarationSpecifiers:
3007 return CodeCompletionContext::CCC_Type;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003008 }
David Blaikie7530c032012-01-17 06:56:22 +00003009
3010 llvm_unreachable("Invalid ParserCompletionContext!");
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003011}
3012
Douglas Gregorf6961522010-08-27 21:18:54 +00003013/// \brief If we're in a C++ virtual member function, add completion results
3014/// that invoke the functions we override, since it's common to invoke the
3015/// overridden function as well as adding new functionality.
3016///
3017/// \param S The semantic analysis object for which we are generating results.
3018///
3019/// \param InContext This context in which the nested-name-specifier preceding
3020/// the code-completion point
3021static void MaybeAddOverrideCalls(Sema &S, DeclContext *InContext,
3022 ResultBuilder &Results) {
3023 // Look through blocks.
3024 DeclContext *CurContext = S.CurContext;
3025 while (isa<BlockDecl>(CurContext))
3026 CurContext = CurContext->getParent();
3027
3028
3029 CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(CurContext);
3030 if (!Method || !Method->isVirtual())
3031 return;
3032
3033 // We need to have names for all of the parameters, if we're going to
3034 // generate a forwarding call.
3035 for (CXXMethodDecl::param_iterator P = Method->param_begin(),
3036 PEnd = Method->param_end();
3037 P != PEnd;
3038 ++P) {
3039 if (!(*P)->getDeclName())
3040 return;
3041 }
3042
Douglas Gregor8987b232011-09-27 23:30:47 +00003043 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
Douglas Gregorf6961522010-08-27 21:18:54 +00003044 for (CXXMethodDecl::method_iterator M = Method->begin_overridden_methods(),
3045 MEnd = Method->end_overridden_methods();
3046 M != MEnd; ++M) {
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003047 CodeCompletionBuilder Builder(Results.getAllocator(),
3048 Results.getCodeCompletionTUInfo());
Douglas Gregorf6961522010-08-27 21:18:54 +00003049 CXXMethodDecl *Overridden = const_cast<CXXMethodDecl *>(*M);
3050 if (Overridden->getCanonicalDecl() == Method->getCanonicalDecl())
3051 continue;
3052
3053 // If we need a nested-name-specifier, add one now.
3054 if (!InContext) {
3055 NestedNameSpecifier *NNS
3056 = getRequiredQualification(S.Context, CurContext,
3057 Overridden->getDeclContext());
3058 if (NNS) {
3059 std::string Str;
3060 llvm::raw_string_ostream OS(Str);
Douglas Gregor8987b232011-09-27 23:30:47 +00003061 NNS->print(OS, Policy);
Douglas Gregordae68752011-02-01 22:57:45 +00003062 Builder.AddTextChunk(Results.getAllocator().CopyString(OS.str()));
Douglas Gregorf6961522010-08-27 21:18:54 +00003063 }
3064 } else if (!InContext->Equals(Overridden->getDeclContext()))
3065 continue;
3066
Douglas Gregordae68752011-02-01 22:57:45 +00003067 Builder.AddTypedTextChunk(Results.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00003068 Overridden->getNameAsString()));
3069 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregorf6961522010-08-27 21:18:54 +00003070 bool FirstParam = true;
3071 for (CXXMethodDecl::param_iterator P = Method->param_begin(),
3072 PEnd = Method->param_end();
3073 P != PEnd; ++P) {
3074 if (FirstParam)
3075 FirstParam = false;
3076 else
Douglas Gregor218937c2011-02-01 19:23:04 +00003077 Builder.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregorf6961522010-08-27 21:18:54 +00003078
Douglas Gregordae68752011-02-01 22:57:45 +00003079 Builder.AddPlaceholderChunk(Results.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00003080 (*P)->getIdentifier()->getName()));
Douglas Gregorf6961522010-08-27 21:18:54 +00003081 }
Douglas Gregor218937c2011-02-01 19:23:04 +00003082 Builder.AddChunk(CodeCompletionString::CK_RightParen);
3083 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregorf6961522010-08-27 21:18:54 +00003084 CCP_SuperCompletion,
Douglas Gregorba103062012-03-27 23:34:16 +00003085 CXCursor_CXXMethod,
3086 CXAvailability_Available,
3087 Overridden));
Douglas Gregorf6961522010-08-27 21:18:54 +00003088 Results.Ignore(Overridden);
3089 }
3090}
3091
Douglas Gregorc5b2e582012-01-29 18:15:03 +00003092void Sema::CodeCompleteModuleImport(SourceLocation ImportLoc,
3093 ModuleIdPath Path) {
3094 typedef CodeCompletionResult Result;
3095 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003096 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorc5b2e582012-01-29 18:15:03 +00003097 CodeCompletionContext::CCC_Other);
3098 Results.EnterNewScope();
3099
3100 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003101 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Douglas Gregorc5b2e582012-01-29 18:15:03 +00003102 typedef CodeCompletionResult Result;
3103 if (Path.empty()) {
3104 // Enumerate all top-level modules.
Dmitri Gribenkocfa88f82013-01-12 19:30:44 +00003105 SmallVector<Module *, 8> Modules;
Douglas Gregorc5b2e582012-01-29 18:15:03 +00003106 PP.getHeaderSearchInfo().collectAllModules(Modules);
3107 for (unsigned I = 0, N = Modules.size(); I != N; ++I) {
3108 Builder.AddTypedTextChunk(
3109 Builder.getAllocator().CopyString(Modules[I]->Name));
3110 Results.AddResult(Result(Builder.TakeString(),
3111 CCP_Declaration,
3112 CXCursor_NotImplemented,
3113 Modules[I]->isAvailable()
3114 ? CXAvailability_Available
3115 : CXAvailability_NotAvailable));
3116 }
3117 } else {
3118 // Load the named module.
3119 Module *Mod = PP.getModuleLoader().loadModule(ImportLoc, Path,
3120 Module::AllVisible,
3121 /*IsInclusionDirective=*/false);
3122 // Enumerate submodules.
3123 if (Mod) {
3124 for (Module::submodule_iterator Sub = Mod->submodule_begin(),
3125 SubEnd = Mod->submodule_end();
3126 Sub != SubEnd; ++Sub) {
3127
3128 Builder.AddTypedTextChunk(
3129 Builder.getAllocator().CopyString((*Sub)->Name));
3130 Results.AddResult(Result(Builder.TakeString(),
3131 CCP_Declaration,
3132 CXCursor_NotImplemented,
3133 (*Sub)->isAvailable()
3134 ? CXAvailability_Available
3135 : CXAvailability_NotAvailable));
3136 }
3137 }
3138 }
3139 Results.ExitScope();
3140 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
3141 Results.data(),Results.size());
3142}
3143
Douglas Gregor01dfea02010-01-10 23:08:15 +00003144void Sema::CodeCompleteOrdinaryName(Scope *S,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003145 ParserCompletionContext CompletionContext) {
Douglas Gregor218937c2011-02-01 19:23:04 +00003146 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003147 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00003148 mapCodeCompletionContext(*this, CompletionContext));
Douglas Gregorf6961522010-08-27 21:18:54 +00003149 Results.EnterNewScope();
Douglas Gregorcee9ff12010-09-20 22:39:41 +00003150
Douglas Gregor01dfea02010-01-10 23:08:15 +00003151 // Determine how to filter results, e.g., so that the names of
3152 // values (functions, enumerators, function templates, etc.) are
3153 // only allowed where we can have an expression.
3154 switch (CompletionContext) {
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003155 case PCC_Namespace:
3156 case PCC_Class:
3157 case PCC_ObjCInterface:
3158 case PCC_ObjCImplementation:
3159 case PCC_ObjCInstanceVariableList:
3160 case PCC_Template:
3161 case PCC_MemberTemplate:
Douglas Gregor72db1082010-08-24 01:11:00 +00003162 case PCC_Type:
Douglas Gregor68e3c2e2011-02-15 20:33:25 +00003163 case PCC_LocalDeclarationSpecifiers:
Douglas Gregor01dfea02010-01-10 23:08:15 +00003164 Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
3165 break;
3166
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003167 case PCC_Statement:
Douglas Gregor02688102010-09-14 23:59:36 +00003168 case PCC_ParenthesizedExpression:
Douglas Gregoreb0d0142010-08-24 23:58:17 +00003169 case PCC_Expression:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003170 case PCC_ForInit:
3171 case PCC_Condition:
David Blaikie4e4d0842012-03-11 07:00:24 +00003172 if (WantTypesInContext(CompletionContext, getLangOpts()))
Douglas Gregor4710e5b2010-05-28 00:49:12 +00003173 Results.setFilter(&ResultBuilder::IsOrdinaryName);
3174 else
3175 Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
Douglas Gregorf6961522010-08-27 21:18:54 +00003176
David Blaikie4e4d0842012-03-11 07:00:24 +00003177 if (getLangOpts().CPlusPlus)
Douglas Gregorf6961522010-08-27 21:18:54 +00003178 MaybeAddOverrideCalls(*this, /*InContext=*/0, Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00003179 break;
Douglas Gregordc845342010-05-25 05:58:43 +00003180
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003181 case PCC_RecoveryInFunction:
Douglas Gregordc845342010-05-25 05:58:43 +00003182 // Unfiltered
3183 break;
Douglas Gregor01dfea02010-01-10 23:08:15 +00003184 }
3185
Douglas Gregor3cdee122010-08-26 16:36:48 +00003186 // If we are in a C++ non-static member function, check the qualifiers on
3187 // the member function to filter/prioritize the results list.
3188 if (CXXMethodDecl *CurMethod = dyn_cast<CXXMethodDecl>(CurContext))
3189 if (CurMethod->isInstance())
3190 Results.setObjectTypeQualifiers(
3191 Qualifiers::fromCVRMask(CurMethod->getTypeQualifiers()));
3192
Douglas Gregor1ca6ae82010-01-14 01:09:38 +00003193 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00003194 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3195 CodeCompleter->includeGlobals());
Douglas Gregor2a7925c2009-12-07 09:54:55 +00003196
Douglas Gregorbca403c2010-01-13 23:51:12 +00003197 AddOrdinaryNameResults(CompletionContext, S, *this, Results);
Douglas Gregor2a7925c2009-12-07 09:54:55 +00003198 Results.ExitScope();
3199
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00003200 switch (CompletionContext) {
Douglas Gregor02688102010-09-14 23:59:36 +00003201 case PCC_ParenthesizedExpression:
Douglas Gregor72db1082010-08-24 01:11:00 +00003202 case PCC_Expression:
3203 case PCC_Statement:
3204 case PCC_RecoveryInFunction:
3205 if (S->getFnParent())
David Blaikie4e4d0842012-03-11 07:00:24 +00003206 AddPrettyFunctionResults(PP.getLangOpts(), Results);
Douglas Gregor72db1082010-08-24 01:11:00 +00003207 break;
3208
3209 case PCC_Namespace:
3210 case PCC_Class:
3211 case PCC_ObjCInterface:
3212 case PCC_ObjCImplementation:
3213 case PCC_ObjCInstanceVariableList:
3214 case PCC_Template:
3215 case PCC_MemberTemplate:
3216 case PCC_ForInit:
3217 case PCC_Condition:
3218 case PCC_Type:
Douglas Gregor68e3c2e2011-02-15 20:33:25 +00003219 case PCC_LocalDeclarationSpecifiers:
Douglas Gregor72db1082010-08-24 01:11:00 +00003220 break;
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00003221 }
3222
Douglas Gregor0c8296d2009-11-07 00:00:49 +00003223 if (CodeCompleter->includeMacros())
Douglas Gregor3644d972012-10-09 16:01:50 +00003224 AddMacroResults(PP, Results, false);
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00003225
Douglas Gregorcee9ff12010-09-20 22:39:41 +00003226 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003227 Results.data(),Results.size());
Douglas Gregor791215b2009-09-21 20:51:25 +00003228}
3229
Douglas Gregorc7b6d882010-09-16 15:14:18 +00003230static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
3231 ParsedType Receiver,
3232 IdentifierInfo **SelIdents,
3233 unsigned NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00003234 bool AtArgumentExpression,
Douglas Gregorc7b6d882010-09-16 15:14:18 +00003235 bool IsSuper,
3236 ResultBuilder &Results);
3237
3238void Sema::CodeCompleteDeclSpec(Scope *S, DeclSpec &DS,
3239 bool AllowNonIdentifiers,
3240 bool AllowNestedNameSpecifiers) {
John McCall0a2c5e22010-08-25 06:19:51 +00003241 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00003242 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003243 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00003244 AllowNestedNameSpecifiers
3245 ? CodeCompletionContext::CCC_PotentiallyQualifiedName
3246 : CodeCompletionContext::CCC_Name);
Douglas Gregor2ccccb32010-08-23 18:23:48 +00003247 Results.EnterNewScope();
3248
3249 // Type qualifiers can come after names.
3250 Results.AddResult(Result("const"));
3251 Results.AddResult(Result("volatile"));
David Blaikie4e4d0842012-03-11 07:00:24 +00003252 if (getLangOpts().C99)
Douglas Gregor2ccccb32010-08-23 18:23:48 +00003253 Results.AddResult(Result("restrict"));
3254
David Blaikie4e4d0842012-03-11 07:00:24 +00003255 if (getLangOpts().CPlusPlus) {
Douglas Gregor2ccccb32010-08-23 18:23:48 +00003256 if (AllowNonIdentifiers) {
3257 Results.AddResult(Result("operator"));
3258 }
3259
3260 // Add nested-name-specifiers.
3261 if (AllowNestedNameSpecifiers) {
3262 Results.allowNestedNameSpecifiers();
Douglas Gregor52779fb2010-09-23 23:01:17 +00003263 Results.setFilter(&ResultBuilder::IsImpossibleToSatisfy);
Douglas Gregor2ccccb32010-08-23 18:23:48 +00003264 CodeCompletionDeclConsumer Consumer(Results, CurContext);
3265 LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer,
3266 CodeCompleter->includeGlobals());
Douglas Gregor52779fb2010-09-23 23:01:17 +00003267 Results.setFilter(0);
Douglas Gregor2ccccb32010-08-23 18:23:48 +00003268 }
3269 }
3270 Results.ExitScope();
3271
Douglas Gregorc7b6d882010-09-16 15:14:18 +00003272 // If we're in a context where we might have an expression (rather than a
3273 // declaration), and what we've seen so far is an Objective-C type that could
3274 // be a receiver of a class message, this may be a class message send with
3275 // the initial opening bracket '[' missing. Add appropriate completions.
3276 if (AllowNonIdentifiers && !AllowNestedNameSpecifiers &&
3277 DS.getTypeSpecType() == DeclSpec::TST_typename &&
3278 DS.getStorageClassSpecAsWritten() == DeclSpec::SCS_unspecified &&
3279 !DS.isThreadSpecified() && !DS.isExternInLinkageSpec() &&
3280 DS.getTypeSpecComplex() == DeclSpec::TSC_unspecified &&
3281 DS.getTypeSpecSign() == DeclSpec::TSS_unspecified &&
3282 DS.getTypeQualifiers() == 0 &&
3283 S &&
3284 (S->getFlags() & Scope::DeclScope) != 0 &&
3285 (S->getFlags() & (Scope::ClassScope | Scope::TemplateParamScope |
3286 Scope::FunctionPrototypeScope |
3287 Scope::AtCatchScope)) == 0) {
3288 ParsedType T = DS.getRepAsType();
3289 if (!T.get().isNull() && T.get()->isObjCObjectOrInterfaceType())
Douglas Gregor70c5ac72010-09-20 23:34:21 +00003290 AddClassMessageCompletions(*this, S, T, 0, 0, false, false, Results);
Douglas Gregorc7b6d882010-09-16 15:14:18 +00003291 }
3292
Douglas Gregor4497dd42010-08-24 04:59:56 +00003293 // Note that we intentionally suppress macro results here, since we do not
3294 // encourage using macros to produce the names of entities.
3295
Douglas Gregor52779fb2010-09-23 23:01:17 +00003296 HandleCodeCompleteResults(this, CodeCompleter,
3297 Results.getCompletionContext(),
Douglas Gregor2ccccb32010-08-23 18:23:48 +00003298 Results.data(), Results.size());
3299}
3300
Douglas Gregorfb629412010-08-23 21:17:50 +00003301struct Sema::CodeCompleteExpressionData {
3302 CodeCompleteExpressionData(QualType PreferredType = QualType())
3303 : PreferredType(PreferredType), IntegralConstantExpression(false),
3304 ObjCCollection(false) { }
3305
3306 QualType PreferredType;
3307 bool IntegralConstantExpression;
3308 bool ObjCCollection;
Chris Lattner5f9e2722011-07-23 10:55:15 +00003309 SmallVector<Decl *, 4> IgnoreDecls;
Douglas Gregorfb629412010-08-23 21:17:50 +00003310};
3311
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003312/// \brief Perform code-completion in an expression context when we know what
3313/// type we're looking for.
Douglas Gregorfb629412010-08-23 21:17:50 +00003314void Sema::CodeCompleteExpression(Scope *S,
3315 const CodeCompleteExpressionData &Data) {
Douglas Gregor218937c2011-02-01 19:23:04 +00003316 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003317 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00003318 CodeCompletionContext::CCC_Expression);
Douglas Gregorfb629412010-08-23 21:17:50 +00003319 if (Data.ObjCCollection)
3320 Results.setFilter(&ResultBuilder::IsObjCCollection);
3321 else if (Data.IntegralConstantExpression)
Douglas Gregorf9578432010-07-28 21:50:18 +00003322 Results.setFilter(&ResultBuilder::IsIntegralConstantValue);
David Blaikie4e4d0842012-03-11 07:00:24 +00003323 else if (WantTypesInContext(PCC_Expression, getLangOpts()))
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003324 Results.setFilter(&ResultBuilder::IsOrdinaryName);
3325 else
3326 Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
Douglas Gregorfb629412010-08-23 21:17:50 +00003327
3328 if (!Data.PreferredType.isNull())
3329 Results.setPreferredType(Data.PreferredType.getNonReferenceType());
3330
3331 // Ignore any declarations that we were told that we don't care about.
3332 for (unsigned I = 0, N = Data.IgnoreDecls.size(); I != N; ++I)
3333 Results.Ignore(Data.IgnoreDecls[I]);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003334
3335 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00003336 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3337 CodeCompleter->includeGlobals());
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003338
3339 Results.EnterNewScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003340 AddOrdinaryNameResults(PCC_Expression, S, *this, Results);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003341 Results.ExitScope();
3342
Douglas Gregor590c7d52010-07-08 20:55:51 +00003343 bool PreferredTypeIsPointer = false;
Douglas Gregorfb629412010-08-23 21:17:50 +00003344 if (!Data.PreferredType.isNull())
3345 PreferredTypeIsPointer = Data.PreferredType->isAnyPointerType()
3346 || Data.PreferredType->isMemberPointerType()
3347 || Data.PreferredType->isBlockPointerType();
Douglas Gregor590c7d52010-07-08 20:55:51 +00003348
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00003349 if (S->getFnParent() &&
3350 !Data.ObjCCollection &&
3351 !Data.IntegralConstantExpression)
David Blaikie4e4d0842012-03-11 07:00:24 +00003352 AddPrettyFunctionResults(PP.getLangOpts(), Results);
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00003353
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003354 if (CodeCompleter->includeMacros())
Douglas Gregor3644d972012-10-09 16:01:50 +00003355 AddMacroResults(PP, Results, false, PreferredTypeIsPointer);
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003356 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregorfb629412010-08-23 21:17:50 +00003357 CodeCompletionContext(CodeCompletionContext::CCC_Expression,
3358 Data.PreferredType),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003359 Results.data(),Results.size());
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003360}
3361
Douglas Gregorac5fd842010-09-18 01:28:11 +00003362void Sema::CodeCompletePostfixExpression(Scope *S, ExprResult E) {
3363 if (E.isInvalid())
3364 CodeCompleteOrdinaryName(S, PCC_RecoveryInFunction);
David Blaikie4e4d0842012-03-11 07:00:24 +00003365 else if (getLangOpts().ObjC1)
Douglas Gregorac5fd842010-09-18 01:28:11 +00003366 CodeCompleteObjCInstanceMessage(S, E.take(), 0, 0, false);
Douglas Gregor78edf512010-09-15 16:23:04 +00003367}
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003368
Douglas Gregor73449212010-12-09 23:01:55 +00003369/// \brief The set of properties that have already been added, referenced by
3370/// property name.
3371typedef llvm::SmallPtrSet<IdentifierInfo*, 16> AddedPropertiesSet;
3372
Douglas Gregorb92a4082012-06-12 13:44:08 +00003373/// \brief Retrieve the container definition, if any?
3374static ObjCContainerDecl *getContainerDef(ObjCContainerDecl *Container) {
3375 if (ObjCInterfaceDecl *Interface = dyn_cast<ObjCInterfaceDecl>(Container)) {
3376 if (Interface->hasDefinition())
3377 return Interface->getDefinition();
3378
3379 return Interface;
3380 }
3381
3382 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
3383 if (Protocol->hasDefinition())
3384 return Protocol->getDefinition();
3385
3386 return Protocol;
3387 }
3388 return Container;
3389}
3390
3391static void AddObjCProperties(ObjCContainerDecl *Container,
Douglas Gregor322328b2009-11-18 22:32:06 +00003392 bool AllowCategories,
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003393 bool AllowNullaryMethods,
Douglas Gregor95ac6552009-11-18 01:29:26 +00003394 DeclContext *CurContext,
Douglas Gregor73449212010-12-09 23:01:55 +00003395 AddedPropertiesSet &AddedProperties,
Douglas Gregor95ac6552009-11-18 01:29:26 +00003396 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00003397 typedef CodeCompletionResult Result;
Douglas Gregor95ac6552009-11-18 01:29:26 +00003398
Douglas Gregorb92a4082012-06-12 13:44:08 +00003399 // Retrieve the definition.
3400 Container = getContainerDef(Container);
3401
Douglas Gregor95ac6552009-11-18 01:29:26 +00003402 // Add properties in this container.
3403 for (ObjCContainerDecl::prop_iterator P = Container->prop_begin(),
3404 PEnd = Container->prop_end();
3405 P != PEnd;
Douglas Gregor73449212010-12-09 23:01:55 +00003406 ++P) {
3407 if (AddedProperties.insert(P->getIdentifier()))
David Blaikie581deb32012-06-06 20:45:41 +00003408 Results.MaybeAddResult(Result(*P, 0), CurContext);
Douglas Gregor73449212010-12-09 23:01:55 +00003409 }
Douglas Gregor95ac6552009-11-18 01:29:26 +00003410
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003411 // Add nullary methods
3412 if (AllowNullaryMethods) {
3413 ASTContext &Context = Container->getASTContext();
Douglas Gregor8987b232011-09-27 23:30:47 +00003414 PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema());
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003415 for (ObjCContainerDecl::method_iterator M = Container->meth_begin(),
3416 MEnd = Container->meth_end();
3417 M != MEnd; ++M) {
3418 if (M->getSelector().isUnarySelector())
3419 if (IdentifierInfo *Name = M->getSelector().getIdentifierInfoForSlot(0))
3420 if (AddedProperties.insert(Name)) {
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003421 CodeCompletionBuilder Builder(Results.getAllocator(),
3422 Results.getCodeCompletionTUInfo());
David Blaikie581deb32012-06-06 20:45:41 +00003423 AddResultTypeChunk(Context, Policy, *M, Builder);
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003424 Builder.AddTypedTextChunk(
3425 Results.getAllocator().CopyString(Name->getName()));
3426
David Blaikie581deb32012-06-06 20:45:41 +00003427 Results.MaybeAddResult(Result(Builder.TakeString(), *M,
Douglas Gregorba103062012-03-27 23:34:16 +00003428 CCP_MemberDeclaration + CCD_MethodAsProperty),
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003429 CurContext);
3430 }
3431 }
3432 }
3433
3434
Douglas Gregor95ac6552009-11-18 01:29:26 +00003435 // Add properties in referenced protocols.
3436 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
3437 for (ObjCProtocolDecl::protocol_iterator P = Protocol->protocol_begin(),
3438 PEnd = Protocol->protocol_end();
3439 P != PEnd; ++P)
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003440 AddObjCProperties(*P, AllowCategories, AllowNullaryMethods, CurContext,
3441 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003442 } else if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)){
Douglas Gregor322328b2009-11-18 22:32:06 +00003443 if (AllowCategories) {
3444 // Look through categories.
Douglas Gregord3297242013-01-16 23:00:23 +00003445 for (ObjCInterfaceDecl::known_categories_iterator
3446 Cat = IFace->known_categories_begin(),
3447 CatEnd = IFace->known_categories_end();
3448 Cat != CatEnd; ++Cat)
3449 AddObjCProperties(*Cat, AllowCategories, AllowNullaryMethods,
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003450 CurContext, AddedProperties, Results);
Douglas Gregor322328b2009-11-18 22:32:06 +00003451 }
Douglas Gregor95ac6552009-11-18 01:29:26 +00003452
3453 // Look through protocols.
Ted Kremenek53b94412010-09-01 01:21:15 +00003454 for (ObjCInterfaceDecl::all_protocol_iterator
3455 I = IFace->all_referenced_protocol_begin(),
3456 E = IFace->all_referenced_protocol_end(); I != E; ++I)
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003457 AddObjCProperties(*I, AllowCategories, AllowNullaryMethods, CurContext,
3458 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003459
3460 // Look in the superclass.
3461 if (IFace->getSuperClass())
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003462 AddObjCProperties(IFace->getSuperClass(), AllowCategories,
3463 AllowNullaryMethods, CurContext,
Douglas Gregor73449212010-12-09 23:01:55 +00003464 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003465 } else if (const ObjCCategoryDecl *Category
3466 = dyn_cast<ObjCCategoryDecl>(Container)) {
3467 // Look through protocols.
Ted Kremenek53b94412010-09-01 01:21:15 +00003468 for (ObjCCategoryDecl::protocol_iterator P = Category->protocol_begin(),
3469 PEnd = Category->protocol_end();
Douglas Gregor95ac6552009-11-18 01:29:26 +00003470 P != PEnd; ++P)
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003471 AddObjCProperties(*P, AllowCategories, AllowNullaryMethods, CurContext,
3472 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003473 }
3474}
3475
Douglas Gregorf5cd27d2012-01-23 15:59:30 +00003476void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base,
Douglas Gregor81b747b2009-09-17 21:32:03 +00003477 SourceLocation OpLoc,
3478 bool IsArrow) {
Douglas Gregorf5cd27d2012-01-23 15:59:30 +00003479 if (!Base || !CodeCompleter)
Douglas Gregor81b747b2009-09-17 21:32:03 +00003480 return;
3481
Douglas Gregorf5cd27d2012-01-23 15:59:30 +00003482 ExprResult ConvertedBase = PerformMemberExprBaseConversion(Base, IsArrow);
3483 if (ConvertedBase.isInvalid())
3484 return;
3485 Base = ConvertedBase.get();
3486
John McCall0a2c5e22010-08-25 06:19:51 +00003487 typedef CodeCompletionResult Result;
Douglas Gregor86d9a522009-09-21 16:56:56 +00003488
Douglas Gregor81b747b2009-09-17 21:32:03 +00003489 QualType BaseType = Base->getType();
Douglas Gregor86d9a522009-09-21 16:56:56 +00003490
3491 if (IsArrow) {
3492 if (const PointerType *Ptr = BaseType->getAs<PointerType>())
3493 BaseType = Ptr->getPointeeType();
3494 else if (BaseType->isObjCObjectPointerType())
Douglas Gregor3cdee122010-08-26 16:36:48 +00003495 /*Do nothing*/ ;
Douglas Gregor86d9a522009-09-21 16:56:56 +00003496 else
3497 return;
3498 }
3499
Douglas Gregor3da626b2011-07-07 16:03:39 +00003500 enum CodeCompletionContext::Kind contextKind;
3501
3502 if (IsArrow) {
3503 contextKind = CodeCompletionContext::CCC_ArrowMemberAccess;
3504 }
3505 else {
3506 if (BaseType->isObjCObjectPointerType() ||
3507 BaseType->isObjCObjectOrInterfaceType()) {
3508 contextKind = CodeCompletionContext::CCC_ObjCPropertyAccess;
3509 }
3510 else {
3511 contextKind = CodeCompletionContext::CCC_DotMemberAccess;
3512 }
3513 }
3514
Douglas Gregor218937c2011-02-01 19:23:04 +00003515 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003516 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor3da626b2011-07-07 16:03:39 +00003517 CodeCompletionContext(contextKind,
Douglas Gregor52779fb2010-09-23 23:01:17 +00003518 BaseType),
3519 &ResultBuilder::IsMember);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003520 Results.EnterNewScope();
3521 if (const RecordType *Record = BaseType->getAs<RecordType>()) {
Douglas Gregor3cdee122010-08-26 16:36:48 +00003522 // Indicate that we are performing a member access, and the cv-qualifiers
3523 // for the base object type.
3524 Results.setObjectTypeQualifiers(BaseType.getQualifiers());
3525
Douglas Gregor95ac6552009-11-18 01:29:26 +00003526 // Access to a C/C++ class, struct, or union.
Douglas Gregor45bcd432010-01-14 03:21:49 +00003527 Results.allowNestedNameSpecifiers();
Douglas Gregor0cc84042010-01-14 15:47:35 +00003528 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00003529 LookupVisibleDecls(Record->getDecl(), LookupMemberName, Consumer,
3530 CodeCompleter->includeGlobals());
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003531
David Blaikie4e4d0842012-03-11 07:00:24 +00003532 if (getLangOpts().CPlusPlus) {
Douglas Gregor95ac6552009-11-18 01:29:26 +00003533 if (!Results.empty()) {
3534 // The "template" keyword can follow "->" or "." in the grammar.
3535 // However, we only want to suggest the template keyword if something
3536 // is dependent.
3537 bool IsDependent = BaseType->isDependentType();
3538 if (!IsDependent) {
3539 for (Scope *DepScope = S; DepScope; DepScope = DepScope->getParent())
3540 if (DeclContext *Ctx = (DeclContext *)DepScope->getEntity()) {
3541 IsDependent = Ctx->isDependentContext();
3542 break;
3543 }
3544 }
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003545
Douglas Gregor95ac6552009-11-18 01:29:26 +00003546 if (IsDependent)
Douglas Gregora4477812010-01-14 16:01:26 +00003547 Results.AddResult(Result("template"));
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003548 }
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003549 }
Douglas Gregor95ac6552009-11-18 01:29:26 +00003550 } else if (!IsArrow && BaseType->getAsObjCInterfacePointerType()) {
3551 // Objective-C property reference.
Douglas Gregor73449212010-12-09 23:01:55 +00003552 AddedPropertiesSet AddedProperties;
Douglas Gregor95ac6552009-11-18 01:29:26 +00003553
3554 // Add property results based on our interface.
3555 const ObjCObjectPointerType *ObjCPtr
3556 = BaseType->getAsObjCInterfacePointerType();
3557 assert(ObjCPtr && "Non-NULL pointer guaranteed above!");
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003558 AddObjCProperties(ObjCPtr->getInterfaceDecl(), true,
3559 /*AllowNullaryMethods=*/true, CurContext,
Douglas Gregor73449212010-12-09 23:01:55 +00003560 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003561
3562 // Add properties from the protocols in a qualified interface.
3563 for (ObjCObjectPointerType::qual_iterator I = ObjCPtr->qual_begin(),
3564 E = ObjCPtr->qual_end();
3565 I != E; ++I)
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003566 AddObjCProperties(*I, true, /*AllowNullaryMethods=*/true, CurContext,
3567 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003568 } else if ((IsArrow && BaseType->isObjCObjectPointerType()) ||
John McCallc12c5bb2010-05-15 11:32:37 +00003569 (!IsArrow && BaseType->isObjCObjectType())) {
Douglas Gregor95ac6552009-11-18 01:29:26 +00003570 // Objective-C instance variable access.
3571 ObjCInterfaceDecl *Class = 0;
3572 if (const ObjCObjectPointerType *ObjCPtr
3573 = BaseType->getAs<ObjCObjectPointerType>())
3574 Class = ObjCPtr->getInterfaceDecl();
3575 else
John McCallc12c5bb2010-05-15 11:32:37 +00003576 Class = BaseType->getAs<ObjCObjectType>()->getInterface();
Douglas Gregor95ac6552009-11-18 01:29:26 +00003577
3578 // Add all ivars from this class and its superclasses.
Douglas Gregor80f4f4c2010-01-14 16:08:12 +00003579 if (Class) {
3580 CodeCompletionDeclConsumer Consumer(Results, CurContext);
3581 Results.setFilter(&ResultBuilder::IsObjCIvar);
Douglas Gregor8071e422010-08-15 06:18:01 +00003582 LookupVisibleDecls(Class, LookupMemberName, Consumer,
3583 CodeCompleter->includeGlobals());
Douglas Gregor95ac6552009-11-18 01:29:26 +00003584 }
Douglas Gregor86d9a522009-09-21 16:56:56 +00003585 }
Douglas Gregor95ac6552009-11-18 01:29:26 +00003586
3587 // FIXME: How do we cope with isa?
3588
3589 Results.ExitScope();
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003590
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003591 // Hand off the results found for code completion.
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003592 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00003593 Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003594 Results.data(),Results.size());
Douglas Gregor81b747b2009-09-17 21:32:03 +00003595}
3596
Douglas Gregor374929f2009-09-18 15:37:17 +00003597void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) {
3598 if (!CodeCompleter)
3599 return;
3600
Douglas Gregor86d9a522009-09-21 16:56:56 +00003601 ResultBuilder::LookupFilter Filter = 0;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003602 enum CodeCompletionContext::Kind ContextKind
3603 = CodeCompletionContext::CCC_Other;
Douglas Gregor374929f2009-09-18 15:37:17 +00003604 switch ((DeclSpec::TST)TagSpec) {
3605 case DeclSpec::TST_enum:
Douglas Gregor86d9a522009-09-21 16:56:56 +00003606 Filter = &ResultBuilder::IsEnum;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003607 ContextKind = CodeCompletionContext::CCC_EnumTag;
Douglas Gregor374929f2009-09-18 15:37:17 +00003608 break;
3609
3610 case DeclSpec::TST_union:
Douglas Gregor86d9a522009-09-21 16:56:56 +00003611 Filter = &ResultBuilder::IsUnion;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003612 ContextKind = CodeCompletionContext::CCC_UnionTag;
Douglas Gregor374929f2009-09-18 15:37:17 +00003613 break;
3614
3615 case DeclSpec::TST_struct:
Douglas Gregor374929f2009-09-18 15:37:17 +00003616 case DeclSpec::TST_class:
Joao Matos6666ed42012-08-31 18:45:21 +00003617 case DeclSpec::TST_interface:
Douglas Gregor86d9a522009-09-21 16:56:56 +00003618 Filter = &ResultBuilder::IsClassOrStruct;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003619 ContextKind = CodeCompletionContext::CCC_ClassOrStructTag;
Douglas Gregor374929f2009-09-18 15:37:17 +00003620 break;
3621
3622 default:
David Blaikieb219cfc2011-09-23 05:06:16 +00003623 llvm_unreachable("Unknown type specifier kind in CodeCompleteTag");
Douglas Gregor374929f2009-09-18 15:37:17 +00003624 }
Douglas Gregor86d9a522009-09-21 16:56:56 +00003625
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003626 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3627 CodeCompleter->getCodeCompletionTUInfo(), ContextKind);
Douglas Gregor5d2fc402010-01-14 03:27:13 +00003628 CodeCompletionDeclConsumer Consumer(Results, CurContext);
John McCall0d6b1642010-04-23 18:46:30 +00003629
3630 // First pass: look for tags.
3631 Results.setFilter(Filter);
Douglas Gregor8071e422010-08-15 06:18:01 +00003632 LookupVisibleDecls(S, LookupTagName, Consumer,
3633 CodeCompleter->includeGlobals());
John McCall0d6b1642010-04-23 18:46:30 +00003634
Douglas Gregor8071e422010-08-15 06:18:01 +00003635 if (CodeCompleter->includeGlobals()) {
3636 // Second pass: look for nested name specifiers.
3637 Results.setFilter(&ResultBuilder::IsNestedNameSpecifier);
3638 LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer);
3639 }
Douglas Gregor86d9a522009-09-21 16:56:56 +00003640
Douglas Gregor52779fb2010-09-23 23:01:17 +00003641 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003642 Results.data(),Results.size());
Douglas Gregor374929f2009-09-18 15:37:17 +00003643}
3644
Douglas Gregor1a480c42010-08-27 17:35:51 +00003645void Sema::CodeCompleteTypeQualifiers(DeclSpec &DS) {
Douglas Gregor218937c2011-02-01 19:23:04 +00003646 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003647 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00003648 CodeCompletionContext::CCC_TypeQualifiers);
Douglas Gregor1a480c42010-08-27 17:35:51 +00003649 Results.EnterNewScope();
3650 if (!(DS.getTypeQualifiers() & DeclSpec::TQ_const))
3651 Results.AddResult("const");
3652 if (!(DS.getTypeQualifiers() & DeclSpec::TQ_volatile))
3653 Results.AddResult("volatile");
David Blaikie4e4d0842012-03-11 07:00:24 +00003654 if (getLangOpts().C99 &&
Douglas Gregor1a480c42010-08-27 17:35:51 +00003655 !(DS.getTypeQualifiers() & DeclSpec::TQ_restrict))
3656 Results.AddResult("restrict");
3657 Results.ExitScope();
3658 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00003659 Results.getCompletionContext(),
Douglas Gregor1a480c42010-08-27 17:35:51 +00003660 Results.data(), Results.size());
3661}
3662
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003663void Sema::CodeCompleteCase(Scope *S) {
John McCall781472f2010-08-25 08:40:02 +00003664 if (getCurFunction()->SwitchStack.empty() || !CodeCompleter)
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003665 return;
John McCalla8e0cd82011-08-06 07:30:58 +00003666
John McCall781472f2010-08-25 08:40:02 +00003667 SwitchStmt *Switch = getCurFunction()->SwitchStack.back();
John McCalla8e0cd82011-08-06 07:30:58 +00003668 QualType type = Switch->getCond()->IgnoreImplicit()->getType();
3669 if (!type->isEnumeralType()) {
3670 CodeCompleteExpressionData Data(type);
Douglas Gregorfb629412010-08-23 21:17:50 +00003671 Data.IntegralConstantExpression = true;
3672 CodeCompleteExpression(S, Data);
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003673 return;
Douglas Gregorf9578432010-07-28 21:50:18 +00003674 }
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003675
3676 // Code-complete the cases of a switch statement over an enumeration type
3677 // by providing the list of
John McCalla8e0cd82011-08-06 07:30:58 +00003678 EnumDecl *Enum = type->castAs<EnumType>()->getDecl();
Douglas Gregorb92a4082012-06-12 13:44:08 +00003679 if (EnumDecl *Def = Enum->getDefinition())
3680 Enum = Def;
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003681
3682 // Determine which enumerators we have already seen in the switch statement.
3683 // FIXME: Ideally, we would also be able to look *past* the code-completion
3684 // token, in case we are code-completing in the middle of the switch and not
3685 // at the end. However, we aren't able to do so at the moment.
3686 llvm::SmallPtrSet<EnumConstantDecl *, 8> EnumeratorsSeen;
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00003687 NestedNameSpecifier *Qualifier = 0;
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003688 for (SwitchCase *SC = Switch->getSwitchCaseList(); SC;
3689 SC = SC->getNextSwitchCase()) {
3690 CaseStmt *Case = dyn_cast<CaseStmt>(SC);
3691 if (!Case)
3692 continue;
3693
3694 Expr *CaseVal = Case->getLHS()->IgnoreParenCasts();
3695 if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CaseVal))
3696 if (EnumConstantDecl *Enumerator
3697 = dyn_cast<EnumConstantDecl>(DRE->getDecl())) {
3698 // We look into the AST of the case statement to determine which
3699 // enumerator was named. Alternatively, we could compute the value of
3700 // the integral constant expression, then compare it against the
3701 // values of each enumerator. However, value-based approach would not
3702 // work as well with C++ templates where enumerators declared within a
3703 // template are type- and value-dependent.
3704 EnumeratorsSeen.insert(Enumerator);
3705
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00003706 // If this is a qualified-id, keep track of the nested-name-specifier
3707 // so that we can reproduce it as part of code completion, e.g.,
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003708 //
3709 // switch (TagD.getKind()) {
3710 // case TagDecl::TK_enum:
3711 // break;
3712 // case XXX
3713 //
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00003714 // At the XXX, our completions are TagDecl::TK_union,
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003715 // TagDecl::TK_struct, and TagDecl::TK_class, rather than TK_union,
3716 // TK_struct, and TK_class.
Douglas Gregora2813ce2009-10-23 18:54:35 +00003717 Qualifier = DRE->getQualifier();
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003718 }
3719 }
3720
David Blaikie4e4d0842012-03-11 07:00:24 +00003721 if (getLangOpts().CPlusPlus && !Qualifier && EnumeratorsSeen.empty()) {
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00003722 // If there are no prior enumerators in C++, check whether we have to
3723 // qualify the names of the enumerators that we suggest, because they
3724 // may not be visible in this scope.
Douglas Gregorb223d8c2012-02-01 05:02:47 +00003725 Qualifier = getRequiredQualification(Context, CurContext, Enum);
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00003726 }
3727
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003728 // Add any enumerators that have not yet been mentioned.
Douglas Gregor218937c2011-02-01 19:23:04 +00003729 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003730 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00003731 CodeCompletionContext::CCC_Expression);
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003732 Results.EnterNewScope();
3733 for (EnumDecl::enumerator_iterator E = Enum->enumerator_begin(),
3734 EEnd = Enum->enumerator_end();
3735 E != EEnd; ++E) {
David Blaikie581deb32012-06-06 20:45:41 +00003736 if (EnumeratorsSeen.count(*E))
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003737 continue;
3738
David Blaikie581deb32012-06-06 20:45:41 +00003739 CodeCompletionResult R(*E, Qualifier);
Douglas Gregor5c722c702011-02-18 23:30:37 +00003740 R.Priority = CCP_EnumInCase;
3741 Results.AddResult(R, CurContext, 0, false);
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003742 }
3743 Results.ExitScope();
Douglas Gregor2f880e42010-04-06 20:02:15 +00003744
Douglas Gregor3da626b2011-07-07 16:03:39 +00003745 //We need to make sure we're setting the right context,
3746 //so only say we include macros if the code completer says we do
3747 enum CodeCompletionContext::Kind kind = CodeCompletionContext::CCC_Other;
3748 if (CodeCompleter->includeMacros()) {
Douglas Gregor3644d972012-10-09 16:01:50 +00003749 AddMacroResults(PP, Results, false);
Douglas Gregor3da626b2011-07-07 16:03:39 +00003750 kind = CodeCompletionContext::CCC_OtherWithMacros;
3751 }
3752
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003753 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor3da626b2011-07-07 16:03:39 +00003754 kind,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003755 Results.data(),Results.size());
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003756}
3757
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003758namespace {
3759 struct IsBetterOverloadCandidate {
3760 Sema &S;
John McCall5769d612010-02-08 23:07:23 +00003761 SourceLocation Loc;
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003762
3763 public:
John McCall5769d612010-02-08 23:07:23 +00003764 explicit IsBetterOverloadCandidate(Sema &S, SourceLocation Loc)
3765 : S(S), Loc(Loc) { }
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003766
3767 bool
3768 operator()(const OverloadCandidate &X, const OverloadCandidate &Y) const {
John McCall120d63c2010-08-24 20:38:10 +00003769 return isBetterOverloadCandidate(S, X, Y, Loc);
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003770 }
3771 };
3772}
3773
Ahmed Charles13a140c2012-02-25 11:00:22 +00003774static bool anyNullArguments(llvm::ArrayRef<Expr*> Args) {
3775 if (Args.size() && !Args.data())
Douglas Gregord28dcd72010-05-30 06:10:08 +00003776 return true;
Ahmed Charles13a140c2012-02-25 11:00:22 +00003777
3778 for (unsigned I = 0; I != Args.size(); ++I)
Douglas Gregord28dcd72010-05-30 06:10:08 +00003779 if (!Args[I])
3780 return true;
Ahmed Charles13a140c2012-02-25 11:00:22 +00003781
Douglas Gregord28dcd72010-05-30 06:10:08 +00003782 return false;
3783}
3784
Richard Trieuf81e5a92011-09-09 02:00:50 +00003785void Sema::CodeCompleteCall(Scope *S, Expr *FnIn,
Ahmed Charles13a140c2012-02-25 11:00:22 +00003786 llvm::ArrayRef<Expr *> Args) {
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003787 if (!CodeCompleter)
3788 return;
Douglas Gregoref96eac2009-12-11 19:06:04 +00003789
3790 // When we're code-completing for a call, we fall back to ordinary
3791 // name code-completion whenever we can't produce specific
3792 // results. We may want to revisit this strategy in the future,
3793 // e.g., by merging the two kinds of results.
3794
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003795 Expr *Fn = (Expr *)FnIn;
Douglas Gregoref96eac2009-12-11 19:06:04 +00003796
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003797 // Ignore type-dependent call expressions entirely.
Ahmed Charles13a140c2012-02-25 11:00:22 +00003798 if (!Fn || Fn->isTypeDependent() || anyNullArguments(Args) ||
3799 Expr::hasAnyTypeDependentArguments(Args)) {
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003800 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003801 return;
Douglas Gregoref96eac2009-12-11 19:06:04 +00003802 }
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003803
John McCall3b4294e2009-12-16 12:17:52 +00003804 // Build an overload candidate set based on the functions we find.
John McCall5769d612010-02-08 23:07:23 +00003805 SourceLocation Loc = Fn->getExprLoc();
3806 OverloadCandidateSet CandidateSet(Loc);
John McCall3b4294e2009-12-16 12:17:52 +00003807
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003808 // FIXME: What if we're calling something that isn't a function declaration?
3809 // FIXME: What if we're calling a pseudo-destructor?
3810 // FIXME: What if we're calling a member function?
3811
Douglas Gregorc0265402010-01-21 15:46:19 +00003812 typedef CodeCompleteConsumer::OverloadCandidate ResultCandidate;
Chris Lattner5f9e2722011-07-23 10:55:15 +00003813 SmallVector<ResultCandidate, 8> Results;
Douglas Gregorc0265402010-01-21 15:46:19 +00003814
John McCall3b4294e2009-12-16 12:17:52 +00003815 Expr *NakedFn = Fn->IgnoreParenCasts();
3816 if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(NakedFn))
Ahmed Charles13a140c2012-02-25 11:00:22 +00003817 AddOverloadedCallCandidates(ULE, Args, CandidateSet,
John McCall3b4294e2009-12-16 12:17:52 +00003818 /*PartialOverloading=*/ true);
3819 else if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(NakedFn)) {
3820 FunctionDecl *FDecl = dyn_cast<FunctionDecl>(DRE->getDecl());
Douglas Gregorc0265402010-01-21 15:46:19 +00003821 if (FDecl) {
David Blaikie4e4d0842012-03-11 07:00:24 +00003822 if (!getLangOpts().CPlusPlus ||
Douglas Gregord28dcd72010-05-30 06:10:08 +00003823 !FDecl->getType()->getAs<FunctionProtoType>())
Douglas Gregorc0265402010-01-21 15:46:19 +00003824 Results.push_back(ResultCandidate(FDecl));
3825 else
John McCall86820f52010-01-26 01:37:31 +00003826 // FIXME: access?
Ahmed Charles13a140c2012-02-25 11:00:22 +00003827 AddOverloadCandidate(FDecl, DeclAccessPair::make(FDecl, AS_none), Args,
3828 CandidateSet, false, /*PartialOverloading*/true);
Douglas Gregorc0265402010-01-21 15:46:19 +00003829 }
John McCall3b4294e2009-12-16 12:17:52 +00003830 }
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003831
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003832 QualType ParamType;
3833
Douglas Gregorc0265402010-01-21 15:46:19 +00003834 if (!CandidateSet.empty()) {
3835 // Sort the overload candidate set by placing the best overloads first.
3836 std::stable_sort(CandidateSet.begin(), CandidateSet.end(),
John McCall5769d612010-02-08 23:07:23 +00003837 IsBetterOverloadCandidate(*this, Loc));
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003838
Douglas Gregorc0265402010-01-21 15:46:19 +00003839 // Add the remaining viable overload candidates as code-completion reslults.
3840 for (OverloadCandidateSet::iterator Cand = CandidateSet.begin(),
3841 CandEnd = CandidateSet.end();
3842 Cand != CandEnd; ++Cand) {
3843 if (Cand->Viable)
3844 Results.push_back(ResultCandidate(Cand->Function));
3845 }
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003846
3847 // From the viable candidates, try to determine the type of this parameter.
3848 for (unsigned I = 0, N = Results.size(); I != N; ++I) {
3849 if (const FunctionType *FType = Results[I].getFunctionType())
3850 if (const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FType))
Ahmed Charles13a140c2012-02-25 11:00:22 +00003851 if (Args.size() < Proto->getNumArgs()) {
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003852 if (ParamType.isNull())
Ahmed Charles13a140c2012-02-25 11:00:22 +00003853 ParamType = Proto->getArgType(Args.size());
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003854 else if (!Context.hasSameUnqualifiedType(
3855 ParamType.getNonReferenceType(),
Ahmed Charles13a140c2012-02-25 11:00:22 +00003856 Proto->getArgType(Args.size()).getNonReferenceType())) {
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003857 ParamType = QualType();
3858 break;
3859 }
3860 }
3861 }
3862 } else {
3863 // Try to determine the parameter type from the type of the expression
3864 // being called.
3865 QualType FunctionType = Fn->getType();
3866 if (const PointerType *Ptr = FunctionType->getAs<PointerType>())
3867 FunctionType = Ptr->getPointeeType();
3868 else if (const BlockPointerType *BlockPtr
3869 = FunctionType->getAs<BlockPointerType>())
3870 FunctionType = BlockPtr->getPointeeType();
3871 else if (const MemberPointerType *MemPtr
3872 = FunctionType->getAs<MemberPointerType>())
3873 FunctionType = MemPtr->getPointeeType();
3874
3875 if (const FunctionProtoType *Proto
3876 = FunctionType->getAs<FunctionProtoType>()) {
Ahmed Charles13a140c2012-02-25 11:00:22 +00003877 if (Args.size() < Proto->getNumArgs())
3878 ParamType = Proto->getArgType(Args.size());
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003879 }
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003880 }
Douglas Gregoref96eac2009-12-11 19:06:04 +00003881
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003882 if (ParamType.isNull())
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003883 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003884 else
3885 CodeCompleteExpression(S, ParamType);
3886
Douglas Gregor2e4c7a52010-04-06 20:19:47 +00003887 if (!Results.empty())
Ahmed Charles13a140c2012-02-25 11:00:22 +00003888 CodeCompleter->ProcessOverloadCandidates(*this, Args.size(), Results.data(),
Douglas Gregoref96eac2009-12-11 19:06:04 +00003889 Results.size());
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003890}
3891
John McCalld226f652010-08-21 09:40:31 +00003892void Sema::CodeCompleteInitializer(Scope *S, Decl *D) {
3893 ValueDecl *VD = dyn_cast_or_null<ValueDecl>(D);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003894 if (!VD) {
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003895 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003896 return;
3897 }
3898
3899 CodeCompleteExpression(S, VD->getType());
3900}
3901
3902void Sema::CodeCompleteReturn(Scope *S) {
3903 QualType ResultType;
3904 if (isa<BlockDecl>(CurContext)) {
3905 if (BlockScopeInfo *BSI = getCurBlock())
3906 ResultType = BSI->ReturnType;
3907 } else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(CurContext))
3908 ResultType = Function->getResultType();
3909 else if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(CurContext))
3910 ResultType = Method->getResultType();
3911
3912 if (ResultType.isNull())
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003913 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003914 else
3915 CodeCompleteExpression(S, ResultType);
3916}
3917
Douglas Gregord2d8be62011-07-30 08:36:53 +00003918void Sema::CodeCompleteAfterIf(Scope *S) {
Douglas Gregord2d8be62011-07-30 08:36:53 +00003919 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003920 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregord2d8be62011-07-30 08:36:53 +00003921 mapCodeCompletionContext(*this, PCC_Statement));
3922 Results.setFilter(&ResultBuilder::IsOrdinaryName);
3923 Results.EnterNewScope();
3924
3925 CodeCompletionDeclConsumer Consumer(Results, CurContext);
3926 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3927 CodeCompleter->includeGlobals());
3928
3929 AddOrdinaryNameResults(PCC_Statement, S, *this, Results);
3930
3931 // "else" block
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003932 CodeCompletionBuilder Builder(Results.getAllocator(),
3933 Results.getCodeCompletionTUInfo());
Douglas Gregord2d8be62011-07-30 08:36:53 +00003934 Builder.AddTypedTextChunk("else");
Douglas Gregorf11641a2012-02-16 17:49:04 +00003935 if (Results.includeCodePatterns()) {
3936 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3937 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
3938 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
3939 Builder.AddPlaceholderChunk("statements");
3940 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
3941 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
3942 }
Douglas Gregord2d8be62011-07-30 08:36:53 +00003943 Results.AddResult(Builder.TakeString());
3944
3945 // "else if" block
3946 Builder.AddTypedTextChunk("else");
3947 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3948 Builder.AddTextChunk("if");
3949 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3950 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikie4e4d0842012-03-11 07:00:24 +00003951 if (getLangOpts().CPlusPlus)
Douglas Gregord2d8be62011-07-30 08:36:53 +00003952 Builder.AddPlaceholderChunk("condition");
3953 else
3954 Builder.AddPlaceholderChunk("expression");
3955 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorf11641a2012-02-16 17:49:04 +00003956 if (Results.includeCodePatterns()) {
3957 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3958 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
3959 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
3960 Builder.AddPlaceholderChunk("statements");
3961 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
3962 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
3963 }
Douglas Gregord2d8be62011-07-30 08:36:53 +00003964 Results.AddResult(Builder.TakeString());
3965
3966 Results.ExitScope();
3967
3968 if (S->getFnParent())
David Blaikie4e4d0842012-03-11 07:00:24 +00003969 AddPrettyFunctionResults(PP.getLangOpts(), Results);
Douglas Gregord2d8be62011-07-30 08:36:53 +00003970
3971 if (CodeCompleter->includeMacros())
Douglas Gregor3644d972012-10-09 16:01:50 +00003972 AddMacroResults(PP, Results, false);
Douglas Gregord2d8be62011-07-30 08:36:53 +00003973
3974 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
3975 Results.data(),Results.size());
3976}
3977
Richard Trieuf81e5a92011-09-09 02:00:50 +00003978void Sema::CodeCompleteAssignmentRHS(Scope *S, Expr *LHS) {
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003979 if (LHS)
3980 CodeCompleteExpression(S, static_cast<Expr *>(LHS)->getType());
3981 else
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003982 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003983}
3984
Jeffrey Yasskin9ab14542010-04-08 16:38:48 +00003985void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS,
Douglas Gregor81b747b2009-09-17 21:32:03 +00003986 bool EnteringContext) {
3987 if (!SS.getScopeRep() || !CodeCompleter)
3988 return;
3989
Douglas Gregor86d9a522009-09-21 16:56:56 +00003990 DeclContext *Ctx = computeDeclContext(SS, EnteringContext);
3991 if (!Ctx)
3992 return;
Douglas Gregord1cd31a2009-12-11 18:28:39 +00003993
3994 // Try to instantiate any non-dependent declaration contexts before
3995 // we look in them.
John McCall77bb1aa2010-05-01 00:40:08 +00003996 if (!isDependentScopeSpecifier(SS) && RequireCompleteDeclContext(SS, Ctx))
Douglas Gregord1cd31a2009-12-11 18:28:39 +00003997 return;
3998
Douglas Gregor218937c2011-02-01 19:23:04 +00003999 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004000 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004001 CodeCompletionContext::CCC_Name);
Douglas Gregorf6961522010-08-27 21:18:54 +00004002 Results.EnterNewScope();
Douglas Gregor52779fb2010-09-23 23:01:17 +00004003
Douglas Gregor86d9a522009-09-21 16:56:56 +00004004 // The "template" keyword can follow "::" in the grammar, but only
4005 // put it into the grammar if the nested-name-specifier is dependent.
4006 NestedNameSpecifier *NNS = (NestedNameSpecifier *)SS.getScopeRep();
4007 if (!Results.empty() && NNS->isDependent())
Douglas Gregora4477812010-01-14 16:01:26 +00004008 Results.AddResult("template");
Douglas Gregorf6961522010-08-27 21:18:54 +00004009
4010 // Add calls to overridden virtual functions, if there are any.
4011 //
4012 // FIXME: This isn't wonderful, because we don't know whether we're actually
4013 // in a context that permits expressions. This is a general issue with
4014 // qualified-id completions.
4015 if (!EnteringContext)
4016 MaybeAddOverrideCalls(*this, Ctx, Results);
4017 Results.ExitScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00004018
Douglas Gregorf6961522010-08-27 21:18:54 +00004019 CodeCompletionDeclConsumer Consumer(Results, CurContext);
4020 LookupVisibleDecls(Ctx, LookupOrdinaryName, Consumer);
4021
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004022 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor430d7a12011-07-25 17:48:11 +00004023 Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004024 Results.data(),Results.size());
Douglas Gregor81b747b2009-09-17 21:32:03 +00004025}
Douglas Gregor49f40bd2009-09-18 19:03:04 +00004026
4027void Sema::CodeCompleteUsing(Scope *S) {
4028 if (!CodeCompleter)
4029 return;
4030
Douglas Gregor218937c2011-02-01 19:23:04 +00004031 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004032 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00004033 CodeCompletionContext::CCC_PotentiallyQualifiedName,
4034 &ResultBuilder::IsNestedNameSpecifier);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004035 Results.EnterNewScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00004036
4037 // If we aren't in class scope, we could see the "namespace" keyword.
4038 if (!S->isClassScope())
John McCall0a2c5e22010-08-25 06:19:51 +00004039 Results.AddResult(CodeCompletionResult("namespace"));
Douglas Gregor86d9a522009-09-21 16:56:56 +00004040
4041 // After "using", we can see anything that would start a
4042 // nested-name-specifier.
Douglas Gregor5d2fc402010-01-14 03:27:13 +00004043 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00004044 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4045 CodeCompleter->includeGlobals());
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004046 Results.ExitScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00004047
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004048 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00004049 CodeCompletionContext::CCC_PotentiallyQualifiedName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004050 Results.data(),Results.size());
Douglas Gregor49f40bd2009-09-18 19:03:04 +00004051}
4052
4053void Sema::CodeCompleteUsingDirective(Scope *S) {
4054 if (!CodeCompleter)
4055 return;
4056
Douglas Gregor86d9a522009-09-21 16:56:56 +00004057 // After "using namespace", we expect to see a namespace name or namespace
4058 // alias.
Douglas Gregor218937c2011-02-01 19:23:04 +00004059 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004060 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004061 CodeCompletionContext::CCC_Namespace,
Douglas Gregor52779fb2010-09-23 23:01:17 +00004062 &ResultBuilder::IsNamespaceOrAlias);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004063 Results.EnterNewScope();
Douglas Gregor5d2fc402010-01-14 03:27:13 +00004064 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00004065 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4066 CodeCompleter->includeGlobals());
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004067 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004068 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor8071e422010-08-15 06:18:01 +00004069 CodeCompletionContext::CCC_Namespace,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004070 Results.data(),Results.size());
Douglas Gregor49f40bd2009-09-18 19:03:04 +00004071}
4072
4073void Sema::CodeCompleteNamespaceDecl(Scope *S) {
4074 if (!CodeCompleter)
4075 return;
4076
Douglas Gregor86d9a522009-09-21 16:56:56 +00004077 DeclContext *Ctx = (DeclContext *)S->getEntity();
4078 if (!S->getParent())
4079 Ctx = Context.getTranslationUnitDecl();
4080
Douglas Gregor52779fb2010-09-23 23:01:17 +00004081 bool SuppressedGlobalResults
4082 = Ctx && !CodeCompleter->includeGlobals() && isa<TranslationUnitDecl>(Ctx);
4083
Douglas Gregor218937c2011-02-01 19:23:04 +00004084 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004085 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00004086 SuppressedGlobalResults
4087 ? CodeCompletionContext::CCC_Namespace
4088 : CodeCompletionContext::CCC_Other,
4089 &ResultBuilder::IsNamespace);
4090
4091 if (Ctx && Ctx->isFileContext() && !SuppressedGlobalResults) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00004092 // We only want to see those namespaces that have already been defined
4093 // within this scope, because its likely that the user is creating an
4094 // extended namespace declaration. Keep track of the most recent
4095 // definition of each namespace.
4096 std::map<NamespaceDecl *, NamespaceDecl *> OrigToLatest;
4097 for (DeclContext::specific_decl_iterator<NamespaceDecl>
4098 NS(Ctx->decls_begin()), NSEnd(Ctx->decls_end());
4099 NS != NSEnd; ++NS)
David Blaikie581deb32012-06-06 20:45:41 +00004100 OrigToLatest[NS->getOriginalNamespace()] = *NS;
Douglas Gregor86d9a522009-09-21 16:56:56 +00004101
4102 // Add the most recent definition (or extended definition) of each
4103 // namespace to the list of results.
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004104 Results.EnterNewScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00004105 for (std::map<NamespaceDecl *, NamespaceDecl *>::iterator
Douglas Gregorba103062012-03-27 23:34:16 +00004106 NS = OrigToLatest.begin(),
4107 NSEnd = OrigToLatest.end();
Douglas Gregor86d9a522009-09-21 16:56:56 +00004108 NS != NSEnd; ++NS)
John McCall0a2c5e22010-08-25 06:19:51 +00004109 Results.AddResult(CodeCompletionResult(NS->second, 0),
Douglas Gregor608300b2010-01-14 16:14:35 +00004110 CurContext, 0, false);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004111 Results.ExitScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00004112 }
4113
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004114 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00004115 Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004116 Results.data(),Results.size());
Douglas Gregor49f40bd2009-09-18 19:03:04 +00004117}
4118
4119void Sema::CodeCompleteNamespaceAliasDecl(Scope *S) {
4120 if (!CodeCompleter)
4121 return;
4122
Douglas Gregor86d9a522009-09-21 16:56:56 +00004123 // After "namespace", we expect to see a namespace or alias.
Douglas Gregor218937c2011-02-01 19:23:04 +00004124 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004125 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004126 CodeCompletionContext::CCC_Namespace,
Douglas Gregor52779fb2010-09-23 23:01:17 +00004127 &ResultBuilder::IsNamespaceOrAlias);
Douglas Gregor5d2fc402010-01-14 03:27:13 +00004128 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00004129 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4130 CodeCompleter->includeGlobals());
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004131 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00004132 Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004133 Results.data(),Results.size());
Douglas Gregor49f40bd2009-09-18 19:03:04 +00004134}
4135
Douglas Gregored8d3222009-09-18 20:05:18 +00004136void Sema::CodeCompleteOperatorName(Scope *S) {
4137 if (!CodeCompleter)
4138 return;
Douglas Gregor86d9a522009-09-21 16:56:56 +00004139
John McCall0a2c5e22010-08-25 06:19:51 +00004140 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00004141 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004142 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004143 CodeCompletionContext::CCC_Type,
Douglas Gregor52779fb2010-09-23 23:01:17 +00004144 &ResultBuilder::IsType);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004145 Results.EnterNewScope();
Douglas Gregored8d3222009-09-18 20:05:18 +00004146
Douglas Gregor86d9a522009-09-21 16:56:56 +00004147 // Add the names of overloadable operators.
4148#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
4149 if (std::strcmp(Spelling, "?")) \
Douglas Gregora4477812010-01-14 16:01:26 +00004150 Results.AddResult(Result(Spelling));
Douglas Gregor86d9a522009-09-21 16:56:56 +00004151#include "clang/Basic/OperatorKinds.def"
4152
4153 // Add any type names visible from the current scope
Douglas Gregor45bcd432010-01-14 03:21:49 +00004154 Results.allowNestedNameSpecifiers();
Douglas Gregor5d2fc402010-01-14 03:27:13 +00004155 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00004156 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4157 CodeCompleter->includeGlobals());
Douglas Gregor86d9a522009-09-21 16:56:56 +00004158
4159 // Add any type specifiers
David Blaikie4e4d0842012-03-11 07:00:24 +00004160 AddTypeSpecifierResults(getLangOpts(), Results);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004161 Results.ExitScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00004162
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004163 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor8071e422010-08-15 06:18:01 +00004164 CodeCompletionContext::CCC_Type,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004165 Results.data(),Results.size());
Douglas Gregored8d3222009-09-18 20:05:18 +00004166}
Douglas Gregor49f40bd2009-09-18 19:03:04 +00004167
Douglas Gregor0133f522010-08-28 00:00:50 +00004168void Sema::CodeCompleteConstructorInitializer(Decl *ConstructorD,
Sean Huntcbb67482011-01-08 20:30:50 +00004169 CXXCtorInitializer** Initializers,
Douglas Gregor0133f522010-08-28 00:00:50 +00004170 unsigned NumInitializers) {
Douglas Gregor8987b232011-09-27 23:30:47 +00004171 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Douglas Gregor0133f522010-08-28 00:00:50 +00004172 CXXConstructorDecl *Constructor
4173 = static_cast<CXXConstructorDecl *>(ConstructorD);
4174 if (!Constructor)
4175 return;
4176
Douglas Gregor218937c2011-02-01 19:23:04 +00004177 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004178 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00004179 CodeCompletionContext::CCC_PotentiallyQualifiedName);
Douglas Gregor0133f522010-08-28 00:00:50 +00004180 Results.EnterNewScope();
4181
4182 // Fill in any already-initialized fields or base classes.
4183 llvm::SmallPtrSet<FieldDecl *, 4> InitializedFields;
4184 llvm::SmallPtrSet<CanQualType, 4> InitializedBases;
4185 for (unsigned I = 0; I != NumInitializers; ++I) {
4186 if (Initializers[I]->isBaseInitializer())
4187 InitializedBases.insert(
4188 Context.getCanonicalType(QualType(Initializers[I]->getBaseClass(), 0)));
4189 else
Francois Pichet00eb3f92010-12-04 09:14:42 +00004190 InitializedFields.insert(cast<FieldDecl>(
4191 Initializers[I]->getAnyMember()));
Douglas Gregor0133f522010-08-28 00:00:50 +00004192 }
4193
4194 // Add completions for base classes.
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004195 CodeCompletionBuilder Builder(Results.getAllocator(),
4196 Results.getCodeCompletionTUInfo());
Douglas Gregor0c431c82010-08-29 19:27:27 +00004197 bool SawLastInitializer = (NumInitializers == 0);
Douglas Gregor0133f522010-08-28 00:00:50 +00004198 CXXRecordDecl *ClassDecl = Constructor->getParent();
4199 for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),
4200 BaseEnd = ClassDecl->bases_end();
4201 Base != BaseEnd; ++Base) {
Douglas Gregor0c431c82010-08-29 19:27:27 +00004202 if (!InitializedBases.insert(Context.getCanonicalType(Base->getType()))) {
4203 SawLastInitializer
4204 = NumInitializers > 0 &&
4205 Initializers[NumInitializers - 1]->isBaseInitializer() &&
4206 Context.hasSameUnqualifiedType(Base->getType(),
4207 QualType(Initializers[NumInitializers - 1]->getBaseClass(), 0));
Douglas Gregor0133f522010-08-28 00:00:50 +00004208 continue;
Douglas Gregor0c431c82010-08-29 19:27:27 +00004209 }
Douglas Gregor0133f522010-08-28 00:00:50 +00004210
Douglas Gregor218937c2011-02-01 19:23:04 +00004211 Builder.AddTypedTextChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00004212 Results.getAllocator().CopyString(
John McCallf85e1932011-06-15 23:02:42 +00004213 Base->getType().getAsString(Policy)));
Douglas Gregor218937c2011-02-01 19:23:04 +00004214 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4215 Builder.AddPlaceholderChunk("args");
4216 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4217 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor0c431c82010-08-29 19:27:27 +00004218 SawLastInitializer? CCP_NextInitializer
4219 : CCP_MemberDeclaration));
4220 SawLastInitializer = false;
Douglas Gregor0133f522010-08-28 00:00:50 +00004221 }
4222
4223 // Add completions for virtual base classes.
4224 for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(),
4225 BaseEnd = ClassDecl->vbases_end();
4226 Base != BaseEnd; ++Base) {
Douglas Gregor0c431c82010-08-29 19:27:27 +00004227 if (!InitializedBases.insert(Context.getCanonicalType(Base->getType()))) {
4228 SawLastInitializer
4229 = NumInitializers > 0 &&
4230 Initializers[NumInitializers - 1]->isBaseInitializer() &&
4231 Context.hasSameUnqualifiedType(Base->getType(),
4232 QualType(Initializers[NumInitializers - 1]->getBaseClass(), 0));
Douglas Gregor0133f522010-08-28 00:00:50 +00004233 continue;
Douglas Gregor0c431c82010-08-29 19:27:27 +00004234 }
Douglas Gregor0133f522010-08-28 00:00:50 +00004235
Douglas Gregor218937c2011-02-01 19:23:04 +00004236 Builder.AddTypedTextChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00004237 Builder.getAllocator().CopyString(
John McCallf85e1932011-06-15 23:02:42 +00004238 Base->getType().getAsString(Policy)));
Douglas Gregor218937c2011-02-01 19:23:04 +00004239 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4240 Builder.AddPlaceholderChunk("args");
4241 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4242 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor0c431c82010-08-29 19:27:27 +00004243 SawLastInitializer? CCP_NextInitializer
4244 : CCP_MemberDeclaration));
4245 SawLastInitializer = false;
Douglas Gregor0133f522010-08-28 00:00:50 +00004246 }
4247
4248 // Add completions for members.
4249 for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
4250 FieldEnd = ClassDecl->field_end();
4251 Field != FieldEnd; ++Field) {
Douglas Gregor0c431c82010-08-29 19:27:27 +00004252 if (!InitializedFields.insert(cast<FieldDecl>(Field->getCanonicalDecl()))) {
4253 SawLastInitializer
4254 = NumInitializers > 0 &&
Francois Pichet00eb3f92010-12-04 09:14:42 +00004255 Initializers[NumInitializers - 1]->isAnyMemberInitializer() &&
David Blaikie581deb32012-06-06 20:45:41 +00004256 Initializers[NumInitializers - 1]->getAnyMember() == *Field;
Douglas Gregor0133f522010-08-28 00:00:50 +00004257 continue;
Douglas Gregor0c431c82010-08-29 19:27:27 +00004258 }
Douglas Gregor0133f522010-08-28 00:00:50 +00004259
4260 if (!Field->getDeclName())
4261 continue;
4262
Douglas Gregordae68752011-02-01 22:57:45 +00004263 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00004264 Field->getIdentifier()->getName()));
4265 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4266 Builder.AddPlaceholderChunk("args");
4267 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4268 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor0c431c82010-08-29 19:27:27 +00004269 SawLastInitializer? CCP_NextInitializer
Douglas Gregora67e03f2010-09-09 21:42:20 +00004270 : CCP_MemberDeclaration,
Douglas Gregorba103062012-03-27 23:34:16 +00004271 CXCursor_MemberRef,
4272 CXAvailability_Available,
David Blaikie581deb32012-06-06 20:45:41 +00004273 *Field));
Douglas Gregor0c431c82010-08-29 19:27:27 +00004274 SawLastInitializer = false;
Douglas Gregor0133f522010-08-28 00:00:50 +00004275 }
4276 Results.ExitScope();
4277
Douglas Gregor52779fb2010-09-23 23:01:17 +00004278 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor0133f522010-08-28 00:00:50 +00004279 Results.data(), Results.size());
4280}
4281
Douglas Gregor81f3bff2012-02-15 15:34:24 +00004282/// \brief Determine whether this scope denotes a namespace.
4283static bool isNamespaceScope(Scope *S) {
4284 DeclContext *DC = static_cast<DeclContext *>(S->getEntity());
4285 if (!DC)
4286 return false;
4287
4288 return DC->isFileContext();
4289}
4290
4291void Sema::CodeCompleteLambdaIntroducer(Scope *S, LambdaIntroducer &Intro,
4292 bool AfterAmpersand) {
4293 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004294 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor81f3bff2012-02-15 15:34:24 +00004295 CodeCompletionContext::CCC_Other);
4296 Results.EnterNewScope();
4297
4298 // Note what has already been captured.
4299 llvm::SmallPtrSet<IdentifierInfo *, 4> Known;
4300 bool IncludedThis = false;
4301 for (SmallVectorImpl<LambdaCapture>::iterator C = Intro.Captures.begin(),
4302 CEnd = Intro.Captures.end();
4303 C != CEnd; ++C) {
4304 if (C->Kind == LCK_This) {
4305 IncludedThis = true;
4306 continue;
4307 }
4308
4309 Known.insert(C->Id);
4310 }
4311
4312 // Look for other capturable variables.
4313 for (; S && !isNamespaceScope(S); S = S->getParent()) {
4314 for (Scope::decl_iterator D = S->decl_begin(), DEnd = S->decl_end();
4315 D != DEnd; ++D) {
4316 VarDecl *Var = dyn_cast<VarDecl>(*D);
4317 if (!Var ||
4318 !Var->hasLocalStorage() ||
4319 Var->hasAttr<BlocksAttr>())
4320 continue;
4321
4322 if (Known.insert(Var->getIdentifier()))
4323 Results.AddResult(CodeCompletionResult(Var), CurContext, 0, false);
4324 }
4325 }
4326
4327 // Add 'this', if it would be valid.
4328 if (!IncludedThis && !AfterAmpersand && Intro.Default != LCD_ByCopy)
4329 addThisCompletion(*this, Results);
4330
4331 Results.ExitScope();
4332
4333 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4334 Results.data(), Results.size());
4335}
4336
James Dennetta40f7922012-06-14 03:11:41 +00004337/// Macro that optionally prepends an "@" to the string literal passed in via
4338/// Keyword, depending on whether NeedAt is true or false.
4339#define OBJC_AT_KEYWORD_NAME(NeedAt,Keyword) ((NeedAt)? "@" Keyword : Keyword)
4340
Douglas Gregorbca403c2010-01-13 23:51:12 +00004341static void AddObjCImplementationResults(const LangOptions &LangOpts,
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004342 ResultBuilder &Results,
4343 bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004344 typedef CodeCompletionResult Result;
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004345 // Since we have an implementation, we can end it.
James Dennetta40f7922012-06-14 03:11:41 +00004346 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"end")));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004347
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004348 CodeCompletionBuilder Builder(Results.getAllocator(),
4349 Results.getCodeCompletionTUInfo());
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004350 if (LangOpts.ObjC2) {
4351 // @dynamic
James Dennetta40f7922012-06-14 03:11:41 +00004352 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"dynamic"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004353 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4354 Builder.AddPlaceholderChunk("property");
4355 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004356
4357 // @synthesize
James Dennetta40f7922012-06-14 03:11:41 +00004358 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"synthesize"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004359 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4360 Builder.AddPlaceholderChunk("property");
4361 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004362 }
4363}
4364
Douglas Gregorbca403c2010-01-13 23:51:12 +00004365static void AddObjCInterfaceResults(const LangOptions &LangOpts,
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004366 ResultBuilder &Results,
4367 bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004368 typedef CodeCompletionResult Result;
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004369
4370 // Since we have an interface or protocol, we can end it.
James Dennetta40f7922012-06-14 03:11:41 +00004371 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"end")));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004372
4373 if (LangOpts.ObjC2) {
4374 // @property
James Dennetta40f7922012-06-14 03:11:41 +00004375 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"property")));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004376
4377 // @required
James Dennetta40f7922012-06-14 03:11:41 +00004378 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"required")));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004379
4380 // @optional
James Dennetta40f7922012-06-14 03:11:41 +00004381 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"optional")));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004382 }
4383}
4384
Douglas Gregorbca403c2010-01-13 23:51:12 +00004385static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004386 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004387 CodeCompletionBuilder Builder(Results.getAllocator(),
4388 Results.getCodeCompletionTUInfo());
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004389
4390 // @class name ;
James Dennetta40f7922012-06-14 03:11:41 +00004391 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"class"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004392 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4393 Builder.AddPlaceholderChunk("name");
4394 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004395
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004396 if (Results.includeCodePatterns()) {
4397 // @interface name
4398 // FIXME: Could introduce the whole pattern, including superclasses and
4399 // such.
James Dennetta40f7922012-06-14 03:11:41 +00004400 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"interface"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004401 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4402 Builder.AddPlaceholderChunk("class");
4403 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004404
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004405 // @protocol name
James Dennetta40f7922012-06-14 03:11:41 +00004406 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"protocol"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004407 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4408 Builder.AddPlaceholderChunk("protocol");
4409 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004410
4411 // @implementation name
James Dennetta40f7922012-06-14 03:11:41 +00004412 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"implementation"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004413 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4414 Builder.AddPlaceholderChunk("class");
4415 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004416 }
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004417
4418 // @compatibility_alias name
James Dennetta40f7922012-06-14 03:11:41 +00004419 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"compatibility_alias"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004420 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4421 Builder.AddPlaceholderChunk("alias");
4422 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4423 Builder.AddPlaceholderChunk("class");
4424 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004425}
4426
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004427void Sema::CodeCompleteObjCAtDirective(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004428 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004429 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004430 CodeCompletionContext::CCC_Other);
Douglas Gregorc464ae82009-12-07 09:27:33 +00004431 Results.EnterNewScope();
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004432 if (isa<ObjCImplDecl>(CurContext))
David Blaikie4e4d0842012-03-11 07:00:24 +00004433 AddObjCImplementationResults(getLangOpts(), Results, false);
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004434 else if (CurContext->isObjCContainer())
David Blaikie4e4d0842012-03-11 07:00:24 +00004435 AddObjCInterfaceResults(getLangOpts(), Results, false);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004436 else
Douglas Gregorbca403c2010-01-13 23:51:12 +00004437 AddObjCTopLevelResults(Results, false);
Douglas Gregorc464ae82009-12-07 09:27:33 +00004438 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004439 HandleCodeCompleteResults(this, CodeCompleter,
4440 CodeCompletionContext::CCC_Other,
4441 Results.data(),Results.size());
Douglas Gregorc464ae82009-12-07 09:27:33 +00004442}
4443
Douglas Gregorbca403c2010-01-13 23:51:12 +00004444static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004445 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004446 CodeCompletionBuilder Builder(Results.getAllocator(),
4447 Results.getCodeCompletionTUInfo());
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004448
4449 // @encode ( type-name )
Douglas Gregor8ca72082011-10-18 21:20:17 +00004450 const char *EncodeType = "char[]";
David Blaikie4e4d0842012-03-11 07:00:24 +00004451 if (Results.getSema().getLangOpts().CPlusPlus ||
4452 Results.getSema().getLangOpts().ConstStrings)
Jordan Rose1f6e22d2012-06-15 18:19:56 +00004453 EncodeType = "const char[]";
Douglas Gregor8ca72082011-10-18 21:20:17 +00004454 Builder.AddResultTypeChunk(EncodeType);
James Dennetta40f7922012-06-14 03:11:41 +00004455 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"encode"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004456 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4457 Builder.AddPlaceholderChunk("type-name");
4458 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4459 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004460
4461 // @protocol ( protocol-name )
Douglas Gregor8ca72082011-10-18 21:20:17 +00004462 Builder.AddResultTypeChunk("Protocol *");
James Dennetta40f7922012-06-14 03:11:41 +00004463 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"protocol"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004464 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4465 Builder.AddPlaceholderChunk("protocol-name");
4466 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4467 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004468
4469 // @selector ( selector )
Douglas Gregor8ca72082011-10-18 21:20:17 +00004470 Builder.AddResultTypeChunk("SEL");
James Dennetta40f7922012-06-14 03:11:41 +00004471 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"selector"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004472 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4473 Builder.AddPlaceholderChunk("selector");
4474 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4475 Results.AddResult(Result(Builder.TakeString()));
Jordan Rose1f6e22d2012-06-15 18:19:56 +00004476
4477 // @"string"
4478 Builder.AddResultTypeChunk("NSString *");
4479 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"\""));
4480 Builder.AddPlaceholderChunk("string");
4481 Builder.AddTextChunk("\"");
4482 Results.AddResult(Result(Builder.TakeString()));
4483
Douglas Gregor79615892012-07-17 23:24:47 +00004484 // @[objects, ...]
Jordan Rose1f6e22d2012-06-15 18:19:56 +00004485 Builder.AddResultTypeChunk("NSArray *");
James Dennetta40f7922012-06-14 03:11:41 +00004486 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"["));
Ted Kremenekebcb57a2012-03-06 20:05:56 +00004487 Builder.AddPlaceholderChunk("objects, ...");
Ted Kremenekebcb57a2012-03-06 20:05:56 +00004488 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
4489 Results.AddResult(Result(Builder.TakeString()));
4490
Douglas Gregor79615892012-07-17 23:24:47 +00004491 // @{key : object, ...}
Jordan Rose1f6e22d2012-06-15 18:19:56 +00004492 Builder.AddResultTypeChunk("NSDictionary *");
James Dennetta40f7922012-06-14 03:11:41 +00004493 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"{"));
Ted Kremenekebcb57a2012-03-06 20:05:56 +00004494 Builder.AddPlaceholderChunk("key");
Ted Kremenekebcb57a2012-03-06 20:05:56 +00004495 Builder.AddChunk(CodeCompletionString::CK_Colon);
4496 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4497 Builder.AddPlaceholderChunk("object, ...");
Ted Kremenekebcb57a2012-03-06 20:05:56 +00004498 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4499 Results.AddResult(Result(Builder.TakeString()));
Jordan Rose1f6e22d2012-06-15 18:19:56 +00004500
Douglas Gregor79615892012-07-17 23:24:47 +00004501 // @(expression)
Jordan Rose1f6e22d2012-06-15 18:19:56 +00004502 Builder.AddResultTypeChunk("id");
4503 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "("));
Jordan Rose1f6e22d2012-06-15 18:19:56 +00004504 Builder.AddPlaceholderChunk("expression");
Jordan Rose1f6e22d2012-06-15 18:19:56 +00004505 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4506 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004507}
4508
Douglas Gregorbca403c2010-01-13 23:51:12 +00004509static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004510 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004511 CodeCompletionBuilder Builder(Results.getAllocator(),
4512 Results.getCodeCompletionTUInfo());
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004513
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004514 if (Results.includeCodePatterns()) {
4515 // @try { statements } @catch ( declaration ) { statements } @finally
4516 // { statements }
James Dennetta40f7922012-06-14 03:11:41 +00004517 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"try"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004518 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4519 Builder.AddPlaceholderChunk("statements");
4520 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4521 Builder.AddTextChunk("@catch");
4522 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4523 Builder.AddPlaceholderChunk("parameter");
4524 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4525 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4526 Builder.AddPlaceholderChunk("statements");
4527 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4528 Builder.AddTextChunk("@finally");
4529 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4530 Builder.AddPlaceholderChunk("statements");
4531 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4532 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004533 }
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004534
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004535 // @throw
James Dennetta40f7922012-06-14 03:11:41 +00004536 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"throw"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004537 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4538 Builder.AddPlaceholderChunk("expression");
4539 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004540
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004541 if (Results.includeCodePatterns()) {
4542 // @synchronized ( expression ) { statements }
James Dennetta40f7922012-06-14 03:11:41 +00004543 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"synchronized"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004544 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4545 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4546 Builder.AddPlaceholderChunk("expression");
4547 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4548 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4549 Builder.AddPlaceholderChunk("statements");
4550 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4551 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004552 }
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004553}
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004554
Douglas Gregorbca403c2010-01-13 23:51:12 +00004555static void AddObjCVisibilityResults(const LangOptions &LangOpts,
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004556 ResultBuilder &Results,
4557 bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004558 typedef CodeCompletionResult Result;
James Dennetta40f7922012-06-14 03:11:41 +00004559 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"private")));
4560 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"protected")));
4561 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"public")));
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004562 if (LangOpts.ObjC2)
James Dennetta40f7922012-06-14 03:11:41 +00004563 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"package")));
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004564}
4565
4566void Sema::CodeCompleteObjCAtVisibility(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004567 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004568 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004569 CodeCompletionContext::CCC_Other);
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004570 Results.EnterNewScope();
David Blaikie4e4d0842012-03-11 07:00:24 +00004571 AddObjCVisibilityResults(getLangOpts(), Results, false);
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004572 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004573 HandleCodeCompleteResults(this, CodeCompleter,
4574 CodeCompletionContext::CCC_Other,
4575 Results.data(),Results.size());
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004576}
4577
4578void Sema::CodeCompleteObjCAtStatement(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004579 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004580 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004581 CodeCompletionContext::CCC_Other);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004582 Results.EnterNewScope();
Douglas Gregorbca403c2010-01-13 23:51:12 +00004583 AddObjCStatementResults(Results, false);
4584 AddObjCExpressionResults(Results, false);
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004585 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004586 HandleCodeCompleteResults(this, CodeCompleter,
4587 CodeCompletionContext::CCC_Other,
4588 Results.data(),Results.size());
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004589}
4590
4591void Sema::CodeCompleteObjCAtExpression(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004592 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004593 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004594 CodeCompletionContext::CCC_Other);
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004595 Results.EnterNewScope();
Douglas Gregorbca403c2010-01-13 23:51:12 +00004596 AddObjCExpressionResults(Results, false);
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004597 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004598 HandleCodeCompleteResults(this, CodeCompleter,
4599 CodeCompletionContext::CCC_Other,
4600 Results.data(),Results.size());
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004601}
4602
Douglas Gregor988358f2009-11-19 00:14:45 +00004603/// \brief Determine whether the addition of the given flag to an Objective-C
4604/// property's attributes will cause a conflict.
Bill Wendlingad017fa2012-12-20 19:22:21 +00004605static bool ObjCPropertyFlagConflicts(unsigned Attributes, unsigned NewFlag) {
Douglas Gregor988358f2009-11-19 00:14:45 +00004606 // Check if we've already added this flag.
Bill Wendlingad017fa2012-12-20 19:22:21 +00004607 if (Attributes & NewFlag)
Douglas Gregor988358f2009-11-19 00:14:45 +00004608 return true;
4609
Bill Wendlingad017fa2012-12-20 19:22:21 +00004610 Attributes |= NewFlag;
Douglas Gregor988358f2009-11-19 00:14:45 +00004611
4612 // Check for collisions with "readonly".
Bill Wendlingad017fa2012-12-20 19:22:21 +00004613 if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) &&
4614 (Attributes & ObjCDeclSpec::DQ_PR_readwrite))
Douglas Gregor988358f2009-11-19 00:14:45 +00004615 return true;
4616
Jordan Rosed7403a72012-08-20 20:01:13 +00004617 // Check for more than one of { assign, copy, retain, strong, weak }.
Bill Wendlingad017fa2012-12-20 19:22:21 +00004618 unsigned AssignCopyRetMask = Attributes & (ObjCDeclSpec::DQ_PR_assign |
John McCallf85e1932011-06-15 23:02:42 +00004619 ObjCDeclSpec::DQ_PR_unsafe_unretained |
Douglas Gregor988358f2009-11-19 00:14:45 +00004620 ObjCDeclSpec::DQ_PR_copy |
Jordan Rosed7403a72012-08-20 20:01:13 +00004621 ObjCDeclSpec::DQ_PR_retain |
4622 ObjCDeclSpec::DQ_PR_strong |
4623 ObjCDeclSpec::DQ_PR_weak);
Douglas Gregor988358f2009-11-19 00:14:45 +00004624 if (AssignCopyRetMask &&
4625 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_assign &&
John McCallf85e1932011-06-15 23:02:42 +00004626 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_unsafe_unretained &&
Douglas Gregor988358f2009-11-19 00:14:45 +00004627 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_copy &&
John McCallf85e1932011-06-15 23:02:42 +00004628 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_retain &&
Jordan Rosed7403a72012-08-20 20:01:13 +00004629 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_strong &&
4630 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_weak)
Douglas Gregor988358f2009-11-19 00:14:45 +00004631 return true;
4632
4633 return false;
4634}
4635
Douglas Gregora93b1082009-11-18 23:08:07 +00004636void Sema::CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS) {
Steve Naroffece8e712009-10-08 21:55:05 +00004637 if (!CodeCompleter)
4638 return;
Douglas Gregord3c68542009-11-19 01:08:35 +00004639
Bill Wendlingad017fa2012-12-20 19:22:21 +00004640 unsigned Attributes = ODS.getPropertyAttributes();
Steve Naroffece8e712009-10-08 21:55:05 +00004641
Douglas Gregor218937c2011-02-01 19:23:04 +00004642 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004643 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004644 CodeCompletionContext::CCC_Other);
Steve Naroffece8e712009-10-08 21:55:05 +00004645 Results.EnterNewScope();
Bill Wendlingad017fa2012-12-20 19:22:21 +00004646 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readonly))
John McCall0a2c5e22010-08-25 06:19:51 +00004647 Results.AddResult(CodeCompletionResult("readonly"));
Bill Wendlingad017fa2012-12-20 19:22:21 +00004648 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_assign))
John McCall0a2c5e22010-08-25 06:19:51 +00004649 Results.AddResult(CodeCompletionResult("assign"));
Bill Wendlingad017fa2012-12-20 19:22:21 +00004650 if (!ObjCPropertyFlagConflicts(Attributes,
John McCallf85e1932011-06-15 23:02:42 +00004651 ObjCDeclSpec::DQ_PR_unsafe_unretained))
4652 Results.AddResult(CodeCompletionResult("unsafe_unretained"));
Bill Wendlingad017fa2012-12-20 19:22:21 +00004653 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readwrite))
John McCall0a2c5e22010-08-25 06:19:51 +00004654 Results.AddResult(CodeCompletionResult("readwrite"));
Bill Wendlingad017fa2012-12-20 19:22:21 +00004655 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_retain))
John McCall0a2c5e22010-08-25 06:19:51 +00004656 Results.AddResult(CodeCompletionResult("retain"));
Bill Wendlingad017fa2012-12-20 19:22:21 +00004657 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_strong))
John McCallf85e1932011-06-15 23:02:42 +00004658 Results.AddResult(CodeCompletionResult("strong"));
Bill Wendlingad017fa2012-12-20 19:22:21 +00004659 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_copy))
John McCall0a2c5e22010-08-25 06:19:51 +00004660 Results.AddResult(CodeCompletionResult("copy"));
Bill Wendlingad017fa2012-12-20 19:22:21 +00004661 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_nonatomic))
John McCall0a2c5e22010-08-25 06:19:51 +00004662 Results.AddResult(CodeCompletionResult("nonatomic"));
Bill Wendlingad017fa2012-12-20 19:22:21 +00004663 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_atomic))
Fariborz Jahanian27f45232011-06-11 17:14:27 +00004664 Results.AddResult(CodeCompletionResult("atomic"));
Jordan Rosed7403a72012-08-20 20:01:13 +00004665
4666 // Only suggest "weak" if we're compiling for ARC-with-weak-references or GC.
John McCall0a7dd782012-08-21 02:47:43 +00004667 if (getLangOpts().ObjCARCWeak || getLangOpts().getGC() != LangOptions::NonGC)
Bill Wendlingad017fa2012-12-20 19:22:21 +00004668 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_weak))
Jordan Rosed7403a72012-08-20 20:01:13 +00004669 Results.AddResult(CodeCompletionResult("weak"));
4670
Bill Wendlingad017fa2012-12-20 19:22:21 +00004671 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_setter)) {
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004672 CodeCompletionBuilder Setter(Results.getAllocator(),
4673 Results.getCodeCompletionTUInfo());
Douglas Gregor218937c2011-02-01 19:23:04 +00004674 Setter.AddTypedTextChunk("setter");
4675 Setter.AddTextChunk(" = ");
4676 Setter.AddPlaceholderChunk("method");
4677 Results.AddResult(CodeCompletionResult(Setter.TakeString()));
Douglas Gregor54f01612009-11-19 00:01:57 +00004678 }
Bill Wendlingad017fa2012-12-20 19:22:21 +00004679 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_getter)) {
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004680 CodeCompletionBuilder Getter(Results.getAllocator(),
4681 Results.getCodeCompletionTUInfo());
Douglas Gregor218937c2011-02-01 19:23:04 +00004682 Getter.AddTypedTextChunk("getter");
4683 Getter.AddTextChunk(" = ");
4684 Getter.AddPlaceholderChunk("method");
4685 Results.AddResult(CodeCompletionResult(Getter.TakeString()));
Douglas Gregor54f01612009-11-19 00:01:57 +00004686 }
Steve Naroffece8e712009-10-08 21:55:05 +00004687 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004688 HandleCodeCompleteResults(this, CodeCompleter,
4689 CodeCompletionContext::CCC_Other,
4690 Results.data(),Results.size());
Steve Naroffece8e712009-10-08 21:55:05 +00004691}
Steve Naroffc4df6d22009-11-07 02:08:14 +00004692
James Dennettde23c7e2012-06-17 05:33:25 +00004693/// \brief Describes the kind of Objective-C method that we want to find
Douglas Gregor4ad96852009-11-19 07:41:15 +00004694/// via code completion.
4695enum ObjCMethodKind {
Dmitri Gribenko49fdccb2012-06-08 23:13:42 +00004696 MK_Any, ///< Any kind of method, provided it means other specified criteria.
4697 MK_ZeroArgSelector, ///< Zero-argument (unary) selector.
4698 MK_OneArgSelector ///< One-argument selector.
Douglas Gregor4ad96852009-11-19 07:41:15 +00004699};
4700
Douglas Gregor458433d2010-08-26 15:07:07 +00004701static bool isAcceptableObjCSelector(Selector Sel,
4702 ObjCMethodKind WantKind,
4703 IdentifierInfo **SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004704 unsigned NumSelIdents,
4705 bool AllowSameLength = true) {
Douglas Gregor458433d2010-08-26 15:07:07 +00004706 if (NumSelIdents > Sel.getNumArgs())
4707 return false;
4708
4709 switch (WantKind) {
4710 case MK_Any: break;
4711 case MK_ZeroArgSelector: return Sel.isUnarySelector();
4712 case MK_OneArgSelector: return Sel.getNumArgs() == 1;
4713 }
4714
Douglas Gregorcf544262010-11-17 21:36:08 +00004715 if (!AllowSameLength && NumSelIdents && NumSelIdents == Sel.getNumArgs())
4716 return false;
4717
Douglas Gregor458433d2010-08-26 15:07:07 +00004718 for (unsigned I = 0; I != NumSelIdents; ++I)
4719 if (SelIdents[I] != Sel.getIdentifierInfoForSlot(I))
4720 return false;
4721
4722 return true;
4723}
4724
Douglas Gregor4ad96852009-11-19 07:41:15 +00004725static bool isAcceptableObjCMethod(ObjCMethodDecl *Method,
4726 ObjCMethodKind WantKind,
4727 IdentifierInfo **SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004728 unsigned NumSelIdents,
4729 bool AllowSameLength = true) {
Douglas Gregor458433d2010-08-26 15:07:07 +00004730 return isAcceptableObjCSelector(Method->getSelector(), WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004731 NumSelIdents, AllowSameLength);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004732}
Douglas Gregord36adf52010-09-16 16:06:31 +00004733
4734namespace {
4735 /// \brief A set of selectors, which is used to avoid introducing multiple
4736 /// completions with the same selector into the result set.
4737 typedef llvm::SmallPtrSet<Selector, 16> VisitedSelectorSet;
4738}
4739
Douglas Gregor36ecb042009-11-17 23:22:23 +00004740/// \brief Add all of the Objective-C methods in the given Objective-C
4741/// container to the set of results.
4742///
4743/// The container will be a class, protocol, category, or implementation of
4744/// any of the above. This mether will recurse to include methods from
4745/// the superclasses of classes along with their categories, protocols, and
4746/// implementations.
4747///
4748/// \param Container the container in which we'll look to find methods.
4749///
James Dennetta40f7922012-06-14 03:11:41 +00004750/// \param WantInstanceMethods Whether to add instance methods (only); if
4751/// false, this routine will add factory methods (only).
Douglas Gregor36ecb042009-11-17 23:22:23 +00004752///
4753/// \param CurContext the context in which we're performing the lookup that
4754/// finds methods.
4755///
Douglas Gregorcf544262010-11-17 21:36:08 +00004756/// \param AllowSameLength Whether we allow a method to be added to the list
4757/// when it has the same number of parameters as we have selector identifiers.
4758///
Douglas Gregor36ecb042009-11-17 23:22:23 +00004759/// \param Results the structure into which we'll add results.
4760static void AddObjCMethods(ObjCContainerDecl *Container,
4761 bool WantInstanceMethods,
Douglas Gregor4ad96852009-11-19 07:41:15 +00004762 ObjCMethodKind WantKind,
Douglas Gregord3c68542009-11-19 01:08:35 +00004763 IdentifierInfo **SelIdents,
4764 unsigned NumSelIdents,
Douglas Gregor36ecb042009-11-17 23:22:23 +00004765 DeclContext *CurContext,
Douglas Gregord36adf52010-09-16 16:06:31 +00004766 VisitedSelectorSet &Selectors,
Douglas Gregorcf544262010-11-17 21:36:08 +00004767 bool AllowSameLength,
Douglas Gregor408be5a2010-08-25 01:08:01 +00004768 ResultBuilder &Results,
4769 bool InOriginalClass = true) {
John McCall0a2c5e22010-08-25 06:19:51 +00004770 typedef CodeCompletionResult Result;
Douglas Gregorb92a4082012-06-12 13:44:08 +00004771 Container = getContainerDef(Container);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004772 for (ObjCContainerDecl::method_iterator M = Container->meth_begin(),
4773 MEnd = Container->meth_end();
4774 M != MEnd; ++M) {
David Blaikie262bc182012-04-30 02:36:29 +00004775 if (M->isInstanceMethod() == WantInstanceMethods) {
Douglas Gregord3c68542009-11-19 01:08:35 +00004776 // Check whether the selector identifiers we've been given are a
4777 // subset of the identifiers for this particular method.
David Blaikie581deb32012-06-06 20:45:41 +00004778 if (!isAcceptableObjCMethod(*M, WantKind, SelIdents, NumSelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004779 AllowSameLength))
Douglas Gregord3c68542009-11-19 01:08:35 +00004780 continue;
Douglas Gregor4ad96852009-11-19 07:41:15 +00004781
David Blaikie262bc182012-04-30 02:36:29 +00004782 if (!Selectors.insert(M->getSelector()))
Douglas Gregord36adf52010-09-16 16:06:31 +00004783 continue;
4784
David Blaikie581deb32012-06-06 20:45:41 +00004785 Result R = Result(*M, 0);
Douglas Gregord3c68542009-11-19 01:08:35 +00004786 R.StartParameter = NumSelIdents;
Douglas Gregor4ad96852009-11-19 07:41:15 +00004787 R.AllParametersAreInformative = (WantKind != MK_Any);
Douglas Gregor408be5a2010-08-25 01:08:01 +00004788 if (!InOriginalClass)
4789 R.Priority += CCD_InBaseClass;
Douglas Gregord3c68542009-11-19 01:08:35 +00004790 Results.MaybeAddResult(R, CurContext);
4791 }
Douglas Gregor36ecb042009-11-17 23:22:23 +00004792 }
4793
Douglas Gregore396c7b2010-09-16 15:34:59 +00004794 // Visit the protocols of protocols.
4795 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Douglas Gregor5e2a1ff2012-01-01 19:29:29 +00004796 if (Protocol->hasDefinition()) {
4797 const ObjCList<ObjCProtocolDecl> &Protocols
4798 = Protocol->getReferencedProtocols();
4799 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
4800 E = Protocols.end();
4801 I != E; ++I)
4802 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents,
4803 NumSelIdents, CurContext, Selectors, AllowSameLength,
4804 Results, false);
4805 }
Douglas Gregore396c7b2010-09-16 15:34:59 +00004806 }
4807
Douglas Gregor36ecb042009-11-17 23:22:23 +00004808 ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container);
Douglas Gregor2e5c15b2011-12-15 05:27:12 +00004809 if (!IFace || !IFace->hasDefinition())
Douglas Gregor36ecb042009-11-17 23:22:23 +00004810 return;
4811
4812 // Add methods in protocols.
Argyrios Kyrtzidisa5f44412012-03-13 01:09:41 +00004813 for (ObjCInterfaceDecl::protocol_iterator I = IFace->protocol_begin(),
4814 E = IFace->protocol_end();
Douglas Gregor36ecb042009-11-17 23:22:23 +00004815 I != E; ++I)
Douglas Gregor4ad96852009-11-19 07:41:15 +00004816 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, NumSelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004817 CurContext, Selectors, AllowSameLength, Results, false);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004818
4819 // Add methods in categories.
Douglas Gregord3297242013-01-16 23:00:23 +00004820 for (ObjCInterfaceDecl::known_categories_iterator
4821 Cat = IFace->known_categories_begin(),
4822 CatEnd = IFace->known_categories_end();
4823 Cat != CatEnd; ++Cat) {
4824 ObjCCategoryDecl *CatDecl = *Cat;
4825
4826 AddObjCMethods(CatDecl, WantInstanceMethods, WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004827 NumSelIdents, CurContext, Selectors, AllowSameLength,
4828 Results, InOriginalClass);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004829
4830 // Add a categories protocol methods.
4831 const ObjCList<ObjCProtocolDecl> &Protocols
4832 = CatDecl->getReferencedProtocols();
4833 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
4834 E = Protocols.end();
4835 I != E; ++I)
Douglas Gregor4ad96852009-11-19 07:41:15 +00004836 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004837 NumSelIdents, CurContext, Selectors, AllowSameLength,
4838 Results, false);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004839
4840 // Add methods in category implementations.
4841 if (ObjCCategoryImplDecl *Impl = CatDecl->getImplementation())
Douglas Gregor4ad96852009-11-19 07:41:15 +00004842 AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004843 NumSelIdents, CurContext, Selectors, AllowSameLength,
4844 Results, InOriginalClass);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004845 }
4846
4847 // Add methods in superclass.
4848 if (IFace->getSuperClass())
Douglas Gregor4ad96852009-11-19 07:41:15 +00004849 AddObjCMethods(IFace->getSuperClass(), WantInstanceMethods, WantKind,
Douglas Gregorcf544262010-11-17 21:36:08 +00004850 SelIdents, NumSelIdents, CurContext, Selectors,
4851 AllowSameLength, Results, false);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004852
4853 // Add methods in our implementation, if any.
4854 if (ObjCImplementationDecl *Impl = IFace->getImplementation())
Douglas Gregor4ad96852009-11-19 07:41:15 +00004855 AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004856 NumSelIdents, CurContext, Selectors, AllowSameLength,
4857 Results, InOriginalClass);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004858}
4859
4860
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004861void Sema::CodeCompleteObjCPropertyGetter(Scope *S) {
Douglas Gregor4ad96852009-11-19 07:41:15 +00004862 // Try to find the interface where getters might live.
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004863 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004864 if (!Class) {
4865 if (ObjCCategoryDecl *Category
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004866 = dyn_cast_or_null<ObjCCategoryDecl>(CurContext))
Douglas Gregor4ad96852009-11-19 07:41:15 +00004867 Class = Category->getClassInterface();
4868
4869 if (!Class)
4870 return;
4871 }
4872
4873 // Find all of the potential getters.
Douglas Gregor218937c2011-02-01 19:23:04 +00004874 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004875 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004876 CodeCompletionContext::CCC_Other);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004877 Results.EnterNewScope();
4878
Douglas Gregord36adf52010-09-16 16:06:31 +00004879 VisitedSelectorSet Selectors;
4880 AddObjCMethods(Class, true, MK_ZeroArgSelector, 0, 0, CurContext, Selectors,
Douglas Gregorcf544262010-11-17 21:36:08 +00004881 /*AllowSameLength=*/true, Results);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004882 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004883 HandleCodeCompleteResults(this, CodeCompleter,
4884 CodeCompletionContext::CCC_Other,
4885 Results.data(),Results.size());
Douglas Gregor4ad96852009-11-19 07:41:15 +00004886}
4887
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004888void Sema::CodeCompleteObjCPropertySetter(Scope *S) {
Douglas Gregor4ad96852009-11-19 07:41:15 +00004889 // Try to find the interface where setters might live.
4890 ObjCInterfaceDecl *Class
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004891 = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004892 if (!Class) {
4893 if (ObjCCategoryDecl *Category
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004894 = dyn_cast_or_null<ObjCCategoryDecl>(CurContext))
Douglas Gregor4ad96852009-11-19 07:41:15 +00004895 Class = Category->getClassInterface();
4896
4897 if (!Class)
4898 return;
4899 }
4900
4901 // Find all of the potential getters.
Douglas Gregor218937c2011-02-01 19:23:04 +00004902 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004903 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004904 CodeCompletionContext::CCC_Other);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004905 Results.EnterNewScope();
4906
Douglas Gregord36adf52010-09-16 16:06:31 +00004907 VisitedSelectorSet Selectors;
4908 AddObjCMethods(Class, true, MK_OneArgSelector, 0, 0, CurContext,
Douglas Gregorcf544262010-11-17 21:36:08 +00004909 Selectors, /*AllowSameLength=*/true, Results);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004910
4911 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004912 HandleCodeCompleteResults(this, CodeCompleter,
4913 CodeCompletionContext::CCC_Other,
4914 Results.data(),Results.size());
Douglas Gregor36ecb042009-11-17 23:22:23 +00004915}
4916
Douglas Gregorafc45782011-02-15 22:19:42 +00004917void Sema::CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS,
4918 bool IsParameter) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004919 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004920 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004921 CodeCompletionContext::CCC_Type);
Douglas Gregord32b0222010-08-24 01:06:58 +00004922 Results.EnterNewScope();
4923
4924 // Add context-sensitive, Objective-C parameter-passing keywords.
4925 bool AddedInOut = false;
4926 if ((DS.getObjCDeclQualifier() &
4927 (ObjCDeclSpec::DQ_In | ObjCDeclSpec::DQ_Inout)) == 0) {
4928 Results.AddResult("in");
4929 Results.AddResult("inout");
4930 AddedInOut = true;
4931 }
4932 if ((DS.getObjCDeclQualifier() &
4933 (ObjCDeclSpec::DQ_Out | ObjCDeclSpec::DQ_Inout)) == 0) {
4934 Results.AddResult("out");
4935 if (!AddedInOut)
4936 Results.AddResult("inout");
4937 }
4938 if ((DS.getObjCDeclQualifier() &
4939 (ObjCDeclSpec::DQ_Bycopy | ObjCDeclSpec::DQ_Byref |
4940 ObjCDeclSpec::DQ_Oneway)) == 0) {
4941 Results.AddResult("bycopy");
4942 Results.AddResult("byref");
4943 Results.AddResult("oneway");
4944 }
4945
Douglas Gregorafc45782011-02-15 22:19:42 +00004946 // If we're completing the return type of an Objective-C method and the
4947 // identifier IBAction refers to a macro, provide a completion item for
4948 // an action, e.g.,
4949 // IBAction)<#selector#>:(id)sender
4950 if (DS.getObjCDeclQualifier() == 0 && !IsParameter &&
4951 Context.Idents.get("IBAction").hasMacroDefinition()) {
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004952 CodeCompletionBuilder Builder(Results.getAllocator(),
4953 Results.getCodeCompletionTUInfo(),
4954 CCP_CodePattern, CXAvailability_Available);
Douglas Gregorafc45782011-02-15 22:19:42 +00004955 Builder.AddTypedTextChunk("IBAction");
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00004956 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorafc45782011-02-15 22:19:42 +00004957 Builder.AddPlaceholderChunk("selector");
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00004958 Builder.AddChunk(CodeCompletionString::CK_Colon);
4959 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregorafc45782011-02-15 22:19:42 +00004960 Builder.AddTextChunk("id");
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00004961 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorafc45782011-02-15 22:19:42 +00004962 Builder.AddTextChunk("sender");
4963 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
4964 }
4965
Douglas Gregord32b0222010-08-24 01:06:58 +00004966 // Add various builtin type names and specifiers.
4967 AddOrdinaryNameResults(PCC_Type, S, *this, Results);
4968 Results.ExitScope();
4969
4970 // Add the various type names
4971 Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
4972 CodeCompletionDeclConsumer Consumer(Results, CurContext);
4973 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4974 CodeCompleter->includeGlobals());
4975
4976 if (CodeCompleter->includeMacros())
Douglas Gregor3644d972012-10-09 16:01:50 +00004977 AddMacroResults(PP, Results, false);
Douglas Gregord32b0222010-08-24 01:06:58 +00004978
4979 HandleCodeCompleteResults(this, CodeCompleter,
4980 CodeCompletionContext::CCC_Type,
4981 Results.data(), Results.size());
4982}
4983
Douglas Gregor22f56992010-04-06 19:22:33 +00004984/// \brief When we have an expression with type "id", we may assume
4985/// that it has some more-specific class type based on knowledge of
4986/// common uses of Objective-C. This routine returns that class type,
4987/// or NULL if no better result could be determined.
4988static ObjCInterfaceDecl *GetAssumedMessageSendExprType(Expr *E) {
Douglas Gregor78edf512010-09-15 16:23:04 +00004989 ObjCMessageExpr *Msg = dyn_cast_or_null<ObjCMessageExpr>(E);
Douglas Gregor22f56992010-04-06 19:22:33 +00004990 if (!Msg)
4991 return 0;
4992
4993 Selector Sel = Msg->getSelector();
4994 if (Sel.isNull())
4995 return 0;
4996
4997 IdentifierInfo *Id = Sel.getIdentifierInfoForSlot(0);
4998 if (!Id)
4999 return 0;
5000
5001 ObjCMethodDecl *Method = Msg->getMethodDecl();
5002 if (!Method)
5003 return 0;
5004
5005 // Determine the class that we're sending the message to.
Douglas Gregor04badcf2010-04-21 00:45:42 +00005006 ObjCInterfaceDecl *IFace = 0;
5007 switch (Msg->getReceiverKind()) {
5008 case ObjCMessageExpr::Class:
John McCallc12c5bb2010-05-15 11:32:37 +00005009 if (const ObjCObjectType *ObjType
5010 = Msg->getClassReceiver()->getAs<ObjCObjectType>())
5011 IFace = ObjType->getInterface();
Douglas Gregor04badcf2010-04-21 00:45:42 +00005012 break;
5013
5014 case ObjCMessageExpr::Instance: {
5015 QualType T = Msg->getInstanceReceiver()->getType();
5016 if (const ObjCObjectPointerType *Ptr = T->getAs<ObjCObjectPointerType>())
5017 IFace = Ptr->getInterfaceDecl();
5018 break;
5019 }
5020
5021 case ObjCMessageExpr::SuperInstance:
5022 case ObjCMessageExpr::SuperClass:
5023 break;
Douglas Gregor22f56992010-04-06 19:22:33 +00005024 }
5025
5026 if (!IFace)
5027 return 0;
5028
5029 ObjCInterfaceDecl *Super = IFace->getSuperClass();
5030 if (Method->isInstanceMethod())
5031 return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
5032 .Case("retain", IFace)
John McCallf85e1932011-06-15 23:02:42 +00005033 .Case("strong", IFace)
Douglas Gregor22f56992010-04-06 19:22:33 +00005034 .Case("autorelease", IFace)
5035 .Case("copy", IFace)
5036 .Case("copyWithZone", IFace)
5037 .Case("mutableCopy", IFace)
5038 .Case("mutableCopyWithZone", IFace)
5039 .Case("awakeFromCoder", IFace)
5040 .Case("replacementObjectFromCoder", IFace)
5041 .Case("class", IFace)
5042 .Case("classForCoder", IFace)
5043 .Case("superclass", Super)
5044 .Default(0);
5045
5046 return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
5047 .Case("new", IFace)
5048 .Case("alloc", IFace)
5049 .Case("allocWithZone", IFace)
5050 .Case("class", IFace)
5051 .Case("superclass", Super)
5052 .Default(0);
5053}
5054
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005055// Add a special completion for a message send to "super", which fills in the
5056// most likely case of forwarding all of our arguments to the superclass
5057// function.
5058///
5059/// \param S The semantic analysis object.
5060///
Dmitri Gribenko70517ca2012-08-23 17:58:28 +00005061/// \param NeedSuperKeyword Whether we need to prefix this completion with
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005062/// the "super" keyword. Otherwise, we just need to provide the arguments.
5063///
5064/// \param SelIdents The identifiers in the selector that have already been
5065/// provided as arguments for a send to "super".
5066///
5067/// \param NumSelIdents The number of identifiers in \p SelIdents.
5068///
5069/// \param Results The set of results to augment.
5070///
5071/// \returns the Objective-C method declaration that would be invoked by
5072/// this "super" completion. If NULL, no completion was added.
5073static ObjCMethodDecl *AddSuperSendCompletion(Sema &S, bool NeedSuperKeyword,
5074 IdentifierInfo **SelIdents,
5075 unsigned NumSelIdents,
5076 ResultBuilder &Results) {
5077 ObjCMethodDecl *CurMethod = S.getCurMethodDecl();
5078 if (!CurMethod)
5079 return 0;
5080
5081 ObjCInterfaceDecl *Class = CurMethod->getClassInterface();
5082 if (!Class)
5083 return 0;
5084
5085 // Try to find a superclass method with the same selector.
5086 ObjCMethodDecl *SuperMethod = 0;
Douglas Gregor78bcd912011-02-16 00:51:18 +00005087 while ((Class = Class->getSuperClass()) && !SuperMethod) {
5088 // Check in the class
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005089 SuperMethod = Class->getMethod(CurMethod->getSelector(),
5090 CurMethod->isInstanceMethod());
5091
Douglas Gregor78bcd912011-02-16 00:51:18 +00005092 // Check in categories or class extensions.
5093 if (!SuperMethod) {
Douglas Gregord3297242013-01-16 23:00:23 +00005094 for (ObjCInterfaceDecl::known_categories_iterator
5095 Cat = Class->known_categories_begin(),
5096 CatEnd = Class->known_categories_end();
5097 Cat != CatEnd; ++Cat) {
5098 if ((SuperMethod = Cat->getMethod(CurMethod->getSelector(),
Douglas Gregor78bcd912011-02-16 00:51:18 +00005099 CurMethod->isInstanceMethod())))
5100 break;
Douglas Gregord3297242013-01-16 23:00:23 +00005101 }
Douglas Gregor78bcd912011-02-16 00:51:18 +00005102 }
5103 }
5104
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005105 if (!SuperMethod)
5106 return 0;
5107
5108 // Check whether the superclass method has the same signature.
5109 if (CurMethod->param_size() != SuperMethod->param_size() ||
5110 CurMethod->isVariadic() != SuperMethod->isVariadic())
5111 return 0;
5112
5113 for (ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin(),
5114 CurPEnd = CurMethod->param_end(),
5115 SuperP = SuperMethod->param_begin();
5116 CurP != CurPEnd; ++CurP, ++SuperP) {
5117 // Make sure the parameter types are compatible.
5118 if (!S.Context.hasSameUnqualifiedType((*CurP)->getType(),
5119 (*SuperP)->getType()))
5120 return 0;
5121
5122 // Make sure we have a parameter name to forward!
5123 if (!(*CurP)->getIdentifier())
5124 return 0;
5125 }
5126
5127 // We have a superclass method. Now, form the send-to-super completion.
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005128 CodeCompletionBuilder Builder(Results.getAllocator(),
5129 Results.getCodeCompletionTUInfo());
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005130
5131 // Give this completion a return type.
Douglas Gregor8987b232011-09-27 23:30:47 +00005132 AddResultTypeChunk(S.Context, getCompletionPrintingPolicy(S), SuperMethod,
5133 Builder);
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005134
5135 // If we need the "super" keyword, add it (plus some spacing).
5136 if (NeedSuperKeyword) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005137 Builder.AddTypedTextChunk("super");
5138 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005139 }
5140
5141 Selector Sel = CurMethod->getSelector();
5142 if (Sel.isUnarySelector()) {
5143 if (NeedSuperKeyword)
Douglas Gregordae68752011-02-01 22:57:45 +00005144 Builder.AddTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00005145 Sel.getNameForSlot(0)));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005146 else
Douglas Gregordae68752011-02-01 22:57:45 +00005147 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00005148 Sel.getNameForSlot(0)));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005149 } else {
5150 ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin();
5151 for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I, ++CurP) {
5152 if (I > NumSelIdents)
Douglas Gregor218937c2011-02-01 19:23:04 +00005153 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005154
5155 if (I < NumSelIdents)
Douglas Gregor218937c2011-02-01 19:23:04 +00005156 Builder.AddInformativeChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00005157 Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00005158 Sel.getNameForSlot(I) + ":"));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005159 else if (NeedSuperKeyword || I > NumSelIdents) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005160 Builder.AddTextChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00005161 Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00005162 Sel.getNameForSlot(I) + ":"));
Douglas Gregordae68752011-02-01 22:57:45 +00005163 Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00005164 (*CurP)->getIdentifier()->getName()));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005165 } else {
Douglas Gregor218937c2011-02-01 19:23:04 +00005166 Builder.AddTypedTextChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00005167 Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00005168 Sel.getNameForSlot(I) + ":"));
Douglas Gregordae68752011-02-01 22:57:45 +00005169 Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00005170 (*CurP)->getIdentifier()->getName()));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005171 }
5172 }
5173 }
5174
Douglas Gregorba103062012-03-27 23:34:16 +00005175 Results.AddResult(CodeCompletionResult(Builder.TakeString(), SuperMethod,
5176 CCP_SuperCompletion));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005177 return SuperMethod;
5178}
5179
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005180void Sema::CodeCompleteObjCMessageReceiver(Scope *S) {
John McCall0a2c5e22010-08-25 06:19:51 +00005181 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00005182 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005183 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00005184 CodeCompletionContext::CCC_ObjCMessageReceiver,
Richard Smith80ad52f2013-01-02 11:42:31 +00005185 getLangOpts().CPlusPlus11
Douglas Gregor81f3bff2012-02-15 15:34:24 +00005186 ? &ResultBuilder::IsObjCMessageReceiverOrLambdaCapture
5187 : &ResultBuilder::IsObjCMessageReceiver);
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005188
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005189 CodeCompletionDeclConsumer Consumer(Results, CurContext);
5190 Results.EnterNewScope();
Douglas Gregor8071e422010-08-15 06:18:01 +00005191 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
5192 CodeCompleter->includeGlobals());
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005193
5194 // If we are in an Objective-C method inside a class that has a superclass,
5195 // add "super" as an option.
5196 if (ObjCMethodDecl *Method = getCurMethodDecl())
5197 if (ObjCInterfaceDecl *Iface = Method->getClassInterface())
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005198 if (Iface->getSuperClass()) {
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005199 Results.AddResult(Result("super"));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005200
5201 AddSuperSendCompletion(*this, /*NeedSuperKeyword=*/true, 0, 0, Results);
5202 }
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005203
Richard Smith80ad52f2013-01-02 11:42:31 +00005204 if (getLangOpts().CPlusPlus11)
Douglas Gregor81f3bff2012-02-15 15:34:24 +00005205 addThisCompletion(*this, Results);
5206
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005207 Results.ExitScope();
5208
5209 if (CodeCompleter->includeMacros())
Douglas Gregor3644d972012-10-09 16:01:50 +00005210 AddMacroResults(PP, Results, false);
Douglas Gregorcee9ff12010-09-20 22:39:41 +00005211 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005212 Results.data(), Results.size());
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005213
5214}
5215
Douglas Gregor2725ca82010-04-21 19:57:20 +00005216void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc,
5217 IdentifierInfo **SelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005218 unsigned NumSelIdents,
5219 bool AtArgumentExpression) {
Douglas Gregor2725ca82010-04-21 19:57:20 +00005220 ObjCInterfaceDecl *CDecl = 0;
5221 if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
5222 // Figure out which interface we're in.
5223 CDecl = CurMethod->getClassInterface();
5224 if (!CDecl)
5225 return;
5226
5227 // Find the superclass of this class.
5228 CDecl = CDecl->getSuperClass();
5229 if (!CDecl)
5230 return;
5231
5232 if (CurMethod->isInstanceMethod()) {
5233 // We are inside an instance method, which means that the message
5234 // send [super ...] is actually calling an instance method on the
Douglas Gregor6b0656a2010-10-13 21:24:53 +00005235 // current object.
5236 return CodeCompleteObjCInstanceMessage(S, 0,
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005237 SelIdents, NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005238 AtArgumentExpression,
Douglas Gregor6b0656a2010-10-13 21:24:53 +00005239 CDecl);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005240 }
5241
5242 // Fall through to send to the superclass in CDecl.
5243 } else {
5244 // "super" may be the name of a type or variable. Figure out which
5245 // it is.
5246 IdentifierInfo *Super = &Context.Idents.get("super");
5247 NamedDecl *ND = LookupSingleName(S, Super, SuperLoc,
5248 LookupOrdinaryName);
5249 if ((CDecl = dyn_cast_or_null<ObjCInterfaceDecl>(ND))) {
5250 // "super" names an interface. Use it.
5251 } else if (TypeDecl *TD = dyn_cast_or_null<TypeDecl>(ND)) {
John McCallc12c5bb2010-05-15 11:32:37 +00005252 if (const ObjCObjectType *Iface
5253 = Context.getTypeDeclType(TD)->getAs<ObjCObjectType>())
5254 CDecl = Iface->getInterface();
Douglas Gregor2725ca82010-04-21 19:57:20 +00005255 } else if (ND && isa<UnresolvedUsingTypenameDecl>(ND)) {
5256 // "super" names an unresolved type; we can't be more specific.
5257 } else {
5258 // Assume that "super" names some kind of value and parse that way.
5259 CXXScopeSpec SS;
Abramo Bagnarae4b92762012-01-27 09:46:47 +00005260 SourceLocation TemplateKWLoc;
Douglas Gregor2725ca82010-04-21 19:57:20 +00005261 UnqualifiedId id;
5262 id.setIdentifier(Super, SuperLoc);
Abramo Bagnarae4b92762012-01-27 09:46:47 +00005263 ExprResult SuperExpr = ActOnIdExpression(S, SS, TemplateKWLoc, id,
5264 false, false);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005265 return CodeCompleteObjCInstanceMessage(S, (Expr *)SuperExpr.get(),
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005266 SelIdents, NumSelIdents,
5267 AtArgumentExpression);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005268 }
5269
5270 // Fall through
5271 }
5272
John McCallb3d87482010-08-24 05:47:05 +00005273 ParsedType Receiver;
Douglas Gregor2725ca82010-04-21 19:57:20 +00005274 if (CDecl)
John McCallb3d87482010-08-24 05:47:05 +00005275 Receiver = ParsedType::make(Context.getObjCInterfaceType(CDecl));
Douglas Gregor2725ca82010-04-21 19:57:20 +00005276 return CodeCompleteObjCClassMessage(S, Receiver, SelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005277 NumSelIdents, AtArgumentExpression,
5278 /*IsSuper=*/true);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005279}
5280
Douglas Gregorb9d77572010-09-21 00:03:25 +00005281/// \brief Given a set of code-completion results for the argument of a message
5282/// send, determine the preferred type (if any) for that argument expression.
5283static QualType getPreferredArgumentTypeForMessageSend(ResultBuilder &Results,
5284 unsigned NumSelIdents) {
5285 typedef CodeCompletionResult Result;
5286 ASTContext &Context = Results.getSema().Context;
5287
5288 QualType PreferredType;
5289 unsigned BestPriority = CCP_Unlikely * 2;
5290 Result *ResultsData = Results.data();
5291 for (unsigned I = 0, N = Results.size(); I != N; ++I) {
5292 Result &R = ResultsData[I];
5293 if (R.Kind == Result::RK_Declaration &&
5294 isa<ObjCMethodDecl>(R.Declaration)) {
5295 if (R.Priority <= BestPriority) {
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00005296 const ObjCMethodDecl *Method = cast<ObjCMethodDecl>(R.Declaration);
Douglas Gregorb9d77572010-09-21 00:03:25 +00005297 if (NumSelIdents <= Method->param_size()) {
5298 QualType MyPreferredType = Method->param_begin()[NumSelIdents - 1]
5299 ->getType();
5300 if (R.Priority < BestPriority || PreferredType.isNull()) {
5301 BestPriority = R.Priority;
5302 PreferredType = MyPreferredType;
5303 } else if (!Context.hasSameUnqualifiedType(PreferredType,
5304 MyPreferredType)) {
5305 PreferredType = QualType();
5306 }
5307 }
5308 }
5309 }
5310 }
5311
5312 return PreferredType;
5313}
5314
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005315static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
5316 ParsedType Receiver,
5317 IdentifierInfo **SelIdents,
5318 unsigned NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005319 bool AtArgumentExpression,
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005320 bool IsSuper,
5321 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00005322 typedef CodeCompletionResult Result;
Douglas Gregor24a069f2009-11-17 17:59:40 +00005323 ObjCInterfaceDecl *CDecl = 0;
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005324
Douglas Gregor24a069f2009-11-17 17:59:40 +00005325 // If the given name refers to an interface type, retrieve the
5326 // corresponding declaration.
Douglas Gregor2725ca82010-04-21 19:57:20 +00005327 if (Receiver) {
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005328 QualType T = SemaRef.GetTypeFromParser(Receiver, 0);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005329 if (!T.isNull())
John McCallc12c5bb2010-05-15 11:32:37 +00005330 if (const ObjCObjectType *Interface = T->getAs<ObjCObjectType>())
5331 CDecl = Interface->getInterface();
Douglas Gregor24a069f2009-11-17 17:59:40 +00005332 }
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005333
Douglas Gregor36ecb042009-11-17 23:22:23 +00005334 // Add all of the factory methods in this Objective-C class, its protocols,
5335 // superclasses, categories, implementation, etc.
Steve Naroffc4df6d22009-11-07 02:08:14 +00005336 Results.EnterNewScope();
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005337
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005338 // If this is a send-to-super, try to add the special "super" send
5339 // completion.
5340 if (IsSuper) {
5341 if (ObjCMethodDecl *SuperMethod
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005342 = AddSuperSendCompletion(SemaRef, false, SelIdents, NumSelIdents,
5343 Results))
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005344 Results.Ignore(SuperMethod);
5345 }
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005346
Douglas Gregor265f7492010-08-27 15:29:55 +00005347 // If we're inside an Objective-C method definition, prefer its selector to
5348 // others.
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005349 if (ObjCMethodDecl *CurMethod = SemaRef.getCurMethodDecl())
Douglas Gregor265f7492010-08-27 15:29:55 +00005350 Results.setPreferredSelector(CurMethod->getSelector());
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005351
Douglas Gregord36adf52010-09-16 16:06:31 +00005352 VisitedSelectorSet Selectors;
Douglas Gregor13438f92010-04-06 16:40:00 +00005353 if (CDecl)
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005354 AddObjCMethods(CDecl, false, MK_Any, SelIdents, NumSelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00005355 SemaRef.CurContext, Selectors, AtArgumentExpression,
5356 Results);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005357 else {
Douglas Gregor13438f92010-04-06 16:40:00 +00005358 // We're messaging "id" as a type; provide all class/factory methods.
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005359
Douglas Gregor719770d2010-04-06 17:30:22 +00005360 // If we have an external source, load the entire class method
Sebastian Redl3c7f4132010-08-18 23:57:06 +00005361 // pool from the AST file.
Axel Naumann0ec56b72012-10-18 19:05:02 +00005362 if (SemaRef.getExternalSource()) {
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005363 for (uint32_t I = 0,
Axel Naumann0ec56b72012-10-18 19:05:02 +00005364 N = SemaRef.getExternalSource()->GetNumExternalSelectors();
John McCall76bd1f32010-06-01 09:23:16 +00005365 I != N; ++I) {
Axel Naumann0ec56b72012-10-18 19:05:02 +00005366 Selector Sel = SemaRef.getExternalSource()->GetExternalSelector(I);
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005367 if (Sel.isNull() || SemaRef.MethodPool.count(Sel))
Douglas Gregor719770d2010-04-06 17:30:22 +00005368 continue;
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005369
5370 SemaRef.ReadMethodPool(Sel);
Douglas Gregor719770d2010-04-06 17:30:22 +00005371 }
5372 }
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005373
5374 for (Sema::GlobalMethodPool::iterator M = SemaRef.MethodPool.begin(),
5375 MEnd = SemaRef.MethodPool.end();
Sebastian Redldb9d2142010-08-02 23:18:59 +00005376 M != MEnd; ++M) {
5377 for (ObjCMethodList *MethList = &M->second.second;
5378 MethList && MethList->Method;
Douglas Gregor13438f92010-04-06 16:40:00 +00005379 MethList = MethList->Next) {
5380 if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents,
5381 NumSelIdents))
5382 continue;
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005383
Douglas Gregor13438f92010-04-06 16:40:00 +00005384 Result R(MethList->Method, 0);
5385 R.StartParameter = NumSelIdents;
5386 R.AllParametersAreInformative = false;
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005387 Results.MaybeAddResult(R, SemaRef.CurContext);
Douglas Gregor13438f92010-04-06 16:40:00 +00005388 }
5389 }
5390 }
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005391
5392 Results.ExitScope();
5393}
Douglas Gregor13438f92010-04-06 16:40:00 +00005394
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005395void Sema::CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver,
5396 IdentifierInfo **SelIdents,
5397 unsigned NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005398 bool AtArgumentExpression,
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005399 bool IsSuper) {
Douglas Gregore081a612011-07-21 01:05:26 +00005400
5401 QualType T = this->GetTypeFromParser(Receiver);
5402
Douglas Gregor218937c2011-02-01 19:23:04 +00005403 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005404 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregore081a612011-07-21 01:05:26 +00005405 CodeCompletionContext(CodeCompletionContext::CCC_ObjCClassMessage,
Douglas Gregor0a47d692011-07-26 15:24:30 +00005406 T, SelIdents, NumSelIdents));
Douglas Gregore081a612011-07-21 01:05:26 +00005407
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005408 AddClassMessageCompletions(*this, S, Receiver, SelIdents, NumSelIdents,
5409 AtArgumentExpression, IsSuper, Results);
Douglas Gregorb9d77572010-09-21 00:03:25 +00005410
5411 // If we're actually at the argument expression (rather than prior to the
5412 // selector), we're actually performing code completion for an expression.
5413 // Determine whether we have a single, best method. If so, we can
5414 // code-complete the expression using the corresponding parameter type as
5415 // our preferred type, improving completion results.
5416 if (AtArgumentExpression) {
5417 QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results,
Douglas Gregore081a612011-07-21 01:05:26 +00005418 NumSelIdents);
Douglas Gregorb9d77572010-09-21 00:03:25 +00005419 if (PreferredType.isNull())
5420 CodeCompleteOrdinaryName(S, PCC_Expression);
5421 else
5422 CodeCompleteExpression(S, PreferredType);
5423 return;
5424 }
5425
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005426 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregore081a612011-07-21 01:05:26 +00005427 Results.getCompletionContext(),
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005428 Results.data(), Results.size());
Steve Naroffc4df6d22009-11-07 02:08:14 +00005429}
5430
Richard Trieuf81e5a92011-09-09 02:00:50 +00005431void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver,
Douglas Gregord3c68542009-11-19 01:08:35 +00005432 IdentifierInfo **SelIdents,
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005433 unsigned NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005434 bool AtArgumentExpression,
Douglas Gregor6b0656a2010-10-13 21:24:53 +00005435 ObjCInterfaceDecl *Super) {
John McCall0a2c5e22010-08-25 06:19:51 +00005436 typedef CodeCompletionResult Result;
Steve Naroffc4df6d22009-11-07 02:08:14 +00005437
5438 Expr *RecExpr = static_cast<Expr *>(Receiver);
Steve Naroffc4df6d22009-11-07 02:08:14 +00005439
Douglas Gregor36ecb042009-11-17 23:22:23 +00005440 // If necessary, apply function/array conversion to the receiver.
5441 // C99 6.7.5.3p[7,8].
John Wiegley429bb272011-04-08 18:41:53 +00005442 if (RecExpr) {
5443 ExprResult Conv = DefaultFunctionArrayLvalueConversion(RecExpr);
5444 if (Conv.isInvalid()) // conversion failed. bail.
5445 return;
5446 RecExpr = Conv.take();
5447 }
Douglas Gregor6b0656a2010-10-13 21:24:53 +00005448 QualType ReceiverType = RecExpr? RecExpr->getType()
5449 : Super? Context.getObjCObjectPointerType(
5450 Context.getObjCInterfaceType(Super))
5451 : Context.getObjCIdType();
Steve Naroffc4df6d22009-11-07 02:08:14 +00005452
Douglas Gregorda892642010-11-08 21:12:30 +00005453 // If we're messaging an expression with type "id" or "Class", check
5454 // whether we know something special about the receiver that allows
5455 // us to assume a more-specific receiver type.
5456 if (ReceiverType->isObjCIdType() || ReceiverType->isObjCClassType())
5457 if (ObjCInterfaceDecl *IFace = GetAssumedMessageSendExprType(RecExpr)) {
5458 if (ReceiverType->isObjCClassType())
5459 return CodeCompleteObjCClassMessage(S,
5460 ParsedType::make(Context.getObjCInterfaceType(IFace)),
5461 SelIdents, NumSelIdents,
5462 AtArgumentExpression, Super);
5463
5464 ReceiverType = Context.getObjCObjectPointerType(
5465 Context.getObjCInterfaceType(IFace));
5466 }
5467
Douglas Gregor36ecb042009-11-17 23:22:23 +00005468 // Build the set of methods we can see.
Douglas Gregor218937c2011-02-01 19:23:04 +00005469 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005470 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregore081a612011-07-21 01:05:26 +00005471 CodeCompletionContext(CodeCompletionContext::CCC_ObjCInstanceMessage,
Douglas Gregor0a47d692011-07-26 15:24:30 +00005472 ReceiverType, SelIdents, NumSelIdents));
Douglas Gregore081a612011-07-21 01:05:26 +00005473
Douglas Gregor36ecb042009-11-17 23:22:23 +00005474 Results.EnterNewScope();
Douglas Gregor22f56992010-04-06 19:22:33 +00005475
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005476 // If this is a send-to-super, try to add the special "super" send
5477 // completion.
Douglas Gregor6b0656a2010-10-13 21:24:53 +00005478 if (Super) {
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005479 if (ObjCMethodDecl *SuperMethod
5480 = AddSuperSendCompletion(*this, false, SelIdents, NumSelIdents,
5481 Results))
5482 Results.Ignore(SuperMethod);
5483 }
5484
Douglas Gregor265f7492010-08-27 15:29:55 +00005485 // If we're inside an Objective-C method definition, prefer its selector to
5486 // others.
5487 if (ObjCMethodDecl *CurMethod = getCurMethodDecl())
5488 Results.setPreferredSelector(CurMethod->getSelector());
Douglas Gregor36ecb042009-11-17 23:22:23 +00005489
Douglas Gregord36adf52010-09-16 16:06:31 +00005490 // Keep track of the selectors we've already added.
5491 VisitedSelectorSet Selectors;
5492
Douglas Gregorf74a4192009-11-18 00:06:18 +00005493 // Handle messages to Class. This really isn't a message to an instance
5494 // method, so we treat it the same way we would treat a message send to a
5495 // class method.
5496 if (ReceiverType->isObjCClassType() ||
5497 ReceiverType->isObjCQualifiedClassType()) {
5498 if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
5499 if (ObjCInterfaceDecl *ClassDecl = CurMethod->getClassInterface())
Douglas Gregor4ad96852009-11-19 07:41:15 +00005500 AddObjCMethods(ClassDecl, false, MK_Any, SelIdents, NumSelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00005501 CurContext, Selectors, AtArgumentExpression, Results);
Douglas Gregorf74a4192009-11-18 00:06:18 +00005502 }
5503 }
5504 // Handle messages to a qualified ID ("id<foo>").
5505 else if (const ObjCObjectPointerType *QualID
5506 = ReceiverType->getAsObjCQualifiedIdType()) {
5507 // Search protocols for instance methods.
5508 for (ObjCObjectPointerType::qual_iterator I = QualID->qual_begin(),
5509 E = QualID->qual_end();
5510 I != E; ++I)
Douglas Gregor4ad96852009-11-19 07:41:15 +00005511 AddObjCMethods(*I, true, MK_Any, SelIdents, NumSelIdents, CurContext,
Douglas Gregorcf544262010-11-17 21:36:08 +00005512 Selectors, AtArgumentExpression, Results);
Douglas Gregorf74a4192009-11-18 00:06:18 +00005513 }
5514 // Handle messages to a pointer to interface type.
5515 else if (const ObjCObjectPointerType *IFacePtr
5516 = ReceiverType->getAsObjCInterfacePointerType()) {
5517 // Search the class, its superclasses, etc., for instance methods.
Douglas Gregor4ad96852009-11-19 07:41:15 +00005518 AddObjCMethods(IFacePtr->getInterfaceDecl(), true, MK_Any, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00005519 NumSelIdents, CurContext, Selectors, AtArgumentExpression,
5520 Results);
Douglas Gregorf74a4192009-11-18 00:06:18 +00005521
5522 // Search protocols for instance methods.
5523 for (ObjCObjectPointerType::qual_iterator I = IFacePtr->qual_begin(),
5524 E = IFacePtr->qual_end();
5525 I != E; ++I)
Douglas Gregor4ad96852009-11-19 07:41:15 +00005526 AddObjCMethods(*I, true, MK_Any, SelIdents, NumSelIdents, CurContext,
Douglas Gregorcf544262010-11-17 21:36:08 +00005527 Selectors, AtArgumentExpression, Results);
Douglas Gregorf74a4192009-11-18 00:06:18 +00005528 }
Douglas Gregor13438f92010-04-06 16:40:00 +00005529 // Handle messages to "id".
5530 else if (ReceiverType->isObjCIdType()) {
Douglas Gregor719770d2010-04-06 17:30:22 +00005531 // We're messaging "id", so provide all instance methods we know
5532 // about as code-completion results.
5533
5534 // If we have an external source, load the entire class method
Sebastian Redl3c7f4132010-08-18 23:57:06 +00005535 // pool from the AST file.
Douglas Gregor719770d2010-04-06 17:30:22 +00005536 if (ExternalSource) {
John McCall76bd1f32010-06-01 09:23:16 +00005537 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
5538 I != N; ++I) {
5539 Selector Sel = ExternalSource->GetExternalSelector(I);
Sebastian Redldb9d2142010-08-02 23:18:59 +00005540 if (Sel.isNull() || MethodPool.count(Sel))
Douglas Gregor719770d2010-04-06 17:30:22 +00005541 continue;
5542
Sebastian Redldb9d2142010-08-02 23:18:59 +00005543 ReadMethodPool(Sel);
Douglas Gregor719770d2010-04-06 17:30:22 +00005544 }
5545 }
5546
Sebastian Redldb9d2142010-08-02 23:18:59 +00005547 for (GlobalMethodPool::iterator M = MethodPool.begin(),
5548 MEnd = MethodPool.end();
5549 M != MEnd; ++M) {
5550 for (ObjCMethodList *MethList = &M->second.first;
5551 MethList && MethList->Method;
Douglas Gregor13438f92010-04-06 16:40:00 +00005552 MethList = MethList->Next) {
5553 if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents,
5554 NumSelIdents))
5555 continue;
Douglas Gregord36adf52010-09-16 16:06:31 +00005556
5557 if (!Selectors.insert(MethList->Method->getSelector()))
5558 continue;
5559
Douglas Gregor13438f92010-04-06 16:40:00 +00005560 Result R(MethList->Method, 0);
5561 R.StartParameter = NumSelIdents;
5562 R.AllParametersAreInformative = false;
5563 Results.MaybeAddResult(R, CurContext);
5564 }
5565 }
5566 }
Steve Naroffc4df6d22009-11-07 02:08:14 +00005567 Results.ExitScope();
Douglas Gregorb9d77572010-09-21 00:03:25 +00005568
5569
5570 // If we're actually at the argument expression (rather than prior to the
5571 // selector), we're actually performing code completion for an expression.
5572 // Determine whether we have a single, best method. If so, we can
5573 // code-complete the expression using the corresponding parameter type as
5574 // our preferred type, improving completion results.
5575 if (AtArgumentExpression) {
5576 QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results,
5577 NumSelIdents);
5578 if (PreferredType.isNull())
5579 CodeCompleteOrdinaryName(S, PCC_Expression);
5580 else
5581 CodeCompleteExpression(S, PreferredType);
5582 return;
5583 }
5584
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005585 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregore081a612011-07-21 01:05:26 +00005586 Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005587 Results.data(),Results.size());
Steve Naroffc4df6d22009-11-07 02:08:14 +00005588}
Douglas Gregor55385fe2009-11-18 04:19:12 +00005589
Douglas Gregorfb629412010-08-23 21:17:50 +00005590void Sema::CodeCompleteObjCForCollection(Scope *S,
5591 DeclGroupPtrTy IterationVar) {
5592 CodeCompleteExpressionData Data;
5593 Data.ObjCCollection = true;
5594
5595 if (IterationVar.getAsOpaquePtr()) {
5596 DeclGroupRef DG = IterationVar.getAsVal<DeclGroupRef>();
5597 for (DeclGroupRef::iterator I = DG.begin(), End = DG.end(); I != End; ++I) {
5598 if (*I)
5599 Data.IgnoreDecls.push_back(*I);
5600 }
5601 }
5602
5603 CodeCompleteExpression(S, Data);
5604}
5605
Douglas Gregor458433d2010-08-26 15:07:07 +00005606void Sema::CodeCompleteObjCSelector(Scope *S, IdentifierInfo **SelIdents,
5607 unsigned NumSelIdents) {
5608 // If we have an external source, load the entire class method
5609 // pool from the AST file.
5610 if (ExternalSource) {
5611 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
5612 I != N; ++I) {
5613 Selector Sel = ExternalSource->GetExternalSelector(I);
5614 if (Sel.isNull() || MethodPool.count(Sel))
5615 continue;
5616
5617 ReadMethodPool(Sel);
5618 }
5619 }
5620
Douglas Gregor218937c2011-02-01 19:23:04 +00005621 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005622 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00005623 CodeCompletionContext::CCC_SelectorName);
Douglas Gregor458433d2010-08-26 15:07:07 +00005624 Results.EnterNewScope();
5625 for (GlobalMethodPool::iterator M = MethodPool.begin(),
5626 MEnd = MethodPool.end();
5627 M != MEnd; ++M) {
5628
5629 Selector Sel = M->first;
5630 if (!isAcceptableObjCSelector(Sel, MK_Any, SelIdents, NumSelIdents))
5631 continue;
5632
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005633 CodeCompletionBuilder Builder(Results.getAllocator(),
5634 Results.getCodeCompletionTUInfo());
Douglas Gregor458433d2010-08-26 15:07:07 +00005635 if (Sel.isUnarySelector()) {
Douglas Gregordae68752011-02-01 22:57:45 +00005636 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00005637 Sel.getNameForSlot(0)));
Douglas Gregor218937c2011-02-01 19:23:04 +00005638 Results.AddResult(Builder.TakeString());
Douglas Gregor458433d2010-08-26 15:07:07 +00005639 continue;
5640 }
5641
Douglas Gregor2d9e21f2010-08-26 16:46:39 +00005642 std::string Accumulator;
Douglas Gregor458433d2010-08-26 15:07:07 +00005643 for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I) {
Douglas Gregor2d9e21f2010-08-26 16:46:39 +00005644 if (I == NumSelIdents) {
5645 if (!Accumulator.empty()) {
Douglas Gregordae68752011-02-01 22:57:45 +00005646 Builder.AddInformativeChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00005647 Accumulator));
Douglas Gregor2d9e21f2010-08-26 16:46:39 +00005648 Accumulator.clear();
5649 }
5650 }
5651
Benjamin Kramera0651c52011-07-26 16:59:25 +00005652 Accumulator += Sel.getNameForSlot(I);
Douglas Gregor2d9e21f2010-08-26 16:46:39 +00005653 Accumulator += ':';
Douglas Gregor458433d2010-08-26 15:07:07 +00005654 }
Douglas Gregordae68752011-02-01 22:57:45 +00005655 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString( Accumulator));
Douglas Gregor218937c2011-02-01 19:23:04 +00005656 Results.AddResult(Builder.TakeString());
Douglas Gregor458433d2010-08-26 15:07:07 +00005657 }
5658 Results.ExitScope();
5659
5660 HandleCodeCompleteResults(this, CodeCompleter,
5661 CodeCompletionContext::CCC_SelectorName,
5662 Results.data(), Results.size());
5663}
5664
Douglas Gregor55385fe2009-11-18 04:19:12 +00005665/// \brief Add all of the protocol declarations that we find in the given
5666/// (translation unit) context.
5667static void AddProtocolResults(DeclContext *Ctx, DeclContext *CurContext,
Douglas Gregor083128f2009-11-18 04:49:41 +00005668 bool OnlyForwardDeclarations,
Douglas Gregor55385fe2009-11-18 04:19:12 +00005669 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00005670 typedef CodeCompletionResult Result;
Douglas Gregor55385fe2009-11-18 04:19:12 +00005671
5672 for (DeclContext::decl_iterator D = Ctx->decls_begin(),
5673 DEnd = Ctx->decls_end();
5674 D != DEnd; ++D) {
5675 // Record any protocols we find.
5676 if (ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>(*D))
Douglas Gregor5e2a1ff2012-01-01 19:29:29 +00005677 if (!OnlyForwardDeclarations || !Proto->hasDefinition())
Douglas Gregor608300b2010-01-14 16:14:35 +00005678 Results.AddResult(Result(Proto, 0), CurContext, 0, false);
Douglas Gregor55385fe2009-11-18 04:19:12 +00005679 }
5680}
5681
5682void Sema::CodeCompleteObjCProtocolReferences(IdentifierLocPair *Protocols,
5683 unsigned NumProtocols) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005684 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005685 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00005686 CodeCompletionContext::CCC_ObjCProtocolName);
Douglas Gregor55385fe2009-11-18 04:19:12 +00005687
Douglas Gregor70c23352010-12-09 21:44:02 +00005688 if (CodeCompleter && CodeCompleter->includeGlobals()) {
5689 Results.EnterNewScope();
5690
5691 // Tell the result set to ignore all of the protocols we have
5692 // already seen.
5693 // FIXME: This doesn't work when caching code-completion results.
5694 for (unsigned I = 0; I != NumProtocols; ++I)
5695 if (ObjCProtocolDecl *Protocol = LookupProtocol(Protocols[I].first,
5696 Protocols[I].second))
5697 Results.Ignore(Protocol);
Douglas Gregor55385fe2009-11-18 04:19:12 +00005698
Douglas Gregor70c23352010-12-09 21:44:02 +00005699 // Add all protocols.
5700 AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, false,
5701 Results);
Douglas Gregor083128f2009-11-18 04:49:41 +00005702
Douglas Gregor70c23352010-12-09 21:44:02 +00005703 Results.ExitScope();
5704 }
5705
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005706 HandleCodeCompleteResults(this, CodeCompleter,
5707 CodeCompletionContext::CCC_ObjCProtocolName,
5708 Results.data(),Results.size());
Douglas Gregor083128f2009-11-18 04:49:41 +00005709}
5710
5711void Sema::CodeCompleteObjCProtocolDecl(Scope *) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005712 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005713 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00005714 CodeCompletionContext::CCC_ObjCProtocolName);
Douglas Gregor083128f2009-11-18 04:49:41 +00005715
Douglas Gregor70c23352010-12-09 21:44:02 +00005716 if (CodeCompleter && CodeCompleter->includeGlobals()) {
5717 Results.EnterNewScope();
5718
5719 // Add all protocols.
5720 AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, true,
5721 Results);
Douglas Gregor55385fe2009-11-18 04:19:12 +00005722
Douglas Gregor70c23352010-12-09 21:44:02 +00005723 Results.ExitScope();
5724 }
5725
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005726 HandleCodeCompleteResults(this, CodeCompleter,
5727 CodeCompletionContext::CCC_ObjCProtocolName,
5728 Results.data(),Results.size());
Douglas Gregor55385fe2009-11-18 04:19:12 +00005729}
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005730
5731/// \brief Add all of the Objective-C interface declarations that we find in
5732/// the given (translation unit) context.
5733static void AddInterfaceResults(DeclContext *Ctx, DeclContext *CurContext,
5734 bool OnlyForwardDeclarations,
5735 bool OnlyUnimplemented,
5736 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00005737 typedef CodeCompletionResult Result;
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005738
5739 for (DeclContext::decl_iterator D = Ctx->decls_begin(),
5740 DEnd = Ctx->decls_end();
5741 D != DEnd; ++D) {
Douglas Gregordeacbdc2010-08-11 12:19:30 +00005742 // Record any interfaces we find.
5743 if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(*D))
Douglas Gregor7723fec2011-12-15 20:29:51 +00005744 if ((!OnlyForwardDeclarations || !Class->hasDefinition()) &&
Douglas Gregordeacbdc2010-08-11 12:19:30 +00005745 (!OnlyUnimplemented || !Class->getImplementation()))
5746 Results.AddResult(Result(Class, 0), CurContext, 0, false);
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005747 }
5748}
5749
5750void Sema::CodeCompleteObjCInterfaceDecl(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005751 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005752 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00005753 CodeCompletionContext::CCC_Other);
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005754 Results.EnterNewScope();
5755
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005756 if (CodeCompleter->includeGlobals()) {
5757 // Add all classes.
5758 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
5759 false, Results);
5760 }
5761
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005762 Results.ExitScope();
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005763
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005764 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005765 CodeCompletionContext::CCC_ObjCInterfaceName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005766 Results.data(),Results.size());
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005767}
5768
Douglas Gregorc83c6872010-04-15 22:33:43 +00005769void Sema::CodeCompleteObjCSuperclass(Scope *S, IdentifierInfo *ClassName,
5770 SourceLocation ClassNameLoc) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005771 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005772 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005773 CodeCompletionContext::CCC_ObjCInterfaceName);
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005774 Results.EnterNewScope();
5775
5776 // Make sure that we ignore the class we're currently defining.
5777 NamedDecl *CurClass
Douglas Gregorc83c6872010-04-15 22:33:43 +00005778 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005779 if (CurClass && isa<ObjCInterfaceDecl>(CurClass))
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005780 Results.Ignore(CurClass);
5781
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005782 if (CodeCompleter->includeGlobals()) {
5783 // Add all classes.
5784 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
5785 false, Results);
5786 }
5787
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005788 Results.ExitScope();
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005789
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005790 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005791 CodeCompletionContext::CCC_ObjCInterfaceName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005792 Results.data(),Results.size());
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005793}
5794
5795void Sema::CodeCompleteObjCImplementationDecl(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005796 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005797 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00005798 CodeCompletionContext::CCC_Other);
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005799 Results.EnterNewScope();
5800
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005801 if (CodeCompleter->includeGlobals()) {
5802 // Add all unimplemented classes.
5803 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
5804 true, Results);
5805 }
5806
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005807 Results.ExitScope();
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005808
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005809 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005810 CodeCompletionContext::CCC_ObjCInterfaceName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005811 Results.data(),Results.size());
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005812}
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005813
5814void Sema::CodeCompleteObjCInterfaceCategory(Scope *S,
Douglas Gregorc83c6872010-04-15 22:33:43 +00005815 IdentifierInfo *ClassName,
5816 SourceLocation ClassNameLoc) {
John McCall0a2c5e22010-08-25 06:19:51 +00005817 typedef CodeCompletionResult Result;
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005818
Douglas Gregor218937c2011-02-01 19:23:04 +00005819 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005820 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor3da626b2011-07-07 16:03:39 +00005821 CodeCompletionContext::CCC_ObjCCategoryName);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005822
5823 // Ignore any categories we find that have already been implemented by this
5824 // interface.
5825 llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
5826 NamedDecl *CurClass
Douglas Gregorc83c6872010-04-15 22:33:43 +00005827 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregord3297242013-01-16 23:00:23 +00005828 if (ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass)){
5829 for (ObjCInterfaceDecl::visible_categories_iterator
5830 Cat = Class->visible_categories_begin(),
5831 CatEnd = Class->visible_categories_end();
5832 Cat != CatEnd; ++Cat) {
5833 CategoryNames.insert(Cat->getIdentifier());
5834 }
5835 }
5836
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005837 // Add all of the categories we know about.
5838 Results.EnterNewScope();
5839 TranslationUnitDecl *TU = Context.getTranslationUnitDecl();
5840 for (DeclContext::decl_iterator D = TU->decls_begin(),
5841 DEnd = TU->decls_end();
5842 D != DEnd; ++D)
5843 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(*D))
5844 if (CategoryNames.insert(Category->getIdentifier()))
Douglas Gregor608300b2010-01-14 16:14:35 +00005845 Results.AddResult(Result(Category, 0), CurContext, 0, false);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005846 Results.ExitScope();
5847
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005848 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor3da626b2011-07-07 16:03:39 +00005849 CodeCompletionContext::CCC_ObjCCategoryName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005850 Results.data(),Results.size());
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005851}
5852
5853void Sema::CodeCompleteObjCImplementationCategory(Scope *S,
Douglas Gregorc83c6872010-04-15 22:33:43 +00005854 IdentifierInfo *ClassName,
5855 SourceLocation ClassNameLoc) {
John McCall0a2c5e22010-08-25 06:19:51 +00005856 typedef CodeCompletionResult Result;
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005857
5858 // Find the corresponding interface. If we couldn't find the interface, the
5859 // program itself is ill-formed. However, we'll try to be helpful still by
5860 // providing the list of all of the categories we know about.
5861 NamedDecl *CurClass
Douglas Gregorc83c6872010-04-15 22:33:43 +00005862 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005863 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass);
5864 if (!Class)
Douglas Gregorc83c6872010-04-15 22:33:43 +00005865 return CodeCompleteObjCInterfaceCategory(S, ClassName, ClassNameLoc);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005866
Douglas Gregor218937c2011-02-01 19:23:04 +00005867 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005868 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor3da626b2011-07-07 16:03:39 +00005869 CodeCompletionContext::CCC_ObjCCategoryName);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005870
5871 // Add all of the categories that have have corresponding interface
5872 // declarations in this class and any of its superclasses, except for
5873 // already-implemented categories in the class itself.
5874 llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
5875 Results.EnterNewScope();
5876 bool IgnoreImplemented = true;
5877 while (Class) {
Douglas Gregord3297242013-01-16 23:00:23 +00005878 for (ObjCInterfaceDecl::visible_categories_iterator
5879 Cat = Class->visible_categories_begin(),
5880 CatEnd = Class->visible_categories_end();
5881 Cat != CatEnd; ++Cat) {
5882 if ((!IgnoreImplemented || !Cat->getImplementation()) &&
5883 CategoryNames.insert(Cat->getIdentifier()))
5884 Results.AddResult(Result(*Cat, 0), CurContext, 0, false);
5885 }
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005886
5887 Class = Class->getSuperClass();
5888 IgnoreImplemented = false;
5889 }
5890 Results.ExitScope();
5891
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005892 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor3da626b2011-07-07 16:03:39 +00005893 CodeCompletionContext::CCC_ObjCCategoryName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005894 Results.data(),Results.size());
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005895}
Douglas Gregor322328b2009-11-18 22:32:06 +00005896
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00005897void Sema::CodeCompleteObjCPropertyDefinition(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005898 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005899 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00005900 CodeCompletionContext::CCC_Other);
Douglas Gregor322328b2009-11-18 22:32:06 +00005901
5902 // Figure out where this @synthesize lives.
5903 ObjCContainerDecl *Container
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00005904 = dyn_cast_or_null<ObjCContainerDecl>(CurContext);
Douglas Gregor322328b2009-11-18 22:32:06 +00005905 if (!Container ||
5906 (!isa<ObjCImplementationDecl>(Container) &&
5907 !isa<ObjCCategoryImplDecl>(Container)))
5908 return;
5909
5910 // Ignore any properties that have already been implemented.
Douglas Gregorb92a4082012-06-12 13:44:08 +00005911 Container = getContainerDef(Container);
5912 for (DeclContext::decl_iterator D = Container->decls_begin(),
Douglas Gregor322328b2009-11-18 22:32:06 +00005913 DEnd = Container->decls_end();
5914 D != DEnd; ++D)
5915 if (ObjCPropertyImplDecl *PropertyImpl = dyn_cast<ObjCPropertyImplDecl>(*D))
5916 Results.Ignore(PropertyImpl->getPropertyDecl());
5917
5918 // Add any properties that we find.
Douglas Gregor73449212010-12-09 23:01:55 +00005919 AddedPropertiesSet AddedProperties;
Douglas Gregor322328b2009-11-18 22:32:06 +00005920 Results.EnterNewScope();
5921 if (ObjCImplementationDecl *ClassImpl
5922 = dyn_cast<ObjCImplementationDecl>(Container))
Douglas Gregor4b81cde2011-05-05 15:50:42 +00005923 AddObjCProperties(ClassImpl->getClassInterface(), false,
5924 /*AllowNullaryMethods=*/false, CurContext,
Douglas Gregor73449212010-12-09 23:01:55 +00005925 AddedProperties, Results);
Douglas Gregor322328b2009-11-18 22:32:06 +00005926 else
5927 AddObjCProperties(cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl(),
Douglas Gregor4b81cde2011-05-05 15:50:42 +00005928 false, /*AllowNullaryMethods=*/false, CurContext,
5929 AddedProperties, Results);
Douglas Gregor322328b2009-11-18 22:32:06 +00005930 Results.ExitScope();
5931
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005932 HandleCodeCompleteResults(this, CodeCompleter,
5933 CodeCompletionContext::CCC_Other,
5934 Results.data(),Results.size());
Douglas Gregor322328b2009-11-18 22:32:06 +00005935}
5936
5937void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S,
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00005938 IdentifierInfo *PropertyName) {
John McCall0a2c5e22010-08-25 06:19:51 +00005939 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00005940 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005941 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00005942 CodeCompletionContext::CCC_Other);
Douglas Gregor322328b2009-11-18 22:32:06 +00005943
5944 // Figure out where this @synthesize lives.
5945 ObjCContainerDecl *Container
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00005946 = dyn_cast_or_null<ObjCContainerDecl>(CurContext);
Douglas Gregor322328b2009-11-18 22:32:06 +00005947 if (!Container ||
5948 (!isa<ObjCImplementationDecl>(Container) &&
5949 !isa<ObjCCategoryImplDecl>(Container)))
5950 return;
5951
5952 // Figure out which interface we're looking into.
5953 ObjCInterfaceDecl *Class = 0;
5954 if (ObjCImplementationDecl *ClassImpl
5955 = dyn_cast<ObjCImplementationDecl>(Container))
5956 Class = ClassImpl->getClassInterface();
5957 else
5958 Class = cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl()
5959 ->getClassInterface();
5960
Douglas Gregore8426052011-04-18 14:40:46 +00005961 // Determine the type of the property we're synthesizing.
5962 QualType PropertyType = Context.getObjCIdType();
5963 if (Class) {
5964 if (ObjCPropertyDecl *Property
5965 = Class->FindPropertyDeclaration(PropertyName)) {
5966 PropertyType
5967 = Property->getType().getNonReferenceType().getUnqualifiedType();
5968
5969 // Give preference to ivars
5970 Results.setPreferredType(PropertyType);
5971 }
5972 }
5973
Douglas Gregor322328b2009-11-18 22:32:06 +00005974 // Add all of the instance variables in this class and its superclasses.
5975 Results.EnterNewScope();
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005976 bool SawSimilarlyNamedIvar = false;
5977 std::string NameWithPrefix;
5978 NameWithPrefix += '_';
Benjamin Kramera0651c52011-07-26 16:59:25 +00005979 NameWithPrefix += PropertyName->getName();
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005980 std::string NameWithSuffix = PropertyName->getName().str();
5981 NameWithSuffix += '_';
Douglas Gregor322328b2009-11-18 22:32:06 +00005982 for(; Class; Class = Class->getSuperClass()) {
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005983 for (ObjCIvarDecl *Ivar = Class->all_declared_ivar_begin(); Ivar;
5984 Ivar = Ivar->getNextIvar()) {
Douglas Gregore8426052011-04-18 14:40:46 +00005985 Results.AddResult(Result(Ivar, 0), CurContext, 0, false);
5986
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005987 // Determine whether we've seen an ivar with a name similar to the
5988 // property.
Douglas Gregore8426052011-04-18 14:40:46 +00005989 if ((PropertyName == Ivar->getIdentifier() ||
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005990 NameWithPrefix == Ivar->getName() ||
Douglas Gregore8426052011-04-18 14:40:46 +00005991 NameWithSuffix == Ivar->getName())) {
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005992 SawSimilarlyNamedIvar = true;
Douglas Gregore8426052011-04-18 14:40:46 +00005993
5994 // Reduce the priority of this result by one, to give it a slight
5995 // advantage over other results whose names don't match so closely.
5996 if (Results.size() &&
5997 Results.data()[Results.size() - 1].Kind
5998 == CodeCompletionResult::RK_Declaration &&
5999 Results.data()[Results.size() - 1].Declaration == Ivar)
6000 Results.data()[Results.size() - 1].Priority--;
6001 }
Douglas Gregoraa490cb2011-04-18 14:13:53 +00006002 }
Douglas Gregor322328b2009-11-18 22:32:06 +00006003 }
Douglas Gregoraa490cb2011-04-18 14:13:53 +00006004
6005 if (!SawSimilarlyNamedIvar) {
6006 // Create ivar result _propName, that the user can use to synthesize
Douglas Gregore8426052011-04-18 14:40:46 +00006007 // an ivar of the appropriate type.
6008 unsigned Priority = CCP_MemberDeclaration + 1;
Douglas Gregoraa490cb2011-04-18 14:13:53 +00006009 typedef CodeCompletionResult Result;
6010 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00006011 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo(),
6012 Priority,CXAvailability_Available);
Douglas Gregoraa490cb2011-04-18 14:13:53 +00006013
Douglas Gregor8987b232011-09-27 23:30:47 +00006014 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Douglas Gregore8426052011-04-18 14:40:46 +00006015 Builder.AddResultTypeChunk(GetCompletionTypeString(PropertyType, Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00006016 Policy, Allocator));
Douglas Gregoraa490cb2011-04-18 14:13:53 +00006017 Builder.AddTypedTextChunk(Allocator.CopyString(NameWithPrefix));
6018 Results.AddResult(Result(Builder.TakeString(), Priority,
6019 CXCursor_ObjCIvarDecl));
6020 }
6021
Douglas Gregor322328b2009-11-18 22:32:06 +00006022 Results.ExitScope();
6023
Douglas Gregore6b1bb62010-08-11 21:23:17 +00006024 HandleCodeCompleteResults(this, CodeCompleter,
6025 CodeCompletionContext::CCC_Other,
6026 Results.data(),Results.size());
Douglas Gregor322328b2009-11-18 22:32:06 +00006027}
Douglas Gregore8f5a172010-04-07 00:21:17 +00006028
Douglas Gregor408be5a2010-08-25 01:08:01 +00006029// Mapping from selectors to the methods that implement that selector, along
6030// with the "in original class" flag.
6031typedef llvm::DenseMap<Selector, std::pair<ObjCMethodDecl *, bool> >
6032 KnownMethodsMap;
Douglas Gregore8f5a172010-04-07 00:21:17 +00006033
6034/// \brief Find all of the methods that reside in the given container
6035/// (and its superclasses, protocols, etc.) that meet the given
6036/// criteria. Insert those methods into the map of known methods,
6037/// indexed by selector so they can be easily found.
6038static void FindImplementableMethods(ASTContext &Context,
6039 ObjCContainerDecl *Container,
6040 bool WantInstanceMethods,
6041 QualType ReturnType,
Douglas Gregor408be5a2010-08-25 01:08:01 +00006042 KnownMethodsMap &KnownMethods,
6043 bool InOriginalClass = true) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00006044 if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)) {
Douglas Gregorb92a4082012-06-12 13:44:08 +00006045 // Make sure we have a definition; that's what we'll walk.
Douglas Gregor2e5c15b2011-12-15 05:27:12 +00006046 if (!IFace->hasDefinition())
6047 return;
Douglas Gregorb92a4082012-06-12 13:44:08 +00006048
6049 IFace = IFace->getDefinition();
6050 Container = IFace;
Douglas Gregor2e5c15b2011-12-15 05:27:12 +00006051
Douglas Gregore8f5a172010-04-07 00:21:17 +00006052 const ObjCList<ObjCProtocolDecl> &Protocols
6053 = IFace->getReferencedProtocols();
6054 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Douglas Gregorea766182010-10-18 18:21:28 +00006055 E = Protocols.end();
Douglas Gregore8f5a172010-04-07 00:21:17 +00006056 I != E; ++I)
6057 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
Douglas Gregorea766182010-10-18 18:21:28 +00006058 KnownMethods, InOriginalClass);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006059
Douglas Gregorea766182010-10-18 18:21:28 +00006060 // Add methods from any class extensions and categories.
Douglas Gregord3297242013-01-16 23:00:23 +00006061 for (ObjCInterfaceDecl::visible_categories_iterator
6062 Cat = IFace->visible_categories_begin(),
6063 CatEnd = IFace->visible_categories_end();
6064 Cat != CatEnd; ++Cat) {
6065 FindImplementableMethods(Context, *Cat, WantInstanceMethods, ReturnType,
Douglas Gregorea766182010-10-18 18:21:28 +00006066 KnownMethods, false);
Douglas Gregord3297242013-01-16 23:00:23 +00006067 }
6068
Douglas Gregorea766182010-10-18 18:21:28 +00006069 // Visit the superclass.
6070 if (IFace->getSuperClass())
6071 FindImplementableMethods(Context, IFace->getSuperClass(),
6072 WantInstanceMethods, ReturnType,
6073 KnownMethods, false);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006074 }
6075
6076 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(Container)) {
6077 // Recurse into protocols.
6078 const ObjCList<ObjCProtocolDecl> &Protocols
6079 = Category->getReferencedProtocols();
6080 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Douglas Gregorea766182010-10-18 18:21:28 +00006081 E = Protocols.end();
Douglas Gregore8f5a172010-04-07 00:21:17 +00006082 I != E; ++I)
6083 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
Douglas Gregorea766182010-10-18 18:21:28 +00006084 KnownMethods, InOriginalClass);
6085
6086 // If this category is the original class, jump to the interface.
6087 if (InOriginalClass && Category->getClassInterface())
6088 FindImplementableMethods(Context, Category->getClassInterface(),
6089 WantInstanceMethods, ReturnType, KnownMethods,
6090 false);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006091 }
6092
6093 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Douglas Gregorb92a4082012-06-12 13:44:08 +00006094 // Make sure we have a definition; that's what we'll walk.
6095 if (!Protocol->hasDefinition())
6096 return;
6097 Protocol = Protocol->getDefinition();
6098 Container = Protocol;
6099
6100 // Recurse into protocols.
6101 const ObjCList<ObjCProtocolDecl> &Protocols
6102 = Protocol->getReferencedProtocols();
6103 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
6104 E = Protocols.end();
6105 I != E; ++I)
6106 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
6107 KnownMethods, false);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006108 }
6109
6110 // Add methods in this container. This operation occurs last because
6111 // we want the methods from this container to override any methods
6112 // we've previously seen with the same selector.
6113 for (ObjCContainerDecl::method_iterator M = Container->meth_begin(),
6114 MEnd = Container->meth_end();
6115 M != MEnd; ++M) {
David Blaikie262bc182012-04-30 02:36:29 +00006116 if (M->isInstanceMethod() == WantInstanceMethods) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00006117 if (!ReturnType.isNull() &&
David Blaikie262bc182012-04-30 02:36:29 +00006118 !Context.hasSameUnqualifiedType(ReturnType, M->getResultType()))
Douglas Gregore8f5a172010-04-07 00:21:17 +00006119 continue;
6120
David Blaikie581deb32012-06-06 20:45:41 +00006121 KnownMethods[M->getSelector()] = std::make_pair(*M, InOriginalClass);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006122 }
6123 }
6124}
6125
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006126/// \brief Add the parenthesized return or parameter type chunk to a code
6127/// completion string.
6128static void AddObjCPassingTypeChunk(QualType Type,
Douglas Gregor90f5f472012-04-10 18:35:07 +00006129 unsigned ObjCDeclQuals,
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006130 ASTContext &Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00006131 const PrintingPolicy &Policy,
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006132 CodeCompletionBuilder &Builder) {
6133 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregor90f5f472012-04-10 18:35:07 +00006134 std::string Quals = formatObjCParamQualifiers(ObjCDeclQuals);
6135 if (!Quals.empty())
6136 Builder.AddTextChunk(Builder.getAllocator().CopyString(Quals));
Douglas Gregor8987b232011-09-27 23:30:47 +00006137 Builder.AddTextChunk(GetCompletionTypeString(Type, Context, Policy,
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006138 Builder.getAllocator()));
6139 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6140}
6141
6142/// \brief Determine whether the given class is or inherits from a class by
6143/// the given name.
6144static bool InheritsFromClassNamed(ObjCInterfaceDecl *Class,
Chris Lattner5f9e2722011-07-23 10:55:15 +00006145 StringRef Name) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006146 if (!Class)
6147 return false;
6148
6149 if (Class->getIdentifier() && Class->getIdentifier()->getName() == Name)
6150 return true;
6151
6152 return InheritsFromClassNamed(Class->getSuperClass(), Name);
6153}
6154
6155/// \brief Add code completions for Objective-C Key-Value Coding (KVC) and
6156/// Key-Value Observing (KVO).
6157static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
6158 bool IsInstanceMethod,
6159 QualType ReturnType,
6160 ASTContext &Context,
Douglas Gregore74c25c2011-05-04 23:50:46 +00006161 VisitedSelectorSet &KnownSelectors,
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006162 ResultBuilder &Results) {
6163 IdentifierInfo *PropName = Property->getIdentifier();
6164 if (!PropName || PropName->getLength() == 0)
6165 return;
6166
Douglas Gregor8987b232011-09-27 23:30:47 +00006167 PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema());
6168
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006169 // Builder that will create each code completion.
6170 typedef CodeCompletionResult Result;
6171 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00006172 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006173
6174 // The selector table.
6175 SelectorTable &Selectors = Context.Selectors;
6176
6177 // The property name, copied into the code completion allocation region
6178 // on demand.
6179 struct KeyHolder {
6180 CodeCompletionAllocator &Allocator;
Chris Lattner5f9e2722011-07-23 10:55:15 +00006181 StringRef Key;
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006182 const char *CopiedKey;
6183
Chris Lattner5f9e2722011-07-23 10:55:15 +00006184 KeyHolder(CodeCompletionAllocator &Allocator, StringRef Key)
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006185 : Allocator(Allocator), Key(Key), CopiedKey(0) { }
6186
6187 operator const char *() {
6188 if (CopiedKey)
6189 return CopiedKey;
6190
6191 return CopiedKey = Allocator.CopyString(Key);
6192 }
6193 } Key(Allocator, PropName->getName());
6194
6195 // The uppercased name of the property name.
6196 std::string UpperKey = PropName->getName();
6197 if (!UpperKey.empty())
6198 UpperKey[0] = toupper(UpperKey[0]);
6199
6200 bool ReturnTypeMatchesProperty = ReturnType.isNull() ||
6201 Context.hasSameUnqualifiedType(ReturnType.getNonReferenceType(),
6202 Property->getType());
6203 bool ReturnTypeMatchesVoid
6204 = ReturnType.isNull() || ReturnType->isVoidType();
6205
6206 // Add the normal accessor -(type)key.
6207 if (IsInstanceMethod &&
Douglas Gregore74c25c2011-05-04 23:50:46 +00006208 KnownSelectors.insert(Selectors.getNullarySelector(PropName)) &&
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006209 ReturnTypeMatchesProperty && !Property->getGetterMethodDecl()) {
6210 if (ReturnType.isNull())
Douglas Gregor90f5f472012-04-10 18:35:07 +00006211 AddObjCPassingTypeChunk(Property->getType(), /*Quals=*/0,
6212 Context, Policy, Builder);
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006213
6214 Builder.AddTypedTextChunk(Key);
6215 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
6216 CXCursor_ObjCInstanceMethodDecl));
6217 }
6218
6219 // If we have an integral or boolean property (or the user has provided
6220 // an integral or boolean return type), add the accessor -(type)isKey.
6221 if (IsInstanceMethod &&
6222 ((!ReturnType.isNull() &&
6223 (ReturnType->isIntegerType() || ReturnType->isBooleanType())) ||
6224 (ReturnType.isNull() &&
6225 (Property->getType()->isIntegerType() ||
6226 Property->getType()->isBooleanType())))) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006227 std::string SelectorName = (Twine("is") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006228 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006229 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006230 if (ReturnType.isNull()) {
6231 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6232 Builder.AddTextChunk("BOOL");
6233 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6234 }
6235
6236 Builder.AddTypedTextChunk(
6237 Allocator.CopyString(SelectorId->getName()));
6238 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
6239 CXCursor_ObjCInstanceMethodDecl));
6240 }
6241 }
6242
6243 // Add the normal mutator.
6244 if (IsInstanceMethod && ReturnTypeMatchesVoid &&
6245 !Property->getSetterMethodDecl()) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006246 std::string SelectorName = (Twine("set") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006247 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006248 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006249 if (ReturnType.isNull()) {
6250 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6251 Builder.AddTextChunk("void");
6252 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6253 }
6254
6255 Builder.AddTypedTextChunk(
6256 Allocator.CopyString(SelectorId->getName()));
6257 Builder.AddTypedTextChunk(":");
Douglas Gregor90f5f472012-04-10 18:35:07 +00006258 AddObjCPassingTypeChunk(Property->getType(), /*Quals=*/0,
6259 Context, Policy, Builder);
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006260 Builder.AddTextChunk(Key);
6261 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
6262 CXCursor_ObjCInstanceMethodDecl));
6263 }
6264 }
6265
6266 // Indexed and unordered accessors
6267 unsigned IndexedGetterPriority = CCP_CodePattern;
6268 unsigned IndexedSetterPriority = CCP_CodePattern;
6269 unsigned UnorderedGetterPriority = CCP_CodePattern;
6270 unsigned UnorderedSetterPriority = CCP_CodePattern;
6271 if (const ObjCObjectPointerType *ObjCPointer
6272 = Property->getType()->getAs<ObjCObjectPointerType>()) {
6273 if (ObjCInterfaceDecl *IFace = ObjCPointer->getInterfaceDecl()) {
6274 // If this interface type is not provably derived from a known
6275 // collection, penalize the corresponding completions.
6276 if (!InheritsFromClassNamed(IFace, "NSMutableArray")) {
6277 IndexedSetterPriority += CCD_ProbablyNotObjCCollection;
6278 if (!InheritsFromClassNamed(IFace, "NSArray"))
6279 IndexedGetterPriority += CCD_ProbablyNotObjCCollection;
6280 }
6281
6282 if (!InheritsFromClassNamed(IFace, "NSMutableSet")) {
6283 UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;
6284 if (!InheritsFromClassNamed(IFace, "NSSet"))
6285 UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;
6286 }
6287 }
6288 } else {
6289 IndexedGetterPriority += CCD_ProbablyNotObjCCollection;
6290 IndexedSetterPriority += CCD_ProbablyNotObjCCollection;
6291 UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;
6292 UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;
6293 }
6294
6295 // Add -(NSUInteger)countOf<key>
6296 if (IsInstanceMethod &&
6297 (ReturnType.isNull() || ReturnType->isIntegerType())) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006298 std::string SelectorName = (Twine("countOf") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006299 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006300 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006301 if (ReturnType.isNull()) {
6302 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6303 Builder.AddTextChunk("NSUInteger");
6304 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6305 }
6306
6307 Builder.AddTypedTextChunk(
6308 Allocator.CopyString(SelectorId->getName()));
6309 Results.AddResult(Result(Builder.TakeString(),
6310 std::min(IndexedGetterPriority,
6311 UnorderedGetterPriority),
6312 CXCursor_ObjCInstanceMethodDecl));
6313 }
6314 }
6315
6316 // Indexed getters
6317 // Add -(id)objectInKeyAtIndex:(NSUInteger)index
6318 if (IsInstanceMethod &&
6319 (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {
Douglas Gregor62041592011-02-17 03:19:26 +00006320 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006321 = (Twine("objectIn") + UpperKey + "AtIndex").str();
Douglas Gregor62041592011-02-17 03:19:26 +00006322 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006323 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006324 if (ReturnType.isNull()) {
6325 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6326 Builder.AddTextChunk("id");
6327 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6328 }
6329
6330 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6331 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6332 Builder.AddTextChunk("NSUInteger");
6333 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6334 Builder.AddTextChunk("index");
6335 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
6336 CXCursor_ObjCInstanceMethodDecl));
6337 }
6338 }
6339
6340 // Add -(NSArray *)keyAtIndexes:(NSIndexSet *)indexes
6341 if (IsInstanceMethod &&
6342 (ReturnType.isNull() ||
6343 (ReturnType->isObjCObjectPointerType() &&
6344 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
6345 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
6346 ->getName() == "NSArray"))) {
Douglas Gregor62041592011-02-17 03:19:26 +00006347 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006348 = (Twine(Property->getName()) + "AtIndexes").str();
Douglas Gregor62041592011-02-17 03:19:26 +00006349 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006350 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006351 if (ReturnType.isNull()) {
6352 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6353 Builder.AddTextChunk("NSArray *");
6354 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6355 }
6356
6357 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6358 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6359 Builder.AddTextChunk("NSIndexSet *");
6360 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6361 Builder.AddTextChunk("indexes");
6362 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
6363 CXCursor_ObjCInstanceMethodDecl));
6364 }
6365 }
6366
6367 // Add -(void)getKey:(type **)buffer range:(NSRange)inRange
6368 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006369 std::string SelectorName = (Twine("get") + UpperKey).str();
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006370 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor62041592011-02-17 03:19:26 +00006371 &Context.Idents.get(SelectorName),
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006372 &Context.Idents.get("range")
6373 };
6374
Douglas Gregore74c25c2011-05-04 23:50:46 +00006375 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006376 if (ReturnType.isNull()) {
6377 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6378 Builder.AddTextChunk("void");
6379 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6380 }
6381
6382 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6383 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6384 Builder.AddPlaceholderChunk("object-type");
6385 Builder.AddTextChunk(" **");
6386 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6387 Builder.AddTextChunk("buffer");
6388 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6389 Builder.AddTypedTextChunk("range:");
6390 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6391 Builder.AddTextChunk("NSRange");
6392 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6393 Builder.AddTextChunk("inRange");
6394 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
6395 CXCursor_ObjCInstanceMethodDecl));
6396 }
6397 }
6398
6399 // Mutable indexed accessors
6400
6401 // - (void)insertObject:(type *)object inKeyAtIndex:(NSUInteger)index
6402 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006403 std::string SelectorName = (Twine("in") + UpperKey + "AtIndex").str();
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006404 IdentifierInfo *SelectorIds[2] = {
6405 &Context.Idents.get("insertObject"),
Douglas Gregor62041592011-02-17 03:19:26 +00006406 &Context.Idents.get(SelectorName)
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006407 };
6408
Douglas Gregore74c25c2011-05-04 23:50:46 +00006409 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006410 if (ReturnType.isNull()) {
6411 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6412 Builder.AddTextChunk("void");
6413 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6414 }
6415
6416 Builder.AddTypedTextChunk("insertObject:");
6417 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6418 Builder.AddPlaceholderChunk("object-type");
6419 Builder.AddTextChunk(" *");
6420 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6421 Builder.AddTextChunk("object");
6422 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6423 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6424 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6425 Builder.AddPlaceholderChunk("NSUInteger");
6426 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6427 Builder.AddTextChunk("index");
6428 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6429 CXCursor_ObjCInstanceMethodDecl));
6430 }
6431 }
6432
6433 // - (void)insertKey:(NSArray *)array atIndexes:(NSIndexSet *)indexes
6434 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006435 std::string SelectorName = (Twine("insert") + UpperKey).str();
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006436 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor62041592011-02-17 03:19:26 +00006437 &Context.Idents.get(SelectorName),
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006438 &Context.Idents.get("atIndexes")
6439 };
6440
Douglas Gregore74c25c2011-05-04 23:50:46 +00006441 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006442 if (ReturnType.isNull()) {
6443 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6444 Builder.AddTextChunk("void");
6445 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6446 }
6447
6448 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6449 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6450 Builder.AddTextChunk("NSArray *");
6451 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6452 Builder.AddTextChunk("array");
6453 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6454 Builder.AddTypedTextChunk("atIndexes:");
6455 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6456 Builder.AddPlaceholderChunk("NSIndexSet *");
6457 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6458 Builder.AddTextChunk("indexes");
6459 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6460 CXCursor_ObjCInstanceMethodDecl));
6461 }
6462 }
6463
6464 // -(void)removeObjectFromKeyAtIndex:(NSUInteger)index
6465 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006466 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006467 = (Twine("removeObjectFrom") + UpperKey + "AtIndex").str();
Douglas Gregor62041592011-02-17 03:19:26 +00006468 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006469 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006470 if (ReturnType.isNull()) {
6471 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6472 Builder.AddTextChunk("void");
6473 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6474 }
6475
6476 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6477 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6478 Builder.AddTextChunk("NSUInteger");
6479 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6480 Builder.AddTextChunk("index");
6481 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6482 CXCursor_ObjCInstanceMethodDecl));
6483 }
6484 }
6485
6486 // -(void)removeKeyAtIndexes:(NSIndexSet *)indexes
6487 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006488 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006489 = (Twine("remove") + UpperKey + "AtIndexes").str();
Douglas Gregor62041592011-02-17 03:19:26 +00006490 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006491 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006492 if (ReturnType.isNull()) {
6493 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6494 Builder.AddTextChunk("void");
6495 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6496 }
6497
6498 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6499 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6500 Builder.AddTextChunk("NSIndexSet *");
6501 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6502 Builder.AddTextChunk("indexes");
6503 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6504 CXCursor_ObjCInstanceMethodDecl));
6505 }
6506 }
6507
6508 // - (void)replaceObjectInKeyAtIndex:(NSUInteger)index withObject:(id)object
6509 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006510 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006511 = (Twine("replaceObjectIn") + UpperKey + "AtIndex").str();
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006512 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor62041592011-02-17 03:19:26 +00006513 &Context.Idents.get(SelectorName),
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006514 &Context.Idents.get("withObject")
6515 };
6516
Douglas Gregore74c25c2011-05-04 23:50:46 +00006517 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006518 if (ReturnType.isNull()) {
6519 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6520 Builder.AddTextChunk("void");
6521 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6522 }
6523
6524 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6525 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6526 Builder.AddPlaceholderChunk("NSUInteger");
6527 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6528 Builder.AddTextChunk("index");
6529 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6530 Builder.AddTypedTextChunk("withObject:");
6531 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6532 Builder.AddTextChunk("id");
6533 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6534 Builder.AddTextChunk("object");
6535 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6536 CXCursor_ObjCInstanceMethodDecl));
6537 }
6538 }
6539
6540 // - (void)replaceKeyAtIndexes:(NSIndexSet *)indexes withKey:(NSArray *)array
6541 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006542 std::string SelectorName1
Chris Lattner5f9e2722011-07-23 10:55:15 +00006543 = (Twine("replace") + UpperKey + "AtIndexes").str();
6544 std::string SelectorName2 = (Twine("with") + UpperKey).str();
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006545 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor62041592011-02-17 03:19:26 +00006546 &Context.Idents.get(SelectorName1),
6547 &Context.Idents.get(SelectorName2)
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006548 };
6549
Douglas Gregore74c25c2011-05-04 23:50:46 +00006550 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006551 if (ReturnType.isNull()) {
6552 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6553 Builder.AddTextChunk("void");
6554 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6555 }
6556
6557 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName1 + ":"));
6558 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6559 Builder.AddPlaceholderChunk("NSIndexSet *");
6560 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6561 Builder.AddTextChunk("indexes");
6562 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6563 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName2 + ":"));
6564 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6565 Builder.AddTextChunk("NSArray *");
6566 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6567 Builder.AddTextChunk("array");
6568 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6569 CXCursor_ObjCInstanceMethodDecl));
6570 }
6571 }
6572
6573 // Unordered getters
6574 // - (NSEnumerator *)enumeratorOfKey
6575 if (IsInstanceMethod &&
6576 (ReturnType.isNull() ||
6577 (ReturnType->isObjCObjectPointerType() &&
6578 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
6579 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
6580 ->getName() == "NSEnumerator"))) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006581 std::string SelectorName = (Twine("enumeratorOf") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006582 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006583 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006584 if (ReturnType.isNull()) {
6585 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6586 Builder.AddTextChunk("NSEnumerator *");
6587 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6588 }
6589
6590 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
6591 Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
6592 CXCursor_ObjCInstanceMethodDecl));
6593 }
6594 }
6595
6596 // - (type *)memberOfKey:(type *)object
6597 if (IsInstanceMethod &&
6598 (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006599 std::string SelectorName = (Twine("memberOf") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006600 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006601 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006602 if (ReturnType.isNull()) {
6603 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6604 Builder.AddPlaceholderChunk("object-type");
6605 Builder.AddTextChunk(" *");
6606 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6607 }
6608
6609 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6610 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6611 if (ReturnType.isNull()) {
6612 Builder.AddPlaceholderChunk("object-type");
6613 Builder.AddTextChunk(" *");
6614 } else {
6615 Builder.AddTextChunk(GetCompletionTypeString(ReturnType, Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00006616 Policy,
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006617 Builder.getAllocator()));
6618 }
6619 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6620 Builder.AddTextChunk("object");
6621 Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
6622 CXCursor_ObjCInstanceMethodDecl));
6623 }
6624 }
6625
6626 // Mutable unordered accessors
6627 // - (void)addKeyObject:(type *)object
6628 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006629 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006630 = (Twine("add") + UpperKey + Twine("Object")).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006631 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006632 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006633 if (ReturnType.isNull()) {
6634 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6635 Builder.AddTextChunk("void");
6636 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6637 }
6638
6639 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6640 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6641 Builder.AddPlaceholderChunk("object-type");
6642 Builder.AddTextChunk(" *");
6643 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6644 Builder.AddTextChunk("object");
6645 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6646 CXCursor_ObjCInstanceMethodDecl));
6647 }
6648 }
6649
6650 // - (void)addKey:(NSSet *)objects
6651 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006652 std::string SelectorName = (Twine("add") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006653 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006654 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006655 if (ReturnType.isNull()) {
6656 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6657 Builder.AddTextChunk("void");
6658 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6659 }
6660
6661 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6662 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6663 Builder.AddTextChunk("NSSet *");
6664 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6665 Builder.AddTextChunk("objects");
6666 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6667 CXCursor_ObjCInstanceMethodDecl));
6668 }
6669 }
6670
6671 // - (void)removeKeyObject:(type *)object
6672 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006673 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006674 = (Twine("remove") + UpperKey + Twine("Object")).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006675 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006676 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006677 if (ReturnType.isNull()) {
6678 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6679 Builder.AddTextChunk("void");
6680 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6681 }
6682
6683 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6684 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6685 Builder.AddPlaceholderChunk("object-type");
6686 Builder.AddTextChunk(" *");
6687 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6688 Builder.AddTextChunk("object");
6689 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6690 CXCursor_ObjCInstanceMethodDecl));
6691 }
6692 }
6693
6694 // - (void)removeKey:(NSSet *)objects
6695 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006696 std::string SelectorName = (Twine("remove") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006697 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006698 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006699 if (ReturnType.isNull()) {
6700 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6701 Builder.AddTextChunk("void");
6702 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6703 }
6704
6705 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6706 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6707 Builder.AddTextChunk("NSSet *");
6708 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6709 Builder.AddTextChunk("objects");
6710 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6711 CXCursor_ObjCInstanceMethodDecl));
6712 }
6713 }
6714
6715 // - (void)intersectKey:(NSSet *)objects
6716 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006717 std::string SelectorName = (Twine("intersect") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006718 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006719 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006720 if (ReturnType.isNull()) {
6721 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6722 Builder.AddTextChunk("void");
6723 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6724 }
6725
6726 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6727 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6728 Builder.AddTextChunk("NSSet *");
6729 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6730 Builder.AddTextChunk("objects");
6731 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6732 CXCursor_ObjCInstanceMethodDecl));
6733 }
6734 }
6735
6736 // Key-Value Observing
6737 // + (NSSet *)keyPathsForValuesAffectingKey
6738 if (!IsInstanceMethod &&
6739 (ReturnType.isNull() ||
6740 (ReturnType->isObjCObjectPointerType() &&
6741 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
6742 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
6743 ->getName() == "NSSet"))) {
Douglas Gregor62041592011-02-17 03:19:26 +00006744 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006745 = (Twine("keyPathsForValuesAffecting") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006746 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006747 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006748 if (ReturnType.isNull()) {
6749 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6750 Builder.AddTextChunk("NSSet *");
6751 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6752 }
6753
6754 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
6755 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Douglas Gregor3f828d12011-06-02 04:02:27 +00006756 CXCursor_ObjCClassMethodDecl));
6757 }
6758 }
6759
6760 // + (BOOL)automaticallyNotifiesObserversForKey
6761 if (!IsInstanceMethod &&
6762 (ReturnType.isNull() ||
6763 ReturnType->isIntegerType() ||
6764 ReturnType->isBooleanType())) {
6765 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006766 = (Twine("automaticallyNotifiesObserversOf") + UpperKey).str();
Douglas Gregor3f828d12011-06-02 04:02:27 +00006767 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
6768 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
6769 if (ReturnType.isNull()) {
6770 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6771 Builder.AddTextChunk("BOOL");
6772 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6773 }
6774
6775 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
6776 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
6777 CXCursor_ObjCClassMethodDecl));
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006778 }
6779 }
6780}
6781
Douglas Gregore8f5a172010-04-07 00:21:17 +00006782void Sema::CodeCompleteObjCMethodDecl(Scope *S,
6783 bool IsInstanceMethod,
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00006784 ParsedType ReturnTy) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00006785 // Determine the return type of the method we're declaring, if
6786 // provided.
6787 QualType ReturnType = GetTypeFromParser(ReturnTy);
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00006788 Decl *IDecl = 0;
6789 if (CurContext->isObjCContainer()) {
6790 ObjCContainerDecl *OCD = dyn_cast<ObjCContainerDecl>(CurContext);
6791 IDecl = cast<Decl>(OCD);
6792 }
Douglas Gregorea766182010-10-18 18:21:28 +00006793 // Determine where we should start searching for methods.
6794 ObjCContainerDecl *SearchDecl = 0;
Douglas Gregore8f5a172010-04-07 00:21:17 +00006795 bool IsInImplementation = false;
John McCalld226f652010-08-21 09:40:31 +00006796 if (Decl *D = IDecl) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00006797 if (ObjCImplementationDecl *Impl = dyn_cast<ObjCImplementationDecl>(D)) {
6798 SearchDecl = Impl->getClassInterface();
Douglas Gregore8f5a172010-04-07 00:21:17 +00006799 IsInImplementation = true;
6800 } else if (ObjCCategoryImplDecl *CatImpl
Douglas Gregorea766182010-10-18 18:21:28 +00006801 = dyn_cast<ObjCCategoryImplDecl>(D)) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00006802 SearchDecl = CatImpl->getCategoryDecl();
Douglas Gregore8f5a172010-04-07 00:21:17 +00006803 IsInImplementation = true;
Douglas Gregorea766182010-10-18 18:21:28 +00006804 } else
Douglas Gregore8f5a172010-04-07 00:21:17 +00006805 SearchDecl = dyn_cast<ObjCContainerDecl>(D);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006806 }
6807
6808 if (!SearchDecl && S) {
Douglas Gregorea766182010-10-18 18:21:28 +00006809 if (DeclContext *DC = static_cast<DeclContext *>(S->getEntity()))
Douglas Gregore8f5a172010-04-07 00:21:17 +00006810 SearchDecl = dyn_cast<ObjCContainerDecl>(DC);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006811 }
6812
Douglas Gregorea766182010-10-18 18:21:28 +00006813 if (!SearchDecl) {
Douglas Gregore6b1bb62010-08-11 21:23:17 +00006814 HandleCodeCompleteResults(this, CodeCompleter,
6815 CodeCompletionContext::CCC_Other,
6816 0, 0);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006817 return;
6818 }
6819
6820 // Find all of the methods that we could declare/implement here.
6821 KnownMethodsMap KnownMethods;
6822 FindImplementableMethods(Context, SearchDecl, IsInstanceMethod,
Douglas Gregorea766182010-10-18 18:21:28 +00006823 ReturnType, KnownMethods);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006824
Douglas Gregore8f5a172010-04-07 00:21:17 +00006825 // Add declarations or definitions for each of the known methods.
John McCall0a2c5e22010-08-25 06:19:51 +00006826 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00006827 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00006828 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00006829 CodeCompletionContext::CCC_Other);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006830 Results.EnterNewScope();
Douglas Gregor8987b232011-09-27 23:30:47 +00006831 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006832 for (KnownMethodsMap::iterator M = KnownMethods.begin(),
6833 MEnd = KnownMethods.end();
6834 M != MEnd; ++M) {
Douglas Gregor408be5a2010-08-25 01:08:01 +00006835 ObjCMethodDecl *Method = M->second.first;
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00006836 CodeCompletionBuilder Builder(Results.getAllocator(),
6837 Results.getCodeCompletionTUInfo());
Douglas Gregore8f5a172010-04-07 00:21:17 +00006838
6839 // If the result type was not already provided, add it to the
6840 // pattern as (type).
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006841 if (ReturnType.isNull())
Douglas Gregor90f5f472012-04-10 18:35:07 +00006842 AddObjCPassingTypeChunk(Method->getResultType(),
6843 Method->getObjCDeclQualifier(),
6844 Context, Policy,
6845 Builder);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006846
6847 Selector Sel = Method->getSelector();
6848
6849 // Add the first part of the selector to the pattern.
Douglas Gregordae68752011-02-01 22:57:45 +00006850 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00006851 Sel.getNameForSlot(0)));
Douglas Gregore8f5a172010-04-07 00:21:17 +00006852
6853 // Add parameters to the pattern.
6854 unsigned I = 0;
6855 for (ObjCMethodDecl::param_iterator P = Method->param_begin(),
6856 PEnd = Method->param_end();
6857 P != PEnd; (void)++P, ++I) {
6858 // Add the part of the selector name.
6859 if (I == 0)
Douglas Gregor218937c2011-02-01 19:23:04 +00006860 Builder.AddTypedTextChunk(":");
Douglas Gregore8f5a172010-04-07 00:21:17 +00006861 else if (I < Sel.getNumArgs()) {
Douglas Gregor218937c2011-02-01 19:23:04 +00006862 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6863 Builder.AddTypedTextChunk(
Douglas Gregor813d8342011-02-18 22:29:55 +00006864 Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":"));
Douglas Gregore8f5a172010-04-07 00:21:17 +00006865 } else
6866 break;
6867
6868 // Add the parameter type.
Douglas Gregor90f5f472012-04-10 18:35:07 +00006869 AddObjCPassingTypeChunk((*P)->getOriginalType(),
6870 (*P)->getObjCDeclQualifier(),
6871 Context, Policy,
Douglas Gregor8987b232011-09-27 23:30:47 +00006872 Builder);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006873
6874 if (IdentifierInfo *Id = (*P)->getIdentifier())
Douglas Gregordae68752011-02-01 22:57:45 +00006875 Builder.AddTextChunk(Builder.getAllocator().CopyString( Id->getName()));
Douglas Gregore8f5a172010-04-07 00:21:17 +00006876 }
6877
6878 if (Method->isVariadic()) {
6879 if (Method->param_size() > 0)
Douglas Gregor218937c2011-02-01 19:23:04 +00006880 Builder.AddChunk(CodeCompletionString::CK_Comma);
6881 Builder.AddTextChunk("...");
Douglas Gregore17794f2010-08-31 05:13:43 +00006882 }
Douglas Gregore8f5a172010-04-07 00:21:17 +00006883
Douglas Gregor447107d2010-05-28 00:57:46 +00006884 if (IsInImplementation && Results.includeCodePatterns()) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00006885 // We will be defining the method here, so add a compound statement.
Douglas Gregor218937c2011-02-01 19:23:04 +00006886 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6887 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
6888 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006889 if (!Method->getResultType()->isVoidType()) {
6890 // If the result type is not void, add a return clause.
Douglas Gregor218937c2011-02-01 19:23:04 +00006891 Builder.AddTextChunk("return");
6892 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6893 Builder.AddPlaceholderChunk("expression");
6894 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006895 } else
Douglas Gregor218937c2011-02-01 19:23:04 +00006896 Builder.AddPlaceholderChunk("statements");
Douglas Gregore8f5a172010-04-07 00:21:17 +00006897
Douglas Gregor218937c2011-02-01 19:23:04 +00006898 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
6899 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006900 }
6901
Douglas Gregor408be5a2010-08-25 01:08:01 +00006902 unsigned Priority = CCP_CodePattern;
6903 if (!M->second.second)
6904 Priority += CCD_InBaseClass;
6905
Douglas Gregorba103062012-03-27 23:34:16 +00006906 Results.AddResult(Result(Builder.TakeString(), Method, Priority));
Douglas Gregore8f5a172010-04-07 00:21:17 +00006907 }
6908
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006909 // Add Key-Value-Coding and Key-Value-Observing accessor methods for all of
6910 // the properties in this class and its categories.
David Blaikie4e4d0842012-03-11 07:00:24 +00006911 if (Context.getLangOpts().ObjC2) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006912 SmallVector<ObjCContainerDecl *, 4> Containers;
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006913 Containers.push_back(SearchDecl);
6914
Douglas Gregore74c25c2011-05-04 23:50:46 +00006915 VisitedSelectorSet KnownSelectors;
6916 for (KnownMethodsMap::iterator M = KnownMethods.begin(),
6917 MEnd = KnownMethods.end();
6918 M != MEnd; ++M)
6919 KnownSelectors.insert(M->first);
6920
6921
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006922 ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(SearchDecl);
6923 if (!IFace)
6924 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(SearchDecl))
6925 IFace = Category->getClassInterface();
6926
6927 if (IFace) {
Douglas Gregord3297242013-01-16 23:00:23 +00006928 for (ObjCInterfaceDecl::visible_categories_iterator
6929 Cat = IFace->visible_categories_begin(),
6930 CatEnd = IFace->visible_categories_end();
6931 Cat != CatEnd; ++Cat) {
6932 Containers.push_back(*Cat);
6933 }
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006934 }
6935
6936 for (unsigned I = 0, N = Containers.size(); I != N; ++I) {
6937 for (ObjCContainerDecl::prop_iterator P = Containers[I]->prop_begin(),
6938 PEnd = Containers[I]->prop_end();
6939 P != PEnd; ++P) {
David Blaikie581deb32012-06-06 20:45:41 +00006940 AddObjCKeyValueCompletions(*P, IsInstanceMethod, ReturnType, Context,
Douglas Gregore74c25c2011-05-04 23:50:46 +00006941 KnownSelectors, Results);
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006942 }
6943 }
6944 }
6945
Douglas Gregore8f5a172010-04-07 00:21:17 +00006946 Results.ExitScope();
6947
Douglas Gregore6b1bb62010-08-11 21:23:17 +00006948 HandleCodeCompleteResults(this, CodeCompleter,
6949 CodeCompletionContext::CCC_Other,
6950 Results.data(),Results.size());
Douglas Gregore8f5a172010-04-07 00:21:17 +00006951}
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006952
6953void Sema::CodeCompleteObjCMethodDeclSelector(Scope *S,
6954 bool IsInstanceMethod,
Douglas Gregor40ed9a12010-07-08 23:37:41 +00006955 bool AtParameterName,
John McCallb3d87482010-08-24 05:47:05 +00006956 ParsedType ReturnTy,
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006957 IdentifierInfo **SelIdents,
6958 unsigned NumSelIdents) {
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006959 // If we have an external source, load the entire class method
Sebastian Redl3c7f4132010-08-18 23:57:06 +00006960 // pool from the AST file.
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006961 if (ExternalSource) {
6962 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
6963 I != N; ++I) {
6964 Selector Sel = ExternalSource->GetExternalSelector(I);
Sebastian Redldb9d2142010-08-02 23:18:59 +00006965 if (Sel.isNull() || MethodPool.count(Sel))
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006966 continue;
Sebastian Redldb9d2142010-08-02 23:18:59 +00006967
6968 ReadMethodPool(Sel);
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006969 }
6970 }
6971
6972 // Build the set of methods we can see.
John McCall0a2c5e22010-08-25 06:19:51 +00006973 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00006974 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00006975 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00006976 CodeCompletionContext::CCC_Other);
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006977
6978 if (ReturnTy)
6979 Results.setPreferredType(GetTypeFromParser(ReturnTy).getNonReferenceType());
Sebastian Redldb9d2142010-08-02 23:18:59 +00006980
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006981 Results.EnterNewScope();
Sebastian Redldb9d2142010-08-02 23:18:59 +00006982 for (GlobalMethodPool::iterator M = MethodPool.begin(),
6983 MEnd = MethodPool.end();
6984 M != MEnd; ++M) {
6985 for (ObjCMethodList *MethList = IsInstanceMethod ? &M->second.first :
6986 &M->second.second;
6987 MethList && MethList->Method;
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006988 MethList = MethList->Next) {
6989 if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents,
6990 NumSelIdents))
6991 continue;
6992
Douglas Gregor40ed9a12010-07-08 23:37:41 +00006993 if (AtParameterName) {
6994 // Suggest parameter names we've seen before.
6995 if (NumSelIdents && NumSelIdents <= MethList->Method->param_size()) {
6996 ParmVarDecl *Param = MethList->Method->param_begin()[NumSelIdents-1];
6997 if (Param->getIdentifier()) {
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00006998 CodeCompletionBuilder Builder(Results.getAllocator(),
6999 Results.getCodeCompletionTUInfo());
Douglas Gregordae68752011-02-01 22:57:45 +00007000 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00007001 Param->getIdentifier()->getName()));
7002 Results.AddResult(Builder.TakeString());
Douglas Gregor40ed9a12010-07-08 23:37:41 +00007003 }
7004 }
7005
7006 continue;
7007 }
7008
Douglas Gregor1f5537a2010-07-08 23:20:03 +00007009 Result R(MethList->Method, 0);
7010 R.StartParameter = NumSelIdents;
7011 R.AllParametersAreInformative = false;
7012 R.DeclaringEntity = true;
7013 Results.MaybeAddResult(R, CurContext);
7014 }
7015 }
7016
7017 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00007018 HandleCodeCompleteResults(this, CodeCompleter,
7019 CodeCompletionContext::CCC_Other,
7020 Results.data(),Results.size());
Douglas Gregor1f5537a2010-07-08 23:20:03 +00007021}
Douglas Gregor87c08a52010-08-13 22:48:40 +00007022
Douglas Gregorf29c5232010-08-24 22:20:20 +00007023void Sema::CodeCompletePreprocessorDirective(bool InConditional) {
Douglas Gregor218937c2011-02-01 19:23:04 +00007024 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00007025 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00007026 CodeCompletionContext::CCC_PreprocessorDirective);
Douglas Gregorf44e8542010-08-24 19:08:16 +00007027 Results.EnterNewScope();
7028
7029 // #if <condition>
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00007030 CodeCompletionBuilder Builder(Results.getAllocator(),
7031 Results.getCodeCompletionTUInfo());
Douglas Gregor218937c2011-02-01 19:23:04 +00007032 Builder.AddTypedTextChunk("if");
7033 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7034 Builder.AddPlaceholderChunk("condition");
7035 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007036
7037 // #ifdef <macro>
Douglas Gregor218937c2011-02-01 19:23:04 +00007038 Builder.AddTypedTextChunk("ifdef");
7039 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7040 Builder.AddPlaceholderChunk("macro");
7041 Results.AddResult(Builder.TakeString());
7042
Douglas Gregorf44e8542010-08-24 19:08:16 +00007043 // #ifndef <macro>
Douglas Gregor218937c2011-02-01 19:23:04 +00007044 Builder.AddTypedTextChunk("ifndef");
7045 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7046 Builder.AddPlaceholderChunk("macro");
7047 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007048
7049 if (InConditional) {
7050 // #elif <condition>
Douglas Gregor218937c2011-02-01 19:23:04 +00007051 Builder.AddTypedTextChunk("elif");
7052 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7053 Builder.AddPlaceholderChunk("condition");
7054 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007055
7056 // #else
Douglas Gregor218937c2011-02-01 19:23:04 +00007057 Builder.AddTypedTextChunk("else");
7058 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007059
7060 // #endif
Douglas Gregor218937c2011-02-01 19:23:04 +00007061 Builder.AddTypedTextChunk("endif");
7062 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007063 }
7064
7065 // #include "header"
Douglas Gregor218937c2011-02-01 19:23:04 +00007066 Builder.AddTypedTextChunk("include");
7067 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7068 Builder.AddTextChunk("\"");
7069 Builder.AddPlaceholderChunk("header");
7070 Builder.AddTextChunk("\"");
7071 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007072
7073 // #include <header>
Douglas Gregor218937c2011-02-01 19:23:04 +00007074 Builder.AddTypedTextChunk("include");
7075 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7076 Builder.AddTextChunk("<");
7077 Builder.AddPlaceholderChunk("header");
7078 Builder.AddTextChunk(">");
7079 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007080
7081 // #define <macro>
Douglas Gregor218937c2011-02-01 19:23:04 +00007082 Builder.AddTypedTextChunk("define");
7083 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7084 Builder.AddPlaceholderChunk("macro");
7085 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007086
7087 // #define <macro>(<args>)
Douglas Gregor218937c2011-02-01 19:23:04 +00007088 Builder.AddTypedTextChunk("define");
7089 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7090 Builder.AddPlaceholderChunk("macro");
7091 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7092 Builder.AddPlaceholderChunk("args");
7093 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7094 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007095
7096 // #undef <macro>
Douglas Gregor218937c2011-02-01 19:23:04 +00007097 Builder.AddTypedTextChunk("undef");
7098 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7099 Builder.AddPlaceholderChunk("macro");
7100 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007101
7102 // #line <number>
Douglas Gregor218937c2011-02-01 19:23:04 +00007103 Builder.AddTypedTextChunk("line");
7104 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7105 Builder.AddPlaceholderChunk("number");
7106 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007107
7108 // #line <number> "filename"
Douglas Gregor218937c2011-02-01 19:23:04 +00007109 Builder.AddTypedTextChunk("line");
7110 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7111 Builder.AddPlaceholderChunk("number");
7112 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7113 Builder.AddTextChunk("\"");
7114 Builder.AddPlaceholderChunk("filename");
7115 Builder.AddTextChunk("\"");
7116 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007117
7118 // #error <message>
Douglas Gregor218937c2011-02-01 19:23:04 +00007119 Builder.AddTypedTextChunk("error");
7120 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7121 Builder.AddPlaceholderChunk("message");
7122 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007123
7124 // #pragma <arguments>
Douglas Gregor218937c2011-02-01 19:23:04 +00007125 Builder.AddTypedTextChunk("pragma");
7126 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7127 Builder.AddPlaceholderChunk("arguments");
7128 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007129
David Blaikie4e4d0842012-03-11 07:00:24 +00007130 if (getLangOpts().ObjC1) {
Douglas Gregorf44e8542010-08-24 19:08:16 +00007131 // #import "header"
Douglas Gregor218937c2011-02-01 19:23:04 +00007132 Builder.AddTypedTextChunk("import");
7133 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7134 Builder.AddTextChunk("\"");
7135 Builder.AddPlaceholderChunk("header");
7136 Builder.AddTextChunk("\"");
7137 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007138
7139 // #import <header>
Douglas Gregor218937c2011-02-01 19:23:04 +00007140 Builder.AddTypedTextChunk("import");
7141 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7142 Builder.AddTextChunk("<");
7143 Builder.AddPlaceholderChunk("header");
7144 Builder.AddTextChunk(">");
7145 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007146 }
7147
7148 // #include_next "header"
Douglas Gregor218937c2011-02-01 19:23:04 +00007149 Builder.AddTypedTextChunk("include_next");
7150 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7151 Builder.AddTextChunk("\"");
7152 Builder.AddPlaceholderChunk("header");
7153 Builder.AddTextChunk("\"");
7154 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007155
7156 // #include_next <header>
Douglas Gregor218937c2011-02-01 19:23:04 +00007157 Builder.AddTypedTextChunk("include_next");
7158 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7159 Builder.AddTextChunk("<");
7160 Builder.AddPlaceholderChunk("header");
7161 Builder.AddTextChunk(">");
7162 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007163
7164 // #warning <message>
Douglas Gregor218937c2011-02-01 19:23:04 +00007165 Builder.AddTypedTextChunk("warning");
7166 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7167 Builder.AddPlaceholderChunk("message");
7168 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007169
7170 // Note: #ident and #sccs are such crazy anachronisms that we don't provide
7171 // completions for them. And __include_macros is a Clang-internal extension
7172 // that we don't want to encourage anyone to use.
7173
7174 // FIXME: we don't support #assert or #unassert, so don't suggest them.
7175 Results.ExitScope();
7176
Douglas Gregorf44e8542010-08-24 19:08:16 +00007177 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor721f3592010-08-25 18:41:16 +00007178 CodeCompletionContext::CCC_PreprocessorDirective,
Douglas Gregorf44e8542010-08-24 19:08:16 +00007179 Results.data(), Results.size());
7180}
7181
7182void Sema::CodeCompleteInPreprocessorConditionalExclusion(Scope *S) {
Douglas Gregorf29c5232010-08-24 22:20:20 +00007183 CodeCompleteOrdinaryName(S,
John McCallf312b1e2010-08-26 23:41:50 +00007184 S->getFnParent()? Sema::PCC_RecoveryInFunction
7185 : Sema::PCC_Namespace);
Douglas Gregorf44e8542010-08-24 19:08:16 +00007186}
7187
Douglas Gregorf29c5232010-08-24 22:20:20 +00007188void Sema::CodeCompletePreprocessorMacroName(bool IsDefinition) {
Douglas Gregor218937c2011-02-01 19:23:04 +00007189 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00007190 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00007191 IsDefinition? CodeCompletionContext::CCC_MacroName
7192 : CodeCompletionContext::CCC_MacroNameUse);
Douglas Gregor1fbb4472010-08-24 20:21:13 +00007193 if (!IsDefinition && (!CodeCompleter || CodeCompleter->includeMacros())) {
7194 // Add just the names of macros, not their arguments.
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00007195 CodeCompletionBuilder Builder(Results.getAllocator(),
7196 Results.getCodeCompletionTUInfo());
Douglas Gregor1fbb4472010-08-24 20:21:13 +00007197 Results.EnterNewScope();
7198 for (Preprocessor::macro_iterator M = PP.macro_begin(),
7199 MEnd = PP.macro_end();
7200 M != MEnd; ++M) {
Douglas Gregordae68752011-02-01 22:57:45 +00007201 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00007202 M->first->getName()));
Argyrios Kyrtzidisc04bb922012-09-27 00:24:09 +00007203 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
7204 CCP_CodePattern,
7205 CXCursor_MacroDefinition));
Douglas Gregor1fbb4472010-08-24 20:21:13 +00007206 }
7207 Results.ExitScope();
7208 } else if (IsDefinition) {
7209 // FIXME: Can we detect when the user just wrote an include guard above?
7210 }
7211
Douglas Gregor52779fb2010-09-23 23:01:17 +00007212 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor1fbb4472010-08-24 20:21:13 +00007213 Results.data(), Results.size());
7214}
7215
Douglas Gregorf29c5232010-08-24 22:20:20 +00007216void Sema::CodeCompletePreprocessorExpression() {
Douglas Gregor218937c2011-02-01 19:23:04 +00007217 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00007218 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00007219 CodeCompletionContext::CCC_PreprocessorExpression);
Douglas Gregorf29c5232010-08-24 22:20:20 +00007220
7221 if (!CodeCompleter || CodeCompleter->includeMacros())
Douglas Gregor3644d972012-10-09 16:01:50 +00007222 AddMacroResults(PP, Results, true);
Douglas Gregorf29c5232010-08-24 22:20:20 +00007223
7224 // defined (<macro>)
7225 Results.EnterNewScope();
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00007226 CodeCompletionBuilder Builder(Results.getAllocator(),
7227 Results.getCodeCompletionTUInfo());
Douglas Gregor218937c2011-02-01 19:23:04 +00007228 Builder.AddTypedTextChunk("defined");
7229 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7230 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7231 Builder.AddPlaceholderChunk("macro");
7232 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7233 Results.AddResult(Builder.TakeString());
Douglas Gregorf29c5232010-08-24 22:20:20 +00007234 Results.ExitScope();
7235
7236 HandleCodeCompleteResults(this, CodeCompleter,
7237 CodeCompletionContext::CCC_PreprocessorExpression,
7238 Results.data(), Results.size());
7239}
7240
7241void Sema::CodeCompletePreprocessorMacroArgument(Scope *S,
7242 IdentifierInfo *Macro,
7243 MacroInfo *MacroInfo,
7244 unsigned Argument) {
7245 // FIXME: In the future, we could provide "overload" results, much like we
7246 // do for function calls.
7247
Argyrios Kyrtzidis5c5f03e2011-08-18 19:41:28 +00007248 // Now just ignore this. There will be another code-completion callback
7249 // for the expanded tokens.
Douglas Gregorf29c5232010-08-24 22:20:20 +00007250}
7251
Douglas Gregor55817af2010-08-25 17:04:25 +00007252void Sema::CodeCompleteNaturalLanguage() {
Douglas Gregor55817af2010-08-25 17:04:25 +00007253 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregoraf1c6b52010-08-25 17:10:00 +00007254 CodeCompletionContext::CCC_NaturalLanguage,
Douglas Gregor55817af2010-08-25 17:04:25 +00007255 0, 0);
7256}
7257
Douglas Gregordae68752011-02-01 22:57:45 +00007258void Sema::GatherGlobalCodeCompletions(CodeCompletionAllocator &Allocator,
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00007259 CodeCompletionTUInfo &CCTUInfo,
Chris Lattner5f9e2722011-07-23 10:55:15 +00007260 SmallVectorImpl<CodeCompletionResult> &Results) {
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00007261 ResultBuilder Builder(*this, Allocator, CCTUInfo,
7262 CodeCompletionContext::CCC_Recovery);
Douglas Gregor8071e422010-08-15 06:18:01 +00007263 if (!CodeCompleter || CodeCompleter->includeGlobals()) {
7264 CodeCompletionDeclConsumer Consumer(Builder,
7265 Context.getTranslationUnitDecl());
7266 LookupVisibleDecls(Context.getTranslationUnitDecl(), LookupAnyName,
7267 Consumer);
7268 }
Douglas Gregor87c08a52010-08-13 22:48:40 +00007269
7270 if (!CodeCompleter || CodeCompleter->includeMacros())
Douglas Gregor3644d972012-10-09 16:01:50 +00007271 AddMacroResults(PP, Builder, true);
Douglas Gregor87c08a52010-08-13 22:48:40 +00007272
7273 Results.clear();
7274 Results.insert(Results.end(),
7275 Builder.data(), Builder.data() + Builder.size());
7276}