blob: 90f55a29358f077197d8400816a820cd0e7e4cc4 [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"
Douglas Gregore737f502010-08-12 20:07:10 +000014#include "clang/Sema/Lookup.h"
John McCall120d63c2010-08-24 20:38:10 +000015#include "clang/Sema/Overload.h"
Douglas Gregor81b747b2009-09-17 21:32:03 +000016#include "clang/Sema/CodeCompleteConsumer.h"
Douglas Gregor719770d2010-04-06 17:30:22 +000017#include "clang/Sema/ExternalSemaSource.h"
John McCall5f1e0942010-08-24 08:50:51 +000018#include "clang/Sema/Scope.h"
John McCall781472f2010-08-25 08:40:02 +000019#include "clang/Sema/ScopeInfo.h"
John McCall7cd088e2010-08-24 07:21:54 +000020#include "clang/AST/DeclObjC.h"
Douglas Gregorb9d0ef72009-09-21 19:57:38 +000021#include "clang/AST/ExprCXX.h"
Douglas Gregor24a069f2009-11-17 17:59:40 +000022#include "clang/AST/ExprObjC.h"
Douglas Gregor3f7c7f42009-10-30 16:50:04 +000023#include "clang/Lex/MacroInfo.h"
24#include "clang/Lex/Preprocessor.h"
Douglas Gregord36adf52010-09-16 16:06:31 +000025#include "llvm/ADT/DenseSet.h"
Douglas Gregor86d9a522009-09-21 16:56:56 +000026#include "llvm/ADT/SmallPtrSet.h"
Douglas Gregor6a684032009-09-28 03:51:44 +000027#include "llvm/ADT/StringExtras.h"
Douglas Gregor22f56992010-04-06 19:22:33 +000028#include "llvm/ADT/StringSwitch.h"
Douglas Gregor458433d2010-08-26 15:07:07 +000029#include "llvm/ADT/Twine.h"
Douglas Gregor86d9a522009-09-21 16:56:56 +000030#include <list>
31#include <map>
32#include <vector>
Douglas Gregor81b747b2009-09-17 21:32:03 +000033
34using namespace clang;
John McCall781472f2010-08-25 08:40:02 +000035using namespace sema;
Douglas Gregor81b747b2009-09-17 21:32:03 +000036
Douglas Gregor86d9a522009-09-21 16:56:56 +000037namespace {
38 /// \brief A container of code-completion results.
39 class ResultBuilder {
40 public:
41 /// \brief The type of a name-lookup filter, which can be provided to the
42 /// name-lookup routines to specify which declarations should be included in
43 /// the result set (when it returns true) and which declarations should be
44 /// filtered out (returns false).
45 typedef bool (ResultBuilder::*LookupFilter)(NamedDecl *) const;
46
John McCall0a2c5e22010-08-25 06:19:51 +000047 typedef CodeCompletionResult Result;
Douglas Gregor86d9a522009-09-21 16:56:56 +000048
49 private:
50 /// \brief The actual results we have found.
51 std::vector<Result> Results;
52
53 /// \brief A record of all of the declarations we have found and placed
54 /// into the result set, used to ensure that no declaration ever gets into
55 /// the result set twice.
56 llvm::SmallPtrSet<Decl*, 16> AllDeclsFound;
57
Douglas Gregorfbcb5d62009-12-06 20:23:50 +000058 typedef std::pair<NamedDecl *, unsigned> DeclIndexPair;
59
60 /// \brief An entry in the shadow map, which is optimized to store
61 /// a single (declaration, index) mapping (the common case) but
62 /// can also store a list of (declaration, index) mappings.
63 class ShadowMapEntry {
64 typedef llvm::SmallVector<DeclIndexPair, 4> DeclIndexPairVector;
65
66 /// \brief Contains either the solitary NamedDecl * or a vector
67 /// of (declaration, index) pairs.
68 llvm::PointerUnion<NamedDecl *, DeclIndexPairVector*> DeclOrVector;
69
70 /// \brief When the entry contains a single declaration, this is
71 /// the index associated with that entry.
72 unsigned SingleDeclIndex;
73
74 public:
75 ShadowMapEntry() : DeclOrVector(), SingleDeclIndex(0) { }
76
77 void Add(NamedDecl *ND, unsigned Index) {
78 if (DeclOrVector.isNull()) {
79 // 0 - > 1 elements: just set the single element information.
80 DeclOrVector = ND;
81 SingleDeclIndex = Index;
82 return;
83 }
84
85 if (NamedDecl *PrevND = DeclOrVector.dyn_cast<NamedDecl *>()) {
86 // 1 -> 2 elements: create the vector of results and push in the
87 // existing declaration.
88 DeclIndexPairVector *Vec = new DeclIndexPairVector;
89 Vec->push_back(DeclIndexPair(PrevND, SingleDeclIndex));
90 DeclOrVector = Vec;
91 }
92
93 // Add the new element to the end of the vector.
94 DeclOrVector.get<DeclIndexPairVector*>()->push_back(
95 DeclIndexPair(ND, Index));
96 }
97
98 void Destroy() {
99 if (DeclIndexPairVector *Vec
100 = DeclOrVector.dyn_cast<DeclIndexPairVector *>()) {
101 delete Vec;
102 DeclOrVector = ((NamedDecl *)0);
103 }
104 }
105
106 // Iteration.
107 class iterator;
108 iterator begin() const;
109 iterator end() const;
110 };
111
Douglas Gregor86d9a522009-09-21 16:56:56 +0000112 /// \brief A mapping from declaration names to the declarations that have
113 /// this name within a particular scope and their index within the list of
114 /// results.
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000115 typedef llvm::DenseMap<DeclarationName, ShadowMapEntry> ShadowMap;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000116
117 /// \brief The semantic analysis object for which results are being
118 /// produced.
119 Sema &SemaRef;
Douglas Gregor218937c2011-02-01 19:23:04 +0000120
121 /// \brief The allocator used to allocate new code-completion strings.
122 llvm::BumpPtrAllocator &Allocator;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000123
124 /// \brief If non-NULL, a filter function used to remove any code-completion
125 /// results that are not desirable.
126 LookupFilter Filter;
Douglas Gregor45bcd432010-01-14 03:21:49 +0000127
128 /// \brief Whether we should allow declarations as
129 /// nested-name-specifiers that would otherwise be filtered out.
130 bool AllowNestedNameSpecifiers;
131
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +0000132 /// \brief If set, the type that we would prefer our resulting value
133 /// declarations to have.
134 ///
135 /// Closely matching the preferred type gives a boost to a result's
136 /// priority.
137 CanQualType PreferredType;
138
Douglas Gregor86d9a522009-09-21 16:56:56 +0000139 /// \brief A list of shadow maps, which is used to model name hiding at
140 /// different levels of, e.g., the inheritance hierarchy.
141 std::list<ShadowMap> ShadowMaps;
142
Douglas Gregor3cdee122010-08-26 16:36:48 +0000143 /// \brief If we're potentially referring to a C++ member function, the set
144 /// of qualifiers applied to the object type.
145 Qualifiers ObjectTypeQualifiers;
146
147 /// \brief Whether the \p ObjectTypeQualifiers field is active.
148 bool HasObjectTypeQualifiers;
149
Douglas Gregor265f7492010-08-27 15:29:55 +0000150 /// \brief The selector that we prefer.
151 Selector PreferredSelector;
152
Douglas Gregorca45da02010-11-02 20:36:02 +0000153 /// \brief The completion context in which we are gathering results.
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000154 CodeCompletionContext CompletionContext;
155
Douglas Gregorca45da02010-11-02 20:36:02 +0000156 /// \brief If we are in an instance method definition, the @implementation
157 /// object.
158 ObjCImplementationDecl *ObjCImplementation;
159
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000160 void AdjustResultPriorityForDecl(Result &R);
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000161
Douglas Gregor6f942b22010-09-21 16:06:22 +0000162 void MaybeAddConstructorResults(Result R);
163
Douglas Gregor86d9a522009-09-21 16:56:56 +0000164 public:
Douglas Gregor218937c2011-02-01 19:23:04 +0000165 explicit ResultBuilder(Sema &SemaRef, llvm::BumpPtrAllocator &Allocator,
Douglas Gregor52779fb2010-09-23 23:01:17 +0000166 const CodeCompletionContext &CompletionContext,
167 LookupFilter Filter = 0)
Douglas Gregor218937c2011-02-01 19:23:04 +0000168 : SemaRef(SemaRef), Allocator(Allocator), Filter(Filter),
169 AllowNestedNameSpecifiers(false), HasObjectTypeQualifiers(false),
Douglas Gregorca45da02010-11-02 20:36:02 +0000170 CompletionContext(CompletionContext),
171 ObjCImplementation(0)
172 {
173 // If this is an Objective-C instance method definition, dig out the
174 // corresponding implementation.
175 switch (CompletionContext.getKind()) {
176 case CodeCompletionContext::CCC_Expression:
177 case CodeCompletionContext::CCC_ObjCMessageReceiver:
178 case CodeCompletionContext::CCC_ParenthesizedExpression:
179 case CodeCompletionContext::CCC_Statement:
180 case CodeCompletionContext::CCC_Recovery:
181 if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl())
182 if (Method->isInstanceMethod())
183 if (ObjCInterfaceDecl *Interface = Method->getClassInterface())
184 ObjCImplementation = Interface->getImplementation();
185 break;
186
187 default:
188 break;
189 }
190 }
Douglas Gregor86d9a522009-09-21 16:56:56 +0000191
Douglas Gregord8e8a582010-05-25 21:41:55 +0000192 /// \brief Whether we should include code patterns in the completion
193 /// results.
194 bool includeCodePatterns() const {
195 return SemaRef.CodeCompleter &&
Douglas Gregorf6961522010-08-27 21:18:54 +0000196 SemaRef.CodeCompleter->includeCodePatterns();
Douglas Gregord8e8a582010-05-25 21:41:55 +0000197 }
198
Douglas Gregor86d9a522009-09-21 16:56:56 +0000199 /// \brief Set the filter used for code-completion results.
200 void setFilter(LookupFilter Filter) {
201 this->Filter = Filter;
202 }
203
Douglas Gregor86d9a522009-09-21 16:56:56 +0000204 Result *data() { return Results.empty()? 0 : &Results.front(); }
205 unsigned size() const { return Results.size(); }
206 bool empty() const { return Results.empty(); }
207
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +0000208 /// \brief Specify the preferred type.
209 void setPreferredType(QualType T) {
210 PreferredType = SemaRef.Context.getCanonicalType(T);
211 }
212
Douglas Gregor3cdee122010-08-26 16:36:48 +0000213 /// \brief Set the cv-qualifiers on the object type, for us in filtering
214 /// calls to member functions.
215 ///
216 /// When there are qualifiers in this set, they will be used to filter
217 /// out member functions that aren't available (because there will be a
218 /// cv-qualifier mismatch) or prefer functions with an exact qualifier
219 /// match.
220 void setObjectTypeQualifiers(Qualifiers Quals) {
221 ObjectTypeQualifiers = Quals;
222 HasObjectTypeQualifiers = true;
223 }
224
Douglas Gregor265f7492010-08-27 15:29:55 +0000225 /// \brief Set the preferred selector.
226 ///
227 /// When an Objective-C method declaration result is added, and that
228 /// method's selector matches this preferred selector, we give that method
229 /// a slight priority boost.
230 void setPreferredSelector(Selector Sel) {
231 PreferredSelector = Sel;
232 }
Douglas Gregorca45da02010-11-02 20:36:02 +0000233
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000234 /// \brief Retrieve the code-completion context for which results are
235 /// being collected.
236 const CodeCompletionContext &getCompletionContext() const {
237 return CompletionContext;
238 }
239
Douglas Gregor45bcd432010-01-14 03:21:49 +0000240 /// \brief Specify whether nested-name-specifiers are allowed.
241 void allowNestedNameSpecifiers(bool Allow = true) {
242 AllowNestedNameSpecifiers = Allow;
243 }
244
Douglas Gregorb9d77572010-09-21 00:03:25 +0000245 /// \brief Return the semantic analysis object for which we are collecting
246 /// code completion results.
247 Sema &getSema() const { return SemaRef; }
248
Douglas Gregor218937c2011-02-01 19:23:04 +0000249 /// \brief Retrieve the allocator used to allocate code completion strings.
250 llvm::BumpPtrAllocator &getAllocator() const { return Allocator; }
251
Douglas Gregore495b7f2010-01-14 00:20:49 +0000252 /// \brief Determine whether the given declaration is at all interesting
253 /// as a code-completion result.
Douglas Gregor45bcd432010-01-14 03:21:49 +0000254 ///
255 /// \param ND the declaration that we are inspecting.
256 ///
257 /// \param AsNestedNameSpecifier will be set true if this declaration is
258 /// only interesting when it is a nested-name-specifier.
259 bool isInterestingDecl(NamedDecl *ND, bool &AsNestedNameSpecifier) const;
Douglas Gregor6660d842010-01-14 00:41:07 +0000260
261 /// \brief Check whether the result is hidden by the Hiding declaration.
262 ///
263 /// \returns true if the result is hidden and cannot be found, false if
264 /// the hidden result could still be found. When false, \p R may be
265 /// modified to describe how the result can be found (e.g., via extra
266 /// qualification).
267 bool CheckHiddenResult(Result &R, DeclContext *CurContext,
268 NamedDecl *Hiding);
269
Douglas Gregor86d9a522009-09-21 16:56:56 +0000270 /// \brief Add a new result to this result set (if it isn't already in one
271 /// of the shadow maps), or replace an existing result (for, e.g., a
272 /// redeclaration).
Douglas Gregor456c4a12009-09-21 20:12:40 +0000273 ///
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000274 /// \param CurContext the result to add (if it is unique).
Douglas Gregor456c4a12009-09-21 20:12:40 +0000275 ///
276 /// \param R the context in which this result will be named.
277 void MaybeAddResult(Result R, DeclContext *CurContext = 0);
Douglas Gregor86d9a522009-09-21 16:56:56 +0000278
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000279 /// \brief Add a new result to this result set, where we already know
280 /// the hiding declation (if any).
281 ///
282 /// \param R the result to add (if it is unique).
283 ///
284 /// \param CurContext the context in which this result will be named.
285 ///
286 /// \param Hiding the declaration that hides the result.
Douglas Gregor0cc84042010-01-14 15:47:35 +0000287 ///
288 /// \param InBaseClass whether the result was found in a base
289 /// class of the searched context.
290 void AddResult(Result R, DeclContext *CurContext, NamedDecl *Hiding,
291 bool InBaseClass);
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000292
Douglas Gregora4477812010-01-14 16:01:26 +0000293 /// \brief Add a new non-declaration result to this result set.
294 void AddResult(Result R);
295
Douglas Gregor86d9a522009-09-21 16:56:56 +0000296 /// \brief Enter into a new scope.
297 void EnterNewScope();
298
299 /// \brief Exit from the current scope.
300 void ExitScope();
301
Douglas Gregor55385fe2009-11-18 04:19:12 +0000302 /// \brief Ignore this declaration, if it is seen again.
303 void Ignore(Decl *D) { AllDeclsFound.insert(D->getCanonicalDecl()); }
304
Douglas Gregor86d9a522009-09-21 16:56:56 +0000305 /// \name Name lookup predicates
306 ///
307 /// These predicates can be passed to the name lookup functions to filter the
308 /// results of name lookup. All of the predicates have the same type, so that
309 ///
310 //@{
Douglas Gregor791215b2009-09-21 20:51:25 +0000311 bool IsOrdinaryName(NamedDecl *ND) const;
Douglas Gregor4710e5b2010-05-28 00:49:12 +0000312 bool IsOrdinaryNonTypeName(NamedDecl *ND) const;
Douglas Gregorf9578432010-07-28 21:50:18 +0000313 bool IsIntegralConstantValue(NamedDecl *ND) const;
Douglas Gregor01dfea02010-01-10 23:08:15 +0000314 bool IsOrdinaryNonValueName(NamedDecl *ND) const;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000315 bool IsNestedNameSpecifier(NamedDecl *ND) const;
316 bool IsEnum(NamedDecl *ND) const;
317 bool IsClassOrStruct(NamedDecl *ND) const;
318 bool IsUnion(NamedDecl *ND) const;
319 bool IsNamespace(NamedDecl *ND) const;
320 bool IsNamespaceOrAlias(NamedDecl *ND) const;
321 bool IsType(NamedDecl *ND) const;
Douglas Gregoreb5758b2009-09-23 22:26:46 +0000322 bool IsMember(NamedDecl *ND) const;
Douglas Gregor80f4f4c2010-01-14 16:08:12 +0000323 bool IsObjCIvar(NamedDecl *ND) const;
Douglas Gregor8e254cf2010-05-27 23:06:34 +0000324 bool IsObjCMessageReceiver(NamedDecl *ND) const;
Douglas Gregorfb629412010-08-23 21:17:50 +0000325 bool IsObjCCollection(NamedDecl *ND) const;
Douglas Gregor52779fb2010-09-23 23:01:17 +0000326 bool IsImpossibleToSatisfy(NamedDecl *ND) const;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000327 //@}
328 };
329}
330
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000331class ResultBuilder::ShadowMapEntry::iterator {
332 llvm::PointerUnion<NamedDecl*, const DeclIndexPair*> DeclOrIterator;
333 unsigned SingleDeclIndex;
334
335public:
336 typedef DeclIndexPair value_type;
337 typedef value_type reference;
338 typedef std::ptrdiff_t difference_type;
339 typedef std::input_iterator_tag iterator_category;
340
341 class pointer {
342 DeclIndexPair Value;
343
344 public:
345 pointer(const DeclIndexPair &Value) : Value(Value) { }
346
347 const DeclIndexPair *operator->() const {
348 return &Value;
349 }
350 };
351
352 iterator() : DeclOrIterator((NamedDecl *)0), SingleDeclIndex(0) { }
353
354 iterator(NamedDecl *SingleDecl, unsigned Index)
355 : DeclOrIterator(SingleDecl), SingleDeclIndex(Index) { }
356
357 iterator(const DeclIndexPair *Iterator)
358 : DeclOrIterator(Iterator), SingleDeclIndex(0) { }
359
360 iterator &operator++() {
361 if (DeclOrIterator.is<NamedDecl *>()) {
362 DeclOrIterator = (NamedDecl *)0;
363 SingleDeclIndex = 0;
364 return *this;
365 }
366
367 const DeclIndexPair *I = DeclOrIterator.get<const DeclIndexPair*>();
368 ++I;
369 DeclOrIterator = I;
370 return *this;
371 }
372
Chris Lattner66392d42010-09-04 18:12:20 +0000373 /*iterator operator++(int) {
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000374 iterator tmp(*this);
375 ++(*this);
376 return tmp;
Chris Lattner66392d42010-09-04 18:12:20 +0000377 }*/
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000378
379 reference operator*() const {
380 if (NamedDecl *ND = DeclOrIterator.dyn_cast<NamedDecl *>())
381 return reference(ND, SingleDeclIndex);
382
Douglas Gregord490f952009-12-06 21:27:58 +0000383 return *DeclOrIterator.get<const DeclIndexPair*>();
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000384 }
385
386 pointer operator->() const {
387 return pointer(**this);
388 }
389
390 friend bool operator==(const iterator &X, const iterator &Y) {
Douglas Gregord490f952009-12-06 21:27:58 +0000391 return X.DeclOrIterator.getOpaqueValue()
392 == Y.DeclOrIterator.getOpaqueValue() &&
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000393 X.SingleDeclIndex == Y.SingleDeclIndex;
394 }
395
396 friend bool operator!=(const iterator &X, const iterator &Y) {
Douglas Gregord490f952009-12-06 21:27:58 +0000397 return !(X == Y);
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000398 }
399};
400
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000401ResultBuilder::ShadowMapEntry::iterator
402ResultBuilder::ShadowMapEntry::begin() const {
403 if (DeclOrVector.isNull())
404 return iterator();
405
406 if (NamedDecl *ND = DeclOrVector.dyn_cast<NamedDecl *>())
407 return iterator(ND, SingleDeclIndex);
408
409 return iterator(DeclOrVector.get<DeclIndexPairVector *>()->begin());
410}
411
412ResultBuilder::ShadowMapEntry::iterator
413ResultBuilder::ShadowMapEntry::end() const {
414 if (DeclOrVector.is<NamedDecl *>() || DeclOrVector.isNull())
415 return iterator();
416
417 return iterator(DeclOrVector.get<DeclIndexPairVector *>()->end());
418}
419
Douglas Gregor456c4a12009-09-21 20:12:40 +0000420/// \brief Compute the qualification required to get from the current context
421/// (\p CurContext) to the target context (\p TargetContext).
422///
423/// \param Context the AST context in which the qualification will be used.
424///
425/// \param CurContext the context where an entity is being named, which is
426/// typically based on the current scope.
427///
428/// \param TargetContext the context in which the named entity actually
429/// resides.
430///
431/// \returns a nested name specifier that refers into the target context, or
432/// NULL if no qualification is needed.
433static NestedNameSpecifier *
434getRequiredQualification(ASTContext &Context,
435 DeclContext *CurContext,
436 DeclContext *TargetContext) {
437 llvm::SmallVector<DeclContext *, 4> TargetParents;
438
439 for (DeclContext *CommonAncestor = TargetContext;
440 CommonAncestor && !CommonAncestor->Encloses(CurContext);
441 CommonAncestor = CommonAncestor->getLookupParent()) {
442 if (CommonAncestor->isTransparentContext() ||
443 CommonAncestor->isFunctionOrMethod())
444 continue;
445
446 TargetParents.push_back(CommonAncestor);
447 }
448
449 NestedNameSpecifier *Result = 0;
450 while (!TargetParents.empty()) {
451 DeclContext *Parent = TargetParents.back();
452 TargetParents.pop_back();
453
Douglas Gregorfb629412010-08-23 21:17:50 +0000454 if (NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Parent)) {
455 if (!Namespace->getIdentifier())
456 continue;
457
Douglas Gregor456c4a12009-09-21 20:12:40 +0000458 Result = NestedNameSpecifier::Create(Context, Result, Namespace);
Douglas Gregorfb629412010-08-23 21:17:50 +0000459 }
Douglas Gregor456c4a12009-09-21 20:12:40 +0000460 else if (TagDecl *TD = dyn_cast<TagDecl>(Parent))
461 Result = NestedNameSpecifier::Create(Context, Result,
462 false,
463 Context.getTypeDeclType(TD).getTypePtr());
Douglas Gregor0c8296d2009-11-07 00:00:49 +0000464 }
Douglas Gregor456c4a12009-09-21 20:12:40 +0000465 return Result;
466}
467
Douglas Gregor45bcd432010-01-14 03:21:49 +0000468bool ResultBuilder::isInterestingDecl(NamedDecl *ND,
469 bool &AsNestedNameSpecifier) const {
470 AsNestedNameSpecifier = false;
471
Douglas Gregore495b7f2010-01-14 00:20:49 +0000472 ND = ND->getUnderlyingDecl();
473 unsigned IDNS = ND->getIdentifierNamespace();
Douglas Gregorf52cede2009-10-09 22:16:47 +0000474
475 // Skip unnamed entities.
Douglas Gregore495b7f2010-01-14 00:20:49 +0000476 if (!ND->getDeclName())
477 return false;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000478
479 // Friend declarations and declarations introduced due to friends are never
480 // added as results.
John McCall92b7f702010-03-11 07:50:04 +0000481 if (IDNS & (Decl::IDNS_OrdinaryFriend | Decl::IDNS_TagFriend))
Douglas Gregore495b7f2010-01-14 00:20:49 +0000482 return false;
483
Douglas Gregor76282942009-12-11 17:31:05 +0000484 // Class template (partial) specializations are never added as results.
Douglas Gregore495b7f2010-01-14 00:20:49 +0000485 if (isa<ClassTemplateSpecializationDecl>(ND) ||
486 isa<ClassTemplatePartialSpecializationDecl>(ND))
487 return false;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000488
Douglas Gregor76282942009-12-11 17:31:05 +0000489 // Using declarations themselves are never added as results.
Douglas Gregore495b7f2010-01-14 00:20:49 +0000490 if (isa<UsingDecl>(ND))
491 return false;
492
493 // Some declarations have reserved names that we don't want to ever show.
494 if (const IdentifierInfo *Id = ND->getIdentifier()) {
Douglas Gregor86d9a522009-09-21 16:56:56 +0000495 // __va_list_tag is a freak of nature. Find it and skip it.
496 if (Id->isStr("__va_list_tag") || Id->isStr("__builtin_va_list"))
Douglas Gregore495b7f2010-01-14 00:20:49 +0000497 return false;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000498
Douglas Gregorf52cede2009-10-09 22:16:47 +0000499 // Filter out names reserved for the implementation (C99 7.1.3,
Douglas Gregor797efb52010-07-14 17:44:04 +0000500 // C++ [lib.global.names]) if they come from a system header.
Daniel Dunbare013d682009-10-18 20:26:12 +0000501 //
502 // FIXME: Add predicate for this.
Douglas Gregorf52cede2009-10-09 22:16:47 +0000503 if (Id->getLength() >= 2) {
Daniel Dunbare013d682009-10-18 20:26:12 +0000504 const char *Name = Id->getNameStart();
Douglas Gregorf52cede2009-10-09 22:16:47 +0000505 if (Name[0] == '_' &&
Douglas Gregor797efb52010-07-14 17:44:04 +0000506 (Name[1] == '_' || (Name[1] >= 'A' && Name[1] <= 'Z')) &&
507 (ND->getLocation().isInvalid() ||
508 SemaRef.SourceMgr.isInSystemHeader(
509 SemaRef.SourceMgr.getSpellingLoc(ND->getLocation()))))
Douglas Gregore495b7f2010-01-14 00:20:49 +0000510 return false;
Douglas Gregorf52cede2009-10-09 22:16:47 +0000511 }
Douglas Gregor86d9a522009-09-21 16:56:56 +0000512 }
Douglas Gregor6f942b22010-09-21 16:06:22 +0000513
Douglas Gregor9b0ba872010-11-09 03:59:40 +0000514 // Skip out-of-line declarations and definitions.
515 // NOTE: Unless it's an Objective-C property, method, or ivar, where
516 // the contexts can be messy.
517 if (!ND->getDeclContext()->Equals(ND->getLexicalDeclContext()) &&
518 !(isa<ObjCPropertyDecl>(ND) || isa<ObjCIvarDecl>(ND) ||
519 isa<ObjCMethodDecl>(ND)))
520 return false;
521
Douglas Gregora5fb7c32010-08-16 23:05:20 +0000522 if (Filter == &ResultBuilder::IsNestedNameSpecifier ||
523 ((isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND)) &&
524 Filter != &ResultBuilder::IsNamespace &&
Douglas Gregor52779fb2010-09-23 23:01:17 +0000525 Filter != &ResultBuilder::IsNamespaceOrAlias &&
526 Filter != 0))
Douglas Gregora5fb7c32010-08-16 23:05:20 +0000527 AsNestedNameSpecifier = true;
528
Douglas Gregor86d9a522009-09-21 16:56:56 +0000529 // Filter out any unwanted results.
Douglas Gregor45bcd432010-01-14 03:21:49 +0000530 if (Filter && !(this->*Filter)(ND)) {
531 // Check whether it is interesting as a nested-name-specifier.
532 if (AllowNestedNameSpecifiers && SemaRef.getLangOptions().CPlusPlus &&
533 IsNestedNameSpecifier(ND) &&
534 (Filter != &ResultBuilder::IsMember ||
535 (isa<CXXRecordDecl>(ND) &&
536 cast<CXXRecordDecl>(ND)->isInjectedClassName()))) {
537 AsNestedNameSpecifier = true;
538 return true;
539 }
540
Douglas Gregore495b7f2010-01-14 00:20:49 +0000541 return false;
Douglas Gregora5fb7c32010-08-16 23:05:20 +0000542 }
Douglas Gregore495b7f2010-01-14 00:20:49 +0000543 // ... then it must be interesting!
544 return true;
545}
546
Douglas Gregor6660d842010-01-14 00:41:07 +0000547bool ResultBuilder::CheckHiddenResult(Result &R, DeclContext *CurContext,
548 NamedDecl *Hiding) {
549 // In C, there is no way to refer to a hidden name.
550 // FIXME: This isn't true; we can find a tag name hidden by an ordinary
551 // name if we introduce the tag type.
552 if (!SemaRef.getLangOptions().CPlusPlus)
553 return true;
554
Sebastian Redl7a126a42010-08-31 00:36:30 +0000555 DeclContext *HiddenCtx = R.Declaration->getDeclContext()->getRedeclContext();
Douglas Gregor6660d842010-01-14 00:41:07 +0000556
557 // There is no way to qualify a name declared in a function or method.
558 if (HiddenCtx->isFunctionOrMethod())
559 return true;
560
Sebastian Redl7a126a42010-08-31 00:36:30 +0000561 if (HiddenCtx == Hiding->getDeclContext()->getRedeclContext())
Douglas Gregor6660d842010-01-14 00:41:07 +0000562 return true;
563
564 // We can refer to the result with the appropriate qualification. Do it.
565 R.Hidden = true;
566 R.QualifierIsInformative = false;
567
568 if (!R.Qualifier)
569 R.Qualifier = getRequiredQualification(SemaRef.Context,
570 CurContext,
571 R.Declaration->getDeclContext());
572 return false;
573}
574
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000575/// \brief A simplified classification of types used to determine whether two
576/// types are "similar enough" when adjusting priorities.
Douglas Gregor1827e102010-08-16 16:18:59 +0000577SimplifiedTypeClass clang::getSimplifiedTypeClass(CanQualType T) {
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000578 switch (T->getTypeClass()) {
579 case Type::Builtin:
580 switch (cast<BuiltinType>(T)->getKind()) {
581 case BuiltinType::Void:
582 return STC_Void;
583
584 case BuiltinType::NullPtr:
585 return STC_Pointer;
586
587 case BuiltinType::Overload:
588 case BuiltinType::Dependent:
589 case BuiltinType::UndeducedAuto:
590 return STC_Other;
591
592 case BuiltinType::ObjCId:
593 case BuiltinType::ObjCClass:
594 case BuiltinType::ObjCSel:
595 return STC_ObjectiveC;
596
597 default:
598 return STC_Arithmetic;
599 }
600 return STC_Other;
601
602 case Type::Complex:
603 return STC_Arithmetic;
604
605 case Type::Pointer:
606 return STC_Pointer;
607
608 case Type::BlockPointer:
609 return STC_Block;
610
611 case Type::LValueReference:
612 case Type::RValueReference:
613 return getSimplifiedTypeClass(T->getAs<ReferenceType>()->getPointeeType());
614
615 case Type::ConstantArray:
616 case Type::IncompleteArray:
617 case Type::VariableArray:
618 case Type::DependentSizedArray:
619 return STC_Array;
620
621 case Type::DependentSizedExtVector:
622 case Type::Vector:
623 case Type::ExtVector:
624 return STC_Arithmetic;
625
626 case Type::FunctionProto:
627 case Type::FunctionNoProto:
628 return STC_Function;
629
630 case Type::Record:
631 return STC_Record;
632
633 case Type::Enum:
634 return STC_Arithmetic;
635
636 case Type::ObjCObject:
637 case Type::ObjCInterface:
638 case Type::ObjCObjectPointer:
639 return STC_ObjectiveC;
640
641 default:
642 return STC_Other;
643 }
644}
645
646/// \brief Get the type that a given expression will have if this declaration
647/// is used as an expression in its "typical" code-completion form.
Douglas Gregor1827e102010-08-16 16:18:59 +0000648QualType clang::getDeclUsageType(ASTContext &C, NamedDecl *ND) {
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000649 ND = cast<NamedDecl>(ND->getUnderlyingDecl());
650
651 if (TypeDecl *Type = dyn_cast<TypeDecl>(ND))
652 return C.getTypeDeclType(Type);
653 if (ObjCInterfaceDecl *Iface = dyn_cast<ObjCInterfaceDecl>(ND))
654 return C.getObjCInterfaceType(Iface);
655
656 QualType T;
657 if (FunctionDecl *Function = dyn_cast<FunctionDecl>(ND))
Douglas Gregor5291c3c2010-07-13 08:18:22 +0000658 T = Function->getCallResultType();
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000659 else if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND))
Douglas Gregor5291c3c2010-07-13 08:18:22 +0000660 T = Method->getSendResultType();
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000661 else if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND))
Douglas Gregor5291c3c2010-07-13 08:18:22 +0000662 T = FunTmpl->getTemplatedDecl()->getCallResultType();
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000663 else if (EnumConstantDecl *Enumerator = dyn_cast<EnumConstantDecl>(ND))
664 T = C.getTypeDeclType(cast<EnumDecl>(Enumerator->getDeclContext()));
665 else if (ObjCPropertyDecl *Property = dyn_cast<ObjCPropertyDecl>(ND))
666 T = Property->getType();
667 else if (ValueDecl *Value = dyn_cast<ValueDecl>(ND))
668 T = Value->getType();
669 else
670 return QualType();
671
672 return T.getNonReferenceType();
673}
674
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000675void ResultBuilder::AdjustResultPriorityForDecl(Result &R) {
676 // If this is an Objective-C method declaration whose selector matches our
677 // preferred selector, give it a priority boost.
678 if (!PreferredSelector.isNull())
679 if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(R.Declaration))
680 if (PreferredSelector == Method->getSelector())
681 R.Priority += CCD_SelectorMatch;
Douglas Gregor08f43cd2010-09-20 23:11:55 +0000682
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000683 // If we have a preferred type, adjust the priority for results with exactly-
684 // matching or nearly-matching types.
685 if (!PreferredType.isNull()) {
686 QualType T = getDeclUsageType(SemaRef.Context, R.Declaration);
687 if (!T.isNull()) {
688 CanQualType TC = SemaRef.Context.getCanonicalType(T);
689 // Check for exactly-matching types (modulo qualifiers).
690 if (SemaRef.Context.hasSameUnqualifiedType(PreferredType, TC))
691 R.Priority /= CCF_ExactTypeMatch;
692 // Check for nearly-matching types, based on classification of each.
693 else if ((getSimplifiedTypeClass(PreferredType)
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000694 == getSimplifiedTypeClass(TC)) &&
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000695 !(PreferredType->isEnumeralType() && TC->isEnumeralType()))
696 R.Priority /= CCF_SimilarTypeMatch;
697 }
698 }
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000699}
700
Douglas Gregor6f942b22010-09-21 16:06:22 +0000701void ResultBuilder::MaybeAddConstructorResults(Result R) {
702 if (!SemaRef.getLangOptions().CPlusPlus || !R.Declaration ||
703 !CompletionContext.wantConstructorResults())
704 return;
705
706 ASTContext &Context = SemaRef.Context;
707 NamedDecl *D = R.Declaration;
708 CXXRecordDecl *Record = 0;
709 if (ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(D))
710 Record = ClassTemplate->getTemplatedDecl();
711 else if ((Record = dyn_cast<CXXRecordDecl>(D))) {
712 // Skip specializations and partial specializations.
713 if (isa<ClassTemplateSpecializationDecl>(Record))
714 return;
715 } else {
716 // There are no constructors here.
717 return;
718 }
719
720 Record = Record->getDefinition();
721 if (!Record)
722 return;
723
724
725 QualType RecordTy = Context.getTypeDeclType(Record);
726 DeclarationName ConstructorName
727 = Context.DeclarationNames.getCXXConstructorName(
728 Context.getCanonicalType(RecordTy));
729 for (DeclContext::lookup_result Ctors = Record->lookup(ConstructorName);
730 Ctors.first != Ctors.second; ++Ctors.first) {
731 R.Declaration = *Ctors.first;
732 R.CursorKind = getCursorKindForDecl(R.Declaration);
733 Results.push_back(R);
734 }
735}
736
Douglas Gregore495b7f2010-01-14 00:20:49 +0000737void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) {
738 assert(!ShadowMaps.empty() && "Must enter into a results scope");
739
740 if (R.Kind != Result::RK_Declaration) {
741 // For non-declaration results, just add the result.
742 Results.push_back(R);
743 return;
744 }
745
746 // Look through using declarations.
747 if (UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(R.Declaration)) {
748 MaybeAddResult(Result(Using->getTargetDecl(), R.Qualifier), CurContext);
749 return;
750 }
751
752 Decl *CanonDecl = R.Declaration->getCanonicalDecl();
753 unsigned IDNS = CanonDecl->getIdentifierNamespace();
754
Douglas Gregor45bcd432010-01-14 03:21:49 +0000755 bool AsNestedNameSpecifier = false;
756 if (!isInterestingDecl(R.Declaration, AsNestedNameSpecifier))
Douglas Gregore495b7f2010-01-14 00:20:49 +0000757 return;
758
Douglas Gregor6f942b22010-09-21 16:06:22 +0000759 // C++ constructors are never found by name lookup.
760 if (isa<CXXConstructorDecl>(R.Declaration))
761 return;
762
Douglas Gregor86d9a522009-09-21 16:56:56 +0000763 ShadowMap &SMap = ShadowMaps.back();
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000764 ShadowMapEntry::iterator I, IEnd;
765 ShadowMap::iterator NamePos = SMap.find(R.Declaration->getDeclName());
766 if (NamePos != SMap.end()) {
767 I = NamePos->second.begin();
768 IEnd = NamePos->second.end();
769 }
770
771 for (; I != IEnd; ++I) {
772 NamedDecl *ND = I->first;
773 unsigned Index = I->second;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000774 if (ND->getCanonicalDecl() == CanonDecl) {
775 // This is a redeclaration. Always pick the newer declaration.
Douglas Gregor86d9a522009-09-21 16:56:56 +0000776 Results[Index].Declaration = R.Declaration;
777
Douglas Gregor86d9a522009-09-21 16:56:56 +0000778 // We're done.
779 return;
780 }
781 }
782
783 // This is a new declaration in this scope. However, check whether this
784 // declaration name is hidden by a similarly-named declaration in an outer
785 // scope.
786 std::list<ShadowMap>::iterator SM, SMEnd = ShadowMaps.end();
787 --SMEnd;
788 for (SM = ShadowMaps.begin(); SM != SMEnd; ++SM) {
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000789 ShadowMapEntry::iterator I, IEnd;
790 ShadowMap::iterator NamePos = SM->find(R.Declaration->getDeclName());
791 if (NamePos != SM->end()) {
792 I = NamePos->second.begin();
793 IEnd = NamePos->second.end();
794 }
795 for (; I != IEnd; ++I) {
Douglas Gregor86d9a522009-09-21 16:56:56 +0000796 // A tag declaration does not hide a non-tag declaration.
John McCall0d6b1642010-04-23 18:46:30 +0000797 if (I->first->hasTagIdentifierNamespace() &&
Douglas Gregor86d9a522009-09-21 16:56:56 +0000798 (IDNS & (Decl::IDNS_Member | Decl::IDNS_Ordinary |
799 Decl::IDNS_ObjCProtocol)))
800 continue;
801
802 // Protocols are in distinct namespaces from everything else.
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000803 if (((I->first->getIdentifierNamespace() & Decl::IDNS_ObjCProtocol)
Douglas Gregor86d9a522009-09-21 16:56:56 +0000804 || (IDNS & Decl::IDNS_ObjCProtocol)) &&
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000805 I->first->getIdentifierNamespace() != IDNS)
Douglas Gregor86d9a522009-09-21 16:56:56 +0000806 continue;
807
808 // The newly-added result is hidden by an entry in the shadow map.
Douglas Gregor6660d842010-01-14 00:41:07 +0000809 if (CheckHiddenResult(R, CurContext, I->first))
Douglas Gregor86d9a522009-09-21 16:56:56 +0000810 return;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000811
812 break;
813 }
814 }
815
816 // Make sure that any given declaration only shows up in the result set once.
817 if (!AllDeclsFound.insert(CanonDecl))
818 return;
Douglas Gregor265f7492010-08-27 15:29:55 +0000819
Douglas Gregoreb5758b2009-09-23 22:26:46 +0000820 // If the filter is for nested-name-specifiers, then this result starts a
821 // nested-name-specifier.
Douglas Gregor12e13132010-05-26 22:00:08 +0000822 if (AsNestedNameSpecifier) {
Douglas Gregoreb5758b2009-09-23 22:26:46 +0000823 R.StartsNestedNameSpecifier = true;
Douglas Gregor12e13132010-05-26 22:00:08 +0000824 R.Priority = CCP_NestedNameSpecifier;
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000825 } else
826 AdjustResultPriorityForDecl(R);
Douglas Gregor265f7492010-08-27 15:29:55 +0000827
Douglas Gregor0563c262009-09-22 23:15:58 +0000828 // If this result is supposed to have an informative qualifier, add one.
Douglas Gregoreb5758b2009-09-23 22:26:46 +0000829 if (R.QualifierIsInformative && !R.Qualifier &&
830 !R.StartsNestedNameSpecifier) {
Douglas Gregor0563c262009-09-22 23:15:58 +0000831 DeclContext *Ctx = R.Declaration->getDeclContext();
832 if (NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Ctx))
833 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, Namespace);
834 else if (TagDecl *Tag = dyn_cast<TagDecl>(Ctx))
835 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, false,
836 SemaRef.Context.getTypeDeclType(Tag).getTypePtr());
837 else
838 R.QualifierIsInformative = false;
839 }
Douglas Gregoreb5758b2009-09-23 22:26:46 +0000840
Douglas Gregor86d9a522009-09-21 16:56:56 +0000841 // Insert this result into the set of results and into the current shadow
842 // map.
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000843 SMap[R.Declaration->getDeclName()].Add(R.Declaration, Results.size());
Douglas Gregor86d9a522009-09-21 16:56:56 +0000844 Results.push_back(R);
Douglas Gregor6f942b22010-09-21 16:06:22 +0000845
846 if (!AsNestedNameSpecifier)
847 MaybeAddConstructorResults(R);
Douglas Gregor86d9a522009-09-21 16:56:56 +0000848}
849
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000850void ResultBuilder::AddResult(Result R, DeclContext *CurContext,
Douglas Gregor0cc84042010-01-14 15:47:35 +0000851 NamedDecl *Hiding, bool InBaseClass = false) {
Douglas Gregora4477812010-01-14 16:01:26 +0000852 if (R.Kind != Result::RK_Declaration) {
853 // For non-declaration results, just add the result.
854 Results.push_back(R);
855 return;
856 }
857
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000858 // Look through using declarations.
859 if (UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(R.Declaration)) {
860 AddResult(Result(Using->getTargetDecl(), R.Qualifier), CurContext, Hiding);
861 return;
862 }
863
Douglas Gregor45bcd432010-01-14 03:21:49 +0000864 bool AsNestedNameSpecifier = false;
865 if (!isInterestingDecl(R.Declaration, AsNestedNameSpecifier))
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000866 return;
867
Douglas Gregor6f942b22010-09-21 16:06:22 +0000868 // C++ constructors are never found by name lookup.
869 if (isa<CXXConstructorDecl>(R.Declaration))
870 return;
871
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000872 if (Hiding && CheckHiddenResult(R, CurContext, Hiding))
873 return;
874
875 // Make sure that any given declaration only shows up in the result set once.
876 if (!AllDeclsFound.insert(R.Declaration->getCanonicalDecl()))
877 return;
878
879 // If the filter is for nested-name-specifiers, then this result starts a
880 // nested-name-specifier.
Douglas Gregor12e13132010-05-26 22:00:08 +0000881 if (AsNestedNameSpecifier) {
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000882 R.StartsNestedNameSpecifier = true;
Douglas Gregor12e13132010-05-26 22:00:08 +0000883 R.Priority = CCP_NestedNameSpecifier;
884 }
Douglas Gregor0cc84042010-01-14 15:47:35 +0000885 else if (Filter == &ResultBuilder::IsMember && !R.Qualifier && InBaseClass &&
886 isa<CXXRecordDecl>(R.Declaration->getDeclContext()
Sebastian Redl7a126a42010-08-31 00:36:30 +0000887 ->getRedeclContext()))
Douglas Gregor0cc84042010-01-14 15:47:35 +0000888 R.QualifierIsInformative = true;
889
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000890 // If this result is supposed to have an informative qualifier, add one.
891 if (R.QualifierIsInformative && !R.Qualifier &&
892 !R.StartsNestedNameSpecifier) {
893 DeclContext *Ctx = R.Declaration->getDeclContext();
894 if (NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Ctx))
895 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, Namespace);
896 else if (TagDecl *Tag = dyn_cast<TagDecl>(Ctx))
897 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, false,
Douglas Gregor45bcd432010-01-14 03:21:49 +0000898 SemaRef.Context.getTypeDeclType(Tag).getTypePtr());
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000899 else
900 R.QualifierIsInformative = false;
901 }
902
Douglas Gregor12e13132010-05-26 22:00:08 +0000903 // Adjust the priority if this result comes from a base class.
904 if (InBaseClass)
905 R.Priority += CCD_InBaseClass;
906
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000907 AdjustResultPriorityForDecl(R);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +0000908
Douglas Gregor3cdee122010-08-26 16:36:48 +0000909 if (HasObjectTypeQualifiers)
910 if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(R.Declaration))
911 if (Method->isInstance()) {
912 Qualifiers MethodQuals
913 = Qualifiers::fromCVRMask(Method->getTypeQualifiers());
914 if (ObjectTypeQualifiers == MethodQuals)
915 R.Priority += CCD_ObjectQualifierMatch;
916 else if (ObjectTypeQualifiers - MethodQuals) {
917 // The method cannot be invoked, because doing so would drop
918 // qualifiers.
919 return;
920 }
921 }
922
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000923 // Insert this result into the set of results.
924 Results.push_back(R);
Douglas Gregor6f942b22010-09-21 16:06:22 +0000925
926 if (!AsNestedNameSpecifier)
927 MaybeAddConstructorResults(R);
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000928}
929
Douglas Gregora4477812010-01-14 16:01:26 +0000930void ResultBuilder::AddResult(Result R) {
931 assert(R.Kind != Result::RK_Declaration &&
932 "Declaration results need more context");
933 Results.push_back(R);
934}
935
Douglas Gregor86d9a522009-09-21 16:56:56 +0000936/// \brief Enter into a new scope.
937void ResultBuilder::EnterNewScope() {
938 ShadowMaps.push_back(ShadowMap());
939}
940
941/// \brief Exit from the current scope.
942void ResultBuilder::ExitScope() {
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000943 for (ShadowMap::iterator E = ShadowMaps.back().begin(),
944 EEnd = ShadowMaps.back().end();
945 E != EEnd;
946 ++E)
947 E->second.Destroy();
948
Douglas Gregor86d9a522009-09-21 16:56:56 +0000949 ShadowMaps.pop_back();
950}
951
Douglas Gregor791215b2009-09-21 20:51:25 +0000952/// \brief Determines whether this given declaration will be found by
953/// ordinary name lookup.
954bool ResultBuilder::IsOrdinaryName(NamedDecl *ND) const {
Douglas Gregor4710e5b2010-05-28 00:49:12 +0000955 ND = cast<NamedDecl>(ND->getUnderlyingDecl());
956
Douglas Gregor791215b2009-09-21 20:51:25 +0000957 unsigned IDNS = Decl::IDNS_Ordinary;
958 if (SemaRef.getLangOptions().CPlusPlus)
Douglas Gregor9b30b262010-06-15 20:26:51 +0000959 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member;
Douglas Gregorca45da02010-11-02 20:36:02 +0000960 else if (SemaRef.getLangOptions().ObjC1) {
961 if (isa<ObjCIvarDecl>(ND))
962 return true;
963 if (isa<ObjCPropertyDecl>(ND) &&
964 SemaRef.canSynthesizeProvisionalIvar(cast<ObjCPropertyDecl>(ND)))
965 return true;
966 }
967
Douglas Gregor791215b2009-09-21 20:51:25 +0000968 return ND->getIdentifierNamespace() & IDNS;
969}
970
Douglas Gregor01dfea02010-01-10 23:08:15 +0000971/// \brief Determines whether this given declaration will be found by
Douglas Gregor4710e5b2010-05-28 00:49:12 +0000972/// ordinary name lookup but is not a type name.
973bool ResultBuilder::IsOrdinaryNonTypeName(NamedDecl *ND) const {
974 ND = cast<NamedDecl>(ND->getUnderlyingDecl());
975 if (isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND))
976 return false;
977
978 unsigned IDNS = Decl::IDNS_Ordinary;
979 if (SemaRef.getLangOptions().CPlusPlus)
Douglas Gregor9b30b262010-06-15 20:26:51 +0000980 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member;
Douglas Gregorca45da02010-11-02 20:36:02 +0000981 else if (SemaRef.getLangOptions().ObjC1) {
982 if (isa<ObjCIvarDecl>(ND))
983 return true;
984 if (isa<ObjCPropertyDecl>(ND) &&
985 SemaRef.canSynthesizeProvisionalIvar(cast<ObjCPropertyDecl>(ND)))
986 return true;
987 }
988
Douglas Gregor4710e5b2010-05-28 00:49:12 +0000989 return ND->getIdentifierNamespace() & IDNS;
990}
991
Douglas Gregorf9578432010-07-28 21:50:18 +0000992bool ResultBuilder::IsIntegralConstantValue(NamedDecl *ND) const {
993 if (!IsOrdinaryNonTypeName(ND))
994 return 0;
995
996 if (ValueDecl *VD = dyn_cast<ValueDecl>(ND->getUnderlyingDecl()))
997 if (VD->getType()->isIntegralOrEnumerationType())
998 return true;
999
1000 return false;
1001}
1002
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001003/// \brief Determines whether this given declaration will be found by
Douglas Gregor01dfea02010-01-10 23:08:15 +00001004/// ordinary name lookup.
1005bool ResultBuilder::IsOrdinaryNonValueName(NamedDecl *ND) const {
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001006 ND = cast<NamedDecl>(ND->getUnderlyingDecl());
1007
Douglas Gregor01dfea02010-01-10 23:08:15 +00001008 unsigned IDNS = Decl::IDNS_Ordinary;
1009 if (SemaRef.getLangOptions().CPlusPlus)
John McCall0d6b1642010-04-23 18:46:30 +00001010 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace;
Douglas Gregor01dfea02010-01-10 23:08:15 +00001011
1012 return (ND->getIdentifierNamespace() & IDNS) &&
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001013 !isa<ValueDecl>(ND) && !isa<FunctionTemplateDecl>(ND) &&
1014 !isa<ObjCPropertyDecl>(ND);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001015}
1016
Douglas Gregor86d9a522009-09-21 16:56:56 +00001017/// \brief Determines whether the given declaration is suitable as the
1018/// start of a C++ nested-name-specifier, e.g., a class or namespace.
1019bool ResultBuilder::IsNestedNameSpecifier(NamedDecl *ND) const {
1020 // Allow us to find class templates, too.
1021 if (ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
1022 ND = ClassTemplate->getTemplatedDecl();
1023
1024 return SemaRef.isAcceptableNestedNameSpecifier(ND);
1025}
1026
1027/// \brief Determines whether the given declaration is an enumeration.
1028bool ResultBuilder::IsEnum(NamedDecl *ND) const {
1029 return isa<EnumDecl>(ND);
1030}
1031
1032/// \brief Determines whether the given declaration is a class or struct.
1033bool ResultBuilder::IsClassOrStruct(NamedDecl *ND) const {
1034 // Allow us to find class templates, too.
1035 if (ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
1036 ND = ClassTemplate->getTemplatedDecl();
1037
1038 if (RecordDecl *RD = dyn_cast<RecordDecl>(ND))
Abramo Bagnara465d41b2010-05-11 21:36:43 +00001039 return RD->getTagKind() == TTK_Class ||
1040 RD->getTagKind() == TTK_Struct;
Douglas Gregor86d9a522009-09-21 16:56:56 +00001041
1042 return false;
1043}
1044
1045/// \brief Determines whether the given declaration is a union.
1046bool ResultBuilder::IsUnion(NamedDecl *ND) const {
1047 // Allow us to find class templates, too.
1048 if (ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
1049 ND = ClassTemplate->getTemplatedDecl();
1050
1051 if (RecordDecl *RD = dyn_cast<RecordDecl>(ND))
Abramo Bagnara465d41b2010-05-11 21:36:43 +00001052 return RD->getTagKind() == TTK_Union;
Douglas Gregor86d9a522009-09-21 16:56:56 +00001053
1054 return false;
1055}
1056
1057/// \brief Determines whether the given declaration is a namespace.
1058bool ResultBuilder::IsNamespace(NamedDecl *ND) const {
1059 return isa<NamespaceDecl>(ND);
1060}
1061
1062/// \brief Determines whether the given declaration is a namespace or
1063/// namespace alias.
1064bool ResultBuilder::IsNamespaceOrAlias(NamedDecl *ND) const {
1065 return isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND);
1066}
1067
Douglas Gregor76282942009-12-11 17:31:05 +00001068/// \brief Determines whether the given declaration is a type.
Douglas Gregor86d9a522009-09-21 16:56:56 +00001069bool ResultBuilder::IsType(NamedDecl *ND) const {
Douglas Gregord32b0222010-08-24 01:06:58 +00001070 if (UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(ND))
1071 ND = Using->getTargetDecl();
1072
1073 return isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND);
Douglas Gregor86d9a522009-09-21 16:56:56 +00001074}
1075
Douglas Gregor76282942009-12-11 17:31:05 +00001076/// \brief Determines which members of a class should be visible via
1077/// "." or "->". Only value declarations, nested name specifiers, and
1078/// using declarations thereof should show up.
Douglas Gregoreb5758b2009-09-23 22:26:46 +00001079bool ResultBuilder::IsMember(NamedDecl *ND) const {
Douglas Gregor76282942009-12-11 17:31:05 +00001080 if (UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(ND))
1081 ND = Using->getTargetDecl();
1082
Douglas Gregorce821962009-12-11 18:14:22 +00001083 return isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND) ||
1084 isa<ObjCPropertyDecl>(ND);
Douglas Gregoreb5758b2009-09-23 22:26:46 +00001085}
1086
Douglas Gregor8e254cf2010-05-27 23:06:34 +00001087static bool isObjCReceiverType(ASTContext &C, QualType T) {
1088 T = C.getCanonicalType(T);
1089 switch (T->getTypeClass()) {
1090 case Type::ObjCObject:
1091 case Type::ObjCInterface:
1092 case Type::ObjCObjectPointer:
1093 return true;
1094
1095 case Type::Builtin:
1096 switch (cast<BuiltinType>(T)->getKind()) {
1097 case BuiltinType::ObjCId:
1098 case BuiltinType::ObjCClass:
1099 case BuiltinType::ObjCSel:
1100 return true;
1101
1102 default:
1103 break;
1104 }
1105 return false;
1106
1107 default:
1108 break;
1109 }
1110
1111 if (!C.getLangOptions().CPlusPlus)
1112 return false;
1113
1114 // FIXME: We could perform more analysis here to determine whether a
1115 // particular class type has any conversions to Objective-C types. For now,
1116 // just accept all class types.
1117 return T->isDependentType() || T->isRecordType();
1118}
1119
1120bool ResultBuilder::IsObjCMessageReceiver(NamedDecl *ND) const {
1121 QualType T = getDeclUsageType(SemaRef.Context, ND);
1122 if (T.isNull())
1123 return false;
1124
1125 T = SemaRef.Context.getBaseElementType(T);
1126 return isObjCReceiverType(SemaRef.Context, T);
1127}
1128
Douglas Gregorfb629412010-08-23 21:17:50 +00001129bool ResultBuilder::IsObjCCollection(NamedDecl *ND) const {
1130 if ((SemaRef.getLangOptions().CPlusPlus && !IsOrdinaryName(ND)) ||
1131 (!SemaRef.getLangOptions().CPlusPlus && !IsOrdinaryNonTypeName(ND)))
1132 return false;
1133
1134 QualType T = getDeclUsageType(SemaRef.Context, ND);
1135 if (T.isNull())
1136 return false;
1137
1138 T = SemaRef.Context.getBaseElementType(T);
1139 return T->isObjCObjectType() || T->isObjCObjectPointerType() ||
1140 T->isObjCIdType() ||
1141 (SemaRef.getLangOptions().CPlusPlus && T->isRecordType());
1142}
Douglas Gregor8e254cf2010-05-27 23:06:34 +00001143
Douglas Gregor52779fb2010-09-23 23:01:17 +00001144bool ResultBuilder::IsImpossibleToSatisfy(NamedDecl *ND) const {
1145 return false;
1146}
1147
Douglas Gregor80f4f4c2010-01-14 16:08:12 +00001148/// \rief Determines whether the given declaration is an Objective-C
1149/// instance variable.
1150bool ResultBuilder::IsObjCIvar(NamedDecl *ND) const {
1151 return isa<ObjCIvarDecl>(ND);
1152}
1153
Douglas Gregor1ca6ae82010-01-14 01:09:38 +00001154namespace {
1155 /// \brief Visible declaration consumer that adds a code-completion result
1156 /// for each visible declaration.
1157 class CodeCompletionDeclConsumer : public VisibleDeclConsumer {
1158 ResultBuilder &Results;
1159 DeclContext *CurContext;
1160
1161 public:
1162 CodeCompletionDeclConsumer(ResultBuilder &Results, DeclContext *CurContext)
1163 : Results(Results), CurContext(CurContext) { }
1164
Douglas Gregor0cc84042010-01-14 15:47:35 +00001165 virtual void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, bool InBaseClass) {
1166 Results.AddResult(ND, CurContext, Hiding, InBaseClass);
Douglas Gregor1ca6ae82010-01-14 01:09:38 +00001167 }
1168 };
1169}
1170
Douglas Gregor86d9a522009-09-21 16:56:56 +00001171/// \brief Add type specifiers for the current language as keyword results.
Douglas Gregorbca403c2010-01-13 23:51:12 +00001172static void AddTypeSpecifierResults(const LangOptions &LangOpts,
Douglas Gregor86d9a522009-09-21 16:56:56 +00001173 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00001174 typedef CodeCompletionResult Result;
Douglas Gregor12e13132010-05-26 22:00:08 +00001175 Results.AddResult(Result("short", CCP_Type));
1176 Results.AddResult(Result("long", CCP_Type));
1177 Results.AddResult(Result("signed", CCP_Type));
1178 Results.AddResult(Result("unsigned", CCP_Type));
1179 Results.AddResult(Result("void", CCP_Type));
1180 Results.AddResult(Result("char", CCP_Type));
1181 Results.AddResult(Result("int", CCP_Type));
1182 Results.AddResult(Result("float", CCP_Type));
1183 Results.AddResult(Result("double", CCP_Type));
1184 Results.AddResult(Result("enum", CCP_Type));
1185 Results.AddResult(Result("struct", CCP_Type));
1186 Results.AddResult(Result("union", CCP_Type));
1187 Results.AddResult(Result("const", CCP_Type));
1188 Results.AddResult(Result("volatile", CCP_Type));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001189
Douglas Gregor86d9a522009-09-21 16:56:56 +00001190 if (LangOpts.C99) {
1191 // C99-specific
Douglas Gregor12e13132010-05-26 22:00:08 +00001192 Results.AddResult(Result("_Complex", CCP_Type));
1193 Results.AddResult(Result("_Imaginary", CCP_Type));
1194 Results.AddResult(Result("_Bool", CCP_Type));
1195 Results.AddResult(Result("restrict", CCP_Type));
Douglas Gregor86d9a522009-09-21 16:56:56 +00001196 }
1197
Douglas Gregor218937c2011-02-01 19:23:04 +00001198 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregor86d9a522009-09-21 16:56:56 +00001199 if (LangOpts.CPlusPlus) {
1200 // C++-specific
Douglas Gregorb05496d2010-09-20 21:11:48 +00001201 Results.AddResult(Result("bool", CCP_Type +
1202 (LangOpts.ObjC1? CCD_bool_in_ObjC : 0)));
Douglas Gregor12e13132010-05-26 22:00:08 +00001203 Results.AddResult(Result("class", CCP_Type));
1204 Results.AddResult(Result("wchar_t", CCP_Type));
Douglas Gregor86d9a522009-09-21 16:56:56 +00001205
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001206 // typename qualified-id
Douglas Gregor218937c2011-02-01 19:23:04 +00001207 Builder.AddTypedTextChunk("typename");
1208 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1209 Builder.AddPlaceholderChunk("qualifier");
1210 Builder.AddTextChunk("::");
1211 Builder.AddPlaceholderChunk("name");
1212 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregord8e8a582010-05-25 21:41:55 +00001213
Douglas Gregor86d9a522009-09-21 16:56:56 +00001214 if (LangOpts.CPlusPlus0x) {
Douglas Gregor12e13132010-05-26 22:00:08 +00001215 Results.AddResult(Result("auto", CCP_Type));
1216 Results.AddResult(Result("char16_t", CCP_Type));
1217 Results.AddResult(Result("char32_t", CCP_Type));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001218
Douglas Gregor218937c2011-02-01 19:23:04 +00001219 Builder.AddTypedTextChunk("decltype");
1220 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1221 Builder.AddPlaceholderChunk("expression");
1222 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1223 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor86d9a522009-09-21 16:56:56 +00001224 }
1225 }
1226
1227 // GNU extensions
1228 if (LangOpts.GNUMode) {
1229 // FIXME: Enable when we actually support decimal floating point.
Douglas Gregora4477812010-01-14 16:01:26 +00001230 // Results.AddResult(Result("_Decimal32"));
1231 // Results.AddResult(Result("_Decimal64"));
1232 // Results.AddResult(Result("_Decimal128"));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001233
Douglas Gregor218937c2011-02-01 19:23:04 +00001234 Builder.AddTypedTextChunk("typeof");
1235 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1236 Builder.AddPlaceholderChunk("expression");
1237 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001238
Douglas Gregor218937c2011-02-01 19:23:04 +00001239 Builder.AddTypedTextChunk("typeof");
1240 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1241 Builder.AddPlaceholderChunk("type");
1242 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1243 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor86d9a522009-09-21 16:56:56 +00001244 }
1245}
1246
John McCallf312b1e2010-08-26 23:41:50 +00001247static void AddStorageSpecifiers(Sema::ParserCompletionContext CCC,
Douglas Gregor01dfea02010-01-10 23:08:15 +00001248 const LangOptions &LangOpts,
Douglas Gregor01dfea02010-01-10 23:08:15 +00001249 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00001250 typedef CodeCompletionResult Result;
Douglas Gregor01dfea02010-01-10 23:08:15 +00001251 // Note: we don't suggest either "auto" or "register", because both
1252 // are pointless as storage specifiers. Elsewhere, we suggest "auto"
1253 // in C++0x as a type specifier.
Douglas Gregora4477812010-01-14 16:01:26 +00001254 Results.AddResult(Result("extern"));
1255 Results.AddResult(Result("static"));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001256}
1257
John McCallf312b1e2010-08-26 23:41:50 +00001258static void AddFunctionSpecifiers(Sema::ParserCompletionContext CCC,
Douglas Gregor01dfea02010-01-10 23:08:15 +00001259 const LangOptions &LangOpts,
Douglas Gregor01dfea02010-01-10 23:08:15 +00001260 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00001261 typedef CodeCompletionResult Result;
Douglas Gregor01dfea02010-01-10 23:08:15 +00001262 switch (CCC) {
John McCallf312b1e2010-08-26 23:41:50 +00001263 case Sema::PCC_Class:
1264 case Sema::PCC_MemberTemplate:
Douglas Gregor01dfea02010-01-10 23:08:15 +00001265 if (LangOpts.CPlusPlus) {
Douglas Gregora4477812010-01-14 16:01:26 +00001266 Results.AddResult(Result("explicit"));
1267 Results.AddResult(Result("friend"));
1268 Results.AddResult(Result("mutable"));
1269 Results.AddResult(Result("virtual"));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001270 }
1271 // Fall through
1272
John McCallf312b1e2010-08-26 23:41:50 +00001273 case Sema::PCC_ObjCInterface:
1274 case Sema::PCC_ObjCImplementation:
1275 case Sema::PCC_Namespace:
1276 case Sema::PCC_Template:
Douglas Gregor01dfea02010-01-10 23:08:15 +00001277 if (LangOpts.CPlusPlus || LangOpts.C99)
Douglas Gregora4477812010-01-14 16:01:26 +00001278 Results.AddResult(Result("inline"));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001279 break;
1280
John McCallf312b1e2010-08-26 23:41:50 +00001281 case Sema::PCC_ObjCInstanceVariableList:
1282 case Sema::PCC_Expression:
1283 case Sema::PCC_Statement:
1284 case Sema::PCC_ForInit:
1285 case Sema::PCC_Condition:
1286 case Sema::PCC_RecoveryInFunction:
1287 case Sema::PCC_Type:
Douglas Gregor02688102010-09-14 23:59:36 +00001288 case Sema::PCC_ParenthesizedExpression:
Douglas Gregor01dfea02010-01-10 23:08:15 +00001289 break;
1290 }
1291}
1292
Douglas Gregorbca403c2010-01-13 23:51:12 +00001293static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt);
1294static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt);
1295static void AddObjCVisibilityResults(const LangOptions &LangOpts,
Douglas Gregorc38c3e12010-01-13 21:54:15 +00001296 ResultBuilder &Results,
1297 bool NeedAt);
Douglas Gregorbca403c2010-01-13 23:51:12 +00001298static void AddObjCImplementationResults(const LangOptions &LangOpts,
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001299 ResultBuilder &Results,
1300 bool NeedAt);
Douglas Gregorbca403c2010-01-13 23:51:12 +00001301static void AddObjCInterfaceResults(const LangOptions &LangOpts,
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001302 ResultBuilder &Results,
1303 bool NeedAt);
Douglas Gregorbca403c2010-01-13 23:51:12 +00001304static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001305
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001306static void AddTypedefResult(ResultBuilder &Results) {
Douglas Gregor218937c2011-02-01 19:23:04 +00001307 CodeCompletionBuilder Builder(Results.getAllocator());
1308 Builder.AddTypedTextChunk("typedef");
1309 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1310 Builder.AddPlaceholderChunk("type");
1311 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1312 Builder.AddPlaceholderChunk("name");
1313 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001314}
1315
John McCallf312b1e2010-08-26 23:41:50 +00001316static bool WantTypesInContext(Sema::ParserCompletionContext CCC,
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001317 const LangOptions &LangOpts) {
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001318 switch (CCC) {
John McCallf312b1e2010-08-26 23:41:50 +00001319 case Sema::PCC_Namespace:
1320 case Sema::PCC_Class:
1321 case Sema::PCC_ObjCInstanceVariableList:
1322 case Sema::PCC_Template:
1323 case Sema::PCC_MemberTemplate:
1324 case Sema::PCC_Statement:
1325 case Sema::PCC_RecoveryInFunction:
1326 case Sema::PCC_Type:
Douglas Gregor02688102010-09-14 23:59:36 +00001327 case Sema::PCC_ParenthesizedExpression:
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001328 return true;
1329
John McCallf312b1e2010-08-26 23:41:50 +00001330 case Sema::PCC_Expression:
1331 case Sema::PCC_Condition:
Douglas Gregor02688102010-09-14 23:59:36 +00001332 return LangOpts.CPlusPlus;
1333
1334 case Sema::PCC_ObjCInterface:
1335 case Sema::PCC_ObjCImplementation:
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001336 return false;
1337
John McCallf312b1e2010-08-26 23:41:50 +00001338 case Sema::PCC_ForInit:
Douglas Gregor02688102010-09-14 23:59:36 +00001339 return LangOpts.CPlusPlus || LangOpts.ObjC1 || LangOpts.C99;
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001340 }
1341
1342 return false;
1343}
1344
Douglas Gregor01dfea02010-01-10 23:08:15 +00001345/// \brief Add language constructs that show up for "ordinary" names.
John McCallf312b1e2010-08-26 23:41:50 +00001346static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
Douglas Gregor01dfea02010-01-10 23:08:15 +00001347 Scope *S,
1348 Sema &SemaRef,
Douglas Gregor01dfea02010-01-10 23:08:15 +00001349 ResultBuilder &Results) {
Douglas Gregor218937c2011-02-01 19:23:04 +00001350 CodeCompletionBuilder Builder(Results.getAllocator());
1351
John McCall0a2c5e22010-08-25 06:19:51 +00001352 typedef CodeCompletionResult Result;
Douglas Gregor01dfea02010-01-10 23:08:15 +00001353 switch (CCC) {
John McCallf312b1e2010-08-26 23:41:50 +00001354 case Sema::PCC_Namespace:
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001355 if (SemaRef.getLangOptions().CPlusPlus) {
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001356 if (Results.includeCodePatterns()) {
1357 // namespace <identifier> { declarations }
Douglas Gregor218937c2011-02-01 19:23:04 +00001358 Builder.AddTypedTextChunk("namespace");
1359 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1360 Builder.AddPlaceholderChunk("identifier");
1361 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1362 Builder.AddPlaceholderChunk("declarations");
1363 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1364 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1365 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001366 }
1367
Douglas Gregor01dfea02010-01-10 23:08:15 +00001368 // namespace identifier = identifier ;
Douglas Gregor218937c2011-02-01 19:23:04 +00001369 Builder.AddTypedTextChunk("namespace");
1370 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1371 Builder.AddPlaceholderChunk("name");
1372 Builder.AddChunk(CodeCompletionString::CK_Equal);
1373 Builder.AddPlaceholderChunk("namespace");
1374 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001375
1376 // Using directives
Douglas Gregor218937c2011-02-01 19:23:04 +00001377 Builder.AddTypedTextChunk("using");
1378 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1379 Builder.AddTextChunk("namespace");
1380 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1381 Builder.AddPlaceholderChunk("identifier");
1382 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001383
1384 // asm(string-literal)
Douglas Gregor218937c2011-02-01 19:23:04 +00001385 Builder.AddTypedTextChunk("asm");
1386 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1387 Builder.AddPlaceholderChunk("string-literal");
1388 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1389 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001390
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001391 if (Results.includeCodePatterns()) {
1392 // Explicit template instantiation
Douglas Gregor218937c2011-02-01 19:23:04 +00001393 Builder.AddTypedTextChunk("template");
1394 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1395 Builder.AddPlaceholderChunk("declaration");
1396 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001397 }
Douglas Gregor01dfea02010-01-10 23:08:15 +00001398 }
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001399
1400 if (SemaRef.getLangOptions().ObjC1)
Douglas Gregorbca403c2010-01-13 23:51:12 +00001401 AddObjCTopLevelResults(Results, true);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001402
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001403 AddTypedefResult(Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001404 // Fall through
1405
John McCallf312b1e2010-08-26 23:41:50 +00001406 case Sema::PCC_Class:
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001407 if (SemaRef.getLangOptions().CPlusPlus) {
Douglas Gregor01dfea02010-01-10 23:08:15 +00001408 // Using declaration
Douglas Gregor218937c2011-02-01 19:23:04 +00001409 Builder.AddTypedTextChunk("using");
1410 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1411 Builder.AddPlaceholderChunk("qualifier");
1412 Builder.AddTextChunk("::");
1413 Builder.AddPlaceholderChunk("name");
1414 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001415
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001416 // using typename qualifier::name (only in a dependent context)
Douglas Gregor01dfea02010-01-10 23:08:15 +00001417 if (SemaRef.CurContext->isDependentContext()) {
Douglas Gregor218937c2011-02-01 19:23:04 +00001418 Builder.AddTypedTextChunk("using");
1419 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1420 Builder.AddTextChunk("typename");
1421 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1422 Builder.AddPlaceholderChunk("qualifier");
1423 Builder.AddTextChunk("::");
1424 Builder.AddPlaceholderChunk("name");
1425 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001426 }
1427
John McCallf312b1e2010-08-26 23:41:50 +00001428 if (CCC == Sema::PCC_Class) {
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001429 AddTypedefResult(Results);
1430
Douglas Gregor01dfea02010-01-10 23:08:15 +00001431 // public:
Douglas Gregor218937c2011-02-01 19:23:04 +00001432 Builder.AddTypedTextChunk("public");
1433 Builder.AddChunk(CodeCompletionString::CK_Colon);
1434 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001435
1436 // protected:
Douglas Gregor218937c2011-02-01 19:23:04 +00001437 Builder.AddTypedTextChunk("protected");
1438 Builder.AddChunk(CodeCompletionString::CK_Colon);
1439 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001440
1441 // private:
Douglas Gregor218937c2011-02-01 19:23:04 +00001442 Builder.AddTypedTextChunk("private");
1443 Builder.AddChunk(CodeCompletionString::CK_Colon);
1444 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001445 }
1446 }
1447 // Fall through
1448
John McCallf312b1e2010-08-26 23:41:50 +00001449 case Sema::PCC_Template:
1450 case Sema::PCC_MemberTemplate:
Douglas Gregord8e8a582010-05-25 21:41:55 +00001451 if (SemaRef.getLangOptions().CPlusPlus && Results.includeCodePatterns()) {
Douglas Gregor01dfea02010-01-10 23:08:15 +00001452 // template < parameters >
Douglas Gregor218937c2011-02-01 19:23:04 +00001453 Builder.AddTypedTextChunk("template");
1454 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1455 Builder.AddPlaceholderChunk("parameters");
1456 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1457 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001458 }
1459
Douglas Gregorbca403c2010-01-13 23:51:12 +00001460 AddStorageSpecifiers(CCC, SemaRef.getLangOptions(), Results);
1461 AddFunctionSpecifiers(CCC, SemaRef.getLangOptions(), Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001462 break;
1463
John McCallf312b1e2010-08-26 23:41:50 +00001464 case Sema::PCC_ObjCInterface:
Douglas Gregorbca403c2010-01-13 23:51:12 +00001465 AddObjCInterfaceResults(SemaRef.getLangOptions(), Results, true);
1466 AddStorageSpecifiers(CCC, SemaRef.getLangOptions(), Results);
1467 AddFunctionSpecifiers(CCC, SemaRef.getLangOptions(), Results);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001468 break;
1469
John McCallf312b1e2010-08-26 23:41:50 +00001470 case Sema::PCC_ObjCImplementation:
Douglas Gregorbca403c2010-01-13 23:51:12 +00001471 AddObjCImplementationResults(SemaRef.getLangOptions(), Results, true);
1472 AddStorageSpecifiers(CCC, SemaRef.getLangOptions(), Results);
1473 AddFunctionSpecifiers(CCC, SemaRef.getLangOptions(), Results);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001474 break;
1475
John McCallf312b1e2010-08-26 23:41:50 +00001476 case Sema::PCC_ObjCInstanceVariableList:
Douglas Gregorbca403c2010-01-13 23:51:12 +00001477 AddObjCVisibilityResults(SemaRef.getLangOptions(), Results, true);
Douglas Gregorc38c3e12010-01-13 21:54:15 +00001478 break;
1479
John McCallf312b1e2010-08-26 23:41:50 +00001480 case Sema::PCC_RecoveryInFunction:
1481 case Sema::PCC_Statement: {
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001482 AddTypedefResult(Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001483
Douglas Gregord8e8a582010-05-25 21:41:55 +00001484 if (SemaRef.getLangOptions().CPlusPlus && Results.includeCodePatterns()) {
Douglas Gregor218937c2011-02-01 19:23:04 +00001485 Builder.AddTypedTextChunk("try");
1486 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1487 Builder.AddPlaceholderChunk("statements");
1488 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1489 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1490 Builder.AddTextChunk("catch");
1491 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1492 Builder.AddPlaceholderChunk("declaration");
1493 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1494 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1495 Builder.AddPlaceholderChunk("statements");
1496 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1497 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1498 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001499 }
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001500 if (SemaRef.getLangOptions().ObjC1)
Douglas Gregorbca403c2010-01-13 23:51:12 +00001501 AddObjCStatementResults(Results, true);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001502
Douglas Gregord8e8a582010-05-25 21:41:55 +00001503 if (Results.includeCodePatterns()) {
1504 // if (condition) { statements }
Douglas Gregor218937c2011-02-01 19:23:04 +00001505 Builder.AddTypedTextChunk("if");
1506 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregord8e8a582010-05-25 21:41:55 +00001507 if (SemaRef.getLangOptions().CPlusPlus)
Douglas Gregor218937c2011-02-01 19:23:04 +00001508 Builder.AddPlaceholderChunk("condition");
Douglas Gregord8e8a582010-05-25 21:41:55 +00001509 else
Douglas Gregor218937c2011-02-01 19:23:04 +00001510 Builder.AddPlaceholderChunk("expression");
1511 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1512 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1513 Builder.AddPlaceholderChunk("statements");
1514 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1515 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1516 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001517
Douglas Gregord8e8a582010-05-25 21:41:55 +00001518 // switch (condition) { }
Douglas Gregor218937c2011-02-01 19:23:04 +00001519 Builder.AddTypedTextChunk("switch");
1520 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregord8e8a582010-05-25 21:41:55 +00001521 if (SemaRef.getLangOptions().CPlusPlus)
Douglas Gregor218937c2011-02-01 19:23:04 +00001522 Builder.AddPlaceholderChunk("condition");
Douglas Gregord8e8a582010-05-25 21:41:55 +00001523 else
Douglas Gregor218937c2011-02-01 19:23:04 +00001524 Builder.AddPlaceholderChunk("expression");
1525 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1526 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1527 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1528 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1529 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregord8e8a582010-05-25 21:41:55 +00001530 }
1531
Douglas Gregor01dfea02010-01-10 23:08:15 +00001532 // Switch-specific statements.
John McCall781472f2010-08-25 08:40:02 +00001533 if (!SemaRef.getCurFunction()->SwitchStack.empty()) {
Douglas Gregor01dfea02010-01-10 23:08:15 +00001534 // case expression:
Douglas Gregor218937c2011-02-01 19:23:04 +00001535 Builder.AddTypedTextChunk("case");
1536 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1537 Builder.AddPlaceholderChunk("expression");
1538 Builder.AddChunk(CodeCompletionString::CK_Colon);
1539 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001540
1541 // default:
Douglas Gregor218937c2011-02-01 19:23:04 +00001542 Builder.AddTypedTextChunk("default");
1543 Builder.AddChunk(CodeCompletionString::CK_Colon);
1544 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001545 }
1546
Douglas Gregord8e8a582010-05-25 21:41:55 +00001547 if (Results.includeCodePatterns()) {
1548 /// while (condition) { statements }
Douglas Gregor218937c2011-02-01 19:23:04 +00001549 Builder.AddTypedTextChunk("while");
1550 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregord8e8a582010-05-25 21:41:55 +00001551 if (SemaRef.getLangOptions().CPlusPlus)
Douglas Gregor218937c2011-02-01 19:23:04 +00001552 Builder.AddPlaceholderChunk("condition");
Douglas Gregord8e8a582010-05-25 21:41:55 +00001553 else
Douglas Gregor218937c2011-02-01 19:23:04 +00001554 Builder.AddPlaceholderChunk("expression");
1555 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1556 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1557 Builder.AddPlaceholderChunk("statements");
1558 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1559 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1560 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregord8e8a582010-05-25 21:41:55 +00001561
1562 // do { statements } while ( expression );
Douglas Gregor218937c2011-02-01 19:23:04 +00001563 Builder.AddTypedTextChunk("do");
1564 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1565 Builder.AddPlaceholderChunk("statements");
1566 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1567 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1568 Builder.AddTextChunk("while");
1569 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1570 Builder.AddPlaceholderChunk("expression");
1571 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1572 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001573
Douglas Gregord8e8a582010-05-25 21:41:55 +00001574 // for ( for-init-statement ; condition ; expression ) { statements }
Douglas Gregor218937c2011-02-01 19:23:04 +00001575 Builder.AddTypedTextChunk("for");
1576 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregord8e8a582010-05-25 21:41:55 +00001577 if (SemaRef.getLangOptions().CPlusPlus || SemaRef.getLangOptions().C99)
Douglas Gregor218937c2011-02-01 19:23:04 +00001578 Builder.AddPlaceholderChunk("init-statement");
Douglas Gregord8e8a582010-05-25 21:41:55 +00001579 else
Douglas Gregor218937c2011-02-01 19:23:04 +00001580 Builder.AddPlaceholderChunk("init-expression");
1581 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
1582 Builder.AddPlaceholderChunk("condition");
1583 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
1584 Builder.AddPlaceholderChunk("inc-expression");
1585 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1586 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1587 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1588 Builder.AddPlaceholderChunk("statements");
1589 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1590 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1591 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregord8e8a582010-05-25 21:41:55 +00001592 }
Douglas Gregor01dfea02010-01-10 23:08:15 +00001593
1594 if (S->getContinueParent()) {
1595 // continue ;
Douglas Gregor218937c2011-02-01 19:23:04 +00001596 Builder.AddTypedTextChunk("continue");
1597 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001598 }
1599
1600 if (S->getBreakParent()) {
1601 // break ;
Douglas Gregor218937c2011-02-01 19:23:04 +00001602 Builder.AddTypedTextChunk("break");
1603 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001604 }
1605
1606 // "return expression ;" or "return ;", depending on whether we
1607 // know the function is void or not.
1608 bool isVoid = false;
1609 if (FunctionDecl *Function = dyn_cast<FunctionDecl>(SemaRef.CurContext))
1610 isVoid = Function->getResultType()->isVoidType();
1611 else if (ObjCMethodDecl *Method
1612 = dyn_cast<ObjCMethodDecl>(SemaRef.CurContext))
1613 isVoid = Method->getResultType()->isVoidType();
Douglas Gregor9ea9bdb2010-03-01 23:15:13 +00001614 else if (SemaRef.getCurBlock() &&
1615 !SemaRef.getCurBlock()->ReturnType.isNull())
1616 isVoid = SemaRef.getCurBlock()->ReturnType->isVoidType();
Douglas Gregor218937c2011-02-01 19:23:04 +00001617 Builder.AddTypedTextChunk("return");
Douglas Gregor93298002010-02-18 04:06:48 +00001618 if (!isVoid) {
Douglas Gregor218937c2011-02-01 19:23:04 +00001619 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1620 Builder.AddPlaceholderChunk("expression");
Douglas Gregor93298002010-02-18 04:06:48 +00001621 }
Douglas Gregor218937c2011-02-01 19:23:04 +00001622 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001623
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001624 // goto identifier ;
Douglas Gregor218937c2011-02-01 19:23:04 +00001625 Builder.AddTypedTextChunk("goto");
1626 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1627 Builder.AddPlaceholderChunk("label");
1628 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001629
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001630 // Using directives
Douglas Gregor218937c2011-02-01 19:23:04 +00001631 Builder.AddTypedTextChunk("using");
1632 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1633 Builder.AddTextChunk("namespace");
1634 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1635 Builder.AddPlaceholderChunk("identifier");
1636 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001637 }
1638
1639 // Fall through (for statement expressions).
John McCallf312b1e2010-08-26 23:41:50 +00001640 case Sema::PCC_ForInit:
1641 case Sema::PCC_Condition:
Douglas Gregorbca403c2010-01-13 23:51:12 +00001642 AddStorageSpecifiers(CCC, SemaRef.getLangOptions(), Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001643 // Fall through: conditions and statements can have expressions.
1644
Douglas Gregor02688102010-09-14 23:59:36 +00001645 case Sema::PCC_ParenthesizedExpression:
John McCallf312b1e2010-08-26 23:41:50 +00001646 case Sema::PCC_Expression: {
Douglas Gregor01dfea02010-01-10 23:08:15 +00001647 if (SemaRef.getLangOptions().CPlusPlus) {
1648 // 'this', if we're in a non-static member function.
1649 if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(SemaRef.CurContext))
1650 if (!Method->isStatic())
Douglas Gregora4477812010-01-14 16:01:26 +00001651 Results.AddResult(Result("this"));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001652
1653 // true, false
Douglas Gregora4477812010-01-14 16:01:26 +00001654 Results.AddResult(Result("true"));
1655 Results.AddResult(Result("false"));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001656
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001657 // dynamic_cast < type-id > ( expression )
Douglas Gregor218937c2011-02-01 19:23:04 +00001658 Builder.AddTypedTextChunk("dynamic_cast");
1659 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1660 Builder.AddPlaceholderChunk("type");
1661 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1662 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1663 Builder.AddPlaceholderChunk("expression");
1664 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1665 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001666
1667 // static_cast < type-id > ( expression )
Douglas Gregor218937c2011-02-01 19:23:04 +00001668 Builder.AddTypedTextChunk("static_cast");
1669 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1670 Builder.AddPlaceholderChunk("type");
1671 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1672 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1673 Builder.AddPlaceholderChunk("expression");
1674 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1675 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001676
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001677 // reinterpret_cast < type-id > ( expression )
Douglas Gregor218937c2011-02-01 19:23:04 +00001678 Builder.AddTypedTextChunk("reinterpret_cast");
1679 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1680 Builder.AddPlaceholderChunk("type");
1681 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1682 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1683 Builder.AddPlaceholderChunk("expression");
1684 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1685 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001686
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001687 // const_cast < type-id > ( expression )
Douglas Gregor218937c2011-02-01 19:23:04 +00001688 Builder.AddTypedTextChunk("const_cast");
1689 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1690 Builder.AddPlaceholderChunk("type");
1691 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1692 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1693 Builder.AddPlaceholderChunk("expression");
1694 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1695 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001696
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001697 // typeid ( expression-or-type )
Douglas Gregor218937c2011-02-01 19:23:04 +00001698 Builder.AddTypedTextChunk("typeid");
1699 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1700 Builder.AddPlaceholderChunk("expression-or-type");
1701 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1702 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001703
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001704 // new T ( ... )
Douglas Gregor218937c2011-02-01 19:23:04 +00001705 Builder.AddTypedTextChunk("new");
1706 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1707 Builder.AddPlaceholderChunk("type");
1708 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1709 Builder.AddPlaceholderChunk("expressions");
1710 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1711 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001712
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001713 // new T [ ] ( ... )
Douglas Gregor218937c2011-02-01 19:23:04 +00001714 Builder.AddTypedTextChunk("new");
1715 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1716 Builder.AddPlaceholderChunk("type");
1717 Builder.AddChunk(CodeCompletionString::CK_LeftBracket);
1718 Builder.AddPlaceholderChunk("size");
1719 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
1720 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1721 Builder.AddPlaceholderChunk("expressions");
1722 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1723 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001724
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001725 // delete expression
Douglas Gregor218937c2011-02-01 19:23:04 +00001726 Builder.AddTypedTextChunk("delete");
1727 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1728 Builder.AddPlaceholderChunk("expression");
1729 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001730
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001731 // delete [] expression
Douglas Gregor218937c2011-02-01 19:23:04 +00001732 Builder.AddTypedTextChunk("delete");
1733 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1734 Builder.AddChunk(CodeCompletionString::CK_LeftBracket);
1735 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
1736 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1737 Builder.AddPlaceholderChunk("expression");
1738 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001739
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001740 // throw expression
Douglas Gregor218937c2011-02-01 19:23:04 +00001741 Builder.AddTypedTextChunk("throw");
1742 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1743 Builder.AddPlaceholderChunk("expression");
1744 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor12e13132010-05-26 22:00:08 +00001745
1746 // FIXME: Rethrow?
Douglas Gregor01dfea02010-01-10 23:08:15 +00001747 }
1748
1749 if (SemaRef.getLangOptions().ObjC1) {
1750 // Add "super", if we're in an Objective-C class with a superclass.
Ted Kremenek681e2562010-05-31 21:43:10 +00001751 if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl()) {
1752 // The interface can be NULL.
1753 if (ObjCInterfaceDecl *ID = Method->getClassInterface())
1754 if (ID->getSuperClass())
1755 Results.AddResult(Result("super"));
1756 }
1757
Douglas Gregorbca403c2010-01-13 23:51:12 +00001758 AddObjCExpressionResults(Results, true);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001759 }
1760
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001761 // sizeof expression
Douglas Gregor218937c2011-02-01 19:23:04 +00001762 Builder.AddTypedTextChunk("sizeof");
1763 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1764 Builder.AddPlaceholderChunk("expression-or-type");
1765 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1766 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001767 break;
1768 }
Douglas Gregord32b0222010-08-24 01:06:58 +00001769
John McCallf312b1e2010-08-26 23:41:50 +00001770 case Sema::PCC_Type:
Douglas Gregord32b0222010-08-24 01:06:58 +00001771 break;
Douglas Gregor01dfea02010-01-10 23:08:15 +00001772 }
1773
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001774 if (WantTypesInContext(CCC, SemaRef.getLangOptions()))
1775 AddTypeSpecifierResults(SemaRef.getLangOptions(), Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001776
John McCallf312b1e2010-08-26 23:41:50 +00001777 if (SemaRef.getLangOptions().CPlusPlus && CCC != Sema::PCC_Type)
Douglas Gregora4477812010-01-14 16:01:26 +00001778 Results.AddResult(Result("operator"));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001779}
1780
Douglas Gregor218937c2011-02-01 19:23:04 +00001781/// \brief Copy the given string into the allocator.
1782static const char*
1783CopyString(llvm::BumpPtrAllocator &Allocator, llvm::StringRef Text) {
1784 char *Mem = (char *)Allocator.Allocate(Text.size() + 1, 1);
1785 std::copy(Text.begin(), Text.end(), Mem);
1786 Mem[Text.size()] = 0;
1787 return Mem;
1788}
1789
Douglas Gregora63f6de2011-02-01 21:15:40 +00001790/// \brief Retrieve the string representation of the given type as a string
1791/// that has the appropriate lifetime for code completion.
1792///
1793/// This routine provides a fast path where we provide constant strings for
1794/// common type names.
1795const char *GetCompletionTypeString(QualType T,
1796 ASTContext &Context,
1797 llvm::BumpPtrAllocator &Allocator) {
1798 PrintingPolicy Policy(Context.PrintingPolicy);
1799 Policy.AnonymousTagLocations = false;
1800
1801 if (!T.getLocalQualifiers()) {
1802 // Built-in type names are constant strings.
1803 if (const BuiltinType *BT = dyn_cast<BuiltinType>(T))
1804 return BT->getName(Context.getLangOptions());
1805
1806 // Anonymous tag types are constant strings.
1807 if (const TagType *TagT = dyn_cast<TagType>(T))
1808 if (TagDecl *Tag = TagT->getDecl())
1809 if (!Tag->getIdentifier() && !Tag->getTypedefForAnonDecl()) {
1810 switch (Tag->getTagKind()) {
1811 case TTK_Struct: return "struct <anonymous>";
1812 case TTK_Class: return "class <anonymous>";
1813 case TTK_Union: return "union <anonymous>";
1814 case TTK_Enum: return "enum <anonymous>";
1815 }
1816 }
1817 }
1818
1819 // Slow path: format the type as a string.
1820 std::string Result;
1821 T.getAsStringInternal(Result, Policy);
1822 return CopyString(Allocator, Result);
1823}
1824
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00001825/// \brief If the given declaration has an associated type, add it as a result
1826/// type chunk.
1827static void AddResultTypeChunk(ASTContext &Context,
1828 NamedDecl *ND,
Douglas Gregor218937c2011-02-01 19:23:04 +00001829 CodeCompletionBuilder &Result) {
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00001830 if (!ND)
1831 return;
Douglas Gregor6f942b22010-09-21 16:06:22 +00001832
1833 // Skip constructors and conversion functions, which have their return types
1834 // built into their names.
1835 if (isa<CXXConstructorDecl>(ND) || isa<CXXConversionDecl>(ND))
1836 return;
1837
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00001838 // Determine the type of the declaration (if it has a type).
Douglas Gregor6f942b22010-09-21 16:06:22 +00001839 QualType T;
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00001840 if (FunctionDecl *Function = dyn_cast<FunctionDecl>(ND))
1841 T = Function->getResultType();
1842 else if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND))
1843 T = Method->getResultType();
1844 else if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND))
1845 T = FunTmpl->getTemplatedDecl()->getResultType();
1846 else if (EnumConstantDecl *Enumerator = dyn_cast<EnumConstantDecl>(ND))
1847 T = Context.getTypeDeclType(cast<TypeDecl>(Enumerator->getDeclContext()));
1848 else if (isa<UnresolvedUsingValueDecl>(ND)) {
1849 /* Do nothing: ignore unresolved using declarations*/
1850 } else if (ValueDecl *Value = dyn_cast<ValueDecl>(ND))
1851 T = Value->getType();
1852 else if (ObjCPropertyDecl *Property = dyn_cast<ObjCPropertyDecl>(ND))
1853 T = Property->getType();
1854
1855 if (T.isNull() || Context.hasSameType(T, Context.DependentTy))
1856 return;
1857
Douglas Gregora63f6de2011-02-01 21:15:40 +00001858 Result.AddResultTypeChunk(GetCompletionTypeString(T, Context,
1859 Result.getAllocator()));
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00001860}
1861
Douglas Gregoraaa107a2010-08-23 23:51:41 +00001862static void MaybeAddSentinel(ASTContext &Context, NamedDecl *FunctionOrMethod,
Douglas Gregor218937c2011-02-01 19:23:04 +00001863 CodeCompletionBuilder &Result) {
Douglas Gregoraaa107a2010-08-23 23:51:41 +00001864 if (SentinelAttr *Sentinel = FunctionOrMethod->getAttr<SentinelAttr>())
1865 if (Sentinel->getSentinel() == 0) {
1866 if (Context.getLangOptions().ObjC1 &&
1867 Context.Idents.get("nil").hasMacroDefinition())
Douglas Gregor218937c2011-02-01 19:23:04 +00001868 Result.AddTextChunk(", nil");
Douglas Gregoraaa107a2010-08-23 23:51:41 +00001869 else if (Context.Idents.get("NULL").hasMacroDefinition())
Douglas Gregor218937c2011-02-01 19:23:04 +00001870 Result.AddTextChunk(", NULL");
Douglas Gregoraaa107a2010-08-23 23:51:41 +00001871 else
Douglas Gregor218937c2011-02-01 19:23:04 +00001872 Result.AddTextChunk(", (void*)0");
Douglas Gregoraaa107a2010-08-23 23:51:41 +00001873 }
1874}
1875
Douglas Gregor83482d12010-08-24 16:15:59 +00001876static std::string FormatFunctionParameter(ASTContext &Context,
Douglas Gregoraba48082010-08-29 19:47:46 +00001877 ParmVarDecl *Param,
1878 bool SuppressName = false) {
Douglas Gregor83482d12010-08-24 16:15:59 +00001879 bool ObjCMethodParam = isa<ObjCMethodDecl>(Param->getDeclContext());
1880 if (Param->getType()->isDependentType() ||
1881 !Param->getType()->isBlockPointerType()) {
1882 // The argument for a dependent or non-block parameter is a placeholder
1883 // containing that parameter's type.
1884 std::string Result;
1885
Douglas Gregoraba48082010-08-29 19:47:46 +00001886 if (Param->getIdentifier() && !ObjCMethodParam && !SuppressName)
Douglas Gregor83482d12010-08-24 16:15:59 +00001887 Result = Param->getIdentifier()->getName();
1888
1889 Param->getType().getAsStringInternal(Result,
1890 Context.PrintingPolicy);
1891
1892 if (ObjCMethodParam) {
1893 Result = "(" + Result;
1894 Result += ")";
Douglas Gregoraba48082010-08-29 19:47:46 +00001895 if (Param->getIdentifier() && !SuppressName)
Douglas Gregor83482d12010-08-24 16:15:59 +00001896 Result += Param->getIdentifier()->getName();
1897 }
1898 return Result;
1899 }
1900
1901 // The argument for a block pointer parameter is a block literal with
1902 // the appropriate type.
1903 FunctionProtoTypeLoc *Block = 0;
1904 TypeLoc TL;
1905 if (TypeSourceInfo *TSInfo = Param->getTypeSourceInfo()) {
1906 TL = TSInfo->getTypeLoc().getUnqualifiedLoc();
1907 while (true) {
1908 // Look through typedefs.
1909 if (TypedefTypeLoc *TypedefTL = dyn_cast<TypedefTypeLoc>(&TL)) {
1910 if (TypeSourceInfo *InnerTSInfo
1911 = TypedefTL->getTypedefDecl()->getTypeSourceInfo()) {
1912 TL = InnerTSInfo->getTypeLoc().getUnqualifiedLoc();
1913 continue;
1914 }
1915 }
1916
1917 // Look through qualified types
1918 if (QualifiedTypeLoc *QualifiedTL = dyn_cast<QualifiedTypeLoc>(&TL)) {
1919 TL = QualifiedTL->getUnqualifiedLoc();
1920 continue;
1921 }
1922
1923 // Try to get the function prototype behind the block pointer type,
1924 // then we're done.
1925 if (BlockPointerTypeLoc *BlockPtr
1926 = dyn_cast<BlockPointerTypeLoc>(&TL)) {
Abramo Bagnara723df242010-12-14 22:11:44 +00001927 TL = BlockPtr->getPointeeLoc().IgnoreParens();
Douglas Gregor83482d12010-08-24 16:15:59 +00001928 Block = dyn_cast<FunctionProtoTypeLoc>(&TL);
1929 }
1930 break;
1931 }
1932 }
1933
1934 if (!Block) {
1935 // We were unable to find a FunctionProtoTypeLoc with parameter names
1936 // for the block; just use the parameter type as a placeholder.
1937 std::string Result;
1938 Param->getType().getUnqualifiedType().
1939 getAsStringInternal(Result, Context.PrintingPolicy);
1940
1941 if (ObjCMethodParam) {
1942 Result = "(" + Result;
1943 Result += ")";
1944 if (Param->getIdentifier())
1945 Result += Param->getIdentifier()->getName();
1946 }
1947
1948 return Result;
1949 }
1950
1951 // We have the function prototype behind the block pointer type, as it was
1952 // written in the source.
Douglas Gregor38276252010-09-08 22:47:51 +00001953 std::string Result;
1954 QualType ResultType = Block->getTypePtr()->getResultType();
1955 if (!ResultType->isVoidType())
1956 ResultType.getAsStringInternal(Result, Context.PrintingPolicy);
1957
1958 Result = '^' + Result;
1959 if (Block->getNumArgs() == 0) {
1960 if (Block->getTypePtr()->isVariadic())
1961 Result += "(...)";
Douglas Gregorc2760bc2010-10-02 23:49:58 +00001962 else
1963 Result += "(void)";
Douglas Gregor38276252010-09-08 22:47:51 +00001964 } else {
1965 Result += "(";
1966 for (unsigned I = 0, N = Block->getNumArgs(); I != N; ++I) {
1967 if (I)
1968 Result += ", ";
1969 Result += FormatFunctionParameter(Context, Block->getArg(I));
1970
1971 if (I == N - 1 && Block->getTypePtr()->isVariadic())
1972 Result += ", ...";
1973 }
1974 Result += ")";
Douglas Gregore17794f2010-08-31 05:13:43 +00001975 }
Douglas Gregor38276252010-09-08 22:47:51 +00001976
Douglas Gregorc2760bc2010-10-02 23:49:58 +00001977 if (Param->getIdentifier())
1978 Result += Param->getIdentifier()->getName();
1979
Douglas Gregor83482d12010-08-24 16:15:59 +00001980 return Result;
1981}
1982
Douglas Gregor86d9a522009-09-21 16:56:56 +00001983/// \brief Add function parameter chunks to the given code completion string.
1984static void AddFunctionParameterChunks(ASTContext &Context,
1985 FunctionDecl *Function,
Douglas Gregor218937c2011-02-01 19:23:04 +00001986 CodeCompletionBuilder &Result,
1987 unsigned Start = 0,
1988 bool InOptional = false) {
Douglas Gregor0c8296d2009-11-07 00:00:49 +00001989 typedef CodeCompletionString::Chunk Chunk;
Douglas Gregor218937c2011-02-01 19:23:04 +00001990 bool FirstParameter = true;
Douglas Gregor0c8296d2009-11-07 00:00:49 +00001991
Douglas Gregor218937c2011-02-01 19:23:04 +00001992 for (unsigned P = Start, N = Function->getNumParams(); P != N; ++P) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00001993 ParmVarDecl *Param = Function->getParamDecl(P);
1994
Douglas Gregor218937c2011-02-01 19:23:04 +00001995 if (Param->hasDefaultArg() && !InOptional) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00001996 // When we see an optional default argument, put that argument and
1997 // the remaining default arguments into a new, optional string.
Douglas Gregor218937c2011-02-01 19:23:04 +00001998 CodeCompletionBuilder Opt(Result.getAllocator());
1999 if (!FirstParameter)
2000 Opt.AddChunk(Chunk(CodeCompletionString::CK_Comma));
2001 AddFunctionParameterChunks(Context, Function, Opt, P, true);
2002 Result.AddOptionalChunk(Opt.TakeString());
2003 break;
Douglas Gregor86d9a522009-09-21 16:56:56 +00002004 }
2005
Douglas Gregor218937c2011-02-01 19:23:04 +00002006 if (FirstParameter)
2007 FirstParameter = false;
2008 else
2009 Result.AddChunk(Chunk(CodeCompletionString::CK_Comma));
2010
2011 InOptional = false;
Douglas Gregor86d9a522009-09-21 16:56:56 +00002012
2013 // Format the placeholder string.
Douglas Gregor83482d12010-08-24 16:15:59 +00002014 std::string PlaceholderStr = FormatFunctionParameter(Context, Param);
2015
Douglas Gregore17794f2010-08-31 05:13:43 +00002016 if (Function->isVariadic() && P == N - 1)
2017 PlaceholderStr += ", ...";
2018
Douglas Gregor86d9a522009-09-21 16:56:56 +00002019 // Add the placeholder string.
Douglas Gregor218937c2011-02-01 19:23:04 +00002020 Result.AddPlaceholderChunk(CopyString(Result.getAllocator(),
2021 PlaceholderStr));
Douglas Gregor86d9a522009-09-21 16:56:56 +00002022 }
Douglas Gregorb3d45252009-09-22 21:42:17 +00002023
2024 if (const FunctionProtoType *Proto
2025 = Function->getType()->getAs<FunctionProtoType>())
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002026 if (Proto->isVariadic()) {
Douglas Gregore17794f2010-08-31 05:13:43 +00002027 if (Proto->getNumArgs() == 0)
Douglas Gregor218937c2011-02-01 19:23:04 +00002028 Result.AddPlaceholderChunk("...");
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002029
Douglas Gregor218937c2011-02-01 19:23:04 +00002030 MaybeAddSentinel(Context, Function, Result);
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002031 }
Douglas Gregor86d9a522009-09-21 16:56:56 +00002032}
2033
2034/// \brief Add template parameter chunks to the given code completion string.
2035static void AddTemplateParameterChunks(ASTContext &Context,
2036 TemplateDecl *Template,
Douglas Gregor218937c2011-02-01 19:23:04 +00002037 CodeCompletionBuilder &Result,
2038 unsigned MaxParameters = 0,
2039 unsigned Start = 0,
2040 bool InDefaultArg = false) {
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002041 typedef CodeCompletionString::Chunk Chunk;
Douglas Gregor86d9a522009-09-21 16:56:56 +00002042 bool FirstParameter = true;
2043
2044 TemplateParameterList *Params = Template->getTemplateParameters();
2045 TemplateParameterList::iterator PEnd = Params->end();
2046 if (MaxParameters)
2047 PEnd = Params->begin() + MaxParameters;
Douglas Gregor218937c2011-02-01 19:23:04 +00002048 for (TemplateParameterList::iterator P = Params->begin() + Start;
2049 P != PEnd; ++P) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002050 bool HasDefaultArg = false;
2051 std::string PlaceholderStr;
2052 if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*P)) {
2053 if (TTP->wasDeclaredWithTypename())
2054 PlaceholderStr = "typename";
2055 else
2056 PlaceholderStr = "class";
2057
2058 if (TTP->getIdentifier()) {
2059 PlaceholderStr += ' ';
2060 PlaceholderStr += TTP->getIdentifier()->getName();
2061 }
2062
2063 HasDefaultArg = TTP->hasDefaultArgument();
2064 } else if (NonTypeTemplateParmDecl *NTTP
Douglas Gregor218937c2011-02-01 19:23:04 +00002065 = dyn_cast<NonTypeTemplateParmDecl>(*P)) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002066 if (NTTP->getIdentifier())
2067 PlaceholderStr = NTTP->getIdentifier()->getName();
2068 NTTP->getType().getAsStringInternal(PlaceholderStr,
2069 Context.PrintingPolicy);
2070 HasDefaultArg = NTTP->hasDefaultArgument();
2071 } else {
2072 assert(isa<TemplateTemplateParmDecl>(*P));
2073 TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*P);
2074
2075 // Since putting the template argument list into the placeholder would
2076 // be very, very long, we just use an abbreviation.
2077 PlaceholderStr = "template<...> class";
2078 if (TTP->getIdentifier()) {
2079 PlaceholderStr += ' ';
2080 PlaceholderStr += TTP->getIdentifier()->getName();
2081 }
2082
2083 HasDefaultArg = TTP->hasDefaultArgument();
2084 }
2085
Douglas Gregor218937c2011-02-01 19:23:04 +00002086 if (HasDefaultArg && !InDefaultArg) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002087 // When we see an optional default argument, put that argument and
2088 // the remaining default arguments into a new, optional string.
Douglas Gregor218937c2011-02-01 19:23:04 +00002089 CodeCompletionBuilder Opt(Result.getAllocator());
2090 if (!FirstParameter)
2091 Opt.AddChunk(Chunk(CodeCompletionString::CK_Comma));
2092 AddTemplateParameterChunks(Context, Template, Opt, MaxParameters,
2093 P - Params->begin(), true);
2094 Result.AddOptionalChunk(Opt.TakeString());
2095 break;
Douglas Gregor86d9a522009-09-21 16:56:56 +00002096 }
2097
Douglas Gregor218937c2011-02-01 19:23:04 +00002098 InDefaultArg = false;
2099
Douglas Gregor86d9a522009-09-21 16:56:56 +00002100 if (FirstParameter)
2101 FirstParameter = false;
2102 else
Douglas Gregor218937c2011-02-01 19:23:04 +00002103 Result.AddChunk(Chunk(CodeCompletionString::CK_Comma));
Douglas Gregor86d9a522009-09-21 16:56:56 +00002104
2105 // Add the placeholder string.
Douglas Gregor218937c2011-02-01 19:23:04 +00002106 Result.AddPlaceholderChunk(CopyString(Result.getAllocator(),
2107 PlaceholderStr));
Douglas Gregor86d9a522009-09-21 16:56:56 +00002108 }
2109}
2110
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00002111/// \brief Add a qualifier to the given code-completion string, if the
2112/// provided nested-name-specifier is non-NULL.
Douglas Gregora61a8792009-12-11 18:44:16 +00002113static void
Douglas Gregor218937c2011-02-01 19:23:04 +00002114AddQualifierToCompletionString(CodeCompletionBuilder &Result,
Douglas Gregora61a8792009-12-11 18:44:16 +00002115 NestedNameSpecifier *Qualifier,
2116 bool QualifierIsInformative,
2117 ASTContext &Context) {
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00002118 if (!Qualifier)
2119 return;
2120
2121 std::string PrintedNNS;
2122 {
2123 llvm::raw_string_ostream OS(PrintedNNS);
2124 Qualifier->print(OS, Context.PrintingPolicy);
2125 }
Douglas Gregor0563c262009-09-22 23:15:58 +00002126 if (QualifierIsInformative)
Douglas Gregor218937c2011-02-01 19:23:04 +00002127 Result.AddInformativeChunk(CopyString(Result.getAllocator(), PrintedNNS));
Douglas Gregor0563c262009-09-22 23:15:58 +00002128 else
Douglas Gregor218937c2011-02-01 19:23:04 +00002129 Result.AddTextChunk(CopyString(Result.getAllocator(), PrintedNNS));
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00002130}
2131
Douglas Gregor218937c2011-02-01 19:23:04 +00002132static void
2133AddFunctionTypeQualsToCompletionString(CodeCompletionBuilder &Result,
2134 FunctionDecl *Function) {
Douglas Gregora61a8792009-12-11 18:44:16 +00002135 const FunctionProtoType *Proto
2136 = Function->getType()->getAs<FunctionProtoType>();
2137 if (!Proto || !Proto->getTypeQuals())
2138 return;
2139
Douglas Gregora63f6de2011-02-01 21:15:40 +00002140 // FIXME: Add ref-qualifier!
2141
2142 // Handle single qualifiers without copying
2143 if (Proto->getTypeQuals() == Qualifiers::Const) {
2144 Result.AddInformativeChunk(" const");
2145 return;
2146 }
2147
2148 if (Proto->getTypeQuals() == Qualifiers::Volatile) {
2149 Result.AddInformativeChunk(" volatile");
2150 return;
2151 }
2152
2153 if (Proto->getTypeQuals() == Qualifiers::Restrict) {
2154 Result.AddInformativeChunk(" restrict");
2155 return;
2156 }
2157
2158 // Handle multiple qualifiers.
Douglas Gregora61a8792009-12-11 18:44:16 +00002159 std::string QualsStr;
2160 if (Proto->getTypeQuals() & Qualifiers::Const)
2161 QualsStr += " const";
2162 if (Proto->getTypeQuals() & Qualifiers::Volatile)
2163 QualsStr += " volatile";
2164 if (Proto->getTypeQuals() & Qualifiers::Restrict)
2165 QualsStr += " restrict";
Douglas Gregor218937c2011-02-01 19:23:04 +00002166 Result.AddInformativeChunk(CopyString(Result.getAllocator(), QualsStr));
Douglas Gregora61a8792009-12-11 18:44:16 +00002167}
2168
Douglas Gregor6f942b22010-09-21 16:06:22 +00002169/// \brief Add the name of the given declaration
2170static void AddTypedNameChunk(ASTContext &Context, NamedDecl *ND,
Douglas Gregor218937c2011-02-01 19:23:04 +00002171 CodeCompletionBuilder &Result) {
Douglas Gregor6f942b22010-09-21 16:06:22 +00002172 typedef CodeCompletionString::Chunk Chunk;
2173
2174 DeclarationName Name = ND->getDeclName();
2175 if (!Name)
2176 return;
2177
2178 switch (Name.getNameKind()) {
Douglas Gregora63f6de2011-02-01 21:15:40 +00002179 case DeclarationName::CXXOperatorName: {
2180 const char *OperatorName = 0;
2181 switch (Name.getCXXOverloadedOperator()) {
2182 case OO_None:
2183 case OO_Conditional:
2184 case NUM_OVERLOADED_OPERATORS:
2185 OperatorName = "operator";
2186 break;
2187
2188#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
2189 case OO_##Name: OperatorName = "operator" Spelling; break;
2190#define OVERLOADED_OPERATOR_MULTI(Name,Spelling,Unary,Binary,MemberOnly)
2191#include "clang/Basic/OperatorKinds.def"
2192
2193 case OO_New: OperatorName = "operator new"; break;
2194 case OO_Delete: OperatorName = "operator delete"; break;
2195 case OO_Array_New: OperatorName = "operator new[]"; break;
2196 case OO_Array_Delete: OperatorName = "operator delete[]"; break;
2197 case OO_Call: OperatorName = "operator()"; break;
2198 case OO_Subscript: OperatorName = "operator[]"; break;
2199 }
2200 Result.AddTypedTextChunk(OperatorName);
2201 break;
2202 }
2203
Douglas Gregor6f942b22010-09-21 16:06:22 +00002204 case DeclarationName::Identifier:
2205 case DeclarationName::CXXConversionFunctionName:
Douglas Gregor6f942b22010-09-21 16:06:22 +00002206 case DeclarationName::CXXDestructorName:
2207 case DeclarationName::CXXLiteralOperatorName:
Douglas Gregor218937c2011-02-01 19:23:04 +00002208 Result.AddTypedTextChunk(CopyString(Result.getAllocator(),
2209 ND->getNameAsString()));
Douglas Gregor6f942b22010-09-21 16:06:22 +00002210 break;
2211
2212 case DeclarationName::CXXUsingDirective:
2213 case DeclarationName::ObjCZeroArgSelector:
2214 case DeclarationName::ObjCOneArgSelector:
2215 case DeclarationName::ObjCMultiArgSelector:
2216 break;
2217
2218 case DeclarationName::CXXConstructorName: {
2219 CXXRecordDecl *Record = 0;
2220 QualType Ty = Name.getCXXNameType();
2221 if (const RecordType *RecordTy = Ty->getAs<RecordType>())
2222 Record = cast<CXXRecordDecl>(RecordTy->getDecl());
2223 else if (const InjectedClassNameType *InjectedTy
2224 = Ty->getAs<InjectedClassNameType>())
2225 Record = InjectedTy->getDecl();
2226 else {
Douglas Gregor218937c2011-02-01 19:23:04 +00002227 Result.AddTypedTextChunk(CopyString(Result.getAllocator(),
2228 ND->getNameAsString()));
Douglas Gregor6f942b22010-09-21 16:06:22 +00002229 break;
2230 }
2231
Douglas Gregor218937c2011-02-01 19:23:04 +00002232 Result.AddTypedTextChunk(CopyString(Result.getAllocator(),
2233 Record->getNameAsString()));
Douglas Gregor6f942b22010-09-21 16:06:22 +00002234 if (ClassTemplateDecl *Template = Record->getDescribedClassTemplate()) {
Douglas Gregor218937c2011-02-01 19:23:04 +00002235 Result.AddChunk(Chunk(CodeCompletionString::CK_LeftAngle));
Douglas Gregor6f942b22010-09-21 16:06:22 +00002236 AddTemplateParameterChunks(Context, Template, Result);
Douglas Gregor218937c2011-02-01 19:23:04 +00002237 Result.AddChunk(Chunk(CodeCompletionString::CK_RightAngle));
Douglas Gregor6f942b22010-09-21 16:06:22 +00002238 }
2239 break;
2240 }
2241 }
2242}
2243
Douglas Gregor86d9a522009-09-21 16:56:56 +00002244/// \brief If possible, create a new code completion string for the given
2245/// result.
2246///
2247/// \returns Either a new, heap-allocated code completion string describing
2248/// how to use this result, or NULL to indicate that the string or name of the
2249/// result is all that is needed.
2250CodeCompletionString *
John McCall0a2c5e22010-08-25 06:19:51 +00002251CodeCompletionResult::CreateCodeCompletionString(Sema &S,
Douglas Gregor218937c2011-02-01 19:23:04 +00002252 llvm::BumpPtrAllocator &Allocator) {
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002253 typedef CodeCompletionString::Chunk Chunk;
Douglas Gregor218937c2011-02-01 19:23:04 +00002254 CodeCompletionBuilder Result(Allocator, Priority, Availability);
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002255
Douglas Gregor218937c2011-02-01 19:23:04 +00002256 if (Kind == RK_Pattern) {
2257 Pattern->Priority = Priority;
2258 Pattern->Availability = Availability;
2259 return Pattern;
2260 }
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002261
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002262 if (Kind == RK_Keyword) {
Douglas Gregor218937c2011-02-01 19:23:04 +00002263 Result.AddTypedTextChunk(Keyword);
2264 return Result.TakeString();
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002265 }
Douglas Gregor86d9a522009-09-21 16:56:56 +00002266
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002267 if (Kind == RK_Macro) {
2268 MacroInfo *MI = S.PP.getMacroInfo(Macro);
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002269 assert(MI && "Not a macro?");
2270
Douglas Gregor218937c2011-02-01 19:23:04 +00002271 Result.AddTypedTextChunk(CopyString(Result.getAllocator(),
2272 Macro->getName()));
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002273
2274 if (!MI->isFunctionLike())
Douglas Gregor218937c2011-02-01 19:23:04 +00002275 return Result.TakeString();
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002276
2277 // Format a function-like macro with placeholders for the arguments.
Douglas Gregor218937c2011-02-01 19:23:04 +00002278 Result.AddChunk(Chunk(CodeCompletionString::CK_LeftParen));
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002279 for (MacroInfo::arg_iterator A = MI->arg_begin(), AEnd = MI->arg_end();
2280 A != AEnd; ++A) {
2281 if (A != MI->arg_begin())
Douglas Gregor218937c2011-02-01 19:23:04 +00002282 Result.AddChunk(Chunk(CodeCompletionString::CK_Comma));
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002283
2284 if (!MI->isVariadic() || A != AEnd - 1) {
2285 // Non-variadic argument.
Douglas Gregor218937c2011-02-01 19:23:04 +00002286 Result.AddPlaceholderChunk(CopyString(Result.getAllocator(),
2287 (*A)->getName()));
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002288 continue;
2289 }
2290
2291 // Variadic argument; cope with the different between GNU and C99
2292 // variadic macros, providing a single placeholder for the rest of the
2293 // arguments.
2294 if ((*A)->isStr("__VA_ARGS__"))
Douglas Gregor218937c2011-02-01 19:23:04 +00002295 Result.AddPlaceholderChunk("...");
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002296 else {
2297 std::string Arg = (*A)->getName();
2298 Arg += "...";
Douglas Gregor218937c2011-02-01 19:23:04 +00002299 Result.AddPlaceholderChunk(CopyString(Result.getAllocator(), Arg));
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002300 }
2301 }
Douglas Gregor218937c2011-02-01 19:23:04 +00002302 Result.AddChunk(Chunk(CodeCompletionString::CK_RightParen));
2303 return Result.TakeString();
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002304 }
2305
Douglas Gregord8e8a582010-05-25 21:41:55 +00002306 assert(Kind == RK_Declaration && "Missed a result kind?");
Douglas Gregor86d9a522009-09-21 16:56:56 +00002307 NamedDecl *ND = Declaration;
2308
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002309 if (StartsNestedNameSpecifier) {
Douglas Gregor218937c2011-02-01 19:23:04 +00002310 Result.AddTypedTextChunk(CopyString(Result.getAllocator(),
2311 ND->getNameAsString()));
2312 Result.AddTextChunk("::");
2313 return Result.TakeString();
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002314 }
2315
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00002316 AddResultTypeChunk(S.Context, ND, Result);
2317
Douglas Gregor86d9a522009-09-21 16:56:56 +00002318 if (FunctionDecl *Function = dyn_cast<FunctionDecl>(ND)) {
Douglas Gregor0563c262009-09-22 23:15:58 +00002319 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
2320 S.Context);
Douglas Gregor6f942b22010-09-21 16:06:22 +00002321 AddTypedNameChunk(S.Context, ND, Result);
Douglas Gregor218937c2011-02-01 19:23:04 +00002322 Result.AddChunk(Chunk(CodeCompletionString::CK_LeftParen));
Douglas Gregor86d9a522009-09-21 16:56:56 +00002323 AddFunctionParameterChunks(S.Context, Function, Result);
Douglas Gregor218937c2011-02-01 19:23:04 +00002324 Result.AddChunk(Chunk(CodeCompletionString::CK_RightParen));
Douglas Gregora61a8792009-12-11 18:44:16 +00002325 AddFunctionTypeQualsToCompletionString(Result, Function);
Douglas Gregor218937c2011-02-01 19:23:04 +00002326 return Result.TakeString();
Douglas Gregor86d9a522009-09-21 16:56:56 +00002327 }
2328
2329 if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND)) {
Douglas Gregor0563c262009-09-22 23:15:58 +00002330 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
2331 S.Context);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002332 FunctionDecl *Function = FunTmpl->getTemplatedDecl();
Douglas Gregor6f942b22010-09-21 16:06:22 +00002333 AddTypedNameChunk(S.Context, Function, Result);
2334
Douglas Gregor86d9a522009-09-21 16:56:56 +00002335 // Figure out which template parameters are deduced (or have default
2336 // arguments).
2337 llvm::SmallVector<bool, 16> Deduced;
2338 S.MarkDeducedTemplateParameters(FunTmpl, Deduced);
2339 unsigned LastDeducibleArgument;
2340 for (LastDeducibleArgument = Deduced.size(); LastDeducibleArgument > 0;
2341 --LastDeducibleArgument) {
2342 if (!Deduced[LastDeducibleArgument - 1]) {
2343 // C++0x: Figure out if the template argument has a default. If so,
2344 // the user doesn't need to type this argument.
2345 // FIXME: We need to abstract template parameters better!
2346 bool HasDefaultArg = false;
2347 NamedDecl *Param = FunTmpl->getTemplateParameters()->getParam(
Douglas Gregor218937c2011-02-01 19:23:04 +00002348 LastDeducibleArgument - 1);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002349 if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param))
2350 HasDefaultArg = TTP->hasDefaultArgument();
2351 else if (NonTypeTemplateParmDecl *NTTP
2352 = dyn_cast<NonTypeTemplateParmDecl>(Param))
2353 HasDefaultArg = NTTP->hasDefaultArgument();
2354 else {
2355 assert(isa<TemplateTemplateParmDecl>(Param));
2356 HasDefaultArg
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002357 = cast<TemplateTemplateParmDecl>(Param)->hasDefaultArgument();
Douglas Gregor86d9a522009-09-21 16:56:56 +00002358 }
2359
2360 if (!HasDefaultArg)
2361 break;
2362 }
2363 }
2364
2365 if (LastDeducibleArgument) {
2366 // Some of the function template arguments cannot be deduced from a
2367 // function call, so we introduce an explicit template argument list
2368 // containing all of the arguments up to the first deducible argument.
Douglas Gregor218937c2011-02-01 19:23:04 +00002369 Result.AddChunk(Chunk(CodeCompletionString::CK_LeftAngle));
Douglas Gregor86d9a522009-09-21 16:56:56 +00002370 AddTemplateParameterChunks(S.Context, FunTmpl, Result,
2371 LastDeducibleArgument);
Douglas Gregor218937c2011-02-01 19:23:04 +00002372 Result.AddChunk(Chunk(CodeCompletionString::CK_RightAngle));
Douglas Gregor86d9a522009-09-21 16:56:56 +00002373 }
2374
2375 // Add the function parameters
Douglas Gregor218937c2011-02-01 19:23:04 +00002376 Result.AddChunk(Chunk(CodeCompletionString::CK_LeftParen));
Douglas Gregor86d9a522009-09-21 16:56:56 +00002377 AddFunctionParameterChunks(S.Context, Function, Result);
Douglas Gregor218937c2011-02-01 19:23:04 +00002378 Result.AddChunk(Chunk(CodeCompletionString::CK_RightParen));
Douglas Gregora61a8792009-12-11 18:44:16 +00002379 AddFunctionTypeQualsToCompletionString(Result, Function);
Douglas Gregor218937c2011-02-01 19:23:04 +00002380 return Result.TakeString();
Douglas Gregor86d9a522009-09-21 16:56:56 +00002381 }
2382
2383 if (TemplateDecl *Template = dyn_cast<TemplateDecl>(ND)) {
Douglas Gregor0563c262009-09-22 23:15:58 +00002384 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
2385 S.Context);
Douglas Gregor218937c2011-02-01 19:23:04 +00002386 Result.AddTypedTextChunk(CopyString(Result.getAllocator(),
2387 Template->getNameAsString()));
2388 Result.AddChunk(Chunk(CodeCompletionString::CK_LeftAngle));
Douglas Gregor86d9a522009-09-21 16:56:56 +00002389 AddTemplateParameterChunks(S.Context, Template, Result);
Douglas Gregor218937c2011-02-01 19:23:04 +00002390 Result.AddChunk(Chunk(CodeCompletionString::CK_RightAngle));
2391 return Result.TakeString();
Douglas Gregor86d9a522009-09-21 16:56:56 +00002392 }
2393
Douglas Gregor9630eb62009-11-17 16:44:22 +00002394 if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND)) {
Douglas Gregor9630eb62009-11-17 16:44:22 +00002395 Selector Sel = Method->getSelector();
2396 if (Sel.isUnarySelector()) {
Douglas Gregor218937c2011-02-01 19:23:04 +00002397 Result.AddTypedTextChunk(CopyString(Result.getAllocator(),
2398 Sel.getIdentifierInfoForSlot(0)->getName()));
2399 return Result.TakeString();
Douglas Gregor9630eb62009-11-17 16:44:22 +00002400 }
2401
Douglas Gregord3c68542009-11-19 01:08:35 +00002402 std::string SelName = Sel.getIdentifierInfoForSlot(0)->getName().str();
2403 SelName += ':';
2404 if (StartParameter == 0)
Douglas Gregor218937c2011-02-01 19:23:04 +00002405 Result.AddTypedTextChunk(CopyString(Result.getAllocator(), SelName));
Douglas Gregord3c68542009-11-19 01:08:35 +00002406 else {
Douglas Gregor218937c2011-02-01 19:23:04 +00002407 Result.AddInformativeChunk(CopyString(Result.getAllocator(), SelName));
Douglas Gregord3c68542009-11-19 01:08:35 +00002408
2409 // If there is only one parameter, and we're past it, add an empty
2410 // typed-text chunk since there is nothing to type.
2411 if (Method->param_size() == 1)
Douglas Gregor218937c2011-02-01 19:23:04 +00002412 Result.AddTypedTextChunk("");
Douglas Gregord3c68542009-11-19 01:08:35 +00002413 }
Douglas Gregor9630eb62009-11-17 16:44:22 +00002414 unsigned Idx = 0;
2415 for (ObjCMethodDecl::param_iterator P = Method->param_begin(),
2416 PEnd = Method->param_end();
2417 P != PEnd; (void)++P, ++Idx) {
2418 if (Idx > 0) {
Douglas Gregord3c68542009-11-19 01:08:35 +00002419 std::string Keyword;
2420 if (Idx > StartParameter)
Douglas Gregor218937c2011-02-01 19:23:04 +00002421 Result.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregor9630eb62009-11-17 16:44:22 +00002422 if (IdentifierInfo *II = Sel.getIdentifierInfoForSlot(Idx))
2423 Keyword += II->getName().str();
2424 Keyword += ":";
Douglas Gregor1f5537a2010-07-08 23:20:03 +00002425 if (Idx < StartParameter || AllParametersAreInformative)
Douglas Gregor218937c2011-02-01 19:23:04 +00002426 Result.AddInformativeChunk(CopyString(Result.getAllocator(),
2427 Keyword));
Douglas Gregorc7b7b7a2010-10-18 21:05:04 +00002428 else
Douglas Gregor218937c2011-02-01 19:23:04 +00002429 Result.AddTypedTextChunk(CopyString(Result.getAllocator(), Keyword));
Douglas Gregor9630eb62009-11-17 16:44:22 +00002430 }
Douglas Gregord3c68542009-11-19 01:08:35 +00002431
2432 // If we're before the starting parameter, skip the placeholder.
2433 if (Idx < StartParameter)
2434 continue;
Douglas Gregor9630eb62009-11-17 16:44:22 +00002435
2436 std::string Arg;
Douglas Gregor83482d12010-08-24 16:15:59 +00002437
2438 if ((*P)->getType()->isBlockPointerType() && !DeclaringEntity)
Douglas Gregoraba48082010-08-29 19:47:46 +00002439 Arg = FormatFunctionParameter(S.Context, *P, true);
Douglas Gregor83482d12010-08-24 16:15:59 +00002440 else {
2441 (*P)->getType().getAsStringInternal(Arg, S.Context.PrintingPolicy);
2442 Arg = "(" + Arg + ")";
2443 if (IdentifierInfo *II = (*P)->getIdentifier())
Douglas Gregoraba48082010-08-29 19:47:46 +00002444 if (DeclaringEntity || AllParametersAreInformative)
2445 Arg += II->getName().str();
Douglas Gregor83482d12010-08-24 16:15:59 +00002446 }
2447
Douglas Gregore17794f2010-08-31 05:13:43 +00002448 if (Method->isVariadic() && (P + 1) == PEnd)
2449 Arg += ", ...";
2450
Douglas Gregor1f5537a2010-07-08 23:20:03 +00002451 if (DeclaringEntity)
Douglas Gregor218937c2011-02-01 19:23:04 +00002452 Result.AddTextChunk(CopyString(Result.getAllocator(), Arg));
Douglas Gregor1f5537a2010-07-08 23:20:03 +00002453 else if (AllParametersAreInformative)
Douglas Gregor218937c2011-02-01 19:23:04 +00002454 Result.AddInformativeChunk(CopyString(Result.getAllocator(), Arg));
Douglas Gregor4ad96852009-11-19 07:41:15 +00002455 else
Douglas Gregor218937c2011-02-01 19:23:04 +00002456 Result.AddPlaceholderChunk(CopyString(Result.getAllocator(), Arg));
Douglas Gregor9630eb62009-11-17 16:44:22 +00002457 }
2458
Douglas Gregor2a17af02009-12-23 00:21:46 +00002459 if (Method->isVariadic()) {
Douglas Gregore17794f2010-08-31 05:13:43 +00002460 if (Method->param_size() == 0) {
2461 if (DeclaringEntity)
Douglas Gregor218937c2011-02-01 19:23:04 +00002462 Result.AddTextChunk(", ...");
Douglas Gregore17794f2010-08-31 05:13:43 +00002463 else if (AllParametersAreInformative)
Douglas Gregor218937c2011-02-01 19:23:04 +00002464 Result.AddInformativeChunk(", ...");
Douglas Gregore17794f2010-08-31 05:13:43 +00002465 else
Douglas Gregor218937c2011-02-01 19:23:04 +00002466 Result.AddPlaceholderChunk(", ...");
Douglas Gregore17794f2010-08-31 05:13:43 +00002467 }
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002468
2469 MaybeAddSentinel(S.Context, Method, Result);
Douglas Gregor2a17af02009-12-23 00:21:46 +00002470 }
2471
Douglas Gregor218937c2011-02-01 19:23:04 +00002472 return Result.TakeString();
Douglas Gregor9630eb62009-11-17 16:44:22 +00002473 }
2474
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002475 if (Qualifier)
Douglas Gregor0563c262009-09-22 23:15:58 +00002476 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
2477 S.Context);
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002478
Douglas Gregor218937c2011-02-01 19:23:04 +00002479 Result.AddTypedTextChunk(CopyString(Result.getAllocator(),
2480 ND->getNameAsString()));
2481 return Result.TakeString();
Douglas Gregor86d9a522009-09-21 16:56:56 +00002482}
2483
Douglas Gregor86d802e2009-09-23 00:34:09 +00002484CodeCompletionString *
2485CodeCompleteConsumer::OverloadCandidate::CreateSignatureString(
2486 unsigned CurrentArg,
Douglas Gregor32be4a52010-10-11 21:37:58 +00002487 Sema &S,
Douglas Gregor218937c2011-02-01 19:23:04 +00002488 llvm::BumpPtrAllocator &Allocator) const {
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002489 typedef CodeCompletionString::Chunk Chunk;
2490
Douglas Gregor218937c2011-02-01 19:23:04 +00002491 // FIXME: Set priority, availability appropriately.
2492 CodeCompletionBuilder Result(Allocator, 1, CXAvailability_Available);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002493 FunctionDecl *FDecl = getFunction();
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00002494 AddResultTypeChunk(S.Context, FDecl, Result);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002495 const FunctionProtoType *Proto
2496 = dyn_cast<FunctionProtoType>(getFunctionType());
2497 if (!FDecl && !Proto) {
2498 // Function without a prototype. Just give the return type and a
2499 // highlighted ellipsis.
2500 const FunctionType *FT = getFunctionType();
Douglas Gregora63f6de2011-02-01 21:15:40 +00002501 Result.AddTextChunk(GetCompletionTypeString(FT->getResultType(),
2502 S.Context,
2503 Result.getAllocator()));
Douglas Gregor218937c2011-02-01 19:23:04 +00002504 Result.AddChunk(Chunk(CodeCompletionString::CK_LeftParen));
2505 Result.AddChunk(Chunk(CodeCompletionString::CK_CurrentParameter, "..."));
2506 Result.AddChunk(Chunk(CodeCompletionString::CK_RightParen));
2507 return Result.TakeString();
Douglas Gregor86d802e2009-09-23 00:34:09 +00002508 }
2509
2510 if (FDecl)
Douglas Gregor218937c2011-02-01 19:23:04 +00002511 Result.AddTextChunk(CopyString(Result.getAllocator(),
2512 FDecl->getNameAsString()));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002513 else
Douglas Gregor218937c2011-02-01 19:23:04 +00002514 Result.AddTextChunk(
2515 CopyString(Result.getAllocator(),
2516 Proto->getResultType().getAsString(S.Context.PrintingPolicy)));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002517
Douglas Gregor218937c2011-02-01 19:23:04 +00002518 Result.AddChunk(Chunk(CodeCompletionString::CK_LeftParen));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002519 unsigned NumParams = FDecl? FDecl->getNumParams() : Proto->getNumArgs();
2520 for (unsigned I = 0; I != NumParams; ++I) {
2521 if (I)
Douglas Gregor218937c2011-02-01 19:23:04 +00002522 Result.AddChunk(Chunk(CodeCompletionString::CK_Comma));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002523
2524 std::string ArgString;
2525 QualType ArgType;
2526
2527 if (FDecl) {
2528 ArgString = FDecl->getParamDecl(I)->getNameAsString();
2529 ArgType = FDecl->getParamDecl(I)->getOriginalType();
2530 } else {
2531 ArgType = Proto->getArgType(I);
2532 }
2533
2534 ArgType.getAsStringInternal(ArgString, S.Context.PrintingPolicy);
2535
2536 if (I == CurrentArg)
Douglas Gregor218937c2011-02-01 19:23:04 +00002537 Result.AddChunk(Chunk(CodeCompletionString::CK_CurrentParameter,
2538 CopyString(Result.getAllocator(), ArgString)));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002539 else
Douglas Gregor218937c2011-02-01 19:23:04 +00002540 Result.AddTextChunk(CopyString(Result.getAllocator(), ArgString));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002541 }
2542
2543 if (Proto && Proto->isVariadic()) {
Douglas Gregor218937c2011-02-01 19:23:04 +00002544 Result.AddChunk(Chunk(CodeCompletionString::CK_Comma));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002545 if (CurrentArg < NumParams)
Douglas Gregor218937c2011-02-01 19:23:04 +00002546 Result.AddTextChunk("...");
Douglas Gregor86d802e2009-09-23 00:34:09 +00002547 else
Douglas Gregor218937c2011-02-01 19:23:04 +00002548 Result.AddChunk(Chunk(CodeCompletionString::CK_CurrentParameter, "..."));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002549 }
Douglas Gregor218937c2011-02-01 19:23:04 +00002550 Result.AddChunk(Chunk(CodeCompletionString::CK_RightParen));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002551
Douglas Gregor218937c2011-02-01 19:23:04 +00002552 return Result.TakeString();
Douglas Gregor86d802e2009-09-23 00:34:09 +00002553}
2554
Douglas Gregor1827e102010-08-16 16:18:59 +00002555unsigned clang::getMacroUsagePriority(llvm::StringRef MacroName,
Douglas Gregorb05496d2010-09-20 21:11:48 +00002556 const LangOptions &LangOpts,
Douglas Gregor1827e102010-08-16 16:18:59 +00002557 bool PreferredTypeIsPointer) {
2558 unsigned Priority = CCP_Macro;
2559
Douglas Gregorb05496d2010-09-20 21:11:48 +00002560 // Treat the "nil", "Nil" and "NULL" macros as null pointer constants.
2561 if (MacroName.equals("nil") || MacroName.equals("NULL") ||
2562 MacroName.equals("Nil")) {
Douglas Gregor1827e102010-08-16 16:18:59 +00002563 Priority = CCP_Constant;
2564 if (PreferredTypeIsPointer)
2565 Priority = Priority / CCF_SimilarTypeMatch;
Douglas Gregorb05496d2010-09-20 21:11:48 +00002566 }
2567 // Treat "YES", "NO", "true", and "false" as constants.
2568 else if (MacroName.equals("YES") || MacroName.equals("NO") ||
2569 MacroName.equals("true") || MacroName.equals("false"))
2570 Priority = CCP_Constant;
2571 // Treat "bool" as a type.
2572 else if (MacroName.equals("bool"))
2573 Priority = CCP_Type + (LangOpts.ObjC1? CCD_bool_in_ObjC : 0);
2574
Douglas Gregor1827e102010-08-16 16:18:59 +00002575
2576 return Priority;
2577}
2578
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002579CXCursorKind clang::getCursorKindForDecl(Decl *D) {
2580 if (!D)
2581 return CXCursor_UnexposedDecl;
2582
2583 switch (D->getKind()) {
2584 case Decl::Enum: return CXCursor_EnumDecl;
2585 case Decl::EnumConstant: return CXCursor_EnumConstantDecl;
2586 case Decl::Field: return CXCursor_FieldDecl;
2587 case Decl::Function:
2588 return CXCursor_FunctionDecl;
2589 case Decl::ObjCCategory: return CXCursor_ObjCCategoryDecl;
2590 case Decl::ObjCCategoryImpl: return CXCursor_ObjCCategoryImplDecl;
2591 case Decl::ObjCClass:
2592 // FIXME
2593 return CXCursor_UnexposedDecl;
2594 case Decl::ObjCForwardProtocol:
2595 // FIXME
2596 return CXCursor_UnexposedDecl;
2597 case Decl::ObjCImplementation: return CXCursor_ObjCImplementationDecl;
2598 case Decl::ObjCInterface: return CXCursor_ObjCInterfaceDecl;
2599 case Decl::ObjCIvar: return CXCursor_ObjCIvarDecl;
2600 case Decl::ObjCMethod:
2601 return cast<ObjCMethodDecl>(D)->isInstanceMethod()
2602 ? CXCursor_ObjCInstanceMethodDecl : CXCursor_ObjCClassMethodDecl;
2603 case Decl::CXXMethod: return CXCursor_CXXMethod;
2604 case Decl::CXXConstructor: return CXCursor_Constructor;
2605 case Decl::CXXDestructor: return CXCursor_Destructor;
2606 case Decl::CXXConversion: return CXCursor_ConversionFunction;
2607 case Decl::ObjCProperty: return CXCursor_ObjCPropertyDecl;
2608 case Decl::ObjCProtocol: return CXCursor_ObjCProtocolDecl;
2609 case Decl::ParmVar: return CXCursor_ParmDecl;
2610 case Decl::Typedef: return CXCursor_TypedefDecl;
2611 case Decl::Var: return CXCursor_VarDecl;
2612 case Decl::Namespace: return CXCursor_Namespace;
2613 case Decl::NamespaceAlias: return CXCursor_NamespaceAlias;
2614 case Decl::TemplateTypeParm: return CXCursor_TemplateTypeParameter;
2615 case Decl::NonTypeTemplateParm:return CXCursor_NonTypeTemplateParameter;
2616 case Decl::TemplateTemplateParm:return CXCursor_TemplateTemplateParameter;
2617 case Decl::FunctionTemplate: return CXCursor_FunctionTemplate;
2618 case Decl::ClassTemplate: return CXCursor_ClassTemplate;
2619 case Decl::ClassTemplatePartialSpecialization:
2620 return CXCursor_ClassTemplatePartialSpecialization;
2621 case Decl::UsingDirective: return CXCursor_UsingDirective;
2622
2623 case Decl::Using:
2624 case Decl::UnresolvedUsingValue:
2625 case Decl::UnresolvedUsingTypename:
2626 return CXCursor_UsingDeclaration;
2627
2628 default:
2629 if (TagDecl *TD = dyn_cast<TagDecl>(D)) {
2630 switch (TD->getTagKind()) {
2631 case TTK_Struct: return CXCursor_StructDecl;
2632 case TTK_Class: return CXCursor_ClassDecl;
2633 case TTK_Union: return CXCursor_UnionDecl;
2634 case TTK_Enum: return CXCursor_EnumDecl;
2635 }
2636 }
2637 }
2638
2639 return CXCursor_UnexposedDecl;
2640}
2641
Douglas Gregor590c7d52010-07-08 20:55:51 +00002642static void AddMacroResults(Preprocessor &PP, ResultBuilder &Results,
2643 bool TargetTypeIsPointer = false) {
John McCall0a2c5e22010-08-25 06:19:51 +00002644 typedef CodeCompletionResult Result;
Douglas Gregor590c7d52010-07-08 20:55:51 +00002645
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002646 Results.EnterNewScope();
Douglas Gregorc7b7b7a2010-10-18 21:05:04 +00002647
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002648 for (Preprocessor::macro_iterator M = PP.macro_begin(),
2649 MEnd = PP.macro_end();
Douglas Gregor590c7d52010-07-08 20:55:51 +00002650 M != MEnd; ++M) {
Douglas Gregor1827e102010-08-16 16:18:59 +00002651 Results.AddResult(Result(M->first,
2652 getMacroUsagePriority(M->first->getName(),
Douglas Gregorb05496d2010-09-20 21:11:48 +00002653 PP.getLangOptions(),
Douglas Gregor1827e102010-08-16 16:18:59 +00002654 TargetTypeIsPointer)));
Douglas Gregor590c7d52010-07-08 20:55:51 +00002655 }
Douglas Gregorc7b7b7a2010-10-18 21:05:04 +00002656
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002657 Results.ExitScope();
Douglas Gregorc7b7b7a2010-10-18 21:05:04 +00002658
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002659}
2660
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00002661static void AddPrettyFunctionResults(const LangOptions &LangOpts,
2662 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00002663 typedef CodeCompletionResult Result;
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00002664
2665 Results.EnterNewScope();
Douglas Gregorc7b7b7a2010-10-18 21:05:04 +00002666
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00002667 Results.AddResult(Result("__PRETTY_FUNCTION__", CCP_Constant));
2668 Results.AddResult(Result("__FUNCTION__", CCP_Constant));
2669 if (LangOpts.C99 || LangOpts.CPlusPlus0x)
2670 Results.AddResult(Result("__func__", CCP_Constant));
2671 Results.ExitScope();
2672}
2673
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00002674static void HandleCodeCompleteResults(Sema *S,
2675 CodeCompleteConsumer *CodeCompleter,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002676 CodeCompletionContext Context,
John McCall0a2c5e22010-08-25 06:19:51 +00002677 CodeCompletionResult *Results,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002678 unsigned NumResults) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002679 if (CodeCompleter)
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002680 CodeCompleter->ProcessCodeCompleteResults(*S, Context, Results, NumResults);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002681}
2682
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002683static enum CodeCompletionContext::Kind mapCodeCompletionContext(Sema &S,
2684 Sema::ParserCompletionContext PCC) {
2685 switch (PCC) {
John McCallf312b1e2010-08-26 23:41:50 +00002686 case Sema::PCC_Namespace:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002687 return CodeCompletionContext::CCC_TopLevel;
2688
John McCallf312b1e2010-08-26 23:41:50 +00002689 case Sema::PCC_Class:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002690 return CodeCompletionContext::CCC_ClassStructUnion;
2691
John McCallf312b1e2010-08-26 23:41:50 +00002692 case Sema::PCC_ObjCInterface:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002693 return CodeCompletionContext::CCC_ObjCInterface;
2694
John McCallf312b1e2010-08-26 23:41:50 +00002695 case Sema::PCC_ObjCImplementation:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002696 return CodeCompletionContext::CCC_ObjCImplementation;
2697
John McCallf312b1e2010-08-26 23:41:50 +00002698 case Sema::PCC_ObjCInstanceVariableList:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002699 return CodeCompletionContext::CCC_ObjCIvarList;
2700
John McCallf312b1e2010-08-26 23:41:50 +00002701 case Sema::PCC_Template:
2702 case Sema::PCC_MemberTemplate:
Douglas Gregor52779fb2010-09-23 23:01:17 +00002703 if (S.CurContext->isFileContext())
2704 return CodeCompletionContext::CCC_TopLevel;
2705 else if (S.CurContext->isRecord())
2706 return CodeCompletionContext::CCC_ClassStructUnion;
2707 else
2708 return CodeCompletionContext::CCC_Other;
2709
John McCallf312b1e2010-08-26 23:41:50 +00002710 case Sema::PCC_RecoveryInFunction:
Douglas Gregor52779fb2010-09-23 23:01:17 +00002711 return CodeCompletionContext::CCC_Recovery;
Douglas Gregora5450a02010-10-18 22:01:46 +00002712
John McCallf312b1e2010-08-26 23:41:50 +00002713 case Sema::PCC_ForInit:
Douglas Gregora5450a02010-10-18 22:01:46 +00002714 if (S.getLangOptions().CPlusPlus || S.getLangOptions().C99 ||
2715 S.getLangOptions().ObjC1)
2716 return CodeCompletionContext::CCC_ParenthesizedExpression;
2717 else
2718 return CodeCompletionContext::CCC_Expression;
2719
2720 case Sema::PCC_Expression:
John McCallf312b1e2010-08-26 23:41:50 +00002721 case Sema::PCC_Condition:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002722 return CodeCompletionContext::CCC_Expression;
2723
John McCallf312b1e2010-08-26 23:41:50 +00002724 case Sema::PCC_Statement:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002725 return CodeCompletionContext::CCC_Statement;
Douglas Gregor72db1082010-08-24 01:11:00 +00002726
John McCallf312b1e2010-08-26 23:41:50 +00002727 case Sema::PCC_Type:
Douglas Gregor72db1082010-08-24 01:11:00 +00002728 return CodeCompletionContext::CCC_Type;
Douglas Gregor02688102010-09-14 23:59:36 +00002729
2730 case Sema::PCC_ParenthesizedExpression:
2731 return CodeCompletionContext::CCC_ParenthesizedExpression;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002732 }
2733
2734 return CodeCompletionContext::CCC_Other;
2735}
2736
Douglas Gregorf6961522010-08-27 21:18:54 +00002737/// \brief If we're in a C++ virtual member function, add completion results
2738/// that invoke the functions we override, since it's common to invoke the
2739/// overridden function as well as adding new functionality.
2740///
2741/// \param S The semantic analysis object for which we are generating results.
2742///
2743/// \param InContext This context in which the nested-name-specifier preceding
2744/// the code-completion point
2745static void MaybeAddOverrideCalls(Sema &S, DeclContext *InContext,
2746 ResultBuilder &Results) {
2747 // Look through blocks.
2748 DeclContext *CurContext = S.CurContext;
2749 while (isa<BlockDecl>(CurContext))
2750 CurContext = CurContext->getParent();
2751
2752
2753 CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(CurContext);
2754 if (!Method || !Method->isVirtual())
2755 return;
2756
2757 // We need to have names for all of the parameters, if we're going to
2758 // generate a forwarding call.
2759 for (CXXMethodDecl::param_iterator P = Method->param_begin(),
2760 PEnd = Method->param_end();
2761 P != PEnd;
2762 ++P) {
2763 if (!(*P)->getDeclName())
2764 return;
2765 }
2766
2767 for (CXXMethodDecl::method_iterator M = Method->begin_overridden_methods(),
2768 MEnd = Method->end_overridden_methods();
2769 M != MEnd; ++M) {
Douglas Gregor218937c2011-02-01 19:23:04 +00002770 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregorf6961522010-08-27 21:18:54 +00002771 CXXMethodDecl *Overridden = const_cast<CXXMethodDecl *>(*M);
2772 if (Overridden->getCanonicalDecl() == Method->getCanonicalDecl())
2773 continue;
2774
2775 // If we need a nested-name-specifier, add one now.
2776 if (!InContext) {
2777 NestedNameSpecifier *NNS
2778 = getRequiredQualification(S.Context, CurContext,
2779 Overridden->getDeclContext());
2780 if (NNS) {
2781 std::string Str;
2782 llvm::raw_string_ostream OS(Str);
2783 NNS->print(OS, S.Context.PrintingPolicy);
Douglas Gregor218937c2011-02-01 19:23:04 +00002784 Builder.AddTextChunk(CopyString(Results.getAllocator(), OS.str()));
Douglas Gregorf6961522010-08-27 21:18:54 +00002785 }
2786 } else if (!InContext->Equals(Overridden->getDeclContext()))
2787 continue;
2788
Douglas Gregor218937c2011-02-01 19:23:04 +00002789 Builder.AddTypedTextChunk(CopyString(Results.getAllocator(),
2790 Overridden->getNameAsString()));
2791 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregorf6961522010-08-27 21:18:54 +00002792 bool FirstParam = true;
2793 for (CXXMethodDecl::param_iterator P = Method->param_begin(),
2794 PEnd = Method->param_end();
2795 P != PEnd; ++P) {
2796 if (FirstParam)
2797 FirstParam = false;
2798 else
Douglas Gregor218937c2011-02-01 19:23:04 +00002799 Builder.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregorf6961522010-08-27 21:18:54 +00002800
Douglas Gregor218937c2011-02-01 19:23:04 +00002801 Builder.AddPlaceholderChunk(CopyString(Results.getAllocator(),
2802 (*P)->getIdentifier()->getName()));
Douglas Gregorf6961522010-08-27 21:18:54 +00002803 }
Douglas Gregor218937c2011-02-01 19:23:04 +00002804 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2805 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregorf6961522010-08-27 21:18:54 +00002806 CCP_SuperCompletion,
2807 CXCursor_CXXMethod));
2808 Results.Ignore(Overridden);
2809 }
2810}
2811
Douglas Gregor01dfea02010-01-10 23:08:15 +00002812void Sema::CodeCompleteOrdinaryName(Scope *S,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002813 ParserCompletionContext CompletionContext) {
John McCall0a2c5e22010-08-25 06:19:51 +00002814 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00002815 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00002816 mapCodeCompletionContext(*this, CompletionContext));
Douglas Gregorf6961522010-08-27 21:18:54 +00002817 Results.EnterNewScope();
Douglas Gregorcee9ff12010-09-20 22:39:41 +00002818
Douglas Gregor01dfea02010-01-10 23:08:15 +00002819 // Determine how to filter results, e.g., so that the names of
2820 // values (functions, enumerators, function templates, etc.) are
2821 // only allowed where we can have an expression.
2822 switch (CompletionContext) {
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002823 case PCC_Namespace:
2824 case PCC_Class:
2825 case PCC_ObjCInterface:
2826 case PCC_ObjCImplementation:
2827 case PCC_ObjCInstanceVariableList:
2828 case PCC_Template:
2829 case PCC_MemberTemplate:
Douglas Gregor72db1082010-08-24 01:11:00 +00002830 case PCC_Type:
Douglas Gregor01dfea02010-01-10 23:08:15 +00002831 Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
2832 break;
2833
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002834 case PCC_Statement:
Douglas Gregor02688102010-09-14 23:59:36 +00002835 case PCC_ParenthesizedExpression:
Douglas Gregoreb0d0142010-08-24 23:58:17 +00002836 case PCC_Expression:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002837 case PCC_ForInit:
2838 case PCC_Condition:
Douglas Gregor4710e5b2010-05-28 00:49:12 +00002839 if (WantTypesInContext(CompletionContext, getLangOptions()))
2840 Results.setFilter(&ResultBuilder::IsOrdinaryName);
2841 else
2842 Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
Douglas Gregorf6961522010-08-27 21:18:54 +00002843
2844 if (getLangOptions().CPlusPlus)
2845 MaybeAddOverrideCalls(*this, /*InContext=*/0, Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00002846 break;
Douglas Gregordc845342010-05-25 05:58:43 +00002847
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002848 case PCC_RecoveryInFunction:
Douglas Gregordc845342010-05-25 05:58:43 +00002849 // Unfiltered
2850 break;
Douglas Gregor01dfea02010-01-10 23:08:15 +00002851 }
2852
Douglas Gregor3cdee122010-08-26 16:36:48 +00002853 // If we are in a C++ non-static member function, check the qualifiers on
2854 // the member function to filter/prioritize the results list.
2855 if (CXXMethodDecl *CurMethod = dyn_cast<CXXMethodDecl>(CurContext))
2856 if (CurMethod->isInstance())
2857 Results.setObjectTypeQualifiers(
2858 Qualifiers::fromCVRMask(CurMethod->getTypeQualifiers()));
2859
Douglas Gregor1ca6ae82010-01-14 01:09:38 +00002860 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00002861 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
2862 CodeCompleter->includeGlobals());
Douglas Gregor2a7925c2009-12-07 09:54:55 +00002863
Douglas Gregorbca403c2010-01-13 23:51:12 +00002864 AddOrdinaryNameResults(CompletionContext, S, *this, Results);
Douglas Gregor2a7925c2009-12-07 09:54:55 +00002865 Results.ExitScope();
2866
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00002867 switch (CompletionContext) {
Douglas Gregor02688102010-09-14 23:59:36 +00002868 case PCC_ParenthesizedExpression:
Douglas Gregor72db1082010-08-24 01:11:00 +00002869 case PCC_Expression:
2870 case PCC_Statement:
2871 case PCC_RecoveryInFunction:
2872 if (S->getFnParent())
2873 AddPrettyFunctionResults(PP.getLangOptions(), Results);
2874 break;
2875
2876 case PCC_Namespace:
2877 case PCC_Class:
2878 case PCC_ObjCInterface:
2879 case PCC_ObjCImplementation:
2880 case PCC_ObjCInstanceVariableList:
2881 case PCC_Template:
2882 case PCC_MemberTemplate:
2883 case PCC_ForInit:
2884 case PCC_Condition:
2885 case PCC_Type:
2886 break;
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00002887 }
2888
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002889 if (CodeCompleter->includeMacros())
Douglas Gregorbca403c2010-01-13 23:51:12 +00002890 AddMacroResults(PP, Results);
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00002891
Douglas Gregorcee9ff12010-09-20 22:39:41 +00002892 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002893 Results.data(),Results.size());
Douglas Gregor791215b2009-09-21 20:51:25 +00002894}
2895
Douglas Gregorc7b6d882010-09-16 15:14:18 +00002896static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
2897 ParsedType Receiver,
2898 IdentifierInfo **SelIdents,
2899 unsigned NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00002900 bool AtArgumentExpression,
Douglas Gregorc7b6d882010-09-16 15:14:18 +00002901 bool IsSuper,
2902 ResultBuilder &Results);
2903
2904void Sema::CodeCompleteDeclSpec(Scope *S, DeclSpec &DS,
2905 bool AllowNonIdentifiers,
2906 bool AllowNestedNameSpecifiers) {
John McCall0a2c5e22010-08-25 06:19:51 +00002907 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00002908 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00002909 AllowNestedNameSpecifiers
2910 ? CodeCompletionContext::CCC_PotentiallyQualifiedName
2911 : CodeCompletionContext::CCC_Name);
Douglas Gregor2ccccb32010-08-23 18:23:48 +00002912 Results.EnterNewScope();
2913
2914 // Type qualifiers can come after names.
2915 Results.AddResult(Result("const"));
2916 Results.AddResult(Result("volatile"));
2917 if (getLangOptions().C99)
2918 Results.AddResult(Result("restrict"));
2919
2920 if (getLangOptions().CPlusPlus) {
2921 if (AllowNonIdentifiers) {
2922 Results.AddResult(Result("operator"));
2923 }
2924
2925 // Add nested-name-specifiers.
2926 if (AllowNestedNameSpecifiers) {
2927 Results.allowNestedNameSpecifiers();
Douglas Gregor52779fb2010-09-23 23:01:17 +00002928 Results.setFilter(&ResultBuilder::IsImpossibleToSatisfy);
Douglas Gregor2ccccb32010-08-23 18:23:48 +00002929 CodeCompletionDeclConsumer Consumer(Results, CurContext);
2930 LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer,
2931 CodeCompleter->includeGlobals());
Douglas Gregor52779fb2010-09-23 23:01:17 +00002932 Results.setFilter(0);
Douglas Gregor2ccccb32010-08-23 18:23:48 +00002933 }
2934 }
2935 Results.ExitScope();
2936
Douglas Gregorc7b6d882010-09-16 15:14:18 +00002937 // If we're in a context where we might have an expression (rather than a
2938 // declaration), and what we've seen so far is an Objective-C type that could
2939 // be a receiver of a class message, this may be a class message send with
2940 // the initial opening bracket '[' missing. Add appropriate completions.
2941 if (AllowNonIdentifiers && !AllowNestedNameSpecifiers &&
2942 DS.getTypeSpecType() == DeclSpec::TST_typename &&
2943 DS.getStorageClassSpecAsWritten() == DeclSpec::SCS_unspecified &&
2944 !DS.isThreadSpecified() && !DS.isExternInLinkageSpec() &&
2945 DS.getTypeSpecComplex() == DeclSpec::TSC_unspecified &&
2946 DS.getTypeSpecSign() == DeclSpec::TSS_unspecified &&
2947 DS.getTypeQualifiers() == 0 &&
2948 S &&
2949 (S->getFlags() & Scope::DeclScope) != 0 &&
2950 (S->getFlags() & (Scope::ClassScope | Scope::TemplateParamScope |
2951 Scope::FunctionPrototypeScope |
2952 Scope::AtCatchScope)) == 0) {
2953 ParsedType T = DS.getRepAsType();
2954 if (!T.get().isNull() && T.get()->isObjCObjectOrInterfaceType())
Douglas Gregor70c5ac72010-09-20 23:34:21 +00002955 AddClassMessageCompletions(*this, S, T, 0, 0, false, false, Results);
Douglas Gregorc7b6d882010-09-16 15:14:18 +00002956 }
2957
Douglas Gregor4497dd42010-08-24 04:59:56 +00002958 // Note that we intentionally suppress macro results here, since we do not
2959 // encourage using macros to produce the names of entities.
2960
Douglas Gregor52779fb2010-09-23 23:01:17 +00002961 HandleCodeCompleteResults(this, CodeCompleter,
2962 Results.getCompletionContext(),
Douglas Gregor2ccccb32010-08-23 18:23:48 +00002963 Results.data(), Results.size());
2964}
2965
Douglas Gregorfb629412010-08-23 21:17:50 +00002966struct Sema::CodeCompleteExpressionData {
2967 CodeCompleteExpressionData(QualType PreferredType = QualType())
2968 : PreferredType(PreferredType), IntegralConstantExpression(false),
2969 ObjCCollection(false) { }
2970
2971 QualType PreferredType;
2972 bool IntegralConstantExpression;
2973 bool ObjCCollection;
2974 llvm::SmallVector<Decl *, 4> IgnoreDecls;
2975};
2976
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00002977/// \brief Perform code-completion in an expression context when we know what
2978/// type we're looking for.
Douglas Gregorf9578432010-07-28 21:50:18 +00002979///
2980/// \param IntegralConstantExpression Only permit integral constant
2981/// expressions.
Douglas Gregorfb629412010-08-23 21:17:50 +00002982void Sema::CodeCompleteExpression(Scope *S,
2983 const CodeCompleteExpressionData &Data) {
John McCall0a2c5e22010-08-25 06:19:51 +00002984 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00002985 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
2986 CodeCompletionContext::CCC_Expression);
Douglas Gregorfb629412010-08-23 21:17:50 +00002987 if (Data.ObjCCollection)
2988 Results.setFilter(&ResultBuilder::IsObjCCollection);
2989 else if (Data.IntegralConstantExpression)
Douglas Gregorf9578432010-07-28 21:50:18 +00002990 Results.setFilter(&ResultBuilder::IsIntegralConstantValue);
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002991 else if (WantTypesInContext(PCC_Expression, getLangOptions()))
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00002992 Results.setFilter(&ResultBuilder::IsOrdinaryName);
2993 else
2994 Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
Douglas Gregorfb629412010-08-23 21:17:50 +00002995
2996 if (!Data.PreferredType.isNull())
2997 Results.setPreferredType(Data.PreferredType.getNonReferenceType());
2998
2999 // Ignore any declarations that we were told that we don't care about.
3000 for (unsigned I = 0, N = Data.IgnoreDecls.size(); I != N; ++I)
3001 Results.Ignore(Data.IgnoreDecls[I]);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003002
3003 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00003004 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3005 CodeCompleter->includeGlobals());
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003006
3007 Results.EnterNewScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003008 AddOrdinaryNameResults(PCC_Expression, S, *this, Results);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003009 Results.ExitScope();
3010
Douglas Gregor590c7d52010-07-08 20:55:51 +00003011 bool PreferredTypeIsPointer = false;
Douglas Gregorfb629412010-08-23 21:17:50 +00003012 if (!Data.PreferredType.isNull())
3013 PreferredTypeIsPointer = Data.PreferredType->isAnyPointerType()
3014 || Data.PreferredType->isMemberPointerType()
3015 || Data.PreferredType->isBlockPointerType();
Douglas Gregor590c7d52010-07-08 20:55:51 +00003016
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00003017 if (S->getFnParent() &&
3018 !Data.ObjCCollection &&
3019 !Data.IntegralConstantExpression)
3020 AddPrettyFunctionResults(PP.getLangOptions(), Results);
3021
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003022 if (CodeCompleter->includeMacros())
Douglas Gregor590c7d52010-07-08 20:55:51 +00003023 AddMacroResults(PP, Results, PreferredTypeIsPointer);
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003024 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregorfb629412010-08-23 21:17:50 +00003025 CodeCompletionContext(CodeCompletionContext::CCC_Expression,
3026 Data.PreferredType),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003027 Results.data(),Results.size());
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003028}
3029
Douglas Gregorac5fd842010-09-18 01:28:11 +00003030void Sema::CodeCompletePostfixExpression(Scope *S, ExprResult E) {
3031 if (E.isInvalid())
3032 CodeCompleteOrdinaryName(S, PCC_RecoveryInFunction);
3033 else if (getLangOptions().ObjC1)
3034 CodeCompleteObjCInstanceMessage(S, E.take(), 0, 0, false);
Douglas Gregor78edf512010-09-15 16:23:04 +00003035}
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003036
Douglas Gregor73449212010-12-09 23:01:55 +00003037/// \brief The set of properties that have already been added, referenced by
3038/// property name.
3039typedef llvm::SmallPtrSet<IdentifierInfo*, 16> AddedPropertiesSet;
3040
Douglas Gregor95ac6552009-11-18 01:29:26 +00003041static void AddObjCProperties(ObjCContainerDecl *Container,
Douglas Gregor322328b2009-11-18 22:32:06 +00003042 bool AllowCategories,
Douglas Gregor95ac6552009-11-18 01:29:26 +00003043 DeclContext *CurContext,
Douglas Gregor73449212010-12-09 23:01:55 +00003044 AddedPropertiesSet &AddedProperties,
Douglas Gregor95ac6552009-11-18 01:29:26 +00003045 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00003046 typedef CodeCompletionResult Result;
Douglas Gregor95ac6552009-11-18 01:29:26 +00003047
3048 // Add properties in this container.
3049 for (ObjCContainerDecl::prop_iterator P = Container->prop_begin(),
3050 PEnd = Container->prop_end();
3051 P != PEnd;
Douglas Gregor73449212010-12-09 23:01:55 +00003052 ++P) {
3053 if (AddedProperties.insert(P->getIdentifier()))
3054 Results.MaybeAddResult(Result(*P, 0), CurContext);
3055 }
Douglas Gregor95ac6552009-11-18 01:29:26 +00003056
3057 // Add properties in referenced protocols.
3058 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
3059 for (ObjCProtocolDecl::protocol_iterator P = Protocol->protocol_begin(),
3060 PEnd = Protocol->protocol_end();
3061 P != PEnd; ++P)
Douglas Gregor73449212010-12-09 23:01:55 +00003062 AddObjCProperties(*P, AllowCategories, CurContext, AddedProperties,
3063 Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003064 } else if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)){
Douglas Gregor322328b2009-11-18 22:32:06 +00003065 if (AllowCategories) {
3066 // Look through categories.
3067 for (ObjCCategoryDecl *Category = IFace->getCategoryList();
3068 Category; Category = Category->getNextClassCategory())
Douglas Gregor73449212010-12-09 23:01:55 +00003069 AddObjCProperties(Category, AllowCategories, CurContext,
3070 AddedProperties, Results);
Douglas Gregor322328b2009-11-18 22:32:06 +00003071 }
Douglas Gregor95ac6552009-11-18 01:29:26 +00003072
3073 // Look through protocols.
Ted Kremenek53b94412010-09-01 01:21:15 +00003074 for (ObjCInterfaceDecl::all_protocol_iterator
3075 I = IFace->all_referenced_protocol_begin(),
3076 E = IFace->all_referenced_protocol_end(); I != E; ++I)
Douglas Gregor73449212010-12-09 23:01:55 +00003077 AddObjCProperties(*I, AllowCategories, CurContext, AddedProperties,
3078 Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003079
3080 // Look in the superclass.
3081 if (IFace->getSuperClass())
Douglas Gregor322328b2009-11-18 22:32:06 +00003082 AddObjCProperties(IFace->getSuperClass(), AllowCategories, CurContext,
Douglas Gregor73449212010-12-09 23:01:55 +00003083 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003084 } else if (const ObjCCategoryDecl *Category
3085 = dyn_cast<ObjCCategoryDecl>(Container)) {
3086 // Look through protocols.
Ted Kremenek53b94412010-09-01 01:21:15 +00003087 for (ObjCCategoryDecl::protocol_iterator P = Category->protocol_begin(),
3088 PEnd = Category->protocol_end();
Douglas Gregor95ac6552009-11-18 01:29:26 +00003089 P != PEnd; ++P)
Douglas Gregor73449212010-12-09 23:01:55 +00003090 AddObjCProperties(*P, AllowCategories, CurContext, AddedProperties,
3091 Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003092 }
3093}
3094
Douglas Gregor81b747b2009-09-17 21:32:03 +00003095void Sema::CodeCompleteMemberReferenceExpr(Scope *S, ExprTy *BaseE,
3096 SourceLocation OpLoc,
3097 bool IsArrow) {
3098 if (!BaseE || !CodeCompleter)
3099 return;
3100
John McCall0a2c5e22010-08-25 06:19:51 +00003101 typedef CodeCompletionResult Result;
Douglas Gregor86d9a522009-09-21 16:56:56 +00003102
Douglas Gregor81b747b2009-09-17 21:32:03 +00003103 Expr *Base = static_cast<Expr *>(BaseE);
3104 QualType BaseType = Base->getType();
Douglas Gregor86d9a522009-09-21 16:56:56 +00003105
3106 if (IsArrow) {
3107 if (const PointerType *Ptr = BaseType->getAs<PointerType>())
3108 BaseType = Ptr->getPointeeType();
3109 else if (BaseType->isObjCObjectPointerType())
Douglas Gregor3cdee122010-08-26 16:36:48 +00003110 /*Do nothing*/ ;
Douglas Gregor86d9a522009-09-21 16:56:56 +00003111 else
3112 return;
3113 }
3114
Douglas Gregor218937c2011-02-01 19:23:04 +00003115 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00003116 CodeCompletionContext(CodeCompletionContext::CCC_MemberAccess,
3117 BaseType),
3118 &ResultBuilder::IsMember);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003119 Results.EnterNewScope();
3120 if (const RecordType *Record = BaseType->getAs<RecordType>()) {
Douglas Gregor3cdee122010-08-26 16:36:48 +00003121 // Indicate that we are performing a member access, and the cv-qualifiers
3122 // for the base object type.
3123 Results.setObjectTypeQualifiers(BaseType.getQualifiers());
3124
Douglas Gregor95ac6552009-11-18 01:29:26 +00003125 // Access to a C/C++ class, struct, or union.
Douglas Gregor45bcd432010-01-14 03:21:49 +00003126 Results.allowNestedNameSpecifiers();
Douglas Gregor0cc84042010-01-14 15:47:35 +00003127 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00003128 LookupVisibleDecls(Record->getDecl(), LookupMemberName, Consumer,
3129 CodeCompleter->includeGlobals());
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003130
Douglas Gregor95ac6552009-11-18 01:29:26 +00003131 if (getLangOptions().CPlusPlus) {
3132 if (!Results.empty()) {
3133 // The "template" keyword can follow "->" or "." in the grammar.
3134 // However, we only want to suggest the template keyword if something
3135 // is dependent.
3136 bool IsDependent = BaseType->isDependentType();
3137 if (!IsDependent) {
3138 for (Scope *DepScope = S; DepScope; DepScope = DepScope->getParent())
3139 if (DeclContext *Ctx = (DeclContext *)DepScope->getEntity()) {
3140 IsDependent = Ctx->isDependentContext();
3141 break;
3142 }
3143 }
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003144
Douglas Gregor95ac6552009-11-18 01:29:26 +00003145 if (IsDependent)
Douglas Gregora4477812010-01-14 16:01:26 +00003146 Results.AddResult(Result("template"));
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003147 }
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003148 }
Douglas Gregor95ac6552009-11-18 01:29:26 +00003149 } else if (!IsArrow && BaseType->getAsObjCInterfacePointerType()) {
3150 // Objective-C property reference.
Douglas Gregor73449212010-12-09 23:01:55 +00003151 AddedPropertiesSet AddedProperties;
Douglas Gregor95ac6552009-11-18 01:29:26 +00003152
3153 // Add property results based on our interface.
3154 const ObjCObjectPointerType *ObjCPtr
3155 = BaseType->getAsObjCInterfacePointerType();
3156 assert(ObjCPtr && "Non-NULL pointer guaranteed above!");
Douglas Gregor73449212010-12-09 23:01:55 +00003157 AddObjCProperties(ObjCPtr->getInterfaceDecl(), true, CurContext,
3158 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003159
3160 // Add properties from the protocols in a qualified interface.
3161 for (ObjCObjectPointerType::qual_iterator I = ObjCPtr->qual_begin(),
3162 E = ObjCPtr->qual_end();
3163 I != E; ++I)
Douglas Gregor73449212010-12-09 23:01:55 +00003164 AddObjCProperties(*I, true, CurContext, AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003165 } else if ((IsArrow && BaseType->isObjCObjectPointerType()) ||
John McCallc12c5bb2010-05-15 11:32:37 +00003166 (!IsArrow && BaseType->isObjCObjectType())) {
Douglas Gregor95ac6552009-11-18 01:29:26 +00003167 // Objective-C instance variable access.
3168 ObjCInterfaceDecl *Class = 0;
3169 if (const ObjCObjectPointerType *ObjCPtr
3170 = BaseType->getAs<ObjCObjectPointerType>())
3171 Class = ObjCPtr->getInterfaceDecl();
3172 else
John McCallc12c5bb2010-05-15 11:32:37 +00003173 Class = BaseType->getAs<ObjCObjectType>()->getInterface();
Douglas Gregor95ac6552009-11-18 01:29:26 +00003174
3175 // Add all ivars from this class and its superclasses.
Douglas Gregor80f4f4c2010-01-14 16:08:12 +00003176 if (Class) {
3177 CodeCompletionDeclConsumer Consumer(Results, CurContext);
3178 Results.setFilter(&ResultBuilder::IsObjCIvar);
Douglas Gregor8071e422010-08-15 06:18:01 +00003179 LookupVisibleDecls(Class, LookupMemberName, Consumer,
3180 CodeCompleter->includeGlobals());
Douglas Gregor95ac6552009-11-18 01:29:26 +00003181 }
Douglas Gregor86d9a522009-09-21 16:56:56 +00003182 }
Douglas Gregor95ac6552009-11-18 01:29:26 +00003183
3184 // FIXME: How do we cope with isa?
3185
3186 Results.ExitScope();
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003187
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003188 // Hand off the results found for code completion.
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003189 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00003190 Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003191 Results.data(),Results.size());
Douglas Gregor81b747b2009-09-17 21:32:03 +00003192}
3193
Douglas Gregor374929f2009-09-18 15:37:17 +00003194void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) {
3195 if (!CodeCompleter)
3196 return;
3197
John McCall0a2c5e22010-08-25 06:19:51 +00003198 typedef CodeCompletionResult Result;
Douglas Gregor86d9a522009-09-21 16:56:56 +00003199 ResultBuilder::LookupFilter Filter = 0;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003200 enum CodeCompletionContext::Kind ContextKind
3201 = CodeCompletionContext::CCC_Other;
Douglas Gregor374929f2009-09-18 15:37:17 +00003202 switch ((DeclSpec::TST)TagSpec) {
3203 case DeclSpec::TST_enum:
Douglas Gregor86d9a522009-09-21 16:56:56 +00003204 Filter = &ResultBuilder::IsEnum;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003205 ContextKind = CodeCompletionContext::CCC_EnumTag;
Douglas Gregor374929f2009-09-18 15:37:17 +00003206 break;
3207
3208 case DeclSpec::TST_union:
Douglas Gregor86d9a522009-09-21 16:56:56 +00003209 Filter = &ResultBuilder::IsUnion;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003210 ContextKind = CodeCompletionContext::CCC_UnionTag;
Douglas Gregor374929f2009-09-18 15:37:17 +00003211 break;
3212
3213 case DeclSpec::TST_struct:
Douglas Gregor374929f2009-09-18 15:37:17 +00003214 case DeclSpec::TST_class:
Douglas Gregor86d9a522009-09-21 16:56:56 +00003215 Filter = &ResultBuilder::IsClassOrStruct;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003216 ContextKind = CodeCompletionContext::CCC_ClassOrStructTag;
Douglas Gregor374929f2009-09-18 15:37:17 +00003217 break;
3218
3219 default:
3220 assert(false && "Unknown type specifier kind in CodeCompleteTag");
3221 return;
3222 }
Douglas Gregor86d9a522009-09-21 16:56:56 +00003223
Douglas Gregor218937c2011-02-01 19:23:04 +00003224 ResultBuilder Results(*this, CodeCompleter->getAllocator(), ContextKind);
Douglas Gregor5d2fc402010-01-14 03:27:13 +00003225 CodeCompletionDeclConsumer Consumer(Results, CurContext);
John McCall0d6b1642010-04-23 18:46:30 +00003226
3227 // First pass: look for tags.
3228 Results.setFilter(Filter);
Douglas Gregor8071e422010-08-15 06:18:01 +00003229 LookupVisibleDecls(S, LookupTagName, Consumer,
3230 CodeCompleter->includeGlobals());
John McCall0d6b1642010-04-23 18:46:30 +00003231
Douglas Gregor8071e422010-08-15 06:18:01 +00003232 if (CodeCompleter->includeGlobals()) {
3233 // Second pass: look for nested name specifiers.
3234 Results.setFilter(&ResultBuilder::IsNestedNameSpecifier);
3235 LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer);
3236 }
Douglas Gregor86d9a522009-09-21 16:56:56 +00003237
Douglas Gregor52779fb2010-09-23 23:01:17 +00003238 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003239 Results.data(),Results.size());
Douglas Gregor374929f2009-09-18 15:37:17 +00003240}
3241
Douglas Gregor1a480c42010-08-27 17:35:51 +00003242void Sema::CodeCompleteTypeQualifiers(DeclSpec &DS) {
Douglas Gregor218937c2011-02-01 19:23:04 +00003243 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3244 CodeCompletionContext::CCC_TypeQualifiers);
Douglas Gregor1a480c42010-08-27 17:35:51 +00003245 Results.EnterNewScope();
3246 if (!(DS.getTypeQualifiers() & DeclSpec::TQ_const))
3247 Results.AddResult("const");
3248 if (!(DS.getTypeQualifiers() & DeclSpec::TQ_volatile))
3249 Results.AddResult("volatile");
3250 if (getLangOptions().C99 &&
3251 !(DS.getTypeQualifiers() & DeclSpec::TQ_restrict))
3252 Results.AddResult("restrict");
3253 Results.ExitScope();
3254 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00003255 Results.getCompletionContext(),
Douglas Gregor1a480c42010-08-27 17:35:51 +00003256 Results.data(), Results.size());
3257}
3258
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003259void Sema::CodeCompleteCase(Scope *S) {
John McCall781472f2010-08-25 08:40:02 +00003260 if (getCurFunction()->SwitchStack.empty() || !CodeCompleter)
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003261 return;
3262
John McCall781472f2010-08-25 08:40:02 +00003263 SwitchStmt *Switch = getCurFunction()->SwitchStack.back();
Douglas Gregorf9578432010-07-28 21:50:18 +00003264 if (!Switch->getCond()->getType()->isEnumeralType()) {
Douglas Gregorfb629412010-08-23 21:17:50 +00003265 CodeCompleteExpressionData Data(Switch->getCond()->getType());
3266 Data.IntegralConstantExpression = true;
3267 CodeCompleteExpression(S, Data);
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003268 return;
Douglas Gregorf9578432010-07-28 21:50:18 +00003269 }
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003270
3271 // Code-complete the cases of a switch statement over an enumeration type
3272 // by providing the list of
3273 EnumDecl *Enum = Switch->getCond()->getType()->getAs<EnumType>()->getDecl();
3274
3275 // Determine which enumerators we have already seen in the switch statement.
3276 // FIXME: Ideally, we would also be able to look *past* the code-completion
3277 // token, in case we are code-completing in the middle of the switch and not
3278 // at the end. However, we aren't able to do so at the moment.
3279 llvm::SmallPtrSet<EnumConstantDecl *, 8> EnumeratorsSeen;
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00003280 NestedNameSpecifier *Qualifier = 0;
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003281 for (SwitchCase *SC = Switch->getSwitchCaseList(); SC;
3282 SC = SC->getNextSwitchCase()) {
3283 CaseStmt *Case = dyn_cast<CaseStmt>(SC);
3284 if (!Case)
3285 continue;
3286
3287 Expr *CaseVal = Case->getLHS()->IgnoreParenCasts();
3288 if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CaseVal))
3289 if (EnumConstantDecl *Enumerator
3290 = dyn_cast<EnumConstantDecl>(DRE->getDecl())) {
3291 // We look into the AST of the case statement to determine which
3292 // enumerator was named. Alternatively, we could compute the value of
3293 // the integral constant expression, then compare it against the
3294 // values of each enumerator. However, value-based approach would not
3295 // work as well with C++ templates where enumerators declared within a
3296 // template are type- and value-dependent.
3297 EnumeratorsSeen.insert(Enumerator);
3298
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00003299 // If this is a qualified-id, keep track of the nested-name-specifier
3300 // so that we can reproduce it as part of code completion, e.g.,
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003301 //
3302 // switch (TagD.getKind()) {
3303 // case TagDecl::TK_enum:
3304 // break;
3305 // case XXX
3306 //
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00003307 // At the XXX, our completions are TagDecl::TK_union,
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003308 // TagDecl::TK_struct, and TagDecl::TK_class, rather than TK_union,
3309 // TK_struct, and TK_class.
Douglas Gregora2813ce2009-10-23 18:54:35 +00003310 Qualifier = DRE->getQualifier();
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003311 }
3312 }
3313
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00003314 if (getLangOptions().CPlusPlus && !Qualifier && EnumeratorsSeen.empty()) {
3315 // If there are no prior enumerators in C++, check whether we have to
3316 // qualify the names of the enumerators that we suggest, because they
3317 // may not be visible in this scope.
3318 Qualifier = getRequiredQualification(Context, CurContext,
3319 Enum->getDeclContext());
3320
3321 // FIXME: Scoped enums need to start with "EnumDecl" as the context!
3322 }
3323
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003324 // Add any enumerators that have not yet been mentioned.
Douglas Gregor218937c2011-02-01 19:23:04 +00003325 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3326 CodeCompletionContext::CCC_Expression);
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003327 Results.EnterNewScope();
3328 for (EnumDecl::enumerator_iterator E = Enum->enumerator_begin(),
3329 EEnd = Enum->enumerator_end();
3330 E != EEnd; ++E) {
3331 if (EnumeratorsSeen.count(*E))
3332 continue;
3333
John McCall0a2c5e22010-08-25 06:19:51 +00003334 Results.AddResult(CodeCompletionResult(*E, Qualifier),
Douglas Gregor608300b2010-01-14 16:14:35 +00003335 CurContext, 0, false);
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003336 }
3337 Results.ExitScope();
Douglas Gregor2f880e42010-04-06 20:02:15 +00003338
Douglas Gregor0c8296d2009-11-07 00:00:49 +00003339 if (CodeCompleter->includeMacros())
Douglas Gregorbca403c2010-01-13 23:51:12 +00003340 AddMacroResults(PP, Results);
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003341 HandleCodeCompleteResults(this, CodeCompleter,
3342 CodeCompletionContext::CCC_Expression,
3343 Results.data(),Results.size());
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003344}
3345
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003346namespace {
3347 struct IsBetterOverloadCandidate {
3348 Sema &S;
John McCall5769d612010-02-08 23:07:23 +00003349 SourceLocation Loc;
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003350
3351 public:
John McCall5769d612010-02-08 23:07:23 +00003352 explicit IsBetterOverloadCandidate(Sema &S, SourceLocation Loc)
3353 : S(S), Loc(Loc) { }
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003354
3355 bool
3356 operator()(const OverloadCandidate &X, const OverloadCandidate &Y) const {
John McCall120d63c2010-08-24 20:38:10 +00003357 return isBetterOverloadCandidate(S, X, Y, Loc);
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003358 }
3359 };
3360}
3361
Douglas Gregord28dcd72010-05-30 06:10:08 +00003362static bool anyNullArguments(Expr **Args, unsigned NumArgs) {
3363 if (NumArgs && !Args)
3364 return true;
3365
3366 for (unsigned I = 0; I != NumArgs; ++I)
3367 if (!Args[I])
3368 return true;
3369
3370 return false;
3371}
3372
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003373void Sema::CodeCompleteCall(Scope *S, ExprTy *FnIn,
3374 ExprTy **ArgsIn, unsigned NumArgs) {
3375 if (!CodeCompleter)
3376 return;
Douglas Gregoref96eac2009-12-11 19:06:04 +00003377
3378 // When we're code-completing for a call, we fall back to ordinary
3379 // name code-completion whenever we can't produce specific
3380 // results. We may want to revisit this strategy in the future,
3381 // e.g., by merging the two kinds of results.
3382
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003383 Expr *Fn = (Expr *)FnIn;
3384 Expr **Args = (Expr **)ArgsIn;
Douglas Gregoref96eac2009-12-11 19:06:04 +00003385
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003386 // Ignore type-dependent call expressions entirely.
Douglas Gregord28dcd72010-05-30 06:10:08 +00003387 if (!Fn || Fn->isTypeDependent() || anyNullArguments(Args, NumArgs) ||
Douglas Gregoref96eac2009-12-11 19:06:04 +00003388 Expr::hasAnyTypeDependentArguments(Args, NumArgs)) {
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003389 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003390 return;
Douglas Gregoref96eac2009-12-11 19:06:04 +00003391 }
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003392
John McCall3b4294e2009-12-16 12:17:52 +00003393 // Build an overload candidate set based on the functions we find.
John McCall5769d612010-02-08 23:07:23 +00003394 SourceLocation Loc = Fn->getExprLoc();
3395 OverloadCandidateSet CandidateSet(Loc);
John McCall3b4294e2009-12-16 12:17:52 +00003396
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003397 // FIXME: What if we're calling something that isn't a function declaration?
3398 // FIXME: What if we're calling a pseudo-destructor?
3399 // FIXME: What if we're calling a member function?
3400
Douglas Gregorc0265402010-01-21 15:46:19 +00003401 typedef CodeCompleteConsumer::OverloadCandidate ResultCandidate;
3402 llvm::SmallVector<ResultCandidate, 8> Results;
3403
John McCall3b4294e2009-12-16 12:17:52 +00003404 Expr *NakedFn = Fn->IgnoreParenCasts();
3405 if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(NakedFn))
3406 AddOverloadedCallCandidates(ULE, Args, NumArgs, CandidateSet,
3407 /*PartialOverloading=*/ true);
3408 else if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(NakedFn)) {
3409 FunctionDecl *FDecl = dyn_cast<FunctionDecl>(DRE->getDecl());
Douglas Gregorc0265402010-01-21 15:46:19 +00003410 if (FDecl) {
Douglas Gregord28dcd72010-05-30 06:10:08 +00003411 if (!getLangOptions().CPlusPlus ||
3412 !FDecl->getType()->getAs<FunctionProtoType>())
Douglas Gregorc0265402010-01-21 15:46:19 +00003413 Results.push_back(ResultCandidate(FDecl));
3414 else
John McCall86820f52010-01-26 01:37:31 +00003415 // FIXME: access?
John McCall9aa472c2010-03-19 07:35:19 +00003416 AddOverloadCandidate(FDecl, DeclAccessPair::make(FDecl, AS_none),
3417 Args, NumArgs, CandidateSet,
Douglas Gregorc27d6c52010-04-16 17:41:49 +00003418 false, /*PartialOverloading*/true);
Douglas Gregorc0265402010-01-21 15:46:19 +00003419 }
John McCall3b4294e2009-12-16 12:17:52 +00003420 }
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003421
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003422 QualType ParamType;
3423
Douglas Gregorc0265402010-01-21 15:46:19 +00003424 if (!CandidateSet.empty()) {
3425 // Sort the overload candidate set by placing the best overloads first.
3426 std::stable_sort(CandidateSet.begin(), CandidateSet.end(),
John McCall5769d612010-02-08 23:07:23 +00003427 IsBetterOverloadCandidate(*this, Loc));
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003428
Douglas Gregorc0265402010-01-21 15:46:19 +00003429 // Add the remaining viable overload candidates as code-completion reslults.
3430 for (OverloadCandidateSet::iterator Cand = CandidateSet.begin(),
3431 CandEnd = CandidateSet.end();
3432 Cand != CandEnd; ++Cand) {
3433 if (Cand->Viable)
3434 Results.push_back(ResultCandidate(Cand->Function));
3435 }
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003436
3437 // From the viable candidates, try to determine the type of this parameter.
3438 for (unsigned I = 0, N = Results.size(); I != N; ++I) {
3439 if (const FunctionType *FType = Results[I].getFunctionType())
3440 if (const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FType))
3441 if (NumArgs < Proto->getNumArgs()) {
3442 if (ParamType.isNull())
3443 ParamType = Proto->getArgType(NumArgs);
3444 else if (!Context.hasSameUnqualifiedType(
3445 ParamType.getNonReferenceType(),
3446 Proto->getArgType(NumArgs).getNonReferenceType())) {
3447 ParamType = QualType();
3448 break;
3449 }
3450 }
3451 }
3452 } else {
3453 // Try to determine the parameter type from the type of the expression
3454 // being called.
3455 QualType FunctionType = Fn->getType();
3456 if (const PointerType *Ptr = FunctionType->getAs<PointerType>())
3457 FunctionType = Ptr->getPointeeType();
3458 else if (const BlockPointerType *BlockPtr
3459 = FunctionType->getAs<BlockPointerType>())
3460 FunctionType = BlockPtr->getPointeeType();
3461 else if (const MemberPointerType *MemPtr
3462 = FunctionType->getAs<MemberPointerType>())
3463 FunctionType = MemPtr->getPointeeType();
3464
3465 if (const FunctionProtoType *Proto
3466 = FunctionType->getAs<FunctionProtoType>()) {
3467 if (NumArgs < Proto->getNumArgs())
3468 ParamType = Proto->getArgType(NumArgs);
3469 }
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003470 }
Douglas Gregoref96eac2009-12-11 19:06:04 +00003471
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003472 if (ParamType.isNull())
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003473 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003474 else
3475 CodeCompleteExpression(S, ParamType);
3476
Douglas Gregor2e4c7a52010-04-06 20:19:47 +00003477 if (!Results.empty())
Douglas Gregoref96eac2009-12-11 19:06:04 +00003478 CodeCompleter->ProcessOverloadCandidates(*this, NumArgs, Results.data(),
3479 Results.size());
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003480}
3481
John McCalld226f652010-08-21 09:40:31 +00003482void Sema::CodeCompleteInitializer(Scope *S, Decl *D) {
3483 ValueDecl *VD = dyn_cast_or_null<ValueDecl>(D);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003484 if (!VD) {
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003485 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003486 return;
3487 }
3488
3489 CodeCompleteExpression(S, VD->getType());
3490}
3491
3492void Sema::CodeCompleteReturn(Scope *S) {
3493 QualType ResultType;
3494 if (isa<BlockDecl>(CurContext)) {
3495 if (BlockScopeInfo *BSI = getCurBlock())
3496 ResultType = BSI->ReturnType;
3497 } else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(CurContext))
3498 ResultType = Function->getResultType();
3499 else if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(CurContext))
3500 ResultType = Method->getResultType();
3501
3502 if (ResultType.isNull())
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003503 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003504 else
3505 CodeCompleteExpression(S, ResultType);
3506}
3507
3508void Sema::CodeCompleteAssignmentRHS(Scope *S, ExprTy *LHS) {
3509 if (LHS)
3510 CodeCompleteExpression(S, static_cast<Expr *>(LHS)->getType());
3511 else
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003512 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003513}
3514
Jeffrey Yasskin9ab14542010-04-08 16:38:48 +00003515void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS,
Douglas Gregor81b747b2009-09-17 21:32:03 +00003516 bool EnteringContext) {
3517 if (!SS.getScopeRep() || !CodeCompleter)
3518 return;
3519
Douglas Gregor86d9a522009-09-21 16:56:56 +00003520 DeclContext *Ctx = computeDeclContext(SS, EnteringContext);
3521 if (!Ctx)
3522 return;
Douglas Gregord1cd31a2009-12-11 18:28:39 +00003523
3524 // Try to instantiate any non-dependent declaration contexts before
3525 // we look in them.
John McCall77bb1aa2010-05-01 00:40:08 +00003526 if (!isDependentScopeSpecifier(SS) && RequireCompleteDeclContext(SS, Ctx))
Douglas Gregord1cd31a2009-12-11 18:28:39 +00003527 return;
3528
Douglas Gregor218937c2011-02-01 19:23:04 +00003529 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3530 CodeCompletionContext::CCC_Name);
Douglas Gregorf6961522010-08-27 21:18:54 +00003531 Results.EnterNewScope();
Douglas Gregor52779fb2010-09-23 23:01:17 +00003532
Douglas Gregor86d9a522009-09-21 16:56:56 +00003533 // The "template" keyword can follow "::" in the grammar, but only
3534 // put it into the grammar if the nested-name-specifier is dependent.
3535 NestedNameSpecifier *NNS = (NestedNameSpecifier *)SS.getScopeRep();
3536 if (!Results.empty() && NNS->isDependent())
Douglas Gregora4477812010-01-14 16:01:26 +00003537 Results.AddResult("template");
Douglas Gregorf6961522010-08-27 21:18:54 +00003538
3539 // Add calls to overridden virtual functions, if there are any.
3540 //
3541 // FIXME: This isn't wonderful, because we don't know whether we're actually
3542 // in a context that permits expressions. This is a general issue with
3543 // qualified-id completions.
3544 if (!EnteringContext)
3545 MaybeAddOverrideCalls(*this, Ctx, Results);
3546 Results.ExitScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00003547
Douglas Gregorf6961522010-08-27 21:18:54 +00003548 CodeCompletionDeclConsumer Consumer(Results, CurContext);
3549 LookupVisibleDecls(Ctx, LookupOrdinaryName, Consumer);
3550
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003551 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregorf6961522010-08-27 21:18:54 +00003552 CodeCompletionContext::CCC_Name,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003553 Results.data(),Results.size());
Douglas Gregor81b747b2009-09-17 21:32:03 +00003554}
Douglas Gregor49f40bd2009-09-18 19:03:04 +00003555
3556void Sema::CodeCompleteUsing(Scope *S) {
3557 if (!CodeCompleter)
3558 return;
3559
Douglas Gregor218937c2011-02-01 19:23:04 +00003560 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00003561 CodeCompletionContext::CCC_PotentiallyQualifiedName,
3562 &ResultBuilder::IsNestedNameSpecifier);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00003563 Results.EnterNewScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00003564
3565 // If we aren't in class scope, we could see the "namespace" keyword.
3566 if (!S->isClassScope())
John McCall0a2c5e22010-08-25 06:19:51 +00003567 Results.AddResult(CodeCompletionResult("namespace"));
Douglas Gregor86d9a522009-09-21 16:56:56 +00003568
3569 // After "using", we can see anything that would start a
3570 // nested-name-specifier.
Douglas Gregor5d2fc402010-01-14 03:27:13 +00003571 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00003572 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3573 CodeCompleter->includeGlobals());
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00003574 Results.ExitScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00003575
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003576 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00003577 CodeCompletionContext::CCC_PotentiallyQualifiedName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003578 Results.data(),Results.size());
Douglas Gregor49f40bd2009-09-18 19:03:04 +00003579}
3580
3581void Sema::CodeCompleteUsingDirective(Scope *S) {
3582 if (!CodeCompleter)
3583 return;
3584
Douglas Gregor86d9a522009-09-21 16:56:56 +00003585 // After "using namespace", we expect to see a namespace name or namespace
3586 // alias.
Douglas Gregor218937c2011-02-01 19:23:04 +00003587 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3588 CodeCompletionContext::CCC_Namespace,
Douglas Gregor52779fb2010-09-23 23:01:17 +00003589 &ResultBuilder::IsNamespaceOrAlias);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00003590 Results.EnterNewScope();
Douglas Gregor5d2fc402010-01-14 03:27:13 +00003591 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00003592 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3593 CodeCompleter->includeGlobals());
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00003594 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003595 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor8071e422010-08-15 06:18:01 +00003596 CodeCompletionContext::CCC_Namespace,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003597 Results.data(),Results.size());
Douglas Gregor49f40bd2009-09-18 19:03:04 +00003598}
3599
3600void Sema::CodeCompleteNamespaceDecl(Scope *S) {
3601 if (!CodeCompleter)
3602 return;
3603
Douglas Gregor86d9a522009-09-21 16:56:56 +00003604 DeclContext *Ctx = (DeclContext *)S->getEntity();
3605 if (!S->getParent())
3606 Ctx = Context.getTranslationUnitDecl();
3607
Douglas Gregor52779fb2010-09-23 23:01:17 +00003608 bool SuppressedGlobalResults
3609 = Ctx && !CodeCompleter->includeGlobals() && isa<TranslationUnitDecl>(Ctx);
3610
Douglas Gregor218937c2011-02-01 19:23:04 +00003611 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00003612 SuppressedGlobalResults
3613 ? CodeCompletionContext::CCC_Namespace
3614 : CodeCompletionContext::CCC_Other,
3615 &ResultBuilder::IsNamespace);
3616
3617 if (Ctx && Ctx->isFileContext() && !SuppressedGlobalResults) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00003618 // We only want to see those namespaces that have already been defined
3619 // within this scope, because its likely that the user is creating an
3620 // extended namespace declaration. Keep track of the most recent
3621 // definition of each namespace.
3622 std::map<NamespaceDecl *, NamespaceDecl *> OrigToLatest;
3623 for (DeclContext::specific_decl_iterator<NamespaceDecl>
3624 NS(Ctx->decls_begin()), NSEnd(Ctx->decls_end());
3625 NS != NSEnd; ++NS)
3626 OrigToLatest[NS->getOriginalNamespace()] = *NS;
3627
3628 // Add the most recent definition (or extended definition) of each
3629 // namespace to the list of results.
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00003630 Results.EnterNewScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00003631 for (std::map<NamespaceDecl *, NamespaceDecl *>::iterator
3632 NS = OrigToLatest.begin(), NSEnd = OrigToLatest.end();
3633 NS != NSEnd; ++NS)
John McCall0a2c5e22010-08-25 06:19:51 +00003634 Results.AddResult(CodeCompletionResult(NS->second, 0),
Douglas Gregor608300b2010-01-14 16:14:35 +00003635 CurContext, 0, false);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00003636 Results.ExitScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00003637 }
3638
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003639 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00003640 Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003641 Results.data(),Results.size());
Douglas Gregor49f40bd2009-09-18 19:03:04 +00003642}
3643
3644void Sema::CodeCompleteNamespaceAliasDecl(Scope *S) {
3645 if (!CodeCompleter)
3646 return;
3647
Douglas Gregor86d9a522009-09-21 16:56:56 +00003648 // After "namespace", we expect to see a namespace or alias.
Douglas Gregor218937c2011-02-01 19:23:04 +00003649 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3650 CodeCompletionContext::CCC_Namespace,
Douglas Gregor52779fb2010-09-23 23:01:17 +00003651 &ResultBuilder::IsNamespaceOrAlias);
Douglas Gregor5d2fc402010-01-14 03:27:13 +00003652 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00003653 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3654 CodeCompleter->includeGlobals());
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003655 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00003656 Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003657 Results.data(),Results.size());
Douglas Gregor49f40bd2009-09-18 19:03:04 +00003658}
3659
Douglas Gregored8d3222009-09-18 20:05:18 +00003660void Sema::CodeCompleteOperatorName(Scope *S) {
3661 if (!CodeCompleter)
3662 return;
Douglas Gregor86d9a522009-09-21 16:56:56 +00003663
John McCall0a2c5e22010-08-25 06:19:51 +00003664 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00003665 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3666 CodeCompletionContext::CCC_Type,
Douglas Gregor52779fb2010-09-23 23:01:17 +00003667 &ResultBuilder::IsType);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00003668 Results.EnterNewScope();
Douglas Gregored8d3222009-09-18 20:05:18 +00003669
Douglas Gregor86d9a522009-09-21 16:56:56 +00003670 // Add the names of overloadable operators.
3671#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
3672 if (std::strcmp(Spelling, "?")) \
Douglas Gregora4477812010-01-14 16:01:26 +00003673 Results.AddResult(Result(Spelling));
Douglas Gregor86d9a522009-09-21 16:56:56 +00003674#include "clang/Basic/OperatorKinds.def"
3675
3676 // Add any type names visible from the current scope
Douglas Gregor45bcd432010-01-14 03:21:49 +00003677 Results.allowNestedNameSpecifiers();
Douglas Gregor5d2fc402010-01-14 03:27:13 +00003678 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00003679 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3680 CodeCompleter->includeGlobals());
Douglas Gregor86d9a522009-09-21 16:56:56 +00003681
3682 // Add any type specifiers
Douglas Gregorbca403c2010-01-13 23:51:12 +00003683 AddTypeSpecifierResults(getLangOptions(), Results);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00003684 Results.ExitScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00003685
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003686 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor8071e422010-08-15 06:18:01 +00003687 CodeCompletionContext::CCC_Type,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003688 Results.data(),Results.size());
Douglas Gregored8d3222009-09-18 20:05:18 +00003689}
Douglas Gregor49f40bd2009-09-18 19:03:04 +00003690
Douglas Gregor0133f522010-08-28 00:00:50 +00003691void Sema::CodeCompleteConstructorInitializer(Decl *ConstructorD,
Sean Huntcbb67482011-01-08 20:30:50 +00003692 CXXCtorInitializer** Initializers,
Douglas Gregor0133f522010-08-28 00:00:50 +00003693 unsigned NumInitializers) {
3694 CXXConstructorDecl *Constructor
3695 = static_cast<CXXConstructorDecl *>(ConstructorD);
3696 if (!Constructor)
3697 return;
3698
Douglas Gregor218937c2011-02-01 19:23:04 +00003699 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00003700 CodeCompletionContext::CCC_PotentiallyQualifiedName);
Douglas Gregor0133f522010-08-28 00:00:50 +00003701 Results.EnterNewScope();
3702
3703 // Fill in any already-initialized fields or base classes.
3704 llvm::SmallPtrSet<FieldDecl *, 4> InitializedFields;
3705 llvm::SmallPtrSet<CanQualType, 4> InitializedBases;
3706 for (unsigned I = 0; I != NumInitializers; ++I) {
3707 if (Initializers[I]->isBaseInitializer())
3708 InitializedBases.insert(
3709 Context.getCanonicalType(QualType(Initializers[I]->getBaseClass(), 0)));
3710 else
Francois Pichet00eb3f92010-12-04 09:14:42 +00003711 InitializedFields.insert(cast<FieldDecl>(
3712 Initializers[I]->getAnyMember()));
Douglas Gregor0133f522010-08-28 00:00:50 +00003713 }
3714
3715 // Add completions for base classes.
Douglas Gregor218937c2011-02-01 19:23:04 +00003716 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregor0c431c82010-08-29 19:27:27 +00003717 bool SawLastInitializer = (NumInitializers == 0);
Douglas Gregor0133f522010-08-28 00:00:50 +00003718 CXXRecordDecl *ClassDecl = Constructor->getParent();
3719 for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),
3720 BaseEnd = ClassDecl->bases_end();
3721 Base != BaseEnd; ++Base) {
Douglas Gregor0c431c82010-08-29 19:27:27 +00003722 if (!InitializedBases.insert(Context.getCanonicalType(Base->getType()))) {
3723 SawLastInitializer
3724 = NumInitializers > 0 &&
3725 Initializers[NumInitializers - 1]->isBaseInitializer() &&
3726 Context.hasSameUnqualifiedType(Base->getType(),
3727 QualType(Initializers[NumInitializers - 1]->getBaseClass(), 0));
Douglas Gregor0133f522010-08-28 00:00:50 +00003728 continue;
Douglas Gregor0c431c82010-08-29 19:27:27 +00003729 }
Douglas Gregor0133f522010-08-28 00:00:50 +00003730
Douglas Gregor218937c2011-02-01 19:23:04 +00003731 Builder.AddTypedTextChunk(
3732 CopyString(Results.getAllocator(),
3733 Base->getType().getAsString(Context.PrintingPolicy)));
3734 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
3735 Builder.AddPlaceholderChunk("args");
3736 Builder.AddChunk(CodeCompletionString::CK_RightParen);
3737 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor0c431c82010-08-29 19:27:27 +00003738 SawLastInitializer? CCP_NextInitializer
3739 : CCP_MemberDeclaration));
3740 SawLastInitializer = false;
Douglas Gregor0133f522010-08-28 00:00:50 +00003741 }
3742
3743 // Add completions for virtual base classes.
3744 for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(),
3745 BaseEnd = ClassDecl->vbases_end();
3746 Base != BaseEnd; ++Base) {
Douglas Gregor0c431c82010-08-29 19:27:27 +00003747 if (!InitializedBases.insert(Context.getCanonicalType(Base->getType()))) {
3748 SawLastInitializer
3749 = NumInitializers > 0 &&
3750 Initializers[NumInitializers - 1]->isBaseInitializer() &&
3751 Context.hasSameUnqualifiedType(Base->getType(),
3752 QualType(Initializers[NumInitializers - 1]->getBaseClass(), 0));
Douglas Gregor0133f522010-08-28 00:00:50 +00003753 continue;
Douglas Gregor0c431c82010-08-29 19:27:27 +00003754 }
Douglas Gregor0133f522010-08-28 00:00:50 +00003755
Douglas Gregor218937c2011-02-01 19:23:04 +00003756 Builder.AddTypedTextChunk(
3757 CopyString(Builder.getAllocator(),
3758 Base->getType().getAsString(Context.PrintingPolicy)));
3759 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
3760 Builder.AddPlaceholderChunk("args");
3761 Builder.AddChunk(CodeCompletionString::CK_RightParen);
3762 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor0c431c82010-08-29 19:27:27 +00003763 SawLastInitializer? CCP_NextInitializer
3764 : CCP_MemberDeclaration));
3765 SawLastInitializer = false;
Douglas Gregor0133f522010-08-28 00:00:50 +00003766 }
3767
3768 // Add completions for members.
3769 for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
3770 FieldEnd = ClassDecl->field_end();
3771 Field != FieldEnd; ++Field) {
Douglas Gregor0c431c82010-08-29 19:27:27 +00003772 if (!InitializedFields.insert(cast<FieldDecl>(Field->getCanonicalDecl()))) {
3773 SawLastInitializer
3774 = NumInitializers > 0 &&
Francois Pichet00eb3f92010-12-04 09:14:42 +00003775 Initializers[NumInitializers - 1]->isAnyMemberInitializer() &&
3776 Initializers[NumInitializers - 1]->getAnyMember() == *Field;
Douglas Gregor0133f522010-08-28 00:00:50 +00003777 continue;
Douglas Gregor0c431c82010-08-29 19:27:27 +00003778 }
Douglas Gregor0133f522010-08-28 00:00:50 +00003779
3780 if (!Field->getDeclName())
3781 continue;
3782
Douglas Gregor218937c2011-02-01 19:23:04 +00003783 Builder.AddTypedTextChunk(CopyString(Builder.getAllocator(),
3784 Field->getIdentifier()->getName()));
3785 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
3786 Builder.AddPlaceholderChunk("args");
3787 Builder.AddChunk(CodeCompletionString::CK_RightParen);
3788 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor0c431c82010-08-29 19:27:27 +00003789 SawLastInitializer? CCP_NextInitializer
Douglas Gregora67e03f2010-09-09 21:42:20 +00003790 : CCP_MemberDeclaration,
3791 CXCursor_MemberRef));
Douglas Gregor0c431c82010-08-29 19:27:27 +00003792 SawLastInitializer = false;
Douglas Gregor0133f522010-08-28 00:00:50 +00003793 }
3794 Results.ExitScope();
3795
Douglas Gregor52779fb2010-09-23 23:01:17 +00003796 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor0133f522010-08-28 00:00:50 +00003797 Results.data(), Results.size());
3798}
3799
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003800// Macro that expands to @Keyword or Keyword, depending on whether NeedAt is
3801// true or false.
3802#define OBJC_AT_KEYWORD_NAME(NeedAt,Keyword) NeedAt? "@" #Keyword : #Keyword
Douglas Gregorbca403c2010-01-13 23:51:12 +00003803static void AddObjCImplementationResults(const LangOptions &LangOpts,
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003804 ResultBuilder &Results,
3805 bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00003806 typedef CodeCompletionResult Result;
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003807 // Since we have an implementation, we can end it.
Douglas Gregora4477812010-01-14 16:01:26 +00003808 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,end)));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003809
Douglas Gregor218937c2011-02-01 19:23:04 +00003810 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003811 if (LangOpts.ObjC2) {
3812 // @dynamic
Douglas Gregor218937c2011-02-01 19:23:04 +00003813 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,dynamic));
3814 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3815 Builder.AddPlaceholderChunk("property");
3816 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003817
3818 // @synthesize
Douglas Gregor218937c2011-02-01 19:23:04 +00003819 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,synthesize));
3820 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3821 Builder.AddPlaceholderChunk("property");
3822 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003823 }
3824}
3825
Douglas Gregorbca403c2010-01-13 23:51:12 +00003826static void AddObjCInterfaceResults(const LangOptions &LangOpts,
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003827 ResultBuilder &Results,
3828 bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00003829 typedef CodeCompletionResult Result;
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003830
3831 // Since we have an interface or protocol, we can end it.
Douglas Gregora4477812010-01-14 16:01:26 +00003832 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,end)));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003833
3834 if (LangOpts.ObjC2) {
3835 // @property
Douglas Gregora4477812010-01-14 16:01:26 +00003836 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,property)));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003837
3838 // @required
Douglas Gregora4477812010-01-14 16:01:26 +00003839 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,required)));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003840
3841 // @optional
Douglas Gregora4477812010-01-14 16:01:26 +00003842 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,optional)));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003843 }
3844}
3845
Douglas Gregorbca403c2010-01-13 23:51:12 +00003846static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00003847 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00003848 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003849
3850 // @class name ;
Douglas Gregor218937c2011-02-01 19:23:04 +00003851 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,class));
3852 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3853 Builder.AddPlaceholderChunk("name");
3854 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003855
Douglas Gregorc8bddde2010-05-28 00:22:41 +00003856 if (Results.includeCodePatterns()) {
3857 // @interface name
3858 // FIXME: Could introduce the whole pattern, including superclasses and
3859 // such.
Douglas Gregor218937c2011-02-01 19:23:04 +00003860 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,interface));
3861 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3862 Builder.AddPlaceholderChunk("class");
3863 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003864
Douglas Gregorc8bddde2010-05-28 00:22:41 +00003865 // @protocol name
Douglas Gregor218937c2011-02-01 19:23:04 +00003866 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,protocol));
3867 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3868 Builder.AddPlaceholderChunk("protocol");
3869 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00003870
3871 // @implementation name
Douglas Gregor218937c2011-02-01 19:23:04 +00003872 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,implementation));
3873 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3874 Builder.AddPlaceholderChunk("class");
3875 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00003876 }
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003877
3878 // @compatibility_alias name
Douglas Gregor218937c2011-02-01 19:23:04 +00003879 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,compatibility_alias));
3880 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3881 Builder.AddPlaceholderChunk("alias");
3882 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3883 Builder.AddPlaceholderChunk("class");
3884 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003885}
3886
John McCalld226f652010-08-21 09:40:31 +00003887void Sema::CodeCompleteObjCAtDirective(Scope *S, Decl *ObjCImpDecl,
Douglas Gregorc464ae82009-12-07 09:27:33 +00003888 bool InInterface) {
John McCall0a2c5e22010-08-25 06:19:51 +00003889 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00003890 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3891 CodeCompletionContext::CCC_Other);
Douglas Gregorc464ae82009-12-07 09:27:33 +00003892 Results.EnterNewScope();
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003893 if (ObjCImpDecl)
Douglas Gregorbca403c2010-01-13 23:51:12 +00003894 AddObjCImplementationResults(getLangOptions(), Results, false);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003895 else if (InInterface)
Douglas Gregorbca403c2010-01-13 23:51:12 +00003896 AddObjCInterfaceResults(getLangOptions(), Results, false);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003897 else
Douglas Gregorbca403c2010-01-13 23:51:12 +00003898 AddObjCTopLevelResults(Results, false);
Douglas Gregorc464ae82009-12-07 09:27:33 +00003899 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003900 HandleCodeCompleteResults(this, CodeCompleter,
3901 CodeCompletionContext::CCC_Other,
3902 Results.data(),Results.size());
Douglas Gregorc464ae82009-12-07 09:27:33 +00003903}
3904
Douglas Gregorbca403c2010-01-13 23:51:12 +00003905static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00003906 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00003907 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00003908
3909 // @encode ( type-name )
Douglas Gregor218937c2011-02-01 19:23:04 +00003910 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,encode));
3911 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
3912 Builder.AddPlaceholderChunk("type-name");
3913 Builder.AddChunk(CodeCompletionString::CK_RightParen);
3914 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00003915
3916 // @protocol ( protocol-name )
Douglas Gregor218937c2011-02-01 19:23:04 +00003917 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,protocol));
3918 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
3919 Builder.AddPlaceholderChunk("protocol-name");
3920 Builder.AddChunk(CodeCompletionString::CK_RightParen);
3921 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00003922
3923 // @selector ( selector )
Douglas Gregor218937c2011-02-01 19:23:04 +00003924 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,selector));
3925 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
3926 Builder.AddPlaceholderChunk("selector");
3927 Builder.AddChunk(CodeCompletionString::CK_RightParen);
3928 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00003929}
3930
Douglas Gregorbca403c2010-01-13 23:51:12 +00003931static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00003932 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00003933 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003934
Douglas Gregorc8bddde2010-05-28 00:22:41 +00003935 if (Results.includeCodePatterns()) {
3936 // @try { statements } @catch ( declaration ) { statements } @finally
3937 // { statements }
Douglas Gregor218937c2011-02-01 19:23:04 +00003938 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,try));
3939 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
3940 Builder.AddPlaceholderChunk("statements");
3941 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
3942 Builder.AddTextChunk("@catch");
3943 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
3944 Builder.AddPlaceholderChunk("parameter");
3945 Builder.AddChunk(CodeCompletionString::CK_RightParen);
3946 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
3947 Builder.AddPlaceholderChunk("statements");
3948 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
3949 Builder.AddTextChunk("@finally");
3950 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
3951 Builder.AddPlaceholderChunk("statements");
3952 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
3953 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00003954 }
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003955
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00003956 // @throw
Douglas Gregor218937c2011-02-01 19:23:04 +00003957 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,throw));
3958 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3959 Builder.AddPlaceholderChunk("expression");
3960 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003961
Douglas Gregorc8bddde2010-05-28 00:22:41 +00003962 if (Results.includeCodePatterns()) {
3963 // @synchronized ( expression ) { statements }
Douglas Gregor218937c2011-02-01 19:23:04 +00003964 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,synchronized));
3965 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3966 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
3967 Builder.AddPlaceholderChunk("expression");
3968 Builder.AddChunk(CodeCompletionString::CK_RightParen);
3969 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
3970 Builder.AddPlaceholderChunk("statements");
3971 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
3972 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00003973 }
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003974}
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00003975
Douglas Gregorbca403c2010-01-13 23:51:12 +00003976static void AddObjCVisibilityResults(const LangOptions &LangOpts,
Douglas Gregorc38c3e12010-01-13 21:54:15 +00003977 ResultBuilder &Results,
3978 bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00003979 typedef CodeCompletionResult Result;
Douglas Gregora4477812010-01-14 16:01:26 +00003980 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,private)));
3981 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,protected)));
3982 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,public)));
Douglas Gregorc38c3e12010-01-13 21:54:15 +00003983 if (LangOpts.ObjC2)
Douglas Gregora4477812010-01-14 16:01:26 +00003984 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,package)));
Douglas Gregorc38c3e12010-01-13 21:54:15 +00003985}
3986
3987void Sema::CodeCompleteObjCAtVisibility(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00003988 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3989 CodeCompletionContext::CCC_Other);
Douglas Gregorc38c3e12010-01-13 21:54:15 +00003990 Results.EnterNewScope();
Douglas Gregorbca403c2010-01-13 23:51:12 +00003991 AddObjCVisibilityResults(getLangOptions(), Results, false);
Douglas Gregorc38c3e12010-01-13 21:54:15 +00003992 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003993 HandleCodeCompleteResults(this, CodeCompleter,
3994 CodeCompletionContext::CCC_Other,
3995 Results.data(),Results.size());
Douglas Gregorc38c3e12010-01-13 21:54:15 +00003996}
3997
3998void Sema::CodeCompleteObjCAtStatement(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00003999 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4000 CodeCompletionContext::CCC_Other);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004001 Results.EnterNewScope();
Douglas Gregorbca403c2010-01-13 23:51:12 +00004002 AddObjCStatementResults(Results, false);
4003 AddObjCExpressionResults(Results, false);
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004004 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004005 HandleCodeCompleteResults(this, CodeCompleter,
4006 CodeCompletionContext::CCC_Other,
4007 Results.data(),Results.size());
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004008}
4009
4010void Sema::CodeCompleteObjCAtExpression(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004011 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4012 CodeCompletionContext::CCC_Other);
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004013 Results.EnterNewScope();
Douglas Gregorbca403c2010-01-13 23:51:12 +00004014 AddObjCExpressionResults(Results, false);
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004015 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004016 HandleCodeCompleteResults(this, CodeCompleter,
4017 CodeCompletionContext::CCC_Other,
4018 Results.data(),Results.size());
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004019}
4020
Douglas Gregor988358f2009-11-19 00:14:45 +00004021/// \brief Determine whether the addition of the given flag to an Objective-C
4022/// property's attributes will cause a conflict.
4023static bool ObjCPropertyFlagConflicts(unsigned Attributes, unsigned NewFlag) {
4024 // Check if we've already added this flag.
4025 if (Attributes & NewFlag)
4026 return true;
4027
4028 Attributes |= NewFlag;
4029
4030 // Check for collisions with "readonly".
4031 if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) &&
4032 (Attributes & (ObjCDeclSpec::DQ_PR_readwrite |
4033 ObjCDeclSpec::DQ_PR_assign |
4034 ObjCDeclSpec::DQ_PR_copy |
4035 ObjCDeclSpec::DQ_PR_retain)))
4036 return true;
4037
4038 // Check for more than one of { assign, copy, retain }.
4039 unsigned AssignCopyRetMask = Attributes & (ObjCDeclSpec::DQ_PR_assign |
4040 ObjCDeclSpec::DQ_PR_copy |
4041 ObjCDeclSpec::DQ_PR_retain);
4042 if (AssignCopyRetMask &&
4043 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_assign &&
4044 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_copy &&
4045 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_retain)
4046 return true;
4047
4048 return false;
4049}
4050
Douglas Gregora93b1082009-11-18 23:08:07 +00004051void Sema::CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS) {
Steve Naroffece8e712009-10-08 21:55:05 +00004052 if (!CodeCompleter)
4053 return;
Douglas Gregord3c68542009-11-19 01:08:35 +00004054
Steve Naroffece8e712009-10-08 21:55:05 +00004055 unsigned Attributes = ODS.getPropertyAttributes();
4056
John McCall0a2c5e22010-08-25 06:19:51 +00004057 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00004058 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4059 CodeCompletionContext::CCC_Other);
Steve Naroffece8e712009-10-08 21:55:05 +00004060 Results.EnterNewScope();
Douglas Gregor988358f2009-11-19 00:14:45 +00004061 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readonly))
John McCall0a2c5e22010-08-25 06:19:51 +00004062 Results.AddResult(CodeCompletionResult("readonly"));
Douglas Gregor988358f2009-11-19 00:14:45 +00004063 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_assign))
John McCall0a2c5e22010-08-25 06:19:51 +00004064 Results.AddResult(CodeCompletionResult("assign"));
Douglas Gregor988358f2009-11-19 00:14:45 +00004065 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readwrite))
John McCall0a2c5e22010-08-25 06:19:51 +00004066 Results.AddResult(CodeCompletionResult("readwrite"));
Douglas Gregor988358f2009-11-19 00:14:45 +00004067 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_retain))
John McCall0a2c5e22010-08-25 06:19:51 +00004068 Results.AddResult(CodeCompletionResult("retain"));
Douglas Gregor988358f2009-11-19 00:14:45 +00004069 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_copy))
John McCall0a2c5e22010-08-25 06:19:51 +00004070 Results.AddResult(CodeCompletionResult("copy"));
Douglas Gregor988358f2009-11-19 00:14:45 +00004071 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_nonatomic))
John McCall0a2c5e22010-08-25 06:19:51 +00004072 Results.AddResult(CodeCompletionResult("nonatomic"));
Douglas Gregor988358f2009-11-19 00:14:45 +00004073 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_setter)) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004074 CodeCompletionBuilder Setter(Results.getAllocator());
4075 Setter.AddTypedTextChunk("setter");
4076 Setter.AddTextChunk(" = ");
4077 Setter.AddPlaceholderChunk("method");
4078 Results.AddResult(CodeCompletionResult(Setter.TakeString()));
Douglas Gregor54f01612009-11-19 00:01:57 +00004079 }
Douglas Gregor988358f2009-11-19 00:14:45 +00004080 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_getter)) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004081 CodeCompletionBuilder Getter(Results.getAllocator());
4082 Getter.AddTypedTextChunk("getter");
4083 Getter.AddTextChunk(" = ");
4084 Getter.AddPlaceholderChunk("method");
4085 Results.AddResult(CodeCompletionResult(Getter.TakeString()));
Douglas Gregor54f01612009-11-19 00:01:57 +00004086 }
Steve Naroffece8e712009-10-08 21:55:05 +00004087 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004088 HandleCodeCompleteResults(this, CodeCompleter,
4089 CodeCompletionContext::CCC_Other,
4090 Results.data(),Results.size());
Steve Naroffece8e712009-10-08 21:55:05 +00004091}
Steve Naroffc4df6d22009-11-07 02:08:14 +00004092
Douglas Gregor4ad96852009-11-19 07:41:15 +00004093/// \brief Descripts the kind of Objective-C method that we want to find
4094/// via code completion.
4095enum ObjCMethodKind {
4096 MK_Any, //< Any kind of method, provided it means other specified criteria.
4097 MK_ZeroArgSelector, //< Zero-argument (unary) selector.
4098 MK_OneArgSelector //< One-argument selector.
4099};
4100
Douglas Gregor458433d2010-08-26 15:07:07 +00004101static bool isAcceptableObjCSelector(Selector Sel,
4102 ObjCMethodKind WantKind,
4103 IdentifierInfo **SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004104 unsigned NumSelIdents,
4105 bool AllowSameLength = true) {
Douglas Gregor458433d2010-08-26 15:07:07 +00004106 if (NumSelIdents > Sel.getNumArgs())
4107 return false;
4108
4109 switch (WantKind) {
4110 case MK_Any: break;
4111 case MK_ZeroArgSelector: return Sel.isUnarySelector();
4112 case MK_OneArgSelector: return Sel.getNumArgs() == 1;
4113 }
4114
Douglas Gregorcf544262010-11-17 21:36:08 +00004115 if (!AllowSameLength && NumSelIdents && NumSelIdents == Sel.getNumArgs())
4116 return false;
4117
Douglas Gregor458433d2010-08-26 15:07:07 +00004118 for (unsigned I = 0; I != NumSelIdents; ++I)
4119 if (SelIdents[I] != Sel.getIdentifierInfoForSlot(I))
4120 return false;
4121
4122 return true;
4123}
4124
Douglas Gregor4ad96852009-11-19 07:41:15 +00004125static bool isAcceptableObjCMethod(ObjCMethodDecl *Method,
4126 ObjCMethodKind WantKind,
4127 IdentifierInfo **SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004128 unsigned NumSelIdents,
4129 bool AllowSameLength = true) {
Douglas Gregor458433d2010-08-26 15:07:07 +00004130 return isAcceptableObjCSelector(Method->getSelector(), WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004131 NumSelIdents, AllowSameLength);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004132}
Douglas Gregord36adf52010-09-16 16:06:31 +00004133
4134namespace {
4135 /// \brief A set of selectors, which is used to avoid introducing multiple
4136 /// completions with the same selector into the result set.
4137 typedef llvm::SmallPtrSet<Selector, 16> VisitedSelectorSet;
4138}
4139
Douglas Gregor36ecb042009-11-17 23:22:23 +00004140/// \brief Add all of the Objective-C methods in the given Objective-C
4141/// container to the set of results.
4142///
4143/// The container will be a class, protocol, category, or implementation of
4144/// any of the above. This mether will recurse to include methods from
4145/// the superclasses of classes along with their categories, protocols, and
4146/// implementations.
4147///
4148/// \param Container the container in which we'll look to find methods.
4149///
4150/// \param WantInstance whether to add instance methods (only); if false, this
4151/// routine will add factory methods (only).
4152///
4153/// \param CurContext the context in which we're performing the lookup that
4154/// finds methods.
4155///
Douglas Gregorcf544262010-11-17 21:36:08 +00004156/// \param AllowSameLength Whether we allow a method to be added to the list
4157/// when it has the same number of parameters as we have selector identifiers.
4158///
Douglas Gregor36ecb042009-11-17 23:22:23 +00004159/// \param Results the structure into which we'll add results.
4160static void AddObjCMethods(ObjCContainerDecl *Container,
4161 bool WantInstanceMethods,
Douglas Gregor4ad96852009-11-19 07:41:15 +00004162 ObjCMethodKind WantKind,
Douglas Gregord3c68542009-11-19 01:08:35 +00004163 IdentifierInfo **SelIdents,
4164 unsigned NumSelIdents,
Douglas Gregor36ecb042009-11-17 23:22:23 +00004165 DeclContext *CurContext,
Douglas Gregord36adf52010-09-16 16:06:31 +00004166 VisitedSelectorSet &Selectors,
Douglas Gregorcf544262010-11-17 21:36:08 +00004167 bool AllowSameLength,
Douglas Gregor408be5a2010-08-25 01:08:01 +00004168 ResultBuilder &Results,
4169 bool InOriginalClass = true) {
John McCall0a2c5e22010-08-25 06:19:51 +00004170 typedef CodeCompletionResult Result;
Douglas Gregor36ecb042009-11-17 23:22:23 +00004171 for (ObjCContainerDecl::method_iterator M = Container->meth_begin(),
4172 MEnd = Container->meth_end();
4173 M != MEnd; ++M) {
Douglas Gregord3c68542009-11-19 01:08:35 +00004174 if ((*M)->isInstanceMethod() == WantInstanceMethods) {
4175 // Check whether the selector identifiers we've been given are a
4176 // subset of the identifiers for this particular method.
Douglas Gregorcf544262010-11-17 21:36:08 +00004177 if (!isAcceptableObjCMethod(*M, WantKind, SelIdents, NumSelIdents,
4178 AllowSameLength))
Douglas Gregord3c68542009-11-19 01:08:35 +00004179 continue;
Douglas Gregor4ad96852009-11-19 07:41:15 +00004180
Douglas Gregord36adf52010-09-16 16:06:31 +00004181 if (!Selectors.insert((*M)->getSelector()))
4182 continue;
4183
Douglas Gregord3c68542009-11-19 01:08:35 +00004184 Result R = Result(*M, 0);
4185 R.StartParameter = NumSelIdents;
Douglas Gregor4ad96852009-11-19 07:41:15 +00004186 R.AllParametersAreInformative = (WantKind != MK_Any);
Douglas Gregor408be5a2010-08-25 01:08:01 +00004187 if (!InOriginalClass)
4188 R.Priority += CCD_InBaseClass;
Douglas Gregord3c68542009-11-19 01:08:35 +00004189 Results.MaybeAddResult(R, CurContext);
4190 }
Douglas Gregor36ecb042009-11-17 23:22:23 +00004191 }
4192
Douglas Gregore396c7b2010-09-16 15:34:59 +00004193 // Visit the protocols of protocols.
4194 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
4195 const ObjCList<ObjCProtocolDecl> &Protocols
4196 = Protocol->getReferencedProtocols();
4197 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
4198 E = Protocols.end();
4199 I != E; ++I)
4200 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, NumSelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004201 CurContext, Selectors, AllowSameLength, Results, false);
Douglas Gregore396c7b2010-09-16 15:34:59 +00004202 }
4203
Douglas Gregor36ecb042009-11-17 23:22:23 +00004204 ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container);
4205 if (!IFace)
4206 return;
4207
4208 // Add methods in protocols.
4209 const ObjCList<ObjCProtocolDecl> &Protocols= IFace->getReferencedProtocols();
4210 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
4211 E = Protocols.end();
4212 I != E; ++I)
Douglas Gregor4ad96852009-11-19 07:41:15 +00004213 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, NumSelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004214 CurContext, Selectors, AllowSameLength, Results, false);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004215
4216 // Add methods in categories.
4217 for (ObjCCategoryDecl *CatDecl = IFace->getCategoryList(); CatDecl;
4218 CatDecl = CatDecl->getNextClassCategory()) {
Douglas Gregor4ad96852009-11-19 07:41:15 +00004219 AddObjCMethods(CatDecl, WantInstanceMethods, WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004220 NumSelIdents, CurContext, Selectors, AllowSameLength,
4221 Results, InOriginalClass);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004222
4223 // Add a categories protocol methods.
4224 const ObjCList<ObjCProtocolDecl> &Protocols
4225 = CatDecl->getReferencedProtocols();
4226 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
4227 E = Protocols.end();
4228 I != E; ++I)
Douglas Gregor4ad96852009-11-19 07:41:15 +00004229 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004230 NumSelIdents, CurContext, Selectors, AllowSameLength,
4231 Results, false);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004232
4233 // Add methods in category implementations.
4234 if (ObjCCategoryImplDecl *Impl = CatDecl->getImplementation())
Douglas Gregor4ad96852009-11-19 07:41:15 +00004235 AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004236 NumSelIdents, CurContext, Selectors, AllowSameLength,
4237 Results, InOriginalClass);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004238 }
4239
4240 // Add methods in superclass.
4241 if (IFace->getSuperClass())
Douglas Gregor4ad96852009-11-19 07:41:15 +00004242 AddObjCMethods(IFace->getSuperClass(), WantInstanceMethods, WantKind,
Douglas Gregorcf544262010-11-17 21:36:08 +00004243 SelIdents, NumSelIdents, CurContext, Selectors,
4244 AllowSameLength, Results, false);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004245
4246 // Add methods in our implementation, if any.
4247 if (ObjCImplementationDecl *Impl = IFace->getImplementation())
Douglas Gregor4ad96852009-11-19 07:41:15 +00004248 AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004249 NumSelIdents, CurContext, Selectors, AllowSameLength,
4250 Results, InOriginalClass);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004251}
4252
4253
Douglas Gregorbdb2d502010-12-21 17:34:17 +00004254void Sema::CodeCompleteObjCPropertyGetter(Scope *S, Decl *ClassDecl) {
John McCall0a2c5e22010-08-25 06:19:51 +00004255 typedef CodeCompletionResult Result;
Douglas Gregor4ad96852009-11-19 07:41:15 +00004256
4257 // Try to find the interface where getters might live.
John McCalld226f652010-08-21 09:40:31 +00004258 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(ClassDecl);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004259 if (!Class) {
4260 if (ObjCCategoryDecl *Category
John McCalld226f652010-08-21 09:40:31 +00004261 = dyn_cast_or_null<ObjCCategoryDecl>(ClassDecl))
Douglas Gregor4ad96852009-11-19 07:41:15 +00004262 Class = Category->getClassInterface();
4263
4264 if (!Class)
4265 return;
4266 }
4267
4268 // Find all of the potential getters.
Douglas Gregor218937c2011-02-01 19:23:04 +00004269 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4270 CodeCompletionContext::CCC_Other);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004271 Results.EnterNewScope();
4272
Douglas Gregord36adf52010-09-16 16:06:31 +00004273 VisitedSelectorSet Selectors;
4274 AddObjCMethods(Class, true, MK_ZeroArgSelector, 0, 0, CurContext, Selectors,
Douglas Gregorcf544262010-11-17 21:36:08 +00004275 /*AllowSameLength=*/true, Results);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004276 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004277 HandleCodeCompleteResults(this, CodeCompleter,
4278 CodeCompletionContext::CCC_Other,
4279 Results.data(),Results.size());
Douglas Gregor4ad96852009-11-19 07:41:15 +00004280}
4281
Douglas Gregorbdb2d502010-12-21 17:34:17 +00004282void Sema::CodeCompleteObjCPropertySetter(Scope *S, Decl *ObjCImplDecl) {
John McCall0a2c5e22010-08-25 06:19:51 +00004283 typedef CodeCompletionResult Result;
Douglas Gregor4ad96852009-11-19 07:41:15 +00004284
4285 // Try to find the interface where setters might live.
4286 ObjCInterfaceDecl *Class
John McCalld226f652010-08-21 09:40:31 +00004287 = dyn_cast_or_null<ObjCInterfaceDecl>(ObjCImplDecl);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004288 if (!Class) {
4289 if (ObjCCategoryDecl *Category
John McCalld226f652010-08-21 09:40:31 +00004290 = dyn_cast_or_null<ObjCCategoryDecl>(ObjCImplDecl))
Douglas Gregor4ad96852009-11-19 07:41:15 +00004291 Class = Category->getClassInterface();
4292
4293 if (!Class)
4294 return;
4295 }
4296
4297 // Find all of the potential getters.
Douglas Gregor218937c2011-02-01 19:23:04 +00004298 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4299 CodeCompletionContext::CCC_Other);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004300 Results.EnterNewScope();
4301
Douglas Gregord36adf52010-09-16 16:06:31 +00004302 VisitedSelectorSet Selectors;
4303 AddObjCMethods(Class, true, MK_OneArgSelector, 0, 0, CurContext,
Douglas Gregorcf544262010-11-17 21:36:08 +00004304 Selectors, /*AllowSameLength=*/true, Results);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004305
4306 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004307 HandleCodeCompleteResults(this, CodeCompleter,
4308 CodeCompletionContext::CCC_Other,
4309 Results.data(),Results.size());
Douglas Gregor36ecb042009-11-17 23:22:23 +00004310}
4311
Douglas Gregord32b0222010-08-24 01:06:58 +00004312void Sema::CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS) {
John McCall0a2c5e22010-08-25 06:19:51 +00004313 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00004314 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4315 CodeCompletionContext::CCC_Type);
Douglas Gregord32b0222010-08-24 01:06:58 +00004316 Results.EnterNewScope();
4317
4318 // Add context-sensitive, Objective-C parameter-passing keywords.
4319 bool AddedInOut = false;
4320 if ((DS.getObjCDeclQualifier() &
4321 (ObjCDeclSpec::DQ_In | ObjCDeclSpec::DQ_Inout)) == 0) {
4322 Results.AddResult("in");
4323 Results.AddResult("inout");
4324 AddedInOut = true;
4325 }
4326 if ((DS.getObjCDeclQualifier() &
4327 (ObjCDeclSpec::DQ_Out | ObjCDeclSpec::DQ_Inout)) == 0) {
4328 Results.AddResult("out");
4329 if (!AddedInOut)
4330 Results.AddResult("inout");
4331 }
4332 if ((DS.getObjCDeclQualifier() &
4333 (ObjCDeclSpec::DQ_Bycopy | ObjCDeclSpec::DQ_Byref |
4334 ObjCDeclSpec::DQ_Oneway)) == 0) {
4335 Results.AddResult("bycopy");
4336 Results.AddResult("byref");
4337 Results.AddResult("oneway");
4338 }
4339
4340 // Add various builtin type names and specifiers.
4341 AddOrdinaryNameResults(PCC_Type, S, *this, Results);
4342 Results.ExitScope();
4343
4344 // Add the various type names
4345 Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
4346 CodeCompletionDeclConsumer Consumer(Results, CurContext);
4347 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4348 CodeCompleter->includeGlobals());
4349
4350 if (CodeCompleter->includeMacros())
4351 AddMacroResults(PP, Results);
4352
4353 HandleCodeCompleteResults(this, CodeCompleter,
4354 CodeCompletionContext::CCC_Type,
4355 Results.data(), Results.size());
4356}
4357
Douglas Gregor22f56992010-04-06 19:22:33 +00004358/// \brief When we have an expression with type "id", we may assume
4359/// that it has some more-specific class type based on knowledge of
4360/// common uses of Objective-C. This routine returns that class type,
4361/// or NULL if no better result could be determined.
4362static ObjCInterfaceDecl *GetAssumedMessageSendExprType(Expr *E) {
Douglas Gregor78edf512010-09-15 16:23:04 +00004363 ObjCMessageExpr *Msg = dyn_cast_or_null<ObjCMessageExpr>(E);
Douglas Gregor22f56992010-04-06 19:22:33 +00004364 if (!Msg)
4365 return 0;
4366
4367 Selector Sel = Msg->getSelector();
4368 if (Sel.isNull())
4369 return 0;
4370
4371 IdentifierInfo *Id = Sel.getIdentifierInfoForSlot(0);
4372 if (!Id)
4373 return 0;
4374
4375 ObjCMethodDecl *Method = Msg->getMethodDecl();
4376 if (!Method)
4377 return 0;
4378
4379 // Determine the class that we're sending the message to.
Douglas Gregor04badcf2010-04-21 00:45:42 +00004380 ObjCInterfaceDecl *IFace = 0;
4381 switch (Msg->getReceiverKind()) {
4382 case ObjCMessageExpr::Class:
John McCallc12c5bb2010-05-15 11:32:37 +00004383 if (const ObjCObjectType *ObjType
4384 = Msg->getClassReceiver()->getAs<ObjCObjectType>())
4385 IFace = ObjType->getInterface();
Douglas Gregor04badcf2010-04-21 00:45:42 +00004386 break;
4387
4388 case ObjCMessageExpr::Instance: {
4389 QualType T = Msg->getInstanceReceiver()->getType();
4390 if (const ObjCObjectPointerType *Ptr = T->getAs<ObjCObjectPointerType>())
4391 IFace = Ptr->getInterfaceDecl();
4392 break;
4393 }
4394
4395 case ObjCMessageExpr::SuperInstance:
4396 case ObjCMessageExpr::SuperClass:
4397 break;
Douglas Gregor22f56992010-04-06 19:22:33 +00004398 }
4399
4400 if (!IFace)
4401 return 0;
4402
4403 ObjCInterfaceDecl *Super = IFace->getSuperClass();
4404 if (Method->isInstanceMethod())
4405 return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
4406 .Case("retain", IFace)
4407 .Case("autorelease", IFace)
4408 .Case("copy", IFace)
4409 .Case("copyWithZone", IFace)
4410 .Case("mutableCopy", IFace)
4411 .Case("mutableCopyWithZone", IFace)
4412 .Case("awakeFromCoder", IFace)
4413 .Case("replacementObjectFromCoder", IFace)
4414 .Case("class", IFace)
4415 .Case("classForCoder", IFace)
4416 .Case("superclass", Super)
4417 .Default(0);
4418
4419 return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
4420 .Case("new", IFace)
4421 .Case("alloc", IFace)
4422 .Case("allocWithZone", IFace)
4423 .Case("class", IFace)
4424 .Case("superclass", Super)
4425 .Default(0);
4426}
4427
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004428// Add a special completion for a message send to "super", which fills in the
4429// most likely case of forwarding all of our arguments to the superclass
4430// function.
4431///
4432/// \param S The semantic analysis object.
4433///
4434/// \param S NeedSuperKeyword Whether we need to prefix this completion with
4435/// the "super" keyword. Otherwise, we just need to provide the arguments.
4436///
4437/// \param SelIdents The identifiers in the selector that have already been
4438/// provided as arguments for a send to "super".
4439///
4440/// \param NumSelIdents The number of identifiers in \p SelIdents.
4441///
4442/// \param Results The set of results to augment.
4443///
4444/// \returns the Objective-C method declaration that would be invoked by
4445/// this "super" completion. If NULL, no completion was added.
4446static ObjCMethodDecl *AddSuperSendCompletion(Sema &S, bool NeedSuperKeyword,
4447 IdentifierInfo **SelIdents,
4448 unsigned NumSelIdents,
4449 ResultBuilder &Results) {
4450 ObjCMethodDecl *CurMethod = S.getCurMethodDecl();
4451 if (!CurMethod)
4452 return 0;
4453
4454 ObjCInterfaceDecl *Class = CurMethod->getClassInterface();
4455 if (!Class)
4456 return 0;
4457
4458 // Try to find a superclass method with the same selector.
4459 ObjCMethodDecl *SuperMethod = 0;
4460 while ((Class = Class->getSuperClass()) && !SuperMethod)
4461 SuperMethod = Class->getMethod(CurMethod->getSelector(),
4462 CurMethod->isInstanceMethod());
4463
4464 if (!SuperMethod)
4465 return 0;
4466
4467 // Check whether the superclass method has the same signature.
4468 if (CurMethod->param_size() != SuperMethod->param_size() ||
4469 CurMethod->isVariadic() != SuperMethod->isVariadic())
4470 return 0;
4471
4472 for (ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin(),
4473 CurPEnd = CurMethod->param_end(),
4474 SuperP = SuperMethod->param_begin();
4475 CurP != CurPEnd; ++CurP, ++SuperP) {
4476 // Make sure the parameter types are compatible.
4477 if (!S.Context.hasSameUnqualifiedType((*CurP)->getType(),
4478 (*SuperP)->getType()))
4479 return 0;
4480
4481 // Make sure we have a parameter name to forward!
4482 if (!(*CurP)->getIdentifier())
4483 return 0;
4484 }
4485
4486 // We have a superclass method. Now, form the send-to-super completion.
Douglas Gregor218937c2011-02-01 19:23:04 +00004487 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004488
4489 // Give this completion a return type.
Douglas Gregor218937c2011-02-01 19:23:04 +00004490 AddResultTypeChunk(S.Context, SuperMethod, Builder);
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004491
4492 // If we need the "super" keyword, add it (plus some spacing).
4493 if (NeedSuperKeyword) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004494 Builder.AddTypedTextChunk("super");
4495 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004496 }
4497
4498 Selector Sel = CurMethod->getSelector();
4499 if (Sel.isUnarySelector()) {
4500 if (NeedSuperKeyword)
Douglas Gregor218937c2011-02-01 19:23:04 +00004501 Builder.AddTextChunk(CopyString(Builder.getAllocator(),
4502 Sel.getIdentifierInfoForSlot(0)->getName()));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004503 else
Douglas Gregor218937c2011-02-01 19:23:04 +00004504 Builder.AddTypedTextChunk(CopyString(Builder.getAllocator(),
4505 Sel.getIdentifierInfoForSlot(0)->getName()));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004506 } else {
4507 ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin();
4508 for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I, ++CurP) {
4509 if (I > NumSelIdents)
Douglas Gregor218937c2011-02-01 19:23:04 +00004510 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004511
4512 if (I < NumSelIdents)
Douglas Gregor218937c2011-02-01 19:23:04 +00004513 Builder.AddInformativeChunk(
4514 CopyString(Builder.getAllocator(),
4515 Sel.getIdentifierInfoForSlot(I)->getName().str() + ":"));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004516 else if (NeedSuperKeyword || I > NumSelIdents) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004517 Builder.AddTextChunk(
4518 CopyString(Builder.getAllocator(),
4519 Sel.getIdentifierInfoForSlot(I)->getName().str() + ":"));
4520 Builder.AddPlaceholderChunk(CopyString(Builder.getAllocator(),
4521 (*CurP)->getIdentifier()->getName()));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004522 } else {
Douglas Gregor218937c2011-02-01 19:23:04 +00004523 Builder.AddTypedTextChunk(
4524 CopyString(Builder.getAllocator(),
4525 Sel.getIdentifierInfoForSlot(I)->getName().str() + ":"));
4526 Builder.AddPlaceholderChunk(CopyString(Builder.getAllocator(),
4527 (*CurP)->getIdentifier()->getName()));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004528 }
4529 }
4530 }
4531
Douglas Gregor218937c2011-02-01 19:23:04 +00004532 Results.AddResult(CodeCompletionResult(Builder.TakeString(), CCP_SuperCompletion,
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004533 SuperMethod->isInstanceMethod()
4534 ? CXCursor_ObjCInstanceMethodDecl
4535 : CXCursor_ObjCClassMethodDecl));
4536 return SuperMethod;
4537}
4538
Douglas Gregor8e254cf2010-05-27 23:06:34 +00004539void Sema::CodeCompleteObjCMessageReceiver(Scope *S) {
John McCall0a2c5e22010-08-25 06:19:51 +00004540 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00004541 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4542 CodeCompletionContext::CCC_ObjCMessageReceiver,
Douglas Gregor52779fb2010-09-23 23:01:17 +00004543 &ResultBuilder::IsObjCMessageReceiver);
Douglas Gregor8e254cf2010-05-27 23:06:34 +00004544
Douglas Gregor8e254cf2010-05-27 23:06:34 +00004545 CodeCompletionDeclConsumer Consumer(Results, CurContext);
4546 Results.EnterNewScope();
Douglas Gregor8071e422010-08-15 06:18:01 +00004547 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4548 CodeCompleter->includeGlobals());
Douglas Gregor8e254cf2010-05-27 23:06:34 +00004549
4550 // If we are in an Objective-C method inside a class that has a superclass,
4551 // add "super" as an option.
4552 if (ObjCMethodDecl *Method = getCurMethodDecl())
4553 if (ObjCInterfaceDecl *Iface = Method->getClassInterface())
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004554 if (Iface->getSuperClass()) {
Douglas Gregor8e254cf2010-05-27 23:06:34 +00004555 Results.AddResult(Result("super"));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004556
4557 AddSuperSendCompletion(*this, /*NeedSuperKeyword=*/true, 0, 0, Results);
4558 }
Douglas Gregor8e254cf2010-05-27 23:06:34 +00004559
4560 Results.ExitScope();
4561
4562 if (CodeCompleter->includeMacros())
4563 AddMacroResults(PP, Results);
Douglas Gregorcee9ff12010-09-20 22:39:41 +00004564 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004565 Results.data(), Results.size());
Douglas Gregor8e254cf2010-05-27 23:06:34 +00004566
4567}
4568
Douglas Gregor2725ca82010-04-21 19:57:20 +00004569void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc,
4570 IdentifierInfo **SelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00004571 unsigned NumSelIdents,
4572 bool AtArgumentExpression) {
Douglas Gregor2725ca82010-04-21 19:57:20 +00004573 ObjCInterfaceDecl *CDecl = 0;
4574 if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
4575 // Figure out which interface we're in.
4576 CDecl = CurMethod->getClassInterface();
4577 if (!CDecl)
4578 return;
4579
4580 // Find the superclass of this class.
4581 CDecl = CDecl->getSuperClass();
4582 if (!CDecl)
4583 return;
4584
4585 if (CurMethod->isInstanceMethod()) {
4586 // We are inside an instance method, which means that the message
4587 // send [super ...] is actually calling an instance method on the
Douglas Gregor6b0656a2010-10-13 21:24:53 +00004588 // current object.
4589 return CodeCompleteObjCInstanceMessage(S, 0,
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004590 SelIdents, NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00004591 AtArgumentExpression,
Douglas Gregor6b0656a2010-10-13 21:24:53 +00004592 CDecl);
Douglas Gregor2725ca82010-04-21 19:57:20 +00004593 }
4594
4595 // Fall through to send to the superclass in CDecl.
4596 } else {
4597 // "super" may be the name of a type or variable. Figure out which
4598 // it is.
4599 IdentifierInfo *Super = &Context.Idents.get("super");
4600 NamedDecl *ND = LookupSingleName(S, Super, SuperLoc,
4601 LookupOrdinaryName);
4602 if ((CDecl = dyn_cast_or_null<ObjCInterfaceDecl>(ND))) {
4603 // "super" names an interface. Use it.
4604 } else if (TypeDecl *TD = dyn_cast_or_null<TypeDecl>(ND)) {
John McCallc12c5bb2010-05-15 11:32:37 +00004605 if (const ObjCObjectType *Iface
4606 = Context.getTypeDeclType(TD)->getAs<ObjCObjectType>())
4607 CDecl = Iface->getInterface();
Douglas Gregor2725ca82010-04-21 19:57:20 +00004608 } else if (ND && isa<UnresolvedUsingTypenameDecl>(ND)) {
4609 // "super" names an unresolved type; we can't be more specific.
4610 } else {
4611 // Assume that "super" names some kind of value and parse that way.
4612 CXXScopeSpec SS;
4613 UnqualifiedId id;
4614 id.setIdentifier(Super, SuperLoc);
John McCall60d7b3a2010-08-24 06:29:42 +00004615 ExprResult SuperExpr = ActOnIdExpression(S, SS, id, false, false);
Douglas Gregor2725ca82010-04-21 19:57:20 +00004616 return CodeCompleteObjCInstanceMessage(S, (Expr *)SuperExpr.get(),
Douglas Gregor70c5ac72010-09-20 23:34:21 +00004617 SelIdents, NumSelIdents,
4618 AtArgumentExpression);
Douglas Gregor2725ca82010-04-21 19:57:20 +00004619 }
4620
4621 // Fall through
4622 }
4623
John McCallb3d87482010-08-24 05:47:05 +00004624 ParsedType Receiver;
Douglas Gregor2725ca82010-04-21 19:57:20 +00004625 if (CDecl)
John McCallb3d87482010-08-24 05:47:05 +00004626 Receiver = ParsedType::make(Context.getObjCInterfaceType(CDecl));
Douglas Gregor2725ca82010-04-21 19:57:20 +00004627 return CodeCompleteObjCClassMessage(S, Receiver, SelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00004628 NumSelIdents, AtArgumentExpression,
4629 /*IsSuper=*/true);
Douglas Gregor2725ca82010-04-21 19:57:20 +00004630}
4631
Douglas Gregorb9d77572010-09-21 00:03:25 +00004632/// \brief Given a set of code-completion results for the argument of a message
4633/// send, determine the preferred type (if any) for that argument expression.
4634static QualType getPreferredArgumentTypeForMessageSend(ResultBuilder &Results,
4635 unsigned NumSelIdents) {
4636 typedef CodeCompletionResult Result;
4637 ASTContext &Context = Results.getSema().Context;
4638
4639 QualType PreferredType;
4640 unsigned BestPriority = CCP_Unlikely * 2;
4641 Result *ResultsData = Results.data();
4642 for (unsigned I = 0, N = Results.size(); I != N; ++I) {
4643 Result &R = ResultsData[I];
4644 if (R.Kind == Result::RK_Declaration &&
4645 isa<ObjCMethodDecl>(R.Declaration)) {
4646 if (R.Priority <= BestPriority) {
4647 ObjCMethodDecl *Method = cast<ObjCMethodDecl>(R.Declaration);
4648 if (NumSelIdents <= Method->param_size()) {
4649 QualType MyPreferredType = Method->param_begin()[NumSelIdents - 1]
4650 ->getType();
4651 if (R.Priority < BestPriority || PreferredType.isNull()) {
4652 BestPriority = R.Priority;
4653 PreferredType = MyPreferredType;
4654 } else if (!Context.hasSameUnqualifiedType(PreferredType,
4655 MyPreferredType)) {
4656 PreferredType = QualType();
4657 }
4658 }
4659 }
4660 }
4661 }
4662
4663 return PreferredType;
4664}
4665
Douglas Gregorc7b6d882010-09-16 15:14:18 +00004666static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
4667 ParsedType Receiver,
4668 IdentifierInfo **SelIdents,
4669 unsigned NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00004670 bool AtArgumentExpression,
Douglas Gregorc7b6d882010-09-16 15:14:18 +00004671 bool IsSuper,
4672 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00004673 typedef CodeCompletionResult Result;
Douglas Gregor24a069f2009-11-17 17:59:40 +00004674 ObjCInterfaceDecl *CDecl = 0;
Douglas Gregorc7b6d882010-09-16 15:14:18 +00004675
Douglas Gregor24a069f2009-11-17 17:59:40 +00004676 // If the given name refers to an interface type, retrieve the
4677 // corresponding declaration.
Douglas Gregor2725ca82010-04-21 19:57:20 +00004678 if (Receiver) {
Douglas Gregorc7b6d882010-09-16 15:14:18 +00004679 QualType T = SemaRef.GetTypeFromParser(Receiver, 0);
Douglas Gregor2725ca82010-04-21 19:57:20 +00004680 if (!T.isNull())
John McCallc12c5bb2010-05-15 11:32:37 +00004681 if (const ObjCObjectType *Interface = T->getAs<ObjCObjectType>())
4682 CDecl = Interface->getInterface();
Douglas Gregor24a069f2009-11-17 17:59:40 +00004683 }
Douglas Gregorc7b6d882010-09-16 15:14:18 +00004684
Douglas Gregor36ecb042009-11-17 23:22:23 +00004685 // Add all of the factory methods in this Objective-C class, its protocols,
4686 // superclasses, categories, implementation, etc.
Steve Naroffc4df6d22009-11-07 02:08:14 +00004687 Results.EnterNewScope();
Douglas Gregorc7b6d882010-09-16 15:14:18 +00004688
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004689 // If this is a send-to-super, try to add the special "super" send
4690 // completion.
4691 if (IsSuper) {
4692 if (ObjCMethodDecl *SuperMethod
Douglas Gregorc7b6d882010-09-16 15:14:18 +00004693 = AddSuperSendCompletion(SemaRef, false, SelIdents, NumSelIdents,
4694 Results))
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004695 Results.Ignore(SuperMethod);
4696 }
Douglas Gregorc7b6d882010-09-16 15:14:18 +00004697
Douglas Gregor265f7492010-08-27 15:29:55 +00004698 // If we're inside an Objective-C method definition, prefer its selector to
4699 // others.
Douglas Gregorc7b6d882010-09-16 15:14:18 +00004700 if (ObjCMethodDecl *CurMethod = SemaRef.getCurMethodDecl())
Douglas Gregor265f7492010-08-27 15:29:55 +00004701 Results.setPreferredSelector(CurMethod->getSelector());
Douglas Gregorc7b6d882010-09-16 15:14:18 +00004702
Douglas Gregord36adf52010-09-16 16:06:31 +00004703 VisitedSelectorSet Selectors;
Douglas Gregor13438f92010-04-06 16:40:00 +00004704 if (CDecl)
Douglas Gregorc7b6d882010-09-16 15:14:18 +00004705 AddObjCMethods(CDecl, false, MK_Any, SelIdents, NumSelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004706 SemaRef.CurContext, Selectors, AtArgumentExpression,
4707 Results);
Douglas Gregor2725ca82010-04-21 19:57:20 +00004708 else {
Douglas Gregor13438f92010-04-06 16:40:00 +00004709 // We're messaging "id" as a type; provide all class/factory methods.
Douglas Gregorc7b6d882010-09-16 15:14:18 +00004710
Douglas Gregor719770d2010-04-06 17:30:22 +00004711 // If we have an external source, load the entire class method
Sebastian Redl3c7f4132010-08-18 23:57:06 +00004712 // pool from the AST file.
Douglas Gregorc7b6d882010-09-16 15:14:18 +00004713 if (SemaRef.ExternalSource) {
4714 for (uint32_t I = 0,
4715 N = SemaRef.ExternalSource->GetNumExternalSelectors();
John McCall76bd1f32010-06-01 09:23:16 +00004716 I != N; ++I) {
Douglas Gregorc7b6d882010-09-16 15:14:18 +00004717 Selector Sel = SemaRef.ExternalSource->GetExternalSelector(I);
4718 if (Sel.isNull() || SemaRef.MethodPool.count(Sel))
Douglas Gregor719770d2010-04-06 17:30:22 +00004719 continue;
Douglas Gregorc7b6d882010-09-16 15:14:18 +00004720
4721 SemaRef.ReadMethodPool(Sel);
Douglas Gregor719770d2010-04-06 17:30:22 +00004722 }
4723 }
Douglas Gregorc7b6d882010-09-16 15:14:18 +00004724
4725 for (Sema::GlobalMethodPool::iterator M = SemaRef.MethodPool.begin(),
4726 MEnd = SemaRef.MethodPool.end();
Sebastian Redldb9d2142010-08-02 23:18:59 +00004727 M != MEnd; ++M) {
4728 for (ObjCMethodList *MethList = &M->second.second;
4729 MethList && MethList->Method;
Douglas Gregor13438f92010-04-06 16:40:00 +00004730 MethList = MethList->Next) {
4731 if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents,
4732 NumSelIdents))
4733 continue;
Douglas Gregorc7b6d882010-09-16 15:14:18 +00004734
Douglas Gregor13438f92010-04-06 16:40:00 +00004735 Result R(MethList->Method, 0);
4736 R.StartParameter = NumSelIdents;
4737 R.AllParametersAreInformative = false;
Douglas Gregorc7b6d882010-09-16 15:14:18 +00004738 Results.MaybeAddResult(R, SemaRef.CurContext);
Douglas Gregor13438f92010-04-06 16:40:00 +00004739 }
4740 }
4741 }
Douglas Gregorc7b6d882010-09-16 15:14:18 +00004742
4743 Results.ExitScope();
4744}
Douglas Gregor13438f92010-04-06 16:40:00 +00004745
Douglas Gregorc7b6d882010-09-16 15:14:18 +00004746void Sema::CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver,
4747 IdentifierInfo **SelIdents,
4748 unsigned NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00004749 bool AtArgumentExpression,
Douglas Gregorc7b6d882010-09-16 15:14:18 +00004750 bool IsSuper) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004751 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4752 CodeCompletionContext::CCC_Other);
Douglas Gregor70c5ac72010-09-20 23:34:21 +00004753 AddClassMessageCompletions(*this, S, Receiver, SelIdents, NumSelIdents,
4754 AtArgumentExpression, IsSuper, Results);
Douglas Gregorb9d77572010-09-21 00:03:25 +00004755
4756 // If we're actually at the argument expression (rather than prior to the
4757 // selector), we're actually performing code completion for an expression.
4758 // Determine whether we have a single, best method. If so, we can
4759 // code-complete the expression using the corresponding parameter type as
4760 // our preferred type, improving completion results.
4761 if (AtArgumentExpression) {
4762 QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results,
4763 NumSelIdents);
4764 if (PreferredType.isNull())
4765 CodeCompleteOrdinaryName(S, PCC_Expression);
4766 else
4767 CodeCompleteExpression(S, PreferredType);
4768 return;
4769 }
4770
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004771 HandleCodeCompleteResults(this, CodeCompleter,
4772 CodeCompletionContext::CCC_Other,
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004773 Results.data(), Results.size());
Steve Naroffc4df6d22009-11-07 02:08:14 +00004774}
4775
Douglas Gregord3c68542009-11-19 01:08:35 +00004776void Sema::CodeCompleteObjCInstanceMessage(Scope *S, ExprTy *Receiver,
4777 IdentifierInfo **SelIdents,
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004778 unsigned NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00004779 bool AtArgumentExpression,
Douglas Gregor6b0656a2010-10-13 21:24:53 +00004780 ObjCInterfaceDecl *Super) {
John McCall0a2c5e22010-08-25 06:19:51 +00004781 typedef CodeCompletionResult Result;
Steve Naroffc4df6d22009-11-07 02:08:14 +00004782
4783 Expr *RecExpr = static_cast<Expr *>(Receiver);
Steve Naroffc4df6d22009-11-07 02:08:14 +00004784
Douglas Gregor36ecb042009-11-17 23:22:23 +00004785 // If necessary, apply function/array conversion to the receiver.
4786 // C99 6.7.5.3p[7,8].
Douglas Gregor78edf512010-09-15 16:23:04 +00004787 if (RecExpr)
4788 DefaultFunctionArrayLvalueConversion(RecExpr);
Douglas Gregor6b0656a2010-10-13 21:24:53 +00004789 QualType ReceiverType = RecExpr? RecExpr->getType()
4790 : Super? Context.getObjCObjectPointerType(
4791 Context.getObjCInterfaceType(Super))
4792 : Context.getObjCIdType();
Steve Naroffc4df6d22009-11-07 02:08:14 +00004793
Douglas Gregorda892642010-11-08 21:12:30 +00004794 // If we're messaging an expression with type "id" or "Class", check
4795 // whether we know something special about the receiver that allows
4796 // us to assume a more-specific receiver type.
4797 if (ReceiverType->isObjCIdType() || ReceiverType->isObjCClassType())
4798 if (ObjCInterfaceDecl *IFace = GetAssumedMessageSendExprType(RecExpr)) {
4799 if (ReceiverType->isObjCClassType())
4800 return CodeCompleteObjCClassMessage(S,
4801 ParsedType::make(Context.getObjCInterfaceType(IFace)),
4802 SelIdents, NumSelIdents,
4803 AtArgumentExpression, Super);
4804
4805 ReceiverType = Context.getObjCObjectPointerType(
4806 Context.getObjCInterfaceType(IFace));
4807 }
4808
Douglas Gregor36ecb042009-11-17 23:22:23 +00004809 // Build the set of methods we can see.
Douglas Gregor218937c2011-02-01 19:23:04 +00004810 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4811 CodeCompletionContext::CCC_Other);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004812 Results.EnterNewScope();
Douglas Gregor22f56992010-04-06 19:22:33 +00004813
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004814 // If this is a send-to-super, try to add the special "super" send
4815 // completion.
Douglas Gregor6b0656a2010-10-13 21:24:53 +00004816 if (Super) {
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004817 if (ObjCMethodDecl *SuperMethod
4818 = AddSuperSendCompletion(*this, false, SelIdents, NumSelIdents,
4819 Results))
4820 Results.Ignore(SuperMethod);
4821 }
4822
Douglas Gregor265f7492010-08-27 15:29:55 +00004823 // If we're inside an Objective-C method definition, prefer its selector to
4824 // others.
4825 if (ObjCMethodDecl *CurMethod = getCurMethodDecl())
4826 Results.setPreferredSelector(CurMethod->getSelector());
Douglas Gregor36ecb042009-11-17 23:22:23 +00004827
Douglas Gregord36adf52010-09-16 16:06:31 +00004828 // Keep track of the selectors we've already added.
4829 VisitedSelectorSet Selectors;
4830
Douglas Gregorf74a4192009-11-18 00:06:18 +00004831 // Handle messages to Class. This really isn't a message to an instance
4832 // method, so we treat it the same way we would treat a message send to a
4833 // class method.
4834 if (ReceiverType->isObjCClassType() ||
4835 ReceiverType->isObjCQualifiedClassType()) {
4836 if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
4837 if (ObjCInterfaceDecl *ClassDecl = CurMethod->getClassInterface())
Douglas Gregor4ad96852009-11-19 07:41:15 +00004838 AddObjCMethods(ClassDecl, false, MK_Any, SelIdents, NumSelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004839 CurContext, Selectors, AtArgumentExpression, Results);
Douglas Gregorf74a4192009-11-18 00:06:18 +00004840 }
4841 }
4842 // Handle messages to a qualified ID ("id<foo>").
4843 else if (const ObjCObjectPointerType *QualID
4844 = ReceiverType->getAsObjCQualifiedIdType()) {
4845 // Search protocols for instance methods.
4846 for (ObjCObjectPointerType::qual_iterator I = QualID->qual_begin(),
4847 E = QualID->qual_end();
4848 I != E; ++I)
Douglas Gregor4ad96852009-11-19 07:41:15 +00004849 AddObjCMethods(*I, true, MK_Any, SelIdents, NumSelIdents, CurContext,
Douglas Gregorcf544262010-11-17 21:36:08 +00004850 Selectors, AtArgumentExpression, Results);
Douglas Gregorf74a4192009-11-18 00:06:18 +00004851 }
4852 // Handle messages to a pointer to interface type.
4853 else if (const ObjCObjectPointerType *IFacePtr
4854 = ReceiverType->getAsObjCInterfacePointerType()) {
4855 // Search the class, its superclasses, etc., for instance methods.
Douglas Gregor4ad96852009-11-19 07:41:15 +00004856 AddObjCMethods(IFacePtr->getInterfaceDecl(), true, MK_Any, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004857 NumSelIdents, CurContext, Selectors, AtArgumentExpression,
4858 Results);
Douglas Gregorf74a4192009-11-18 00:06:18 +00004859
4860 // Search protocols for instance methods.
4861 for (ObjCObjectPointerType::qual_iterator I = IFacePtr->qual_begin(),
4862 E = IFacePtr->qual_end();
4863 I != E; ++I)
Douglas Gregor4ad96852009-11-19 07:41:15 +00004864 AddObjCMethods(*I, true, MK_Any, SelIdents, NumSelIdents, CurContext,
Douglas Gregorcf544262010-11-17 21:36:08 +00004865 Selectors, AtArgumentExpression, Results);
Douglas Gregorf74a4192009-11-18 00:06:18 +00004866 }
Douglas Gregor13438f92010-04-06 16:40:00 +00004867 // Handle messages to "id".
4868 else if (ReceiverType->isObjCIdType()) {
Douglas Gregor719770d2010-04-06 17:30:22 +00004869 // We're messaging "id", so provide all instance methods we know
4870 // about as code-completion results.
4871
4872 // If we have an external source, load the entire class method
Sebastian Redl3c7f4132010-08-18 23:57:06 +00004873 // pool from the AST file.
Douglas Gregor719770d2010-04-06 17:30:22 +00004874 if (ExternalSource) {
John McCall76bd1f32010-06-01 09:23:16 +00004875 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
4876 I != N; ++I) {
4877 Selector Sel = ExternalSource->GetExternalSelector(I);
Sebastian Redldb9d2142010-08-02 23:18:59 +00004878 if (Sel.isNull() || MethodPool.count(Sel))
Douglas Gregor719770d2010-04-06 17:30:22 +00004879 continue;
4880
Sebastian Redldb9d2142010-08-02 23:18:59 +00004881 ReadMethodPool(Sel);
Douglas Gregor719770d2010-04-06 17:30:22 +00004882 }
4883 }
4884
Sebastian Redldb9d2142010-08-02 23:18:59 +00004885 for (GlobalMethodPool::iterator M = MethodPool.begin(),
4886 MEnd = MethodPool.end();
4887 M != MEnd; ++M) {
4888 for (ObjCMethodList *MethList = &M->second.first;
4889 MethList && MethList->Method;
Douglas Gregor13438f92010-04-06 16:40:00 +00004890 MethList = MethList->Next) {
4891 if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents,
4892 NumSelIdents))
4893 continue;
Douglas Gregord36adf52010-09-16 16:06:31 +00004894
4895 if (!Selectors.insert(MethList->Method->getSelector()))
4896 continue;
4897
Douglas Gregor13438f92010-04-06 16:40:00 +00004898 Result R(MethList->Method, 0);
4899 R.StartParameter = NumSelIdents;
4900 R.AllParametersAreInformative = false;
4901 Results.MaybeAddResult(R, CurContext);
4902 }
4903 }
4904 }
Steve Naroffc4df6d22009-11-07 02:08:14 +00004905 Results.ExitScope();
Douglas Gregorb9d77572010-09-21 00:03:25 +00004906
4907
4908 // If we're actually at the argument expression (rather than prior to the
4909 // selector), we're actually performing code completion for an expression.
4910 // Determine whether we have a single, best method. If so, we can
4911 // code-complete the expression using the corresponding parameter type as
4912 // our preferred type, improving completion results.
4913 if (AtArgumentExpression) {
4914 QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results,
4915 NumSelIdents);
4916 if (PreferredType.isNull())
4917 CodeCompleteOrdinaryName(S, PCC_Expression);
4918 else
4919 CodeCompleteExpression(S, PreferredType);
4920 return;
4921 }
4922
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004923 HandleCodeCompleteResults(this, CodeCompleter,
4924 CodeCompletionContext::CCC_Other,
4925 Results.data(),Results.size());
Steve Naroffc4df6d22009-11-07 02:08:14 +00004926}
Douglas Gregor55385fe2009-11-18 04:19:12 +00004927
Douglas Gregorfb629412010-08-23 21:17:50 +00004928void Sema::CodeCompleteObjCForCollection(Scope *S,
4929 DeclGroupPtrTy IterationVar) {
4930 CodeCompleteExpressionData Data;
4931 Data.ObjCCollection = true;
4932
4933 if (IterationVar.getAsOpaquePtr()) {
4934 DeclGroupRef DG = IterationVar.getAsVal<DeclGroupRef>();
4935 for (DeclGroupRef::iterator I = DG.begin(), End = DG.end(); I != End; ++I) {
4936 if (*I)
4937 Data.IgnoreDecls.push_back(*I);
4938 }
4939 }
4940
4941 CodeCompleteExpression(S, Data);
4942}
4943
Douglas Gregor458433d2010-08-26 15:07:07 +00004944void Sema::CodeCompleteObjCSelector(Scope *S, IdentifierInfo **SelIdents,
4945 unsigned NumSelIdents) {
4946 // If we have an external source, load the entire class method
4947 // pool from the AST file.
4948 if (ExternalSource) {
4949 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
4950 I != N; ++I) {
4951 Selector Sel = ExternalSource->GetExternalSelector(I);
4952 if (Sel.isNull() || MethodPool.count(Sel))
4953 continue;
4954
4955 ReadMethodPool(Sel);
4956 }
4957 }
4958
Douglas Gregor218937c2011-02-01 19:23:04 +00004959 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4960 CodeCompletionContext::CCC_SelectorName);
Douglas Gregor458433d2010-08-26 15:07:07 +00004961 Results.EnterNewScope();
4962 for (GlobalMethodPool::iterator M = MethodPool.begin(),
4963 MEnd = MethodPool.end();
4964 M != MEnd; ++M) {
4965
4966 Selector Sel = M->first;
4967 if (!isAcceptableObjCSelector(Sel, MK_Any, SelIdents, NumSelIdents))
4968 continue;
4969
Douglas Gregor218937c2011-02-01 19:23:04 +00004970 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregor458433d2010-08-26 15:07:07 +00004971 if (Sel.isUnarySelector()) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004972 Builder.AddTypedTextChunk(CopyString(Builder.getAllocator(),
4973 Sel.getIdentifierInfoForSlot(0)->getName()));
4974 Results.AddResult(Builder.TakeString());
Douglas Gregor458433d2010-08-26 15:07:07 +00004975 continue;
4976 }
4977
Douglas Gregor2d9e21f2010-08-26 16:46:39 +00004978 std::string Accumulator;
Douglas Gregor458433d2010-08-26 15:07:07 +00004979 for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I) {
Douglas Gregor2d9e21f2010-08-26 16:46:39 +00004980 if (I == NumSelIdents) {
4981 if (!Accumulator.empty()) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004982 Builder.AddInformativeChunk(CopyString(Builder.getAllocator(),
4983 Accumulator));
Douglas Gregor2d9e21f2010-08-26 16:46:39 +00004984 Accumulator.clear();
4985 }
4986 }
4987
4988 Accumulator += Sel.getIdentifierInfoForSlot(I)->getName().str();
4989 Accumulator += ':';
Douglas Gregor458433d2010-08-26 15:07:07 +00004990 }
Douglas Gregor218937c2011-02-01 19:23:04 +00004991 Builder.AddTypedTextChunk(CopyString(Builder.getAllocator(), Accumulator));
4992 Results.AddResult(Builder.TakeString());
Douglas Gregor458433d2010-08-26 15:07:07 +00004993 }
4994 Results.ExitScope();
4995
4996 HandleCodeCompleteResults(this, CodeCompleter,
4997 CodeCompletionContext::CCC_SelectorName,
4998 Results.data(), Results.size());
4999}
5000
Douglas Gregor55385fe2009-11-18 04:19:12 +00005001/// \brief Add all of the protocol declarations that we find in the given
5002/// (translation unit) context.
5003static void AddProtocolResults(DeclContext *Ctx, DeclContext *CurContext,
Douglas Gregor083128f2009-11-18 04:49:41 +00005004 bool OnlyForwardDeclarations,
Douglas Gregor55385fe2009-11-18 04:19:12 +00005005 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00005006 typedef CodeCompletionResult Result;
Douglas Gregor55385fe2009-11-18 04:19:12 +00005007
5008 for (DeclContext::decl_iterator D = Ctx->decls_begin(),
5009 DEnd = Ctx->decls_end();
5010 D != DEnd; ++D) {
5011 // Record any protocols we find.
5012 if (ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>(*D))
Douglas Gregor083128f2009-11-18 04:49:41 +00005013 if (!OnlyForwardDeclarations || Proto->isForwardDecl())
Douglas Gregor608300b2010-01-14 16:14:35 +00005014 Results.AddResult(Result(Proto, 0), CurContext, 0, false);
Douglas Gregor55385fe2009-11-18 04:19:12 +00005015
5016 // Record any forward-declared protocols we find.
5017 if (ObjCForwardProtocolDecl *Forward
5018 = dyn_cast<ObjCForwardProtocolDecl>(*D)) {
5019 for (ObjCForwardProtocolDecl::protocol_iterator
5020 P = Forward->protocol_begin(),
5021 PEnd = Forward->protocol_end();
5022 P != PEnd; ++P)
Douglas Gregor083128f2009-11-18 04:49:41 +00005023 if (!OnlyForwardDeclarations || (*P)->isForwardDecl())
Douglas Gregor608300b2010-01-14 16:14:35 +00005024 Results.AddResult(Result(*P, 0), CurContext, 0, false);
Douglas Gregor55385fe2009-11-18 04:19:12 +00005025 }
5026 }
5027}
5028
5029void Sema::CodeCompleteObjCProtocolReferences(IdentifierLocPair *Protocols,
5030 unsigned NumProtocols) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005031 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5032 CodeCompletionContext::CCC_ObjCProtocolName);
Douglas Gregor55385fe2009-11-18 04:19:12 +00005033
Douglas Gregor70c23352010-12-09 21:44:02 +00005034 if (CodeCompleter && CodeCompleter->includeGlobals()) {
5035 Results.EnterNewScope();
5036
5037 // Tell the result set to ignore all of the protocols we have
5038 // already seen.
5039 // FIXME: This doesn't work when caching code-completion results.
5040 for (unsigned I = 0; I != NumProtocols; ++I)
5041 if (ObjCProtocolDecl *Protocol = LookupProtocol(Protocols[I].first,
5042 Protocols[I].second))
5043 Results.Ignore(Protocol);
Douglas Gregor55385fe2009-11-18 04:19:12 +00005044
Douglas Gregor70c23352010-12-09 21:44:02 +00005045 // Add all protocols.
5046 AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, false,
5047 Results);
Douglas Gregor083128f2009-11-18 04:49:41 +00005048
Douglas Gregor70c23352010-12-09 21:44:02 +00005049 Results.ExitScope();
5050 }
5051
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005052 HandleCodeCompleteResults(this, CodeCompleter,
5053 CodeCompletionContext::CCC_ObjCProtocolName,
5054 Results.data(),Results.size());
Douglas Gregor083128f2009-11-18 04:49:41 +00005055}
5056
5057void Sema::CodeCompleteObjCProtocolDecl(Scope *) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005058 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5059 CodeCompletionContext::CCC_ObjCProtocolName);
Douglas Gregor083128f2009-11-18 04:49:41 +00005060
Douglas Gregor70c23352010-12-09 21:44:02 +00005061 if (CodeCompleter && CodeCompleter->includeGlobals()) {
5062 Results.EnterNewScope();
5063
5064 // Add all protocols.
5065 AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, true,
5066 Results);
Douglas Gregor55385fe2009-11-18 04:19:12 +00005067
Douglas Gregor70c23352010-12-09 21:44:02 +00005068 Results.ExitScope();
5069 }
5070
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005071 HandleCodeCompleteResults(this, CodeCompleter,
5072 CodeCompletionContext::CCC_ObjCProtocolName,
5073 Results.data(),Results.size());
Douglas Gregor55385fe2009-11-18 04:19:12 +00005074}
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005075
5076/// \brief Add all of the Objective-C interface declarations that we find in
5077/// the given (translation unit) context.
5078static void AddInterfaceResults(DeclContext *Ctx, DeclContext *CurContext,
5079 bool OnlyForwardDeclarations,
5080 bool OnlyUnimplemented,
5081 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00005082 typedef CodeCompletionResult Result;
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005083
5084 for (DeclContext::decl_iterator D = Ctx->decls_begin(),
5085 DEnd = Ctx->decls_end();
5086 D != DEnd; ++D) {
Douglas Gregordeacbdc2010-08-11 12:19:30 +00005087 // Record any interfaces we find.
5088 if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(*D))
5089 if ((!OnlyForwardDeclarations || Class->isForwardDecl()) &&
5090 (!OnlyUnimplemented || !Class->getImplementation()))
5091 Results.AddResult(Result(Class, 0), CurContext, 0, false);
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005092
5093 // Record any forward-declared interfaces we find.
5094 if (ObjCClassDecl *Forward = dyn_cast<ObjCClassDecl>(*D)) {
5095 for (ObjCClassDecl::iterator C = Forward->begin(), CEnd = Forward->end();
Douglas Gregordeacbdc2010-08-11 12:19:30 +00005096 C != CEnd; ++C)
5097 if ((!OnlyForwardDeclarations || C->getInterface()->isForwardDecl()) &&
5098 (!OnlyUnimplemented || !C->getInterface()->getImplementation()))
5099 Results.AddResult(Result(C->getInterface(), 0), CurContext,
Douglas Gregor608300b2010-01-14 16:14:35 +00005100 0, false);
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005101 }
5102 }
5103}
5104
5105void Sema::CodeCompleteObjCInterfaceDecl(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005106 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5107 CodeCompletionContext::CCC_Other);
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005108 Results.EnterNewScope();
5109
5110 // Add all classes.
5111 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, true,
5112 false, Results);
5113
5114 Results.ExitScope();
Douglas Gregor52779fb2010-09-23 23:01:17 +00005115 // FIXME: Add a special context for this, use cached global completion
5116 // results.
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005117 HandleCodeCompleteResults(this, CodeCompleter,
5118 CodeCompletionContext::CCC_Other,
5119 Results.data(),Results.size());
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005120}
5121
Douglas Gregorc83c6872010-04-15 22:33:43 +00005122void Sema::CodeCompleteObjCSuperclass(Scope *S, IdentifierInfo *ClassName,
5123 SourceLocation ClassNameLoc) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005124 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5125 CodeCompletionContext::CCC_Other);
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005126 Results.EnterNewScope();
5127
5128 // Make sure that we ignore the class we're currently defining.
5129 NamedDecl *CurClass
Douglas Gregorc83c6872010-04-15 22:33:43 +00005130 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005131 if (CurClass && isa<ObjCInterfaceDecl>(CurClass))
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005132 Results.Ignore(CurClass);
5133
5134 // Add all classes.
5135 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
5136 false, Results);
5137
5138 Results.ExitScope();
Douglas Gregor52779fb2010-09-23 23:01:17 +00005139 // FIXME: Add a special context for this, use cached global completion
5140 // results.
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005141 HandleCodeCompleteResults(this, CodeCompleter,
5142 CodeCompletionContext::CCC_Other,
5143 Results.data(),Results.size());
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005144}
5145
5146void Sema::CodeCompleteObjCImplementationDecl(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005147 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5148 CodeCompletionContext::CCC_Other);
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005149 Results.EnterNewScope();
5150
5151 // Add all unimplemented classes.
5152 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
5153 true, Results);
5154
5155 Results.ExitScope();
Douglas Gregor52779fb2010-09-23 23:01:17 +00005156 // FIXME: Add a special context for this, use cached global completion
5157 // results.
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005158 HandleCodeCompleteResults(this, CodeCompleter,
5159 CodeCompletionContext::CCC_Other,
5160 Results.data(),Results.size());
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005161}
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005162
5163void Sema::CodeCompleteObjCInterfaceCategory(Scope *S,
Douglas Gregorc83c6872010-04-15 22:33:43 +00005164 IdentifierInfo *ClassName,
5165 SourceLocation ClassNameLoc) {
John McCall0a2c5e22010-08-25 06:19:51 +00005166 typedef CodeCompletionResult Result;
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005167
Douglas Gregor218937c2011-02-01 19:23:04 +00005168 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5169 CodeCompletionContext::CCC_Other);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005170
5171 // Ignore any categories we find that have already been implemented by this
5172 // interface.
5173 llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
5174 NamedDecl *CurClass
Douglas Gregorc83c6872010-04-15 22:33:43 +00005175 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005176 if (ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass))
5177 for (ObjCCategoryDecl *Category = Class->getCategoryList(); Category;
5178 Category = Category->getNextClassCategory())
5179 CategoryNames.insert(Category->getIdentifier());
5180
5181 // Add all of the categories we know about.
5182 Results.EnterNewScope();
5183 TranslationUnitDecl *TU = Context.getTranslationUnitDecl();
5184 for (DeclContext::decl_iterator D = TU->decls_begin(),
5185 DEnd = TU->decls_end();
5186 D != DEnd; ++D)
5187 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(*D))
5188 if (CategoryNames.insert(Category->getIdentifier()))
Douglas Gregor608300b2010-01-14 16:14:35 +00005189 Results.AddResult(Result(Category, 0), CurContext, 0, false);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005190 Results.ExitScope();
5191
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005192 HandleCodeCompleteResults(this, CodeCompleter,
5193 CodeCompletionContext::CCC_Other,
5194 Results.data(),Results.size());
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005195}
5196
5197void Sema::CodeCompleteObjCImplementationCategory(Scope *S,
Douglas Gregorc83c6872010-04-15 22:33:43 +00005198 IdentifierInfo *ClassName,
5199 SourceLocation ClassNameLoc) {
John McCall0a2c5e22010-08-25 06:19:51 +00005200 typedef CodeCompletionResult Result;
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005201
5202 // Find the corresponding interface. If we couldn't find the interface, the
5203 // program itself is ill-formed. However, we'll try to be helpful still by
5204 // providing the list of all of the categories we know about.
5205 NamedDecl *CurClass
Douglas Gregorc83c6872010-04-15 22:33:43 +00005206 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005207 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass);
5208 if (!Class)
Douglas Gregorc83c6872010-04-15 22:33:43 +00005209 return CodeCompleteObjCInterfaceCategory(S, ClassName, ClassNameLoc);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005210
Douglas Gregor218937c2011-02-01 19:23:04 +00005211 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5212 CodeCompletionContext::CCC_Other);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005213
5214 // Add all of the categories that have have corresponding interface
5215 // declarations in this class and any of its superclasses, except for
5216 // already-implemented categories in the class itself.
5217 llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
5218 Results.EnterNewScope();
5219 bool IgnoreImplemented = true;
5220 while (Class) {
5221 for (ObjCCategoryDecl *Category = Class->getCategoryList(); Category;
5222 Category = Category->getNextClassCategory())
5223 if ((!IgnoreImplemented || !Category->getImplementation()) &&
5224 CategoryNames.insert(Category->getIdentifier()))
Douglas Gregor608300b2010-01-14 16:14:35 +00005225 Results.AddResult(Result(Category, 0), CurContext, 0, false);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005226
5227 Class = Class->getSuperClass();
5228 IgnoreImplemented = false;
5229 }
5230 Results.ExitScope();
5231
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005232 HandleCodeCompleteResults(this, CodeCompleter,
5233 CodeCompletionContext::CCC_Other,
5234 Results.data(),Results.size());
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005235}
Douglas Gregor322328b2009-11-18 22:32:06 +00005236
John McCalld226f652010-08-21 09:40:31 +00005237void Sema::CodeCompleteObjCPropertyDefinition(Scope *S, Decl *ObjCImpDecl) {
John McCall0a2c5e22010-08-25 06:19:51 +00005238 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00005239 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5240 CodeCompletionContext::CCC_Other);
Douglas Gregor322328b2009-11-18 22:32:06 +00005241
5242 // Figure out where this @synthesize lives.
5243 ObjCContainerDecl *Container
John McCalld226f652010-08-21 09:40:31 +00005244 = dyn_cast_or_null<ObjCContainerDecl>(ObjCImpDecl);
Douglas Gregor322328b2009-11-18 22:32:06 +00005245 if (!Container ||
5246 (!isa<ObjCImplementationDecl>(Container) &&
5247 !isa<ObjCCategoryImplDecl>(Container)))
5248 return;
5249
5250 // Ignore any properties that have already been implemented.
5251 for (DeclContext::decl_iterator D = Container->decls_begin(),
5252 DEnd = Container->decls_end();
5253 D != DEnd; ++D)
5254 if (ObjCPropertyImplDecl *PropertyImpl = dyn_cast<ObjCPropertyImplDecl>(*D))
5255 Results.Ignore(PropertyImpl->getPropertyDecl());
5256
5257 // Add any properties that we find.
Douglas Gregor73449212010-12-09 23:01:55 +00005258 AddedPropertiesSet AddedProperties;
Douglas Gregor322328b2009-11-18 22:32:06 +00005259 Results.EnterNewScope();
5260 if (ObjCImplementationDecl *ClassImpl
5261 = dyn_cast<ObjCImplementationDecl>(Container))
5262 AddObjCProperties(ClassImpl->getClassInterface(), false, CurContext,
Douglas Gregor73449212010-12-09 23:01:55 +00005263 AddedProperties, Results);
Douglas Gregor322328b2009-11-18 22:32:06 +00005264 else
5265 AddObjCProperties(cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl(),
Douglas Gregor73449212010-12-09 23:01:55 +00005266 false, CurContext, AddedProperties, Results);
Douglas Gregor322328b2009-11-18 22:32:06 +00005267 Results.ExitScope();
5268
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005269 HandleCodeCompleteResults(this, CodeCompleter,
5270 CodeCompletionContext::CCC_Other,
5271 Results.data(),Results.size());
Douglas Gregor322328b2009-11-18 22:32:06 +00005272}
5273
5274void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S,
5275 IdentifierInfo *PropertyName,
John McCalld226f652010-08-21 09:40:31 +00005276 Decl *ObjCImpDecl) {
John McCall0a2c5e22010-08-25 06:19:51 +00005277 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00005278 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5279 CodeCompletionContext::CCC_Other);
Douglas Gregor322328b2009-11-18 22:32:06 +00005280
5281 // Figure out where this @synthesize lives.
5282 ObjCContainerDecl *Container
John McCalld226f652010-08-21 09:40:31 +00005283 = dyn_cast_or_null<ObjCContainerDecl>(ObjCImpDecl);
Douglas Gregor322328b2009-11-18 22:32:06 +00005284 if (!Container ||
5285 (!isa<ObjCImplementationDecl>(Container) &&
5286 !isa<ObjCCategoryImplDecl>(Container)))
5287 return;
5288
5289 // Figure out which interface we're looking into.
5290 ObjCInterfaceDecl *Class = 0;
5291 if (ObjCImplementationDecl *ClassImpl
5292 = dyn_cast<ObjCImplementationDecl>(Container))
5293 Class = ClassImpl->getClassInterface();
5294 else
5295 Class = cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl()
5296 ->getClassInterface();
5297
5298 // Add all of the instance variables in this class and its superclasses.
5299 Results.EnterNewScope();
5300 for(; Class; Class = Class->getSuperClass()) {
5301 // FIXME: We could screen the type of each ivar for compatibility with
5302 // the property, but is that being too paternal?
5303 for (ObjCInterfaceDecl::ivar_iterator IVar = Class->ivar_begin(),
5304 IVarEnd = Class->ivar_end();
5305 IVar != IVarEnd; ++IVar)
Douglas Gregor608300b2010-01-14 16:14:35 +00005306 Results.AddResult(Result(*IVar, 0), CurContext, 0, false);
Douglas Gregor322328b2009-11-18 22:32:06 +00005307 }
5308 Results.ExitScope();
5309
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005310 HandleCodeCompleteResults(this, CodeCompleter,
5311 CodeCompletionContext::CCC_Other,
5312 Results.data(),Results.size());
Douglas Gregor322328b2009-11-18 22:32:06 +00005313}
Douglas Gregore8f5a172010-04-07 00:21:17 +00005314
Douglas Gregor408be5a2010-08-25 01:08:01 +00005315// Mapping from selectors to the methods that implement that selector, along
5316// with the "in original class" flag.
5317typedef llvm::DenseMap<Selector, std::pair<ObjCMethodDecl *, bool> >
5318 KnownMethodsMap;
Douglas Gregore8f5a172010-04-07 00:21:17 +00005319
5320/// \brief Find all of the methods that reside in the given container
5321/// (and its superclasses, protocols, etc.) that meet the given
5322/// criteria. Insert those methods into the map of known methods,
5323/// indexed by selector so they can be easily found.
5324static void FindImplementableMethods(ASTContext &Context,
5325 ObjCContainerDecl *Container,
5326 bool WantInstanceMethods,
5327 QualType ReturnType,
Douglas Gregor408be5a2010-08-25 01:08:01 +00005328 KnownMethodsMap &KnownMethods,
5329 bool InOriginalClass = true) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00005330 if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)) {
5331 // Recurse into protocols.
5332 const ObjCList<ObjCProtocolDecl> &Protocols
5333 = IFace->getReferencedProtocols();
5334 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Douglas Gregorea766182010-10-18 18:21:28 +00005335 E = Protocols.end();
Douglas Gregore8f5a172010-04-07 00:21:17 +00005336 I != E; ++I)
5337 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
Douglas Gregorea766182010-10-18 18:21:28 +00005338 KnownMethods, InOriginalClass);
Douglas Gregore8f5a172010-04-07 00:21:17 +00005339
Douglas Gregorea766182010-10-18 18:21:28 +00005340 // Add methods from any class extensions and categories.
5341 for (const ObjCCategoryDecl *Cat = IFace->getCategoryList(); Cat;
5342 Cat = Cat->getNextClassCategory())
Fariborz Jahanian80aa1cd2010-06-22 23:20:40 +00005343 FindImplementableMethods(Context, const_cast<ObjCCategoryDecl*>(Cat),
5344 WantInstanceMethods, ReturnType,
Douglas Gregorea766182010-10-18 18:21:28 +00005345 KnownMethods, false);
5346
5347 // Visit the superclass.
5348 if (IFace->getSuperClass())
5349 FindImplementableMethods(Context, IFace->getSuperClass(),
5350 WantInstanceMethods, ReturnType,
5351 KnownMethods, false);
Douglas Gregore8f5a172010-04-07 00:21:17 +00005352 }
5353
5354 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(Container)) {
5355 // Recurse into protocols.
5356 const ObjCList<ObjCProtocolDecl> &Protocols
5357 = Category->getReferencedProtocols();
5358 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Douglas Gregorea766182010-10-18 18:21:28 +00005359 E = Protocols.end();
Douglas Gregore8f5a172010-04-07 00:21:17 +00005360 I != E; ++I)
5361 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
Douglas Gregorea766182010-10-18 18:21:28 +00005362 KnownMethods, InOriginalClass);
5363
5364 // If this category is the original class, jump to the interface.
5365 if (InOriginalClass && Category->getClassInterface())
5366 FindImplementableMethods(Context, Category->getClassInterface(),
5367 WantInstanceMethods, ReturnType, KnownMethods,
5368 false);
Douglas Gregore8f5a172010-04-07 00:21:17 +00005369 }
5370
5371 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
5372 // Recurse into protocols.
5373 const ObjCList<ObjCProtocolDecl> &Protocols
5374 = Protocol->getReferencedProtocols();
5375 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
5376 E = Protocols.end();
5377 I != E; ++I)
5378 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
Douglas Gregorea766182010-10-18 18:21:28 +00005379 KnownMethods, false);
Douglas Gregore8f5a172010-04-07 00:21:17 +00005380 }
5381
5382 // Add methods in this container. This operation occurs last because
5383 // we want the methods from this container to override any methods
5384 // we've previously seen with the same selector.
5385 for (ObjCContainerDecl::method_iterator M = Container->meth_begin(),
5386 MEnd = Container->meth_end();
5387 M != MEnd; ++M) {
5388 if ((*M)->isInstanceMethod() == WantInstanceMethods) {
5389 if (!ReturnType.isNull() &&
5390 !Context.hasSameUnqualifiedType(ReturnType, (*M)->getResultType()))
5391 continue;
5392
Douglas Gregor408be5a2010-08-25 01:08:01 +00005393 KnownMethods[(*M)->getSelector()] = std::make_pair(*M, InOriginalClass);
Douglas Gregore8f5a172010-04-07 00:21:17 +00005394 }
5395 }
5396}
5397
5398void Sema::CodeCompleteObjCMethodDecl(Scope *S,
5399 bool IsInstanceMethod,
John McCallb3d87482010-08-24 05:47:05 +00005400 ParsedType ReturnTy,
John McCalld226f652010-08-21 09:40:31 +00005401 Decl *IDecl) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00005402 // Determine the return type of the method we're declaring, if
5403 // provided.
5404 QualType ReturnType = GetTypeFromParser(ReturnTy);
5405
Douglas Gregorea766182010-10-18 18:21:28 +00005406 // Determine where we should start searching for methods.
5407 ObjCContainerDecl *SearchDecl = 0;
Douglas Gregore8f5a172010-04-07 00:21:17 +00005408 bool IsInImplementation = false;
John McCalld226f652010-08-21 09:40:31 +00005409 if (Decl *D = IDecl) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00005410 if (ObjCImplementationDecl *Impl = dyn_cast<ObjCImplementationDecl>(D)) {
5411 SearchDecl = Impl->getClassInterface();
Douglas Gregore8f5a172010-04-07 00:21:17 +00005412 IsInImplementation = true;
5413 } else if (ObjCCategoryImplDecl *CatImpl
Douglas Gregorea766182010-10-18 18:21:28 +00005414 = dyn_cast<ObjCCategoryImplDecl>(D)) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00005415 SearchDecl = CatImpl->getCategoryDecl();
Douglas Gregore8f5a172010-04-07 00:21:17 +00005416 IsInImplementation = true;
Douglas Gregorea766182010-10-18 18:21:28 +00005417 } else
Douglas Gregore8f5a172010-04-07 00:21:17 +00005418 SearchDecl = dyn_cast<ObjCContainerDecl>(D);
Douglas Gregore8f5a172010-04-07 00:21:17 +00005419 }
5420
5421 if (!SearchDecl && S) {
Douglas Gregorea766182010-10-18 18:21:28 +00005422 if (DeclContext *DC = static_cast<DeclContext *>(S->getEntity()))
Douglas Gregore8f5a172010-04-07 00:21:17 +00005423 SearchDecl = dyn_cast<ObjCContainerDecl>(DC);
Douglas Gregore8f5a172010-04-07 00:21:17 +00005424 }
5425
Douglas Gregorea766182010-10-18 18:21:28 +00005426 if (!SearchDecl) {
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005427 HandleCodeCompleteResults(this, CodeCompleter,
5428 CodeCompletionContext::CCC_Other,
5429 0, 0);
Douglas Gregore8f5a172010-04-07 00:21:17 +00005430 return;
5431 }
5432
5433 // Find all of the methods that we could declare/implement here.
5434 KnownMethodsMap KnownMethods;
5435 FindImplementableMethods(Context, SearchDecl, IsInstanceMethod,
Douglas Gregorea766182010-10-18 18:21:28 +00005436 ReturnType, KnownMethods);
Douglas Gregore8f5a172010-04-07 00:21:17 +00005437
Douglas Gregore8f5a172010-04-07 00:21:17 +00005438 // Add declarations or definitions for each of the known methods.
John McCall0a2c5e22010-08-25 06:19:51 +00005439 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00005440 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5441 CodeCompletionContext::CCC_Other);
Douglas Gregore8f5a172010-04-07 00:21:17 +00005442 Results.EnterNewScope();
5443 PrintingPolicy Policy(Context.PrintingPolicy);
5444 Policy.AnonymousTagLocations = false;
5445 for (KnownMethodsMap::iterator M = KnownMethods.begin(),
5446 MEnd = KnownMethods.end();
5447 M != MEnd; ++M) {
Douglas Gregor408be5a2010-08-25 01:08:01 +00005448 ObjCMethodDecl *Method = M->second.first;
Douglas Gregor218937c2011-02-01 19:23:04 +00005449 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregore8f5a172010-04-07 00:21:17 +00005450
5451 // If the result type was not already provided, add it to the
5452 // pattern as (type).
5453 if (ReturnType.isNull()) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005454 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregora63f6de2011-02-01 21:15:40 +00005455 Builder.AddTextChunk(GetCompletionTypeString(Method->getResultType(),
5456 Context,
5457 Builder.getAllocator()));
Douglas Gregor218937c2011-02-01 19:23:04 +00005458 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregore8f5a172010-04-07 00:21:17 +00005459 }
5460
5461 Selector Sel = Method->getSelector();
5462
5463 // Add the first part of the selector to the pattern.
Douglas Gregor218937c2011-02-01 19:23:04 +00005464 Builder.AddTypedTextChunk(CopyString(Builder.getAllocator(),
5465 Sel.getIdentifierInfoForSlot(0)->getName()));
Douglas Gregore8f5a172010-04-07 00:21:17 +00005466
5467 // Add parameters to the pattern.
5468 unsigned I = 0;
5469 for (ObjCMethodDecl::param_iterator P = Method->param_begin(),
5470 PEnd = Method->param_end();
5471 P != PEnd; (void)++P, ++I) {
5472 // Add the part of the selector name.
5473 if (I == 0)
Douglas Gregor218937c2011-02-01 19:23:04 +00005474 Builder.AddTypedTextChunk(":");
Douglas Gregore8f5a172010-04-07 00:21:17 +00005475 else if (I < Sel.getNumArgs()) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005476 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5477 Builder.AddTypedTextChunk(
5478 CopyString(Builder.getAllocator(),
5479 (Sel.getIdentifierInfoForSlot(I)->getName()
5480 + ":").str()));
Douglas Gregore8f5a172010-04-07 00:21:17 +00005481 } else
5482 break;
5483
5484 // Add the parameter type.
Douglas Gregor218937c2011-02-01 19:23:04 +00005485 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregora63f6de2011-02-01 21:15:40 +00005486 Builder.AddTextChunk(GetCompletionTypeString((*P)->getOriginalType(),
5487 Context,
5488 Builder.getAllocator()));
Douglas Gregor218937c2011-02-01 19:23:04 +00005489 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregore8f5a172010-04-07 00:21:17 +00005490
5491 if (IdentifierInfo *Id = (*P)->getIdentifier())
Douglas Gregor218937c2011-02-01 19:23:04 +00005492 Builder.AddTextChunk(CopyString(Builder.getAllocator(), Id->getName()));
Douglas Gregore8f5a172010-04-07 00:21:17 +00005493 }
5494
5495 if (Method->isVariadic()) {
5496 if (Method->param_size() > 0)
Douglas Gregor218937c2011-02-01 19:23:04 +00005497 Builder.AddChunk(CodeCompletionString::CK_Comma);
5498 Builder.AddTextChunk("...");
Douglas Gregore17794f2010-08-31 05:13:43 +00005499 }
Douglas Gregore8f5a172010-04-07 00:21:17 +00005500
Douglas Gregor447107d2010-05-28 00:57:46 +00005501 if (IsInImplementation && Results.includeCodePatterns()) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00005502 // We will be defining the method here, so add a compound statement.
Douglas Gregor218937c2011-02-01 19:23:04 +00005503 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5504 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5505 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
Douglas Gregore8f5a172010-04-07 00:21:17 +00005506 if (!Method->getResultType()->isVoidType()) {
5507 // If the result type is not void, add a return clause.
Douglas Gregor218937c2011-02-01 19:23:04 +00005508 Builder.AddTextChunk("return");
5509 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5510 Builder.AddPlaceholderChunk("expression");
5511 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Douglas Gregore8f5a172010-04-07 00:21:17 +00005512 } else
Douglas Gregor218937c2011-02-01 19:23:04 +00005513 Builder.AddPlaceholderChunk("statements");
Douglas Gregore8f5a172010-04-07 00:21:17 +00005514
Douglas Gregor218937c2011-02-01 19:23:04 +00005515 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
5516 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
Douglas Gregore8f5a172010-04-07 00:21:17 +00005517 }
5518
Douglas Gregor408be5a2010-08-25 01:08:01 +00005519 unsigned Priority = CCP_CodePattern;
5520 if (!M->second.second)
5521 Priority += CCD_InBaseClass;
5522
Douglas Gregor218937c2011-02-01 19:23:04 +00005523 Results.AddResult(Result(Builder.TakeString(), Priority,
Douglas Gregor16ed9ad2010-08-17 16:06:07 +00005524 Method->isInstanceMethod()
5525 ? CXCursor_ObjCInstanceMethodDecl
5526 : CXCursor_ObjCClassMethodDecl));
Douglas Gregore8f5a172010-04-07 00:21:17 +00005527 }
5528
5529 Results.ExitScope();
5530
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005531 HandleCodeCompleteResults(this, CodeCompleter,
5532 CodeCompletionContext::CCC_Other,
5533 Results.data(),Results.size());
Douglas Gregore8f5a172010-04-07 00:21:17 +00005534}
Douglas Gregor1f5537a2010-07-08 23:20:03 +00005535
5536void Sema::CodeCompleteObjCMethodDeclSelector(Scope *S,
5537 bool IsInstanceMethod,
Douglas Gregor40ed9a12010-07-08 23:37:41 +00005538 bool AtParameterName,
John McCallb3d87482010-08-24 05:47:05 +00005539 ParsedType ReturnTy,
Douglas Gregor1f5537a2010-07-08 23:20:03 +00005540 IdentifierInfo **SelIdents,
5541 unsigned NumSelIdents) {
Douglas Gregor1f5537a2010-07-08 23:20:03 +00005542 // If we have an external source, load the entire class method
Sebastian Redl3c7f4132010-08-18 23:57:06 +00005543 // pool from the AST file.
Douglas Gregor1f5537a2010-07-08 23:20:03 +00005544 if (ExternalSource) {
5545 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
5546 I != N; ++I) {
5547 Selector Sel = ExternalSource->GetExternalSelector(I);
Sebastian Redldb9d2142010-08-02 23:18:59 +00005548 if (Sel.isNull() || MethodPool.count(Sel))
Douglas Gregor1f5537a2010-07-08 23:20:03 +00005549 continue;
Sebastian Redldb9d2142010-08-02 23:18:59 +00005550
5551 ReadMethodPool(Sel);
Douglas Gregor1f5537a2010-07-08 23:20:03 +00005552 }
5553 }
5554
5555 // Build the set of methods we can see.
John McCall0a2c5e22010-08-25 06:19:51 +00005556 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00005557 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5558 CodeCompletionContext::CCC_Other);
Douglas Gregor1f5537a2010-07-08 23:20:03 +00005559
5560 if (ReturnTy)
5561 Results.setPreferredType(GetTypeFromParser(ReturnTy).getNonReferenceType());
Sebastian Redldb9d2142010-08-02 23:18:59 +00005562
Douglas Gregor1f5537a2010-07-08 23:20:03 +00005563 Results.EnterNewScope();
Sebastian Redldb9d2142010-08-02 23:18:59 +00005564 for (GlobalMethodPool::iterator M = MethodPool.begin(),
5565 MEnd = MethodPool.end();
5566 M != MEnd; ++M) {
5567 for (ObjCMethodList *MethList = IsInstanceMethod ? &M->second.first :
5568 &M->second.second;
5569 MethList && MethList->Method;
Douglas Gregor1f5537a2010-07-08 23:20:03 +00005570 MethList = MethList->Next) {
5571 if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents,
5572 NumSelIdents))
5573 continue;
5574
Douglas Gregor40ed9a12010-07-08 23:37:41 +00005575 if (AtParameterName) {
5576 // Suggest parameter names we've seen before.
5577 if (NumSelIdents && NumSelIdents <= MethList->Method->param_size()) {
5578 ParmVarDecl *Param = MethList->Method->param_begin()[NumSelIdents-1];
5579 if (Param->getIdentifier()) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005580 CodeCompletionBuilder Builder(Results.getAllocator());
5581 Builder.AddTypedTextChunk(CopyString(Builder.getAllocator(),
5582 Param->getIdentifier()->getName()));
5583 Results.AddResult(Builder.TakeString());
Douglas Gregor40ed9a12010-07-08 23:37:41 +00005584 }
5585 }
5586
5587 continue;
5588 }
5589
Douglas Gregor1f5537a2010-07-08 23:20:03 +00005590 Result R(MethList->Method, 0);
5591 R.StartParameter = NumSelIdents;
5592 R.AllParametersAreInformative = false;
5593 R.DeclaringEntity = true;
5594 Results.MaybeAddResult(R, CurContext);
5595 }
5596 }
5597
5598 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005599 HandleCodeCompleteResults(this, CodeCompleter,
5600 CodeCompletionContext::CCC_Other,
5601 Results.data(),Results.size());
Douglas Gregor1f5537a2010-07-08 23:20:03 +00005602}
Douglas Gregor87c08a52010-08-13 22:48:40 +00005603
Douglas Gregorf29c5232010-08-24 22:20:20 +00005604void Sema::CodeCompletePreprocessorDirective(bool InConditional) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005605 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00005606 CodeCompletionContext::CCC_PreprocessorDirective);
Douglas Gregorf44e8542010-08-24 19:08:16 +00005607 Results.EnterNewScope();
5608
5609 // #if <condition>
Douglas Gregor218937c2011-02-01 19:23:04 +00005610 CodeCompletionBuilder Builder(Results.getAllocator());
5611 Builder.AddTypedTextChunk("if");
5612 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5613 Builder.AddPlaceholderChunk("condition");
5614 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00005615
5616 // #ifdef <macro>
Douglas Gregor218937c2011-02-01 19:23:04 +00005617 Builder.AddTypedTextChunk("ifdef");
5618 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5619 Builder.AddPlaceholderChunk("macro");
5620 Results.AddResult(Builder.TakeString());
5621
Douglas Gregorf44e8542010-08-24 19:08:16 +00005622 // #ifndef <macro>
Douglas Gregor218937c2011-02-01 19:23:04 +00005623 Builder.AddTypedTextChunk("ifndef");
5624 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5625 Builder.AddPlaceholderChunk("macro");
5626 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00005627
5628 if (InConditional) {
5629 // #elif <condition>
Douglas Gregor218937c2011-02-01 19:23:04 +00005630 Builder.AddTypedTextChunk("elif");
5631 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5632 Builder.AddPlaceholderChunk("condition");
5633 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00005634
5635 // #else
Douglas Gregor218937c2011-02-01 19:23:04 +00005636 Builder.AddTypedTextChunk("else");
5637 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00005638
5639 // #endif
Douglas Gregor218937c2011-02-01 19:23:04 +00005640 Builder.AddTypedTextChunk("endif");
5641 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00005642 }
5643
5644 // #include "header"
Douglas Gregor218937c2011-02-01 19:23:04 +00005645 Builder.AddTypedTextChunk("include");
5646 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5647 Builder.AddTextChunk("\"");
5648 Builder.AddPlaceholderChunk("header");
5649 Builder.AddTextChunk("\"");
5650 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00005651
5652 // #include <header>
Douglas Gregor218937c2011-02-01 19:23:04 +00005653 Builder.AddTypedTextChunk("include");
5654 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5655 Builder.AddTextChunk("<");
5656 Builder.AddPlaceholderChunk("header");
5657 Builder.AddTextChunk(">");
5658 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00005659
5660 // #define <macro>
Douglas Gregor218937c2011-02-01 19:23:04 +00005661 Builder.AddTypedTextChunk("define");
5662 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5663 Builder.AddPlaceholderChunk("macro");
5664 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00005665
5666 // #define <macro>(<args>)
Douglas Gregor218937c2011-02-01 19:23:04 +00005667 Builder.AddTypedTextChunk("define");
5668 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5669 Builder.AddPlaceholderChunk("macro");
5670 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5671 Builder.AddPlaceholderChunk("args");
5672 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5673 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00005674
5675 // #undef <macro>
Douglas Gregor218937c2011-02-01 19:23:04 +00005676 Builder.AddTypedTextChunk("undef");
5677 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5678 Builder.AddPlaceholderChunk("macro");
5679 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00005680
5681 // #line <number>
Douglas Gregor218937c2011-02-01 19:23:04 +00005682 Builder.AddTypedTextChunk("line");
5683 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5684 Builder.AddPlaceholderChunk("number");
5685 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00005686
5687 // #line <number> "filename"
Douglas Gregor218937c2011-02-01 19:23:04 +00005688 Builder.AddTypedTextChunk("line");
5689 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5690 Builder.AddPlaceholderChunk("number");
5691 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5692 Builder.AddTextChunk("\"");
5693 Builder.AddPlaceholderChunk("filename");
5694 Builder.AddTextChunk("\"");
5695 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00005696
5697 // #error <message>
Douglas Gregor218937c2011-02-01 19:23:04 +00005698 Builder.AddTypedTextChunk("error");
5699 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5700 Builder.AddPlaceholderChunk("message");
5701 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00005702
5703 // #pragma <arguments>
Douglas Gregor218937c2011-02-01 19:23:04 +00005704 Builder.AddTypedTextChunk("pragma");
5705 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5706 Builder.AddPlaceholderChunk("arguments");
5707 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00005708
5709 if (getLangOptions().ObjC1) {
5710 // #import "header"
Douglas Gregor218937c2011-02-01 19:23:04 +00005711 Builder.AddTypedTextChunk("import");
5712 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5713 Builder.AddTextChunk("\"");
5714 Builder.AddPlaceholderChunk("header");
5715 Builder.AddTextChunk("\"");
5716 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00005717
5718 // #import <header>
Douglas Gregor218937c2011-02-01 19:23:04 +00005719 Builder.AddTypedTextChunk("import");
5720 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5721 Builder.AddTextChunk("<");
5722 Builder.AddPlaceholderChunk("header");
5723 Builder.AddTextChunk(">");
5724 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00005725 }
5726
5727 // #include_next "header"
Douglas Gregor218937c2011-02-01 19:23:04 +00005728 Builder.AddTypedTextChunk("include_next");
5729 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5730 Builder.AddTextChunk("\"");
5731 Builder.AddPlaceholderChunk("header");
5732 Builder.AddTextChunk("\"");
5733 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00005734
5735 // #include_next <header>
Douglas Gregor218937c2011-02-01 19:23:04 +00005736 Builder.AddTypedTextChunk("include_next");
5737 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5738 Builder.AddTextChunk("<");
5739 Builder.AddPlaceholderChunk("header");
5740 Builder.AddTextChunk(">");
5741 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00005742
5743 // #warning <message>
Douglas Gregor218937c2011-02-01 19:23:04 +00005744 Builder.AddTypedTextChunk("warning");
5745 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5746 Builder.AddPlaceholderChunk("message");
5747 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00005748
5749 // Note: #ident and #sccs are such crazy anachronisms that we don't provide
5750 // completions for them. And __include_macros is a Clang-internal extension
5751 // that we don't want to encourage anyone to use.
5752
5753 // FIXME: we don't support #assert or #unassert, so don't suggest them.
5754 Results.ExitScope();
5755
Douglas Gregorf44e8542010-08-24 19:08:16 +00005756 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor721f3592010-08-25 18:41:16 +00005757 CodeCompletionContext::CCC_PreprocessorDirective,
Douglas Gregorf44e8542010-08-24 19:08:16 +00005758 Results.data(), Results.size());
5759}
5760
5761void Sema::CodeCompleteInPreprocessorConditionalExclusion(Scope *S) {
Douglas Gregorf29c5232010-08-24 22:20:20 +00005762 CodeCompleteOrdinaryName(S,
John McCallf312b1e2010-08-26 23:41:50 +00005763 S->getFnParent()? Sema::PCC_RecoveryInFunction
5764 : Sema::PCC_Namespace);
Douglas Gregorf44e8542010-08-24 19:08:16 +00005765}
5766
Douglas Gregorf29c5232010-08-24 22:20:20 +00005767void Sema::CodeCompletePreprocessorMacroName(bool IsDefinition) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005768 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00005769 IsDefinition? CodeCompletionContext::CCC_MacroName
5770 : CodeCompletionContext::CCC_MacroNameUse);
Douglas Gregor1fbb4472010-08-24 20:21:13 +00005771 if (!IsDefinition && (!CodeCompleter || CodeCompleter->includeMacros())) {
5772 // Add just the names of macros, not their arguments.
Douglas Gregor218937c2011-02-01 19:23:04 +00005773 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregor1fbb4472010-08-24 20:21:13 +00005774 Results.EnterNewScope();
5775 for (Preprocessor::macro_iterator M = PP.macro_begin(),
5776 MEnd = PP.macro_end();
5777 M != MEnd; ++M) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005778 Builder.AddTypedTextChunk(CopyString(Builder.getAllocator(),
5779 M->first->getName()));
5780 Results.AddResult(Builder.TakeString());
Douglas Gregor1fbb4472010-08-24 20:21:13 +00005781 }
5782 Results.ExitScope();
5783 } else if (IsDefinition) {
5784 // FIXME: Can we detect when the user just wrote an include guard above?
5785 }
5786
Douglas Gregor52779fb2010-09-23 23:01:17 +00005787 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor1fbb4472010-08-24 20:21:13 +00005788 Results.data(), Results.size());
5789}
5790
Douglas Gregorf29c5232010-08-24 22:20:20 +00005791void Sema::CodeCompletePreprocessorExpression() {
Douglas Gregor218937c2011-02-01 19:23:04 +00005792 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00005793 CodeCompletionContext::CCC_PreprocessorExpression);
Douglas Gregorf29c5232010-08-24 22:20:20 +00005794
5795 if (!CodeCompleter || CodeCompleter->includeMacros())
5796 AddMacroResults(PP, Results);
5797
5798 // defined (<macro>)
5799 Results.EnterNewScope();
Douglas Gregor218937c2011-02-01 19:23:04 +00005800 CodeCompletionBuilder Builder(Results.getAllocator());
5801 Builder.AddTypedTextChunk("defined");
5802 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5803 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5804 Builder.AddPlaceholderChunk("macro");
5805 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5806 Results.AddResult(Builder.TakeString());
Douglas Gregorf29c5232010-08-24 22:20:20 +00005807 Results.ExitScope();
5808
5809 HandleCodeCompleteResults(this, CodeCompleter,
5810 CodeCompletionContext::CCC_PreprocessorExpression,
5811 Results.data(), Results.size());
5812}
5813
5814void Sema::CodeCompletePreprocessorMacroArgument(Scope *S,
5815 IdentifierInfo *Macro,
5816 MacroInfo *MacroInfo,
5817 unsigned Argument) {
5818 // FIXME: In the future, we could provide "overload" results, much like we
5819 // do for function calls.
5820
5821 CodeCompleteOrdinaryName(S,
John McCallf312b1e2010-08-26 23:41:50 +00005822 S->getFnParent()? Sema::PCC_RecoveryInFunction
5823 : Sema::PCC_Namespace);
Douglas Gregorf29c5232010-08-24 22:20:20 +00005824}
5825
Douglas Gregor55817af2010-08-25 17:04:25 +00005826void Sema::CodeCompleteNaturalLanguage() {
Douglas Gregor55817af2010-08-25 17:04:25 +00005827 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregoraf1c6b52010-08-25 17:10:00 +00005828 CodeCompletionContext::CCC_NaturalLanguage,
Douglas Gregor55817af2010-08-25 17:04:25 +00005829 0, 0);
5830}
5831
Douglas Gregor218937c2011-02-01 19:23:04 +00005832void Sema::GatherGlobalCodeCompletions(llvm::BumpPtrAllocator &Allocator,
John McCall0a2c5e22010-08-25 06:19:51 +00005833 llvm::SmallVectorImpl<CodeCompletionResult> &Results) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005834 ResultBuilder Builder(*this, Allocator, CodeCompletionContext::CCC_Recovery);
Douglas Gregor8071e422010-08-15 06:18:01 +00005835 if (!CodeCompleter || CodeCompleter->includeGlobals()) {
5836 CodeCompletionDeclConsumer Consumer(Builder,
5837 Context.getTranslationUnitDecl());
5838 LookupVisibleDecls(Context.getTranslationUnitDecl(), LookupAnyName,
5839 Consumer);
5840 }
Douglas Gregor87c08a52010-08-13 22:48:40 +00005841
5842 if (!CodeCompleter || CodeCompleter->includeMacros())
5843 AddMacroResults(PP, Builder);
5844
5845 Results.clear();
5846 Results.insert(Results.end(),
5847 Builder.data(), Builder.data() + Builder.size());
5848}