blob: 051603ce6de27bbfb711cd5ace3391ea14727acd [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 Gregorff5ce6e2009-12-18 18:53:37 +00001790/// \brief If the given declaration has an associated type, add it as a result
1791/// type chunk.
1792static void AddResultTypeChunk(ASTContext &Context,
1793 NamedDecl *ND,
Douglas Gregor218937c2011-02-01 19:23:04 +00001794 CodeCompletionBuilder &Result) {
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00001795 if (!ND)
1796 return;
Douglas Gregor6f942b22010-09-21 16:06:22 +00001797
1798 // Skip constructors and conversion functions, which have their return types
1799 // built into their names.
1800 if (isa<CXXConstructorDecl>(ND) || isa<CXXConversionDecl>(ND))
1801 return;
1802
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00001803 // Determine the type of the declaration (if it has a type).
Douglas Gregor6f942b22010-09-21 16:06:22 +00001804 QualType T;
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00001805 if (FunctionDecl *Function = dyn_cast<FunctionDecl>(ND))
1806 T = Function->getResultType();
1807 else if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND))
1808 T = Method->getResultType();
1809 else if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND))
1810 T = FunTmpl->getTemplatedDecl()->getResultType();
1811 else if (EnumConstantDecl *Enumerator = dyn_cast<EnumConstantDecl>(ND))
1812 T = Context.getTypeDeclType(cast<TypeDecl>(Enumerator->getDeclContext()));
1813 else if (isa<UnresolvedUsingValueDecl>(ND)) {
1814 /* Do nothing: ignore unresolved using declarations*/
1815 } else if (ValueDecl *Value = dyn_cast<ValueDecl>(ND))
1816 T = Value->getType();
1817 else if (ObjCPropertyDecl *Property = dyn_cast<ObjCPropertyDecl>(ND))
1818 T = Property->getType();
1819
1820 if (T.isNull() || Context.hasSameType(T, Context.DependentTy))
1821 return;
1822
Douglas Gregor84139d62010-04-05 21:25:31 +00001823 PrintingPolicy Policy(Context.PrintingPolicy);
1824 Policy.AnonymousTagLocations = false;
1825
Douglas Gregor218937c2011-02-01 19:23:04 +00001826 // FIXME: Fast-path common strings.
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00001827 std::string TypeStr;
Douglas Gregor84139d62010-04-05 21:25:31 +00001828 T.getAsStringInternal(TypeStr, Policy);
Douglas Gregor218937c2011-02-01 19:23:04 +00001829 Result.AddResultTypeChunk(CopyString(Result.getAllocator(), TypeStr));
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00001830}
1831
Douglas Gregoraaa107a2010-08-23 23:51:41 +00001832static void MaybeAddSentinel(ASTContext &Context, NamedDecl *FunctionOrMethod,
Douglas Gregor218937c2011-02-01 19:23:04 +00001833 CodeCompletionBuilder &Result) {
Douglas Gregoraaa107a2010-08-23 23:51:41 +00001834 if (SentinelAttr *Sentinel = FunctionOrMethod->getAttr<SentinelAttr>())
1835 if (Sentinel->getSentinel() == 0) {
1836 if (Context.getLangOptions().ObjC1 &&
1837 Context.Idents.get("nil").hasMacroDefinition())
Douglas Gregor218937c2011-02-01 19:23:04 +00001838 Result.AddTextChunk(", nil");
Douglas Gregoraaa107a2010-08-23 23:51:41 +00001839 else if (Context.Idents.get("NULL").hasMacroDefinition())
Douglas Gregor218937c2011-02-01 19:23:04 +00001840 Result.AddTextChunk(", NULL");
Douglas Gregoraaa107a2010-08-23 23:51:41 +00001841 else
Douglas Gregor218937c2011-02-01 19:23:04 +00001842 Result.AddTextChunk(", (void*)0");
Douglas Gregoraaa107a2010-08-23 23:51:41 +00001843 }
1844}
1845
Douglas Gregor83482d12010-08-24 16:15:59 +00001846static std::string FormatFunctionParameter(ASTContext &Context,
Douglas Gregoraba48082010-08-29 19:47:46 +00001847 ParmVarDecl *Param,
1848 bool SuppressName = false) {
Douglas Gregor83482d12010-08-24 16:15:59 +00001849 bool ObjCMethodParam = isa<ObjCMethodDecl>(Param->getDeclContext());
1850 if (Param->getType()->isDependentType() ||
1851 !Param->getType()->isBlockPointerType()) {
1852 // The argument for a dependent or non-block parameter is a placeholder
1853 // containing that parameter's type.
1854 std::string Result;
1855
Douglas Gregoraba48082010-08-29 19:47:46 +00001856 if (Param->getIdentifier() && !ObjCMethodParam && !SuppressName)
Douglas Gregor83482d12010-08-24 16:15:59 +00001857 Result = Param->getIdentifier()->getName();
1858
1859 Param->getType().getAsStringInternal(Result,
1860 Context.PrintingPolicy);
1861
1862 if (ObjCMethodParam) {
1863 Result = "(" + Result;
1864 Result += ")";
Douglas Gregoraba48082010-08-29 19:47:46 +00001865 if (Param->getIdentifier() && !SuppressName)
Douglas Gregor83482d12010-08-24 16:15:59 +00001866 Result += Param->getIdentifier()->getName();
1867 }
1868 return Result;
1869 }
1870
1871 // The argument for a block pointer parameter is a block literal with
1872 // the appropriate type.
1873 FunctionProtoTypeLoc *Block = 0;
1874 TypeLoc TL;
1875 if (TypeSourceInfo *TSInfo = Param->getTypeSourceInfo()) {
1876 TL = TSInfo->getTypeLoc().getUnqualifiedLoc();
1877 while (true) {
1878 // Look through typedefs.
1879 if (TypedefTypeLoc *TypedefTL = dyn_cast<TypedefTypeLoc>(&TL)) {
1880 if (TypeSourceInfo *InnerTSInfo
1881 = TypedefTL->getTypedefDecl()->getTypeSourceInfo()) {
1882 TL = InnerTSInfo->getTypeLoc().getUnqualifiedLoc();
1883 continue;
1884 }
1885 }
1886
1887 // Look through qualified types
1888 if (QualifiedTypeLoc *QualifiedTL = dyn_cast<QualifiedTypeLoc>(&TL)) {
1889 TL = QualifiedTL->getUnqualifiedLoc();
1890 continue;
1891 }
1892
1893 // Try to get the function prototype behind the block pointer type,
1894 // then we're done.
1895 if (BlockPointerTypeLoc *BlockPtr
1896 = dyn_cast<BlockPointerTypeLoc>(&TL)) {
Abramo Bagnara723df242010-12-14 22:11:44 +00001897 TL = BlockPtr->getPointeeLoc().IgnoreParens();
Douglas Gregor83482d12010-08-24 16:15:59 +00001898 Block = dyn_cast<FunctionProtoTypeLoc>(&TL);
1899 }
1900 break;
1901 }
1902 }
1903
1904 if (!Block) {
1905 // We were unable to find a FunctionProtoTypeLoc with parameter names
1906 // for the block; just use the parameter type as a placeholder.
1907 std::string Result;
1908 Param->getType().getUnqualifiedType().
1909 getAsStringInternal(Result, Context.PrintingPolicy);
1910
1911 if (ObjCMethodParam) {
1912 Result = "(" + Result;
1913 Result += ")";
1914 if (Param->getIdentifier())
1915 Result += Param->getIdentifier()->getName();
1916 }
1917
1918 return Result;
1919 }
1920
1921 // We have the function prototype behind the block pointer type, as it was
1922 // written in the source.
Douglas Gregor38276252010-09-08 22:47:51 +00001923 std::string Result;
1924 QualType ResultType = Block->getTypePtr()->getResultType();
1925 if (!ResultType->isVoidType())
1926 ResultType.getAsStringInternal(Result, Context.PrintingPolicy);
1927
1928 Result = '^' + Result;
1929 if (Block->getNumArgs() == 0) {
1930 if (Block->getTypePtr()->isVariadic())
1931 Result += "(...)";
Douglas Gregorc2760bc2010-10-02 23:49:58 +00001932 else
1933 Result += "(void)";
Douglas Gregor38276252010-09-08 22:47:51 +00001934 } else {
1935 Result += "(";
1936 for (unsigned I = 0, N = Block->getNumArgs(); I != N; ++I) {
1937 if (I)
1938 Result += ", ";
1939 Result += FormatFunctionParameter(Context, Block->getArg(I));
1940
1941 if (I == N - 1 && Block->getTypePtr()->isVariadic())
1942 Result += ", ...";
1943 }
1944 Result += ")";
Douglas Gregore17794f2010-08-31 05:13:43 +00001945 }
Douglas Gregor38276252010-09-08 22:47:51 +00001946
Douglas Gregorc2760bc2010-10-02 23:49:58 +00001947 if (Param->getIdentifier())
1948 Result += Param->getIdentifier()->getName();
1949
Douglas Gregor83482d12010-08-24 16:15:59 +00001950 return Result;
1951}
1952
Douglas Gregor86d9a522009-09-21 16:56:56 +00001953/// \brief Add function parameter chunks to the given code completion string.
1954static void AddFunctionParameterChunks(ASTContext &Context,
1955 FunctionDecl *Function,
Douglas Gregor218937c2011-02-01 19:23:04 +00001956 CodeCompletionBuilder &Result,
1957 unsigned Start = 0,
1958 bool InOptional = false) {
Douglas Gregor0c8296d2009-11-07 00:00:49 +00001959 typedef CodeCompletionString::Chunk Chunk;
Douglas Gregor218937c2011-02-01 19:23:04 +00001960 bool FirstParameter = true;
Douglas Gregor0c8296d2009-11-07 00:00:49 +00001961
Douglas Gregor218937c2011-02-01 19:23:04 +00001962 for (unsigned P = Start, N = Function->getNumParams(); P != N; ++P) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00001963 ParmVarDecl *Param = Function->getParamDecl(P);
1964
Douglas Gregor218937c2011-02-01 19:23:04 +00001965 if (Param->hasDefaultArg() && !InOptional) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00001966 // When we see an optional default argument, put that argument and
1967 // the remaining default arguments into a new, optional string.
Douglas Gregor218937c2011-02-01 19:23:04 +00001968 CodeCompletionBuilder Opt(Result.getAllocator());
1969 if (!FirstParameter)
1970 Opt.AddChunk(Chunk(CodeCompletionString::CK_Comma));
1971 AddFunctionParameterChunks(Context, Function, Opt, P, true);
1972 Result.AddOptionalChunk(Opt.TakeString());
1973 break;
Douglas Gregor86d9a522009-09-21 16:56:56 +00001974 }
1975
Douglas Gregor218937c2011-02-01 19:23:04 +00001976 if (FirstParameter)
1977 FirstParameter = false;
1978 else
1979 Result.AddChunk(Chunk(CodeCompletionString::CK_Comma));
1980
1981 InOptional = false;
Douglas Gregor86d9a522009-09-21 16:56:56 +00001982
1983 // Format the placeholder string.
Douglas Gregor83482d12010-08-24 16:15:59 +00001984 std::string PlaceholderStr = FormatFunctionParameter(Context, Param);
1985
Douglas Gregore17794f2010-08-31 05:13:43 +00001986 if (Function->isVariadic() && P == N - 1)
1987 PlaceholderStr += ", ...";
1988
Douglas Gregor86d9a522009-09-21 16:56:56 +00001989 // Add the placeholder string.
Douglas Gregor218937c2011-02-01 19:23:04 +00001990 Result.AddPlaceholderChunk(CopyString(Result.getAllocator(),
1991 PlaceholderStr));
Douglas Gregor86d9a522009-09-21 16:56:56 +00001992 }
Douglas Gregorb3d45252009-09-22 21:42:17 +00001993
1994 if (const FunctionProtoType *Proto
1995 = Function->getType()->getAs<FunctionProtoType>())
Douglas Gregoraaa107a2010-08-23 23:51:41 +00001996 if (Proto->isVariadic()) {
Douglas Gregore17794f2010-08-31 05:13:43 +00001997 if (Proto->getNumArgs() == 0)
Douglas Gregor218937c2011-02-01 19:23:04 +00001998 Result.AddPlaceholderChunk("...");
Douglas Gregoraaa107a2010-08-23 23:51:41 +00001999
Douglas Gregor218937c2011-02-01 19:23:04 +00002000 MaybeAddSentinel(Context, Function, Result);
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002001 }
Douglas Gregor86d9a522009-09-21 16:56:56 +00002002}
2003
2004/// \brief Add template parameter chunks to the given code completion string.
2005static void AddTemplateParameterChunks(ASTContext &Context,
2006 TemplateDecl *Template,
Douglas Gregor218937c2011-02-01 19:23:04 +00002007 CodeCompletionBuilder &Result,
2008 unsigned MaxParameters = 0,
2009 unsigned Start = 0,
2010 bool InDefaultArg = false) {
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002011 typedef CodeCompletionString::Chunk Chunk;
Douglas Gregor86d9a522009-09-21 16:56:56 +00002012 bool FirstParameter = true;
2013
2014 TemplateParameterList *Params = Template->getTemplateParameters();
2015 TemplateParameterList::iterator PEnd = Params->end();
2016 if (MaxParameters)
2017 PEnd = Params->begin() + MaxParameters;
Douglas Gregor218937c2011-02-01 19:23:04 +00002018 for (TemplateParameterList::iterator P = Params->begin() + Start;
2019 P != PEnd; ++P) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002020 bool HasDefaultArg = false;
2021 std::string PlaceholderStr;
2022 if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*P)) {
2023 if (TTP->wasDeclaredWithTypename())
2024 PlaceholderStr = "typename";
2025 else
2026 PlaceholderStr = "class";
2027
2028 if (TTP->getIdentifier()) {
2029 PlaceholderStr += ' ';
2030 PlaceholderStr += TTP->getIdentifier()->getName();
2031 }
2032
2033 HasDefaultArg = TTP->hasDefaultArgument();
2034 } else if (NonTypeTemplateParmDecl *NTTP
Douglas Gregor218937c2011-02-01 19:23:04 +00002035 = dyn_cast<NonTypeTemplateParmDecl>(*P)) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002036 if (NTTP->getIdentifier())
2037 PlaceholderStr = NTTP->getIdentifier()->getName();
2038 NTTP->getType().getAsStringInternal(PlaceholderStr,
2039 Context.PrintingPolicy);
2040 HasDefaultArg = NTTP->hasDefaultArgument();
2041 } else {
2042 assert(isa<TemplateTemplateParmDecl>(*P));
2043 TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*P);
2044
2045 // Since putting the template argument list into the placeholder would
2046 // be very, very long, we just use an abbreviation.
2047 PlaceholderStr = "template<...> class";
2048 if (TTP->getIdentifier()) {
2049 PlaceholderStr += ' ';
2050 PlaceholderStr += TTP->getIdentifier()->getName();
2051 }
2052
2053 HasDefaultArg = TTP->hasDefaultArgument();
2054 }
2055
Douglas Gregor218937c2011-02-01 19:23:04 +00002056 if (HasDefaultArg && !InDefaultArg) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002057 // When we see an optional default argument, put that argument and
2058 // the remaining default arguments into a new, optional string.
Douglas Gregor218937c2011-02-01 19:23:04 +00002059 CodeCompletionBuilder Opt(Result.getAllocator());
2060 if (!FirstParameter)
2061 Opt.AddChunk(Chunk(CodeCompletionString::CK_Comma));
2062 AddTemplateParameterChunks(Context, Template, Opt, MaxParameters,
2063 P - Params->begin(), true);
2064 Result.AddOptionalChunk(Opt.TakeString());
2065 break;
Douglas Gregor86d9a522009-09-21 16:56:56 +00002066 }
2067
Douglas Gregor218937c2011-02-01 19:23:04 +00002068 InDefaultArg = false;
2069
Douglas Gregor86d9a522009-09-21 16:56:56 +00002070 if (FirstParameter)
2071 FirstParameter = false;
2072 else
Douglas Gregor218937c2011-02-01 19:23:04 +00002073 Result.AddChunk(Chunk(CodeCompletionString::CK_Comma));
Douglas Gregor86d9a522009-09-21 16:56:56 +00002074
2075 // Add the placeholder string.
Douglas Gregor218937c2011-02-01 19:23:04 +00002076 Result.AddPlaceholderChunk(CopyString(Result.getAllocator(),
2077 PlaceholderStr));
Douglas Gregor86d9a522009-09-21 16:56:56 +00002078 }
2079}
2080
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00002081/// \brief Add a qualifier to the given code-completion string, if the
2082/// provided nested-name-specifier is non-NULL.
Douglas Gregora61a8792009-12-11 18:44:16 +00002083static void
Douglas Gregor218937c2011-02-01 19:23:04 +00002084AddQualifierToCompletionString(CodeCompletionBuilder &Result,
Douglas Gregora61a8792009-12-11 18:44:16 +00002085 NestedNameSpecifier *Qualifier,
2086 bool QualifierIsInformative,
2087 ASTContext &Context) {
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00002088 if (!Qualifier)
2089 return;
2090
2091 std::string PrintedNNS;
2092 {
2093 llvm::raw_string_ostream OS(PrintedNNS);
2094 Qualifier->print(OS, Context.PrintingPolicy);
2095 }
Douglas Gregor0563c262009-09-22 23:15:58 +00002096 if (QualifierIsInformative)
Douglas Gregor218937c2011-02-01 19:23:04 +00002097 Result.AddInformativeChunk(CopyString(Result.getAllocator(), PrintedNNS));
Douglas Gregor0563c262009-09-22 23:15:58 +00002098 else
Douglas Gregor218937c2011-02-01 19:23:04 +00002099 Result.AddTextChunk(CopyString(Result.getAllocator(), PrintedNNS));
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00002100}
2101
Douglas Gregor218937c2011-02-01 19:23:04 +00002102static void
2103AddFunctionTypeQualsToCompletionString(CodeCompletionBuilder &Result,
2104 FunctionDecl *Function) {
Douglas Gregora61a8792009-12-11 18:44:16 +00002105 const FunctionProtoType *Proto
2106 = Function->getType()->getAs<FunctionProtoType>();
2107 if (!Proto || !Proto->getTypeQuals())
2108 return;
2109
Douglas Gregor218937c2011-02-01 19:23:04 +00002110 // FIXME: Fast-path single-qualifier strings.
Douglas Gregora61a8792009-12-11 18:44:16 +00002111 std::string QualsStr;
2112 if (Proto->getTypeQuals() & Qualifiers::Const)
2113 QualsStr += " const";
2114 if (Proto->getTypeQuals() & Qualifiers::Volatile)
2115 QualsStr += " volatile";
2116 if (Proto->getTypeQuals() & Qualifiers::Restrict)
2117 QualsStr += " restrict";
Douglas Gregor218937c2011-02-01 19:23:04 +00002118 Result.AddInformativeChunk(CopyString(Result.getAllocator(), QualsStr));
Douglas Gregora61a8792009-12-11 18:44:16 +00002119}
2120
Douglas Gregor6f942b22010-09-21 16:06:22 +00002121/// \brief Add the name of the given declaration
2122static void AddTypedNameChunk(ASTContext &Context, NamedDecl *ND,
Douglas Gregor218937c2011-02-01 19:23:04 +00002123 CodeCompletionBuilder &Result) {
Douglas Gregor6f942b22010-09-21 16:06:22 +00002124 typedef CodeCompletionString::Chunk Chunk;
2125
2126 DeclarationName Name = ND->getDeclName();
2127 if (!Name)
2128 return;
2129
2130 switch (Name.getNameKind()) {
2131 case DeclarationName::Identifier:
2132 case DeclarationName::CXXConversionFunctionName:
2133 case DeclarationName::CXXOperatorName:
2134 case DeclarationName::CXXDestructorName:
2135 case DeclarationName::CXXLiteralOperatorName:
Douglas Gregor218937c2011-02-01 19:23:04 +00002136 // FIXME: Fast-path operator names?
2137 Result.AddTypedTextChunk(CopyString(Result.getAllocator(),
2138 ND->getNameAsString()));
Douglas Gregor6f942b22010-09-21 16:06:22 +00002139 break;
2140
2141 case DeclarationName::CXXUsingDirective:
2142 case DeclarationName::ObjCZeroArgSelector:
2143 case DeclarationName::ObjCOneArgSelector:
2144 case DeclarationName::ObjCMultiArgSelector:
2145 break;
2146
2147 case DeclarationName::CXXConstructorName: {
2148 CXXRecordDecl *Record = 0;
2149 QualType Ty = Name.getCXXNameType();
2150 if (const RecordType *RecordTy = Ty->getAs<RecordType>())
2151 Record = cast<CXXRecordDecl>(RecordTy->getDecl());
2152 else if (const InjectedClassNameType *InjectedTy
2153 = Ty->getAs<InjectedClassNameType>())
2154 Record = InjectedTy->getDecl();
2155 else {
Douglas Gregor218937c2011-02-01 19:23:04 +00002156 Result.AddTypedTextChunk(CopyString(Result.getAllocator(),
2157 ND->getNameAsString()));
Douglas Gregor6f942b22010-09-21 16:06:22 +00002158 break;
2159 }
2160
Douglas Gregor218937c2011-02-01 19:23:04 +00002161 Result.AddTypedTextChunk(CopyString(Result.getAllocator(),
2162 Record->getNameAsString()));
Douglas Gregor6f942b22010-09-21 16:06:22 +00002163 if (ClassTemplateDecl *Template = Record->getDescribedClassTemplate()) {
Douglas Gregor218937c2011-02-01 19:23:04 +00002164 Result.AddChunk(Chunk(CodeCompletionString::CK_LeftAngle));
Douglas Gregor6f942b22010-09-21 16:06:22 +00002165 AddTemplateParameterChunks(Context, Template, Result);
Douglas Gregor218937c2011-02-01 19:23:04 +00002166 Result.AddChunk(Chunk(CodeCompletionString::CK_RightAngle));
Douglas Gregor6f942b22010-09-21 16:06:22 +00002167 }
2168 break;
2169 }
2170 }
2171}
2172
Douglas Gregor86d9a522009-09-21 16:56:56 +00002173/// \brief If possible, create a new code completion string for the given
2174/// result.
2175///
2176/// \returns Either a new, heap-allocated code completion string describing
2177/// how to use this result, or NULL to indicate that the string or name of the
2178/// result is all that is needed.
2179CodeCompletionString *
John McCall0a2c5e22010-08-25 06:19:51 +00002180CodeCompletionResult::CreateCodeCompletionString(Sema &S,
Douglas Gregor218937c2011-02-01 19:23:04 +00002181 llvm::BumpPtrAllocator &Allocator) {
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002182 typedef CodeCompletionString::Chunk Chunk;
Douglas Gregor218937c2011-02-01 19:23:04 +00002183 CodeCompletionBuilder Result(Allocator, Priority, Availability);
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002184
Douglas Gregor218937c2011-02-01 19:23:04 +00002185 if (Kind == RK_Pattern) {
2186 Pattern->Priority = Priority;
2187 Pattern->Availability = Availability;
2188 return Pattern;
2189 }
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002190
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002191 if (Kind == RK_Keyword) {
Douglas Gregor218937c2011-02-01 19:23:04 +00002192 Result.AddTypedTextChunk(Keyword);
2193 return Result.TakeString();
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002194 }
Douglas Gregor86d9a522009-09-21 16:56:56 +00002195
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002196 if (Kind == RK_Macro) {
2197 MacroInfo *MI = S.PP.getMacroInfo(Macro);
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002198 assert(MI && "Not a macro?");
2199
Douglas Gregor218937c2011-02-01 19:23:04 +00002200 Result.AddTypedTextChunk(CopyString(Result.getAllocator(),
2201 Macro->getName()));
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002202
2203 if (!MI->isFunctionLike())
Douglas Gregor218937c2011-02-01 19:23:04 +00002204 return Result.TakeString();
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002205
2206 // Format a function-like macro with placeholders for the arguments.
Douglas Gregor218937c2011-02-01 19:23:04 +00002207 Result.AddChunk(Chunk(CodeCompletionString::CK_LeftParen));
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002208 for (MacroInfo::arg_iterator A = MI->arg_begin(), AEnd = MI->arg_end();
2209 A != AEnd; ++A) {
2210 if (A != MI->arg_begin())
Douglas Gregor218937c2011-02-01 19:23:04 +00002211 Result.AddChunk(Chunk(CodeCompletionString::CK_Comma));
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002212
2213 if (!MI->isVariadic() || A != AEnd - 1) {
2214 // Non-variadic argument.
Douglas Gregor218937c2011-02-01 19:23:04 +00002215 Result.AddPlaceholderChunk(CopyString(Result.getAllocator(),
2216 (*A)->getName()));
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002217 continue;
2218 }
2219
2220 // Variadic argument; cope with the different between GNU and C99
2221 // variadic macros, providing a single placeholder for the rest of the
2222 // arguments.
2223 if ((*A)->isStr("__VA_ARGS__"))
Douglas Gregor218937c2011-02-01 19:23:04 +00002224 Result.AddPlaceholderChunk("...");
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002225 else {
2226 std::string Arg = (*A)->getName();
2227 Arg += "...";
Douglas Gregor218937c2011-02-01 19:23:04 +00002228 Result.AddPlaceholderChunk(CopyString(Result.getAllocator(), Arg));
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002229 }
2230 }
Douglas Gregor218937c2011-02-01 19:23:04 +00002231 Result.AddChunk(Chunk(CodeCompletionString::CK_RightParen));
2232 return Result.TakeString();
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002233 }
2234
Douglas Gregord8e8a582010-05-25 21:41:55 +00002235 assert(Kind == RK_Declaration && "Missed a result kind?");
Douglas Gregor86d9a522009-09-21 16:56:56 +00002236 NamedDecl *ND = Declaration;
2237
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002238 if (StartsNestedNameSpecifier) {
Douglas Gregor218937c2011-02-01 19:23:04 +00002239 Result.AddTypedTextChunk(CopyString(Result.getAllocator(),
2240 ND->getNameAsString()));
2241 Result.AddTextChunk("::");
2242 return Result.TakeString();
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002243 }
2244
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00002245 AddResultTypeChunk(S.Context, ND, Result);
2246
Douglas Gregor86d9a522009-09-21 16:56:56 +00002247 if (FunctionDecl *Function = dyn_cast<FunctionDecl>(ND)) {
Douglas Gregor0563c262009-09-22 23:15:58 +00002248 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
2249 S.Context);
Douglas Gregor6f942b22010-09-21 16:06:22 +00002250 AddTypedNameChunk(S.Context, ND, Result);
Douglas Gregor218937c2011-02-01 19:23:04 +00002251 Result.AddChunk(Chunk(CodeCompletionString::CK_LeftParen));
Douglas Gregor86d9a522009-09-21 16:56:56 +00002252 AddFunctionParameterChunks(S.Context, Function, Result);
Douglas Gregor218937c2011-02-01 19:23:04 +00002253 Result.AddChunk(Chunk(CodeCompletionString::CK_RightParen));
Douglas Gregora61a8792009-12-11 18:44:16 +00002254 AddFunctionTypeQualsToCompletionString(Result, Function);
Douglas Gregor218937c2011-02-01 19:23:04 +00002255 return Result.TakeString();
Douglas Gregor86d9a522009-09-21 16:56:56 +00002256 }
2257
2258 if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND)) {
Douglas Gregor0563c262009-09-22 23:15:58 +00002259 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
2260 S.Context);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002261 FunctionDecl *Function = FunTmpl->getTemplatedDecl();
Douglas Gregor6f942b22010-09-21 16:06:22 +00002262 AddTypedNameChunk(S.Context, Function, Result);
2263
Douglas Gregor86d9a522009-09-21 16:56:56 +00002264 // Figure out which template parameters are deduced (or have default
2265 // arguments).
2266 llvm::SmallVector<bool, 16> Deduced;
2267 S.MarkDeducedTemplateParameters(FunTmpl, Deduced);
2268 unsigned LastDeducibleArgument;
2269 for (LastDeducibleArgument = Deduced.size(); LastDeducibleArgument > 0;
2270 --LastDeducibleArgument) {
2271 if (!Deduced[LastDeducibleArgument - 1]) {
2272 // C++0x: Figure out if the template argument has a default. If so,
2273 // the user doesn't need to type this argument.
2274 // FIXME: We need to abstract template parameters better!
2275 bool HasDefaultArg = false;
2276 NamedDecl *Param = FunTmpl->getTemplateParameters()->getParam(
Douglas Gregor218937c2011-02-01 19:23:04 +00002277 LastDeducibleArgument - 1);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002278 if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param))
2279 HasDefaultArg = TTP->hasDefaultArgument();
2280 else if (NonTypeTemplateParmDecl *NTTP
2281 = dyn_cast<NonTypeTemplateParmDecl>(Param))
2282 HasDefaultArg = NTTP->hasDefaultArgument();
2283 else {
2284 assert(isa<TemplateTemplateParmDecl>(Param));
2285 HasDefaultArg
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002286 = cast<TemplateTemplateParmDecl>(Param)->hasDefaultArgument();
Douglas Gregor86d9a522009-09-21 16:56:56 +00002287 }
2288
2289 if (!HasDefaultArg)
2290 break;
2291 }
2292 }
2293
2294 if (LastDeducibleArgument) {
2295 // Some of the function template arguments cannot be deduced from a
2296 // function call, so we introduce an explicit template argument list
2297 // containing all of the arguments up to the first deducible argument.
Douglas Gregor218937c2011-02-01 19:23:04 +00002298 Result.AddChunk(Chunk(CodeCompletionString::CK_LeftAngle));
Douglas Gregor86d9a522009-09-21 16:56:56 +00002299 AddTemplateParameterChunks(S.Context, FunTmpl, Result,
2300 LastDeducibleArgument);
Douglas Gregor218937c2011-02-01 19:23:04 +00002301 Result.AddChunk(Chunk(CodeCompletionString::CK_RightAngle));
Douglas Gregor86d9a522009-09-21 16:56:56 +00002302 }
2303
2304 // Add the function parameters
Douglas Gregor218937c2011-02-01 19:23:04 +00002305 Result.AddChunk(Chunk(CodeCompletionString::CK_LeftParen));
Douglas Gregor86d9a522009-09-21 16:56:56 +00002306 AddFunctionParameterChunks(S.Context, Function, Result);
Douglas Gregor218937c2011-02-01 19:23:04 +00002307 Result.AddChunk(Chunk(CodeCompletionString::CK_RightParen));
Douglas Gregora61a8792009-12-11 18:44:16 +00002308 AddFunctionTypeQualsToCompletionString(Result, Function);
Douglas Gregor218937c2011-02-01 19:23:04 +00002309 return Result.TakeString();
Douglas Gregor86d9a522009-09-21 16:56:56 +00002310 }
2311
2312 if (TemplateDecl *Template = dyn_cast<TemplateDecl>(ND)) {
Douglas Gregor0563c262009-09-22 23:15:58 +00002313 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
2314 S.Context);
Douglas Gregor218937c2011-02-01 19:23:04 +00002315 Result.AddTypedTextChunk(CopyString(Result.getAllocator(),
2316 Template->getNameAsString()));
2317 Result.AddChunk(Chunk(CodeCompletionString::CK_LeftAngle));
Douglas Gregor86d9a522009-09-21 16:56:56 +00002318 AddTemplateParameterChunks(S.Context, Template, Result);
Douglas Gregor218937c2011-02-01 19:23:04 +00002319 Result.AddChunk(Chunk(CodeCompletionString::CK_RightAngle));
2320 return Result.TakeString();
Douglas Gregor86d9a522009-09-21 16:56:56 +00002321 }
2322
Douglas Gregor9630eb62009-11-17 16:44:22 +00002323 if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND)) {
Douglas Gregor9630eb62009-11-17 16:44:22 +00002324 Selector Sel = Method->getSelector();
2325 if (Sel.isUnarySelector()) {
Douglas Gregor218937c2011-02-01 19:23:04 +00002326 Result.AddTypedTextChunk(CopyString(Result.getAllocator(),
2327 Sel.getIdentifierInfoForSlot(0)->getName()));
2328 return Result.TakeString();
Douglas Gregor9630eb62009-11-17 16:44:22 +00002329 }
2330
Douglas Gregord3c68542009-11-19 01:08:35 +00002331 std::string SelName = Sel.getIdentifierInfoForSlot(0)->getName().str();
2332 SelName += ':';
2333 if (StartParameter == 0)
Douglas Gregor218937c2011-02-01 19:23:04 +00002334 Result.AddTypedTextChunk(CopyString(Result.getAllocator(), SelName));
Douglas Gregord3c68542009-11-19 01:08:35 +00002335 else {
Douglas Gregor218937c2011-02-01 19:23:04 +00002336 Result.AddInformativeChunk(CopyString(Result.getAllocator(), SelName));
Douglas Gregord3c68542009-11-19 01:08:35 +00002337
2338 // If there is only one parameter, and we're past it, add an empty
2339 // typed-text chunk since there is nothing to type.
2340 if (Method->param_size() == 1)
Douglas Gregor218937c2011-02-01 19:23:04 +00002341 Result.AddTypedTextChunk("");
Douglas Gregord3c68542009-11-19 01:08:35 +00002342 }
Douglas Gregor9630eb62009-11-17 16:44:22 +00002343 unsigned Idx = 0;
2344 for (ObjCMethodDecl::param_iterator P = Method->param_begin(),
2345 PEnd = Method->param_end();
2346 P != PEnd; (void)++P, ++Idx) {
2347 if (Idx > 0) {
Douglas Gregord3c68542009-11-19 01:08:35 +00002348 std::string Keyword;
2349 if (Idx > StartParameter)
Douglas Gregor218937c2011-02-01 19:23:04 +00002350 Result.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregor9630eb62009-11-17 16:44:22 +00002351 if (IdentifierInfo *II = Sel.getIdentifierInfoForSlot(Idx))
2352 Keyword += II->getName().str();
2353 Keyword += ":";
Douglas Gregor1f5537a2010-07-08 23:20:03 +00002354 if (Idx < StartParameter || AllParametersAreInformative)
Douglas Gregor218937c2011-02-01 19:23:04 +00002355 Result.AddInformativeChunk(CopyString(Result.getAllocator(),
2356 Keyword));
Douglas Gregorc7b7b7a2010-10-18 21:05:04 +00002357 else
Douglas Gregor218937c2011-02-01 19:23:04 +00002358 Result.AddTypedTextChunk(CopyString(Result.getAllocator(), Keyword));
Douglas Gregor9630eb62009-11-17 16:44:22 +00002359 }
Douglas Gregord3c68542009-11-19 01:08:35 +00002360
2361 // If we're before the starting parameter, skip the placeholder.
2362 if (Idx < StartParameter)
2363 continue;
Douglas Gregor9630eb62009-11-17 16:44:22 +00002364
2365 std::string Arg;
Douglas Gregor83482d12010-08-24 16:15:59 +00002366
2367 if ((*P)->getType()->isBlockPointerType() && !DeclaringEntity)
Douglas Gregoraba48082010-08-29 19:47:46 +00002368 Arg = FormatFunctionParameter(S.Context, *P, true);
Douglas Gregor83482d12010-08-24 16:15:59 +00002369 else {
2370 (*P)->getType().getAsStringInternal(Arg, S.Context.PrintingPolicy);
2371 Arg = "(" + Arg + ")";
2372 if (IdentifierInfo *II = (*P)->getIdentifier())
Douglas Gregoraba48082010-08-29 19:47:46 +00002373 if (DeclaringEntity || AllParametersAreInformative)
2374 Arg += II->getName().str();
Douglas Gregor83482d12010-08-24 16:15:59 +00002375 }
2376
Douglas Gregore17794f2010-08-31 05:13:43 +00002377 if (Method->isVariadic() && (P + 1) == PEnd)
2378 Arg += ", ...";
2379
Douglas Gregor1f5537a2010-07-08 23:20:03 +00002380 if (DeclaringEntity)
Douglas Gregor218937c2011-02-01 19:23:04 +00002381 Result.AddTextChunk(CopyString(Result.getAllocator(), Arg));
Douglas Gregor1f5537a2010-07-08 23:20:03 +00002382 else if (AllParametersAreInformative)
Douglas Gregor218937c2011-02-01 19:23:04 +00002383 Result.AddInformativeChunk(CopyString(Result.getAllocator(), Arg));
Douglas Gregor4ad96852009-11-19 07:41:15 +00002384 else
Douglas Gregor218937c2011-02-01 19:23:04 +00002385 Result.AddPlaceholderChunk(CopyString(Result.getAllocator(), Arg));
Douglas Gregor9630eb62009-11-17 16:44:22 +00002386 }
2387
Douglas Gregor2a17af02009-12-23 00:21:46 +00002388 if (Method->isVariadic()) {
Douglas Gregore17794f2010-08-31 05:13:43 +00002389 if (Method->param_size() == 0) {
2390 if (DeclaringEntity)
Douglas Gregor218937c2011-02-01 19:23:04 +00002391 Result.AddTextChunk(", ...");
Douglas Gregore17794f2010-08-31 05:13:43 +00002392 else if (AllParametersAreInformative)
Douglas Gregor218937c2011-02-01 19:23:04 +00002393 Result.AddInformativeChunk(", ...");
Douglas Gregore17794f2010-08-31 05:13:43 +00002394 else
Douglas Gregor218937c2011-02-01 19:23:04 +00002395 Result.AddPlaceholderChunk(", ...");
Douglas Gregore17794f2010-08-31 05:13:43 +00002396 }
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002397
2398 MaybeAddSentinel(S.Context, Method, Result);
Douglas Gregor2a17af02009-12-23 00:21:46 +00002399 }
2400
Douglas Gregor218937c2011-02-01 19:23:04 +00002401 return Result.TakeString();
Douglas Gregor9630eb62009-11-17 16:44:22 +00002402 }
2403
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002404 if (Qualifier)
Douglas Gregor0563c262009-09-22 23:15:58 +00002405 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
2406 S.Context);
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002407
Douglas Gregor218937c2011-02-01 19:23:04 +00002408 Result.AddTypedTextChunk(CopyString(Result.getAllocator(),
2409 ND->getNameAsString()));
2410 return Result.TakeString();
Douglas Gregor86d9a522009-09-21 16:56:56 +00002411}
2412
Douglas Gregor86d802e2009-09-23 00:34:09 +00002413CodeCompletionString *
2414CodeCompleteConsumer::OverloadCandidate::CreateSignatureString(
2415 unsigned CurrentArg,
Douglas Gregor32be4a52010-10-11 21:37:58 +00002416 Sema &S,
Douglas Gregor218937c2011-02-01 19:23:04 +00002417 llvm::BumpPtrAllocator &Allocator) const {
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002418 typedef CodeCompletionString::Chunk Chunk;
2419
Douglas Gregor218937c2011-02-01 19:23:04 +00002420 // FIXME: Set priority, availability appropriately.
2421 CodeCompletionBuilder Result(Allocator, 1, CXAvailability_Available);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002422 FunctionDecl *FDecl = getFunction();
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00002423 AddResultTypeChunk(S.Context, FDecl, Result);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002424 const FunctionProtoType *Proto
2425 = dyn_cast<FunctionProtoType>(getFunctionType());
2426 if (!FDecl && !Proto) {
2427 // Function without a prototype. Just give the return type and a
2428 // highlighted ellipsis.
Douglas Gregor218937c2011-02-01 19:23:04 +00002429 // FIXME: Fast-path common types?
Douglas Gregor86d802e2009-09-23 00:34:09 +00002430 const FunctionType *FT = getFunctionType();
Douglas Gregor218937c2011-02-01 19:23:04 +00002431 Result.AddTextChunk(CopyString(Result.getAllocator(),
2432 FT->getResultType().getAsString(S.Context.PrintingPolicy)));
2433 Result.AddChunk(Chunk(CodeCompletionString::CK_LeftParen));
2434 Result.AddChunk(Chunk(CodeCompletionString::CK_CurrentParameter, "..."));
2435 Result.AddChunk(Chunk(CodeCompletionString::CK_RightParen));
2436 return Result.TakeString();
Douglas Gregor86d802e2009-09-23 00:34:09 +00002437 }
2438
2439 if (FDecl)
Douglas Gregor218937c2011-02-01 19:23:04 +00002440 Result.AddTextChunk(CopyString(Result.getAllocator(),
2441 FDecl->getNameAsString()));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002442 else
Douglas Gregor218937c2011-02-01 19:23:04 +00002443 Result.AddTextChunk(
2444 CopyString(Result.getAllocator(),
2445 Proto->getResultType().getAsString(S.Context.PrintingPolicy)));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002446
Douglas Gregor218937c2011-02-01 19:23:04 +00002447 Result.AddChunk(Chunk(CodeCompletionString::CK_LeftParen));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002448 unsigned NumParams = FDecl? FDecl->getNumParams() : Proto->getNumArgs();
2449 for (unsigned I = 0; I != NumParams; ++I) {
2450 if (I)
Douglas Gregor218937c2011-02-01 19:23:04 +00002451 Result.AddChunk(Chunk(CodeCompletionString::CK_Comma));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002452
2453 std::string ArgString;
2454 QualType ArgType;
2455
2456 if (FDecl) {
2457 ArgString = FDecl->getParamDecl(I)->getNameAsString();
2458 ArgType = FDecl->getParamDecl(I)->getOriginalType();
2459 } else {
2460 ArgType = Proto->getArgType(I);
2461 }
2462
2463 ArgType.getAsStringInternal(ArgString, S.Context.PrintingPolicy);
2464
2465 if (I == CurrentArg)
Douglas Gregor218937c2011-02-01 19:23:04 +00002466 Result.AddChunk(Chunk(CodeCompletionString::CK_CurrentParameter,
2467 CopyString(Result.getAllocator(), ArgString)));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002468 else
Douglas Gregor218937c2011-02-01 19:23:04 +00002469 Result.AddTextChunk(CopyString(Result.getAllocator(), ArgString));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002470 }
2471
2472 if (Proto && Proto->isVariadic()) {
Douglas Gregor218937c2011-02-01 19:23:04 +00002473 Result.AddChunk(Chunk(CodeCompletionString::CK_Comma));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002474 if (CurrentArg < NumParams)
Douglas Gregor218937c2011-02-01 19:23:04 +00002475 Result.AddTextChunk("...");
Douglas Gregor86d802e2009-09-23 00:34:09 +00002476 else
Douglas Gregor218937c2011-02-01 19:23:04 +00002477 Result.AddChunk(Chunk(CodeCompletionString::CK_CurrentParameter, "..."));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002478 }
Douglas Gregor218937c2011-02-01 19:23:04 +00002479 Result.AddChunk(Chunk(CodeCompletionString::CK_RightParen));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002480
Douglas Gregor218937c2011-02-01 19:23:04 +00002481 return Result.TakeString();
Douglas Gregor86d802e2009-09-23 00:34:09 +00002482}
2483
Douglas Gregor1827e102010-08-16 16:18:59 +00002484unsigned clang::getMacroUsagePriority(llvm::StringRef MacroName,
Douglas Gregorb05496d2010-09-20 21:11:48 +00002485 const LangOptions &LangOpts,
Douglas Gregor1827e102010-08-16 16:18:59 +00002486 bool PreferredTypeIsPointer) {
2487 unsigned Priority = CCP_Macro;
2488
Douglas Gregorb05496d2010-09-20 21:11:48 +00002489 // Treat the "nil", "Nil" and "NULL" macros as null pointer constants.
2490 if (MacroName.equals("nil") || MacroName.equals("NULL") ||
2491 MacroName.equals("Nil")) {
Douglas Gregor1827e102010-08-16 16:18:59 +00002492 Priority = CCP_Constant;
2493 if (PreferredTypeIsPointer)
2494 Priority = Priority / CCF_SimilarTypeMatch;
Douglas Gregorb05496d2010-09-20 21:11:48 +00002495 }
2496 // Treat "YES", "NO", "true", and "false" as constants.
2497 else if (MacroName.equals("YES") || MacroName.equals("NO") ||
2498 MacroName.equals("true") || MacroName.equals("false"))
2499 Priority = CCP_Constant;
2500 // Treat "bool" as a type.
2501 else if (MacroName.equals("bool"))
2502 Priority = CCP_Type + (LangOpts.ObjC1? CCD_bool_in_ObjC : 0);
2503
Douglas Gregor1827e102010-08-16 16:18:59 +00002504
2505 return Priority;
2506}
2507
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002508CXCursorKind clang::getCursorKindForDecl(Decl *D) {
2509 if (!D)
2510 return CXCursor_UnexposedDecl;
2511
2512 switch (D->getKind()) {
2513 case Decl::Enum: return CXCursor_EnumDecl;
2514 case Decl::EnumConstant: return CXCursor_EnumConstantDecl;
2515 case Decl::Field: return CXCursor_FieldDecl;
2516 case Decl::Function:
2517 return CXCursor_FunctionDecl;
2518 case Decl::ObjCCategory: return CXCursor_ObjCCategoryDecl;
2519 case Decl::ObjCCategoryImpl: return CXCursor_ObjCCategoryImplDecl;
2520 case Decl::ObjCClass:
2521 // FIXME
2522 return CXCursor_UnexposedDecl;
2523 case Decl::ObjCForwardProtocol:
2524 // FIXME
2525 return CXCursor_UnexposedDecl;
2526 case Decl::ObjCImplementation: return CXCursor_ObjCImplementationDecl;
2527 case Decl::ObjCInterface: return CXCursor_ObjCInterfaceDecl;
2528 case Decl::ObjCIvar: return CXCursor_ObjCIvarDecl;
2529 case Decl::ObjCMethod:
2530 return cast<ObjCMethodDecl>(D)->isInstanceMethod()
2531 ? CXCursor_ObjCInstanceMethodDecl : CXCursor_ObjCClassMethodDecl;
2532 case Decl::CXXMethod: return CXCursor_CXXMethod;
2533 case Decl::CXXConstructor: return CXCursor_Constructor;
2534 case Decl::CXXDestructor: return CXCursor_Destructor;
2535 case Decl::CXXConversion: return CXCursor_ConversionFunction;
2536 case Decl::ObjCProperty: return CXCursor_ObjCPropertyDecl;
2537 case Decl::ObjCProtocol: return CXCursor_ObjCProtocolDecl;
2538 case Decl::ParmVar: return CXCursor_ParmDecl;
2539 case Decl::Typedef: return CXCursor_TypedefDecl;
2540 case Decl::Var: return CXCursor_VarDecl;
2541 case Decl::Namespace: return CXCursor_Namespace;
2542 case Decl::NamespaceAlias: return CXCursor_NamespaceAlias;
2543 case Decl::TemplateTypeParm: return CXCursor_TemplateTypeParameter;
2544 case Decl::NonTypeTemplateParm:return CXCursor_NonTypeTemplateParameter;
2545 case Decl::TemplateTemplateParm:return CXCursor_TemplateTemplateParameter;
2546 case Decl::FunctionTemplate: return CXCursor_FunctionTemplate;
2547 case Decl::ClassTemplate: return CXCursor_ClassTemplate;
2548 case Decl::ClassTemplatePartialSpecialization:
2549 return CXCursor_ClassTemplatePartialSpecialization;
2550 case Decl::UsingDirective: return CXCursor_UsingDirective;
2551
2552 case Decl::Using:
2553 case Decl::UnresolvedUsingValue:
2554 case Decl::UnresolvedUsingTypename:
2555 return CXCursor_UsingDeclaration;
2556
2557 default:
2558 if (TagDecl *TD = dyn_cast<TagDecl>(D)) {
2559 switch (TD->getTagKind()) {
2560 case TTK_Struct: return CXCursor_StructDecl;
2561 case TTK_Class: return CXCursor_ClassDecl;
2562 case TTK_Union: return CXCursor_UnionDecl;
2563 case TTK_Enum: return CXCursor_EnumDecl;
2564 }
2565 }
2566 }
2567
2568 return CXCursor_UnexposedDecl;
2569}
2570
Douglas Gregor590c7d52010-07-08 20:55:51 +00002571static void AddMacroResults(Preprocessor &PP, ResultBuilder &Results,
2572 bool TargetTypeIsPointer = false) {
John McCall0a2c5e22010-08-25 06:19:51 +00002573 typedef CodeCompletionResult Result;
Douglas Gregor590c7d52010-07-08 20:55:51 +00002574
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002575 Results.EnterNewScope();
Douglas Gregorc7b7b7a2010-10-18 21:05:04 +00002576
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002577 for (Preprocessor::macro_iterator M = PP.macro_begin(),
2578 MEnd = PP.macro_end();
Douglas Gregor590c7d52010-07-08 20:55:51 +00002579 M != MEnd; ++M) {
Douglas Gregor1827e102010-08-16 16:18:59 +00002580 Results.AddResult(Result(M->first,
2581 getMacroUsagePriority(M->first->getName(),
Douglas Gregorb05496d2010-09-20 21:11:48 +00002582 PP.getLangOptions(),
Douglas Gregor1827e102010-08-16 16:18:59 +00002583 TargetTypeIsPointer)));
Douglas Gregor590c7d52010-07-08 20:55:51 +00002584 }
Douglas Gregorc7b7b7a2010-10-18 21:05:04 +00002585
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002586 Results.ExitScope();
Douglas Gregorc7b7b7a2010-10-18 21:05:04 +00002587
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002588}
2589
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00002590static void AddPrettyFunctionResults(const LangOptions &LangOpts,
2591 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00002592 typedef CodeCompletionResult Result;
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00002593
2594 Results.EnterNewScope();
Douglas Gregorc7b7b7a2010-10-18 21:05:04 +00002595
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00002596 Results.AddResult(Result("__PRETTY_FUNCTION__", CCP_Constant));
2597 Results.AddResult(Result("__FUNCTION__", CCP_Constant));
2598 if (LangOpts.C99 || LangOpts.CPlusPlus0x)
2599 Results.AddResult(Result("__func__", CCP_Constant));
2600 Results.ExitScope();
2601}
2602
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00002603static void HandleCodeCompleteResults(Sema *S,
2604 CodeCompleteConsumer *CodeCompleter,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002605 CodeCompletionContext Context,
John McCall0a2c5e22010-08-25 06:19:51 +00002606 CodeCompletionResult *Results,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002607 unsigned NumResults) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002608 if (CodeCompleter)
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002609 CodeCompleter->ProcessCodeCompleteResults(*S, Context, Results, NumResults);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002610}
2611
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002612static enum CodeCompletionContext::Kind mapCodeCompletionContext(Sema &S,
2613 Sema::ParserCompletionContext PCC) {
2614 switch (PCC) {
John McCallf312b1e2010-08-26 23:41:50 +00002615 case Sema::PCC_Namespace:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002616 return CodeCompletionContext::CCC_TopLevel;
2617
John McCallf312b1e2010-08-26 23:41:50 +00002618 case Sema::PCC_Class:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002619 return CodeCompletionContext::CCC_ClassStructUnion;
2620
John McCallf312b1e2010-08-26 23:41:50 +00002621 case Sema::PCC_ObjCInterface:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002622 return CodeCompletionContext::CCC_ObjCInterface;
2623
John McCallf312b1e2010-08-26 23:41:50 +00002624 case Sema::PCC_ObjCImplementation:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002625 return CodeCompletionContext::CCC_ObjCImplementation;
2626
John McCallf312b1e2010-08-26 23:41:50 +00002627 case Sema::PCC_ObjCInstanceVariableList:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002628 return CodeCompletionContext::CCC_ObjCIvarList;
2629
John McCallf312b1e2010-08-26 23:41:50 +00002630 case Sema::PCC_Template:
2631 case Sema::PCC_MemberTemplate:
Douglas Gregor52779fb2010-09-23 23:01:17 +00002632 if (S.CurContext->isFileContext())
2633 return CodeCompletionContext::CCC_TopLevel;
2634 else if (S.CurContext->isRecord())
2635 return CodeCompletionContext::CCC_ClassStructUnion;
2636 else
2637 return CodeCompletionContext::CCC_Other;
2638
John McCallf312b1e2010-08-26 23:41:50 +00002639 case Sema::PCC_RecoveryInFunction:
Douglas Gregor52779fb2010-09-23 23:01:17 +00002640 return CodeCompletionContext::CCC_Recovery;
Douglas Gregora5450a02010-10-18 22:01:46 +00002641
John McCallf312b1e2010-08-26 23:41:50 +00002642 case Sema::PCC_ForInit:
Douglas Gregora5450a02010-10-18 22:01:46 +00002643 if (S.getLangOptions().CPlusPlus || S.getLangOptions().C99 ||
2644 S.getLangOptions().ObjC1)
2645 return CodeCompletionContext::CCC_ParenthesizedExpression;
2646 else
2647 return CodeCompletionContext::CCC_Expression;
2648
2649 case Sema::PCC_Expression:
John McCallf312b1e2010-08-26 23:41:50 +00002650 case Sema::PCC_Condition:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002651 return CodeCompletionContext::CCC_Expression;
2652
John McCallf312b1e2010-08-26 23:41:50 +00002653 case Sema::PCC_Statement:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002654 return CodeCompletionContext::CCC_Statement;
Douglas Gregor72db1082010-08-24 01:11:00 +00002655
John McCallf312b1e2010-08-26 23:41:50 +00002656 case Sema::PCC_Type:
Douglas Gregor72db1082010-08-24 01:11:00 +00002657 return CodeCompletionContext::CCC_Type;
Douglas Gregor02688102010-09-14 23:59:36 +00002658
2659 case Sema::PCC_ParenthesizedExpression:
2660 return CodeCompletionContext::CCC_ParenthesizedExpression;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002661 }
2662
2663 return CodeCompletionContext::CCC_Other;
2664}
2665
Douglas Gregorf6961522010-08-27 21:18:54 +00002666/// \brief If we're in a C++ virtual member function, add completion results
2667/// that invoke the functions we override, since it's common to invoke the
2668/// overridden function as well as adding new functionality.
2669///
2670/// \param S The semantic analysis object for which we are generating results.
2671///
2672/// \param InContext This context in which the nested-name-specifier preceding
2673/// the code-completion point
2674static void MaybeAddOverrideCalls(Sema &S, DeclContext *InContext,
2675 ResultBuilder &Results) {
2676 // Look through blocks.
2677 DeclContext *CurContext = S.CurContext;
2678 while (isa<BlockDecl>(CurContext))
2679 CurContext = CurContext->getParent();
2680
2681
2682 CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(CurContext);
2683 if (!Method || !Method->isVirtual())
2684 return;
2685
2686 // We need to have names for all of the parameters, if we're going to
2687 // generate a forwarding call.
2688 for (CXXMethodDecl::param_iterator P = Method->param_begin(),
2689 PEnd = Method->param_end();
2690 P != PEnd;
2691 ++P) {
2692 if (!(*P)->getDeclName())
2693 return;
2694 }
2695
2696 for (CXXMethodDecl::method_iterator M = Method->begin_overridden_methods(),
2697 MEnd = Method->end_overridden_methods();
2698 M != MEnd; ++M) {
Douglas Gregor218937c2011-02-01 19:23:04 +00002699 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregorf6961522010-08-27 21:18:54 +00002700 CXXMethodDecl *Overridden = const_cast<CXXMethodDecl *>(*M);
2701 if (Overridden->getCanonicalDecl() == Method->getCanonicalDecl())
2702 continue;
2703
2704 // If we need a nested-name-specifier, add one now.
2705 if (!InContext) {
2706 NestedNameSpecifier *NNS
2707 = getRequiredQualification(S.Context, CurContext,
2708 Overridden->getDeclContext());
2709 if (NNS) {
2710 std::string Str;
2711 llvm::raw_string_ostream OS(Str);
2712 NNS->print(OS, S.Context.PrintingPolicy);
Douglas Gregor218937c2011-02-01 19:23:04 +00002713 Builder.AddTextChunk(CopyString(Results.getAllocator(), OS.str()));
Douglas Gregorf6961522010-08-27 21:18:54 +00002714 }
2715 } else if (!InContext->Equals(Overridden->getDeclContext()))
2716 continue;
2717
Douglas Gregor218937c2011-02-01 19:23:04 +00002718 Builder.AddTypedTextChunk(CopyString(Results.getAllocator(),
2719 Overridden->getNameAsString()));
2720 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregorf6961522010-08-27 21:18:54 +00002721 bool FirstParam = true;
2722 for (CXXMethodDecl::param_iterator P = Method->param_begin(),
2723 PEnd = Method->param_end();
2724 P != PEnd; ++P) {
2725 if (FirstParam)
2726 FirstParam = false;
2727 else
Douglas Gregor218937c2011-02-01 19:23:04 +00002728 Builder.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregorf6961522010-08-27 21:18:54 +00002729
Douglas Gregor218937c2011-02-01 19:23:04 +00002730 Builder.AddPlaceholderChunk(CopyString(Results.getAllocator(),
2731 (*P)->getIdentifier()->getName()));
Douglas Gregorf6961522010-08-27 21:18:54 +00002732 }
Douglas Gregor218937c2011-02-01 19:23:04 +00002733 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2734 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregorf6961522010-08-27 21:18:54 +00002735 CCP_SuperCompletion,
2736 CXCursor_CXXMethod));
2737 Results.Ignore(Overridden);
2738 }
2739}
2740
Douglas Gregor01dfea02010-01-10 23:08:15 +00002741void Sema::CodeCompleteOrdinaryName(Scope *S,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002742 ParserCompletionContext CompletionContext) {
John McCall0a2c5e22010-08-25 06:19:51 +00002743 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00002744 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00002745 mapCodeCompletionContext(*this, CompletionContext));
Douglas Gregorf6961522010-08-27 21:18:54 +00002746 Results.EnterNewScope();
Douglas Gregorcee9ff12010-09-20 22:39:41 +00002747
Douglas Gregor01dfea02010-01-10 23:08:15 +00002748 // Determine how to filter results, e.g., so that the names of
2749 // values (functions, enumerators, function templates, etc.) are
2750 // only allowed where we can have an expression.
2751 switch (CompletionContext) {
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002752 case PCC_Namespace:
2753 case PCC_Class:
2754 case PCC_ObjCInterface:
2755 case PCC_ObjCImplementation:
2756 case PCC_ObjCInstanceVariableList:
2757 case PCC_Template:
2758 case PCC_MemberTemplate:
Douglas Gregor72db1082010-08-24 01:11:00 +00002759 case PCC_Type:
Douglas Gregor01dfea02010-01-10 23:08:15 +00002760 Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
2761 break;
2762
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002763 case PCC_Statement:
Douglas Gregor02688102010-09-14 23:59:36 +00002764 case PCC_ParenthesizedExpression:
Douglas Gregoreb0d0142010-08-24 23:58:17 +00002765 case PCC_Expression:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002766 case PCC_ForInit:
2767 case PCC_Condition:
Douglas Gregor4710e5b2010-05-28 00:49:12 +00002768 if (WantTypesInContext(CompletionContext, getLangOptions()))
2769 Results.setFilter(&ResultBuilder::IsOrdinaryName);
2770 else
2771 Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
Douglas Gregorf6961522010-08-27 21:18:54 +00002772
2773 if (getLangOptions().CPlusPlus)
2774 MaybeAddOverrideCalls(*this, /*InContext=*/0, Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00002775 break;
Douglas Gregordc845342010-05-25 05:58:43 +00002776
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002777 case PCC_RecoveryInFunction:
Douglas Gregordc845342010-05-25 05:58:43 +00002778 // Unfiltered
2779 break;
Douglas Gregor01dfea02010-01-10 23:08:15 +00002780 }
2781
Douglas Gregor3cdee122010-08-26 16:36:48 +00002782 // If we are in a C++ non-static member function, check the qualifiers on
2783 // the member function to filter/prioritize the results list.
2784 if (CXXMethodDecl *CurMethod = dyn_cast<CXXMethodDecl>(CurContext))
2785 if (CurMethod->isInstance())
2786 Results.setObjectTypeQualifiers(
2787 Qualifiers::fromCVRMask(CurMethod->getTypeQualifiers()));
2788
Douglas Gregor1ca6ae82010-01-14 01:09:38 +00002789 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00002790 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
2791 CodeCompleter->includeGlobals());
Douglas Gregor2a7925c2009-12-07 09:54:55 +00002792
Douglas Gregorbca403c2010-01-13 23:51:12 +00002793 AddOrdinaryNameResults(CompletionContext, S, *this, Results);
Douglas Gregor2a7925c2009-12-07 09:54:55 +00002794 Results.ExitScope();
2795
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00002796 switch (CompletionContext) {
Douglas Gregor02688102010-09-14 23:59:36 +00002797 case PCC_ParenthesizedExpression:
Douglas Gregor72db1082010-08-24 01:11:00 +00002798 case PCC_Expression:
2799 case PCC_Statement:
2800 case PCC_RecoveryInFunction:
2801 if (S->getFnParent())
2802 AddPrettyFunctionResults(PP.getLangOptions(), Results);
2803 break;
2804
2805 case PCC_Namespace:
2806 case PCC_Class:
2807 case PCC_ObjCInterface:
2808 case PCC_ObjCImplementation:
2809 case PCC_ObjCInstanceVariableList:
2810 case PCC_Template:
2811 case PCC_MemberTemplate:
2812 case PCC_ForInit:
2813 case PCC_Condition:
2814 case PCC_Type:
2815 break;
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00002816 }
2817
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002818 if (CodeCompleter->includeMacros())
Douglas Gregorbca403c2010-01-13 23:51:12 +00002819 AddMacroResults(PP, Results);
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00002820
Douglas Gregorcee9ff12010-09-20 22:39:41 +00002821 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002822 Results.data(),Results.size());
Douglas Gregor791215b2009-09-21 20:51:25 +00002823}
2824
Douglas Gregorc7b6d882010-09-16 15:14:18 +00002825static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
2826 ParsedType Receiver,
2827 IdentifierInfo **SelIdents,
2828 unsigned NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00002829 bool AtArgumentExpression,
Douglas Gregorc7b6d882010-09-16 15:14:18 +00002830 bool IsSuper,
2831 ResultBuilder &Results);
2832
2833void Sema::CodeCompleteDeclSpec(Scope *S, DeclSpec &DS,
2834 bool AllowNonIdentifiers,
2835 bool AllowNestedNameSpecifiers) {
John McCall0a2c5e22010-08-25 06:19:51 +00002836 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00002837 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00002838 AllowNestedNameSpecifiers
2839 ? CodeCompletionContext::CCC_PotentiallyQualifiedName
2840 : CodeCompletionContext::CCC_Name);
Douglas Gregor2ccccb32010-08-23 18:23:48 +00002841 Results.EnterNewScope();
2842
2843 // Type qualifiers can come after names.
2844 Results.AddResult(Result("const"));
2845 Results.AddResult(Result("volatile"));
2846 if (getLangOptions().C99)
2847 Results.AddResult(Result("restrict"));
2848
2849 if (getLangOptions().CPlusPlus) {
2850 if (AllowNonIdentifiers) {
2851 Results.AddResult(Result("operator"));
2852 }
2853
2854 // Add nested-name-specifiers.
2855 if (AllowNestedNameSpecifiers) {
2856 Results.allowNestedNameSpecifiers();
Douglas Gregor52779fb2010-09-23 23:01:17 +00002857 Results.setFilter(&ResultBuilder::IsImpossibleToSatisfy);
Douglas Gregor2ccccb32010-08-23 18:23:48 +00002858 CodeCompletionDeclConsumer Consumer(Results, CurContext);
2859 LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer,
2860 CodeCompleter->includeGlobals());
Douglas Gregor52779fb2010-09-23 23:01:17 +00002861 Results.setFilter(0);
Douglas Gregor2ccccb32010-08-23 18:23:48 +00002862 }
2863 }
2864 Results.ExitScope();
2865
Douglas Gregorc7b6d882010-09-16 15:14:18 +00002866 // If we're in a context where we might have an expression (rather than a
2867 // declaration), and what we've seen so far is an Objective-C type that could
2868 // be a receiver of a class message, this may be a class message send with
2869 // the initial opening bracket '[' missing. Add appropriate completions.
2870 if (AllowNonIdentifiers && !AllowNestedNameSpecifiers &&
2871 DS.getTypeSpecType() == DeclSpec::TST_typename &&
2872 DS.getStorageClassSpecAsWritten() == DeclSpec::SCS_unspecified &&
2873 !DS.isThreadSpecified() && !DS.isExternInLinkageSpec() &&
2874 DS.getTypeSpecComplex() == DeclSpec::TSC_unspecified &&
2875 DS.getTypeSpecSign() == DeclSpec::TSS_unspecified &&
2876 DS.getTypeQualifiers() == 0 &&
2877 S &&
2878 (S->getFlags() & Scope::DeclScope) != 0 &&
2879 (S->getFlags() & (Scope::ClassScope | Scope::TemplateParamScope |
2880 Scope::FunctionPrototypeScope |
2881 Scope::AtCatchScope)) == 0) {
2882 ParsedType T = DS.getRepAsType();
2883 if (!T.get().isNull() && T.get()->isObjCObjectOrInterfaceType())
Douglas Gregor70c5ac72010-09-20 23:34:21 +00002884 AddClassMessageCompletions(*this, S, T, 0, 0, false, false, Results);
Douglas Gregorc7b6d882010-09-16 15:14:18 +00002885 }
2886
Douglas Gregor4497dd42010-08-24 04:59:56 +00002887 // Note that we intentionally suppress macro results here, since we do not
2888 // encourage using macros to produce the names of entities.
2889
Douglas Gregor52779fb2010-09-23 23:01:17 +00002890 HandleCodeCompleteResults(this, CodeCompleter,
2891 Results.getCompletionContext(),
Douglas Gregor2ccccb32010-08-23 18:23:48 +00002892 Results.data(), Results.size());
2893}
2894
Douglas Gregorfb629412010-08-23 21:17:50 +00002895struct Sema::CodeCompleteExpressionData {
2896 CodeCompleteExpressionData(QualType PreferredType = QualType())
2897 : PreferredType(PreferredType), IntegralConstantExpression(false),
2898 ObjCCollection(false) { }
2899
2900 QualType PreferredType;
2901 bool IntegralConstantExpression;
2902 bool ObjCCollection;
2903 llvm::SmallVector<Decl *, 4> IgnoreDecls;
2904};
2905
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00002906/// \brief Perform code-completion in an expression context when we know what
2907/// type we're looking for.
Douglas Gregorf9578432010-07-28 21:50:18 +00002908///
2909/// \param IntegralConstantExpression Only permit integral constant
2910/// expressions.
Douglas Gregorfb629412010-08-23 21:17:50 +00002911void Sema::CodeCompleteExpression(Scope *S,
2912 const CodeCompleteExpressionData &Data) {
John McCall0a2c5e22010-08-25 06:19:51 +00002913 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00002914 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
2915 CodeCompletionContext::CCC_Expression);
Douglas Gregorfb629412010-08-23 21:17:50 +00002916 if (Data.ObjCCollection)
2917 Results.setFilter(&ResultBuilder::IsObjCCollection);
2918 else if (Data.IntegralConstantExpression)
Douglas Gregorf9578432010-07-28 21:50:18 +00002919 Results.setFilter(&ResultBuilder::IsIntegralConstantValue);
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002920 else if (WantTypesInContext(PCC_Expression, getLangOptions()))
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00002921 Results.setFilter(&ResultBuilder::IsOrdinaryName);
2922 else
2923 Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
Douglas Gregorfb629412010-08-23 21:17:50 +00002924
2925 if (!Data.PreferredType.isNull())
2926 Results.setPreferredType(Data.PreferredType.getNonReferenceType());
2927
2928 // Ignore any declarations that we were told that we don't care about.
2929 for (unsigned I = 0, N = Data.IgnoreDecls.size(); I != N; ++I)
2930 Results.Ignore(Data.IgnoreDecls[I]);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00002931
2932 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00002933 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
2934 CodeCompleter->includeGlobals());
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00002935
2936 Results.EnterNewScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002937 AddOrdinaryNameResults(PCC_Expression, S, *this, Results);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00002938 Results.ExitScope();
2939
Douglas Gregor590c7d52010-07-08 20:55:51 +00002940 bool PreferredTypeIsPointer = false;
Douglas Gregorfb629412010-08-23 21:17:50 +00002941 if (!Data.PreferredType.isNull())
2942 PreferredTypeIsPointer = Data.PreferredType->isAnyPointerType()
2943 || Data.PreferredType->isMemberPointerType()
2944 || Data.PreferredType->isBlockPointerType();
Douglas Gregor590c7d52010-07-08 20:55:51 +00002945
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00002946 if (S->getFnParent() &&
2947 !Data.ObjCCollection &&
2948 !Data.IntegralConstantExpression)
2949 AddPrettyFunctionResults(PP.getLangOptions(), Results);
2950
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00002951 if (CodeCompleter->includeMacros())
Douglas Gregor590c7d52010-07-08 20:55:51 +00002952 AddMacroResults(PP, Results, PreferredTypeIsPointer);
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002953 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregorfb629412010-08-23 21:17:50 +00002954 CodeCompletionContext(CodeCompletionContext::CCC_Expression,
2955 Data.PreferredType),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002956 Results.data(),Results.size());
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00002957}
2958
Douglas Gregorac5fd842010-09-18 01:28:11 +00002959void Sema::CodeCompletePostfixExpression(Scope *S, ExprResult E) {
2960 if (E.isInvalid())
2961 CodeCompleteOrdinaryName(S, PCC_RecoveryInFunction);
2962 else if (getLangOptions().ObjC1)
2963 CodeCompleteObjCInstanceMessage(S, E.take(), 0, 0, false);
Douglas Gregor78edf512010-09-15 16:23:04 +00002964}
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00002965
Douglas Gregor73449212010-12-09 23:01:55 +00002966/// \brief The set of properties that have already been added, referenced by
2967/// property name.
2968typedef llvm::SmallPtrSet<IdentifierInfo*, 16> AddedPropertiesSet;
2969
Douglas Gregor95ac6552009-11-18 01:29:26 +00002970static void AddObjCProperties(ObjCContainerDecl *Container,
Douglas Gregor322328b2009-11-18 22:32:06 +00002971 bool AllowCategories,
Douglas Gregor95ac6552009-11-18 01:29:26 +00002972 DeclContext *CurContext,
Douglas Gregor73449212010-12-09 23:01:55 +00002973 AddedPropertiesSet &AddedProperties,
Douglas Gregor95ac6552009-11-18 01:29:26 +00002974 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00002975 typedef CodeCompletionResult Result;
Douglas Gregor95ac6552009-11-18 01:29:26 +00002976
2977 // Add properties in this container.
2978 for (ObjCContainerDecl::prop_iterator P = Container->prop_begin(),
2979 PEnd = Container->prop_end();
2980 P != PEnd;
Douglas Gregor73449212010-12-09 23:01:55 +00002981 ++P) {
2982 if (AddedProperties.insert(P->getIdentifier()))
2983 Results.MaybeAddResult(Result(*P, 0), CurContext);
2984 }
Douglas Gregor95ac6552009-11-18 01:29:26 +00002985
2986 // Add properties in referenced protocols.
2987 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
2988 for (ObjCProtocolDecl::protocol_iterator P = Protocol->protocol_begin(),
2989 PEnd = Protocol->protocol_end();
2990 P != PEnd; ++P)
Douglas Gregor73449212010-12-09 23:01:55 +00002991 AddObjCProperties(*P, AllowCategories, CurContext, AddedProperties,
2992 Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00002993 } else if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)){
Douglas Gregor322328b2009-11-18 22:32:06 +00002994 if (AllowCategories) {
2995 // Look through categories.
2996 for (ObjCCategoryDecl *Category = IFace->getCategoryList();
2997 Category; Category = Category->getNextClassCategory())
Douglas Gregor73449212010-12-09 23:01:55 +00002998 AddObjCProperties(Category, AllowCategories, CurContext,
2999 AddedProperties, Results);
Douglas Gregor322328b2009-11-18 22:32:06 +00003000 }
Douglas Gregor95ac6552009-11-18 01:29:26 +00003001
3002 // Look through protocols.
Ted Kremenek53b94412010-09-01 01:21:15 +00003003 for (ObjCInterfaceDecl::all_protocol_iterator
3004 I = IFace->all_referenced_protocol_begin(),
3005 E = IFace->all_referenced_protocol_end(); I != E; ++I)
Douglas Gregor73449212010-12-09 23:01:55 +00003006 AddObjCProperties(*I, AllowCategories, CurContext, AddedProperties,
3007 Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003008
3009 // Look in the superclass.
3010 if (IFace->getSuperClass())
Douglas Gregor322328b2009-11-18 22:32:06 +00003011 AddObjCProperties(IFace->getSuperClass(), AllowCategories, CurContext,
Douglas Gregor73449212010-12-09 23:01:55 +00003012 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003013 } else if (const ObjCCategoryDecl *Category
3014 = dyn_cast<ObjCCategoryDecl>(Container)) {
3015 // Look through protocols.
Ted Kremenek53b94412010-09-01 01:21:15 +00003016 for (ObjCCategoryDecl::protocol_iterator P = Category->protocol_begin(),
3017 PEnd = Category->protocol_end();
Douglas Gregor95ac6552009-11-18 01:29:26 +00003018 P != PEnd; ++P)
Douglas Gregor73449212010-12-09 23:01:55 +00003019 AddObjCProperties(*P, AllowCategories, CurContext, AddedProperties,
3020 Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003021 }
3022}
3023
Douglas Gregor81b747b2009-09-17 21:32:03 +00003024void Sema::CodeCompleteMemberReferenceExpr(Scope *S, ExprTy *BaseE,
3025 SourceLocation OpLoc,
3026 bool IsArrow) {
3027 if (!BaseE || !CodeCompleter)
3028 return;
3029
John McCall0a2c5e22010-08-25 06:19:51 +00003030 typedef CodeCompletionResult Result;
Douglas Gregor86d9a522009-09-21 16:56:56 +00003031
Douglas Gregor81b747b2009-09-17 21:32:03 +00003032 Expr *Base = static_cast<Expr *>(BaseE);
3033 QualType BaseType = Base->getType();
Douglas Gregor86d9a522009-09-21 16:56:56 +00003034
3035 if (IsArrow) {
3036 if (const PointerType *Ptr = BaseType->getAs<PointerType>())
3037 BaseType = Ptr->getPointeeType();
3038 else if (BaseType->isObjCObjectPointerType())
Douglas Gregor3cdee122010-08-26 16:36:48 +00003039 /*Do nothing*/ ;
Douglas Gregor86d9a522009-09-21 16:56:56 +00003040 else
3041 return;
3042 }
3043
Douglas Gregor218937c2011-02-01 19:23:04 +00003044 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00003045 CodeCompletionContext(CodeCompletionContext::CCC_MemberAccess,
3046 BaseType),
3047 &ResultBuilder::IsMember);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003048 Results.EnterNewScope();
3049 if (const RecordType *Record = BaseType->getAs<RecordType>()) {
Douglas Gregor3cdee122010-08-26 16:36:48 +00003050 // Indicate that we are performing a member access, and the cv-qualifiers
3051 // for the base object type.
3052 Results.setObjectTypeQualifiers(BaseType.getQualifiers());
3053
Douglas Gregor95ac6552009-11-18 01:29:26 +00003054 // Access to a C/C++ class, struct, or union.
Douglas Gregor45bcd432010-01-14 03:21:49 +00003055 Results.allowNestedNameSpecifiers();
Douglas Gregor0cc84042010-01-14 15:47:35 +00003056 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00003057 LookupVisibleDecls(Record->getDecl(), LookupMemberName, Consumer,
3058 CodeCompleter->includeGlobals());
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003059
Douglas Gregor95ac6552009-11-18 01:29:26 +00003060 if (getLangOptions().CPlusPlus) {
3061 if (!Results.empty()) {
3062 // The "template" keyword can follow "->" or "." in the grammar.
3063 // However, we only want to suggest the template keyword if something
3064 // is dependent.
3065 bool IsDependent = BaseType->isDependentType();
3066 if (!IsDependent) {
3067 for (Scope *DepScope = S; DepScope; DepScope = DepScope->getParent())
3068 if (DeclContext *Ctx = (DeclContext *)DepScope->getEntity()) {
3069 IsDependent = Ctx->isDependentContext();
3070 break;
3071 }
3072 }
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003073
Douglas Gregor95ac6552009-11-18 01:29:26 +00003074 if (IsDependent)
Douglas Gregora4477812010-01-14 16:01:26 +00003075 Results.AddResult(Result("template"));
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003076 }
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003077 }
Douglas Gregor95ac6552009-11-18 01:29:26 +00003078 } else if (!IsArrow && BaseType->getAsObjCInterfacePointerType()) {
3079 // Objective-C property reference.
Douglas Gregor73449212010-12-09 23:01:55 +00003080 AddedPropertiesSet AddedProperties;
Douglas Gregor95ac6552009-11-18 01:29:26 +00003081
3082 // Add property results based on our interface.
3083 const ObjCObjectPointerType *ObjCPtr
3084 = BaseType->getAsObjCInterfacePointerType();
3085 assert(ObjCPtr && "Non-NULL pointer guaranteed above!");
Douglas Gregor73449212010-12-09 23:01:55 +00003086 AddObjCProperties(ObjCPtr->getInterfaceDecl(), true, CurContext,
3087 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003088
3089 // Add properties from the protocols in a qualified interface.
3090 for (ObjCObjectPointerType::qual_iterator I = ObjCPtr->qual_begin(),
3091 E = ObjCPtr->qual_end();
3092 I != E; ++I)
Douglas Gregor73449212010-12-09 23:01:55 +00003093 AddObjCProperties(*I, true, CurContext, AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003094 } else if ((IsArrow && BaseType->isObjCObjectPointerType()) ||
John McCallc12c5bb2010-05-15 11:32:37 +00003095 (!IsArrow && BaseType->isObjCObjectType())) {
Douglas Gregor95ac6552009-11-18 01:29:26 +00003096 // Objective-C instance variable access.
3097 ObjCInterfaceDecl *Class = 0;
3098 if (const ObjCObjectPointerType *ObjCPtr
3099 = BaseType->getAs<ObjCObjectPointerType>())
3100 Class = ObjCPtr->getInterfaceDecl();
3101 else
John McCallc12c5bb2010-05-15 11:32:37 +00003102 Class = BaseType->getAs<ObjCObjectType>()->getInterface();
Douglas Gregor95ac6552009-11-18 01:29:26 +00003103
3104 // Add all ivars from this class and its superclasses.
Douglas Gregor80f4f4c2010-01-14 16:08:12 +00003105 if (Class) {
3106 CodeCompletionDeclConsumer Consumer(Results, CurContext);
3107 Results.setFilter(&ResultBuilder::IsObjCIvar);
Douglas Gregor8071e422010-08-15 06:18:01 +00003108 LookupVisibleDecls(Class, LookupMemberName, Consumer,
3109 CodeCompleter->includeGlobals());
Douglas Gregor95ac6552009-11-18 01:29:26 +00003110 }
Douglas Gregor86d9a522009-09-21 16:56:56 +00003111 }
Douglas Gregor95ac6552009-11-18 01:29:26 +00003112
3113 // FIXME: How do we cope with isa?
3114
3115 Results.ExitScope();
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003116
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003117 // Hand off the results found for code completion.
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003118 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00003119 Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003120 Results.data(),Results.size());
Douglas Gregor81b747b2009-09-17 21:32:03 +00003121}
3122
Douglas Gregor374929f2009-09-18 15:37:17 +00003123void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) {
3124 if (!CodeCompleter)
3125 return;
3126
John McCall0a2c5e22010-08-25 06:19:51 +00003127 typedef CodeCompletionResult Result;
Douglas Gregor86d9a522009-09-21 16:56:56 +00003128 ResultBuilder::LookupFilter Filter = 0;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003129 enum CodeCompletionContext::Kind ContextKind
3130 = CodeCompletionContext::CCC_Other;
Douglas Gregor374929f2009-09-18 15:37:17 +00003131 switch ((DeclSpec::TST)TagSpec) {
3132 case DeclSpec::TST_enum:
Douglas Gregor86d9a522009-09-21 16:56:56 +00003133 Filter = &ResultBuilder::IsEnum;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003134 ContextKind = CodeCompletionContext::CCC_EnumTag;
Douglas Gregor374929f2009-09-18 15:37:17 +00003135 break;
3136
3137 case DeclSpec::TST_union:
Douglas Gregor86d9a522009-09-21 16:56:56 +00003138 Filter = &ResultBuilder::IsUnion;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003139 ContextKind = CodeCompletionContext::CCC_UnionTag;
Douglas Gregor374929f2009-09-18 15:37:17 +00003140 break;
3141
3142 case DeclSpec::TST_struct:
Douglas Gregor374929f2009-09-18 15:37:17 +00003143 case DeclSpec::TST_class:
Douglas Gregor86d9a522009-09-21 16:56:56 +00003144 Filter = &ResultBuilder::IsClassOrStruct;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003145 ContextKind = CodeCompletionContext::CCC_ClassOrStructTag;
Douglas Gregor374929f2009-09-18 15:37:17 +00003146 break;
3147
3148 default:
3149 assert(false && "Unknown type specifier kind in CodeCompleteTag");
3150 return;
3151 }
Douglas Gregor86d9a522009-09-21 16:56:56 +00003152
Douglas Gregor218937c2011-02-01 19:23:04 +00003153 ResultBuilder Results(*this, CodeCompleter->getAllocator(), ContextKind);
Douglas Gregor5d2fc402010-01-14 03:27:13 +00003154 CodeCompletionDeclConsumer Consumer(Results, CurContext);
John McCall0d6b1642010-04-23 18:46:30 +00003155
3156 // First pass: look for tags.
3157 Results.setFilter(Filter);
Douglas Gregor8071e422010-08-15 06:18:01 +00003158 LookupVisibleDecls(S, LookupTagName, Consumer,
3159 CodeCompleter->includeGlobals());
John McCall0d6b1642010-04-23 18:46:30 +00003160
Douglas Gregor8071e422010-08-15 06:18:01 +00003161 if (CodeCompleter->includeGlobals()) {
3162 // Second pass: look for nested name specifiers.
3163 Results.setFilter(&ResultBuilder::IsNestedNameSpecifier);
3164 LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer);
3165 }
Douglas Gregor86d9a522009-09-21 16:56:56 +00003166
Douglas Gregor52779fb2010-09-23 23:01:17 +00003167 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003168 Results.data(),Results.size());
Douglas Gregor374929f2009-09-18 15:37:17 +00003169}
3170
Douglas Gregor1a480c42010-08-27 17:35:51 +00003171void Sema::CodeCompleteTypeQualifiers(DeclSpec &DS) {
Douglas Gregor218937c2011-02-01 19:23:04 +00003172 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3173 CodeCompletionContext::CCC_TypeQualifiers);
Douglas Gregor1a480c42010-08-27 17:35:51 +00003174 Results.EnterNewScope();
3175 if (!(DS.getTypeQualifiers() & DeclSpec::TQ_const))
3176 Results.AddResult("const");
3177 if (!(DS.getTypeQualifiers() & DeclSpec::TQ_volatile))
3178 Results.AddResult("volatile");
3179 if (getLangOptions().C99 &&
3180 !(DS.getTypeQualifiers() & DeclSpec::TQ_restrict))
3181 Results.AddResult("restrict");
3182 Results.ExitScope();
3183 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00003184 Results.getCompletionContext(),
Douglas Gregor1a480c42010-08-27 17:35:51 +00003185 Results.data(), Results.size());
3186}
3187
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003188void Sema::CodeCompleteCase(Scope *S) {
John McCall781472f2010-08-25 08:40:02 +00003189 if (getCurFunction()->SwitchStack.empty() || !CodeCompleter)
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003190 return;
3191
John McCall781472f2010-08-25 08:40:02 +00003192 SwitchStmt *Switch = getCurFunction()->SwitchStack.back();
Douglas Gregorf9578432010-07-28 21:50:18 +00003193 if (!Switch->getCond()->getType()->isEnumeralType()) {
Douglas Gregorfb629412010-08-23 21:17:50 +00003194 CodeCompleteExpressionData Data(Switch->getCond()->getType());
3195 Data.IntegralConstantExpression = true;
3196 CodeCompleteExpression(S, Data);
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003197 return;
Douglas Gregorf9578432010-07-28 21:50:18 +00003198 }
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003199
3200 // Code-complete the cases of a switch statement over an enumeration type
3201 // by providing the list of
3202 EnumDecl *Enum = Switch->getCond()->getType()->getAs<EnumType>()->getDecl();
3203
3204 // Determine which enumerators we have already seen in the switch statement.
3205 // FIXME: Ideally, we would also be able to look *past* the code-completion
3206 // token, in case we are code-completing in the middle of the switch and not
3207 // at the end. However, we aren't able to do so at the moment.
3208 llvm::SmallPtrSet<EnumConstantDecl *, 8> EnumeratorsSeen;
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00003209 NestedNameSpecifier *Qualifier = 0;
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003210 for (SwitchCase *SC = Switch->getSwitchCaseList(); SC;
3211 SC = SC->getNextSwitchCase()) {
3212 CaseStmt *Case = dyn_cast<CaseStmt>(SC);
3213 if (!Case)
3214 continue;
3215
3216 Expr *CaseVal = Case->getLHS()->IgnoreParenCasts();
3217 if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CaseVal))
3218 if (EnumConstantDecl *Enumerator
3219 = dyn_cast<EnumConstantDecl>(DRE->getDecl())) {
3220 // We look into the AST of the case statement to determine which
3221 // enumerator was named. Alternatively, we could compute the value of
3222 // the integral constant expression, then compare it against the
3223 // values of each enumerator. However, value-based approach would not
3224 // work as well with C++ templates where enumerators declared within a
3225 // template are type- and value-dependent.
3226 EnumeratorsSeen.insert(Enumerator);
3227
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00003228 // If this is a qualified-id, keep track of the nested-name-specifier
3229 // so that we can reproduce it as part of code completion, e.g.,
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003230 //
3231 // switch (TagD.getKind()) {
3232 // case TagDecl::TK_enum:
3233 // break;
3234 // case XXX
3235 //
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00003236 // At the XXX, our completions are TagDecl::TK_union,
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003237 // TagDecl::TK_struct, and TagDecl::TK_class, rather than TK_union,
3238 // TK_struct, and TK_class.
Douglas Gregora2813ce2009-10-23 18:54:35 +00003239 Qualifier = DRE->getQualifier();
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003240 }
3241 }
3242
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00003243 if (getLangOptions().CPlusPlus && !Qualifier && EnumeratorsSeen.empty()) {
3244 // If there are no prior enumerators in C++, check whether we have to
3245 // qualify the names of the enumerators that we suggest, because they
3246 // may not be visible in this scope.
3247 Qualifier = getRequiredQualification(Context, CurContext,
3248 Enum->getDeclContext());
3249
3250 // FIXME: Scoped enums need to start with "EnumDecl" as the context!
3251 }
3252
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003253 // Add any enumerators that have not yet been mentioned.
Douglas Gregor218937c2011-02-01 19:23:04 +00003254 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3255 CodeCompletionContext::CCC_Expression);
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003256 Results.EnterNewScope();
3257 for (EnumDecl::enumerator_iterator E = Enum->enumerator_begin(),
3258 EEnd = Enum->enumerator_end();
3259 E != EEnd; ++E) {
3260 if (EnumeratorsSeen.count(*E))
3261 continue;
3262
John McCall0a2c5e22010-08-25 06:19:51 +00003263 Results.AddResult(CodeCompletionResult(*E, Qualifier),
Douglas Gregor608300b2010-01-14 16:14:35 +00003264 CurContext, 0, false);
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003265 }
3266 Results.ExitScope();
Douglas Gregor2f880e42010-04-06 20:02:15 +00003267
Douglas Gregor0c8296d2009-11-07 00:00:49 +00003268 if (CodeCompleter->includeMacros())
Douglas Gregorbca403c2010-01-13 23:51:12 +00003269 AddMacroResults(PP, Results);
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003270 HandleCodeCompleteResults(this, CodeCompleter,
3271 CodeCompletionContext::CCC_Expression,
3272 Results.data(),Results.size());
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003273}
3274
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003275namespace {
3276 struct IsBetterOverloadCandidate {
3277 Sema &S;
John McCall5769d612010-02-08 23:07:23 +00003278 SourceLocation Loc;
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003279
3280 public:
John McCall5769d612010-02-08 23:07:23 +00003281 explicit IsBetterOverloadCandidate(Sema &S, SourceLocation Loc)
3282 : S(S), Loc(Loc) { }
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003283
3284 bool
3285 operator()(const OverloadCandidate &X, const OverloadCandidate &Y) const {
John McCall120d63c2010-08-24 20:38:10 +00003286 return isBetterOverloadCandidate(S, X, Y, Loc);
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003287 }
3288 };
3289}
3290
Douglas Gregord28dcd72010-05-30 06:10:08 +00003291static bool anyNullArguments(Expr **Args, unsigned NumArgs) {
3292 if (NumArgs && !Args)
3293 return true;
3294
3295 for (unsigned I = 0; I != NumArgs; ++I)
3296 if (!Args[I])
3297 return true;
3298
3299 return false;
3300}
3301
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003302void Sema::CodeCompleteCall(Scope *S, ExprTy *FnIn,
3303 ExprTy **ArgsIn, unsigned NumArgs) {
3304 if (!CodeCompleter)
3305 return;
Douglas Gregoref96eac2009-12-11 19:06:04 +00003306
3307 // When we're code-completing for a call, we fall back to ordinary
3308 // name code-completion whenever we can't produce specific
3309 // results. We may want to revisit this strategy in the future,
3310 // e.g., by merging the two kinds of results.
3311
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003312 Expr *Fn = (Expr *)FnIn;
3313 Expr **Args = (Expr **)ArgsIn;
Douglas Gregoref96eac2009-12-11 19:06:04 +00003314
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003315 // Ignore type-dependent call expressions entirely.
Douglas Gregord28dcd72010-05-30 06:10:08 +00003316 if (!Fn || Fn->isTypeDependent() || anyNullArguments(Args, NumArgs) ||
Douglas Gregoref96eac2009-12-11 19:06:04 +00003317 Expr::hasAnyTypeDependentArguments(Args, NumArgs)) {
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003318 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003319 return;
Douglas Gregoref96eac2009-12-11 19:06:04 +00003320 }
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003321
John McCall3b4294e2009-12-16 12:17:52 +00003322 // Build an overload candidate set based on the functions we find.
John McCall5769d612010-02-08 23:07:23 +00003323 SourceLocation Loc = Fn->getExprLoc();
3324 OverloadCandidateSet CandidateSet(Loc);
John McCall3b4294e2009-12-16 12:17:52 +00003325
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003326 // FIXME: What if we're calling something that isn't a function declaration?
3327 // FIXME: What if we're calling a pseudo-destructor?
3328 // FIXME: What if we're calling a member function?
3329
Douglas Gregorc0265402010-01-21 15:46:19 +00003330 typedef CodeCompleteConsumer::OverloadCandidate ResultCandidate;
3331 llvm::SmallVector<ResultCandidate, 8> Results;
3332
John McCall3b4294e2009-12-16 12:17:52 +00003333 Expr *NakedFn = Fn->IgnoreParenCasts();
3334 if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(NakedFn))
3335 AddOverloadedCallCandidates(ULE, Args, NumArgs, CandidateSet,
3336 /*PartialOverloading=*/ true);
3337 else if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(NakedFn)) {
3338 FunctionDecl *FDecl = dyn_cast<FunctionDecl>(DRE->getDecl());
Douglas Gregorc0265402010-01-21 15:46:19 +00003339 if (FDecl) {
Douglas Gregord28dcd72010-05-30 06:10:08 +00003340 if (!getLangOptions().CPlusPlus ||
3341 !FDecl->getType()->getAs<FunctionProtoType>())
Douglas Gregorc0265402010-01-21 15:46:19 +00003342 Results.push_back(ResultCandidate(FDecl));
3343 else
John McCall86820f52010-01-26 01:37:31 +00003344 // FIXME: access?
John McCall9aa472c2010-03-19 07:35:19 +00003345 AddOverloadCandidate(FDecl, DeclAccessPair::make(FDecl, AS_none),
3346 Args, NumArgs, CandidateSet,
Douglas Gregorc27d6c52010-04-16 17:41:49 +00003347 false, /*PartialOverloading*/true);
Douglas Gregorc0265402010-01-21 15:46:19 +00003348 }
John McCall3b4294e2009-12-16 12:17:52 +00003349 }
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003350
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003351 QualType ParamType;
3352
Douglas Gregorc0265402010-01-21 15:46:19 +00003353 if (!CandidateSet.empty()) {
3354 // Sort the overload candidate set by placing the best overloads first.
3355 std::stable_sort(CandidateSet.begin(), CandidateSet.end(),
John McCall5769d612010-02-08 23:07:23 +00003356 IsBetterOverloadCandidate(*this, Loc));
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003357
Douglas Gregorc0265402010-01-21 15:46:19 +00003358 // Add the remaining viable overload candidates as code-completion reslults.
3359 for (OverloadCandidateSet::iterator Cand = CandidateSet.begin(),
3360 CandEnd = CandidateSet.end();
3361 Cand != CandEnd; ++Cand) {
3362 if (Cand->Viable)
3363 Results.push_back(ResultCandidate(Cand->Function));
3364 }
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003365
3366 // From the viable candidates, try to determine the type of this parameter.
3367 for (unsigned I = 0, N = Results.size(); I != N; ++I) {
3368 if (const FunctionType *FType = Results[I].getFunctionType())
3369 if (const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FType))
3370 if (NumArgs < Proto->getNumArgs()) {
3371 if (ParamType.isNull())
3372 ParamType = Proto->getArgType(NumArgs);
3373 else if (!Context.hasSameUnqualifiedType(
3374 ParamType.getNonReferenceType(),
3375 Proto->getArgType(NumArgs).getNonReferenceType())) {
3376 ParamType = QualType();
3377 break;
3378 }
3379 }
3380 }
3381 } else {
3382 // Try to determine the parameter type from the type of the expression
3383 // being called.
3384 QualType FunctionType = Fn->getType();
3385 if (const PointerType *Ptr = FunctionType->getAs<PointerType>())
3386 FunctionType = Ptr->getPointeeType();
3387 else if (const BlockPointerType *BlockPtr
3388 = FunctionType->getAs<BlockPointerType>())
3389 FunctionType = BlockPtr->getPointeeType();
3390 else if (const MemberPointerType *MemPtr
3391 = FunctionType->getAs<MemberPointerType>())
3392 FunctionType = MemPtr->getPointeeType();
3393
3394 if (const FunctionProtoType *Proto
3395 = FunctionType->getAs<FunctionProtoType>()) {
3396 if (NumArgs < Proto->getNumArgs())
3397 ParamType = Proto->getArgType(NumArgs);
3398 }
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003399 }
Douglas Gregoref96eac2009-12-11 19:06:04 +00003400
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003401 if (ParamType.isNull())
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003402 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003403 else
3404 CodeCompleteExpression(S, ParamType);
3405
Douglas Gregor2e4c7a52010-04-06 20:19:47 +00003406 if (!Results.empty())
Douglas Gregoref96eac2009-12-11 19:06:04 +00003407 CodeCompleter->ProcessOverloadCandidates(*this, NumArgs, Results.data(),
3408 Results.size());
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003409}
3410
John McCalld226f652010-08-21 09:40:31 +00003411void Sema::CodeCompleteInitializer(Scope *S, Decl *D) {
3412 ValueDecl *VD = dyn_cast_or_null<ValueDecl>(D);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003413 if (!VD) {
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003414 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003415 return;
3416 }
3417
3418 CodeCompleteExpression(S, VD->getType());
3419}
3420
3421void Sema::CodeCompleteReturn(Scope *S) {
3422 QualType ResultType;
3423 if (isa<BlockDecl>(CurContext)) {
3424 if (BlockScopeInfo *BSI = getCurBlock())
3425 ResultType = BSI->ReturnType;
3426 } else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(CurContext))
3427 ResultType = Function->getResultType();
3428 else if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(CurContext))
3429 ResultType = Method->getResultType();
3430
3431 if (ResultType.isNull())
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003432 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003433 else
3434 CodeCompleteExpression(S, ResultType);
3435}
3436
3437void Sema::CodeCompleteAssignmentRHS(Scope *S, ExprTy *LHS) {
3438 if (LHS)
3439 CodeCompleteExpression(S, static_cast<Expr *>(LHS)->getType());
3440 else
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003441 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003442}
3443
Jeffrey Yasskin9ab14542010-04-08 16:38:48 +00003444void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS,
Douglas Gregor81b747b2009-09-17 21:32:03 +00003445 bool EnteringContext) {
3446 if (!SS.getScopeRep() || !CodeCompleter)
3447 return;
3448
Douglas Gregor86d9a522009-09-21 16:56:56 +00003449 DeclContext *Ctx = computeDeclContext(SS, EnteringContext);
3450 if (!Ctx)
3451 return;
Douglas Gregord1cd31a2009-12-11 18:28:39 +00003452
3453 // Try to instantiate any non-dependent declaration contexts before
3454 // we look in them.
John McCall77bb1aa2010-05-01 00:40:08 +00003455 if (!isDependentScopeSpecifier(SS) && RequireCompleteDeclContext(SS, Ctx))
Douglas Gregord1cd31a2009-12-11 18:28:39 +00003456 return;
3457
Douglas Gregor218937c2011-02-01 19:23:04 +00003458 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3459 CodeCompletionContext::CCC_Name);
Douglas Gregorf6961522010-08-27 21:18:54 +00003460 Results.EnterNewScope();
Douglas Gregor52779fb2010-09-23 23:01:17 +00003461
Douglas Gregor86d9a522009-09-21 16:56:56 +00003462 // The "template" keyword can follow "::" in the grammar, but only
3463 // put it into the grammar if the nested-name-specifier is dependent.
3464 NestedNameSpecifier *NNS = (NestedNameSpecifier *)SS.getScopeRep();
3465 if (!Results.empty() && NNS->isDependent())
Douglas Gregora4477812010-01-14 16:01:26 +00003466 Results.AddResult("template");
Douglas Gregorf6961522010-08-27 21:18:54 +00003467
3468 // Add calls to overridden virtual functions, if there are any.
3469 //
3470 // FIXME: This isn't wonderful, because we don't know whether we're actually
3471 // in a context that permits expressions. This is a general issue with
3472 // qualified-id completions.
3473 if (!EnteringContext)
3474 MaybeAddOverrideCalls(*this, Ctx, Results);
3475 Results.ExitScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00003476
Douglas Gregorf6961522010-08-27 21:18:54 +00003477 CodeCompletionDeclConsumer Consumer(Results, CurContext);
3478 LookupVisibleDecls(Ctx, LookupOrdinaryName, Consumer);
3479
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003480 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregorf6961522010-08-27 21:18:54 +00003481 CodeCompletionContext::CCC_Name,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003482 Results.data(),Results.size());
Douglas Gregor81b747b2009-09-17 21:32:03 +00003483}
Douglas Gregor49f40bd2009-09-18 19:03:04 +00003484
3485void Sema::CodeCompleteUsing(Scope *S) {
3486 if (!CodeCompleter)
3487 return;
3488
Douglas Gregor218937c2011-02-01 19:23:04 +00003489 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00003490 CodeCompletionContext::CCC_PotentiallyQualifiedName,
3491 &ResultBuilder::IsNestedNameSpecifier);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00003492 Results.EnterNewScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00003493
3494 // If we aren't in class scope, we could see the "namespace" keyword.
3495 if (!S->isClassScope())
John McCall0a2c5e22010-08-25 06:19:51 +00003496 Results.AddResult(CodeCompletionResult("namespace"));
Douglas Gregor86d9a522009-09-21 16:56:56 +00003497
3498 // After "using", we can see anything that would start a
3499 // nested-name-specifier.
Douglas Gregor5d2fc402010-01-14 03:27:13 +00003500 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00003501 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3502 CodeCompleter->includeGlobals());
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00003503 Results.ExitScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00003504
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003505 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00003506 CodeCompletionContext::CCC_PotentiallyQualifiedName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003507 Results.data(),Results.size());
Douglas Gregor49f40bd2009-09-18 19:03:04 +00003508}
3509
3510void Sema::CodeCompleteUsingDirective(Scope *S) {
3511 if (!CodeCompleter)
3512 return;
3513
Douglas Gregor86d9a522009-09-21 16:56:56 +00003514 // After "using namespace", we expect to see a namespace name or namespace
3515 // alias.
Douglas Gregor218937c2011-02-01 19:23:04 +00003516 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3517 CodeCompletionContext::CCC_Namespace,
Douglas Gregor52779fb2010-09-23 23:01:17 +00003518 &ResultBuilder::IsNamespaceOrAlias);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00003519 Results.EnterNewScope();
Douglas Gregor5d2fc402010-01-14 03:27:13 +00003520 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00003521 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3522 CodeCompleter->includeGlobals());
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00003523 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003524 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor8071e422010-08-15 06:18:01 +00003525 CodeCompletionContext::CCC_Namespace,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003526 Results.data(),Results.size());
Douglas Gregor49f40bd2009-09-18 19:03:04 +00003527}
3528
3529void Sema::CodeCompleteNamespaceDecl(Scope *S) {
3530 if (!CodeCompleter)
3531 return;
3532
Douglas Gregor86d9a522009-09-21 16:56:56 +00003533 DeclContext *Ctx = (DeclContext *)S->getEntity();
3534 if (!S->getParent())
3535 Ctx = Context.getTranslationUnitDecl();
3536
Douglas Gregor52779fb2010-09-23 23:01:17 +00003537 bool SuppressedGlobalResults
3538 = Ctx && !CodeCompleter->includeGlobals() && isa<TranslationUnitDecl>(Ctx);
3539
Douglas Gregor218937c2011-02-01 19:23:04 +00003540 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00003541 SuppressedGlobalResults
3542 ? CodeCompletionContext::CCC_Namespace
3543 : CodeCompletionContext::CCC_Other,
3544 &ResultBuilder::IsNamespace);
3545
3546 if (Ctx && Ctx->isFileContext() && !SuppressedGlobalResults) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00003547 // We only want to see those namespaces that have already been defined
3548 // within this scope, because its likely that the user is creating an
3549 // extended namespace declaration. Keep track of the most recent
3550 // definition of each namespace.
3551 std::map<NamespaceDecl *, NamespaceDecl *> OrigToLatest;
3552 for (DeclContext::specific_decl_iterator<NamespaceDecl>
3553 NS(Ctx->decls_begin()), NSEnd(Ctx->decls_end());
3554 NS != NSEnd; ++NS)
3555 OrigToLatest[NS->getOriginalNamespace()] = *NS;
3556
3557 // Add the most recent definition (or extended definition) of each
3558 // namespace to the list of results.
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00003559 Results.EnterNewScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00003560 for (std::map<NamespaceDecl *, NamespaceDecl *>::iterator
3561 NS = OrigToLatest.begin(), NSEnd = OrigToLatest.end();
3562 NS != NSEnd; ++NS)
John McCall0a2c5e22010-08-25 06:19:51 +00003563 Results.AddResult(CodeCompletionResult(NS->second, 0),
Douglas Gregor608300b2010-01-14 16:14:35 +00003564 CurContext, 0, false);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00003565 Results.ExitScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00003566 }
3567
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003568 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00003569 Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003570 Results.data(),Results.size());
Douglas Gregor49f40bd2009-09-18 19:03:04 +00003571}
3572
3573void Sema::CodeCompleteNamespaceAliasDecl(Scope *S) {
3574 if (!CodeCompleter)
3575 return;
3576
Douglas Gregor86d9a522009-09-21 16:56:56 +00003577 // After "namespace", we expect to see a namespace or alias.
Douglas Gregor218937c2011-02-01 19:23:04 +00003578 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3579 CodeCompletionContext::CCC_Namespace,
Douglas Gregor52779fb2010-09-23 23:01:17 +00003580 &ResultBuilder::IsNamespaceOrAlias);
Douglas Gregor5d2fc402010-01-14 03:27:13 +00003581 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00003582 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3583 CodeCompleter->includeGlobals());
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003584 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00003585 Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003586 Results.data(),Results.size());
Douglas Gregor49f40bd2009-09-18 19:03:04 +00003587}
3588
Douglas Gregored8d3222009-09-18 20:05:18 +00003589void Sema::CodeCompleteOperatorName(Scope *S) {
3590 if (!CodeCompleter)
3591 return;
Douglas Gregor86d9a522009-09-21 16:56:56 +00003592
John McCall0a2c5e22010-08-25 06:19:51 +00003593 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00003594 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3595 CodeCompletionContext::CCC_Type,
Douglas Gregor52779fb2010-09-23 23:01:17 +00003596 &ResultBuilder::IsType);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00003597 Results.EnterNewScope();
Douglas Gregored8d3222009-09-18 20:05:18 +00003598
Douglas Gregor86d9a522009-09-21 16:56:56 +00003599 // Add the names of overloadable operators.
3600#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
3601 if (std::strcmp(Spelling, "?")) \
Douglas Gregora4477812010-01-14 16:01:26 +00003602 Results.AddResult(Result(Spelling));
Douglas Gregor86d9a522009-09-21 16:56:56 +00003603#include "clang/Basic/OperatorKinds.def"
3604
3605 // Add any type names visible from the current scope
Douglas Gregor45bcd432010-01-14 03:21:49 +00003606 Results.allowNestedNameSpecifiers();
Douglas Gregor5d2fc402010-01-14 03:27:13 +00003607 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00003608 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3609 CodeCompleter->includeGlobals());
Douglas Gregor86d9a522009-09-21 16:56:56 +00003610
3611 // Add any type specifiers
Douglas Gregorbca403c2010-01-13 23:51:12 +00003612 AddTypeSpecifierResults(getLangOptions(), Results);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00003613 Results.ExitScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00003614
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003615 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor8071e422010-08-15 06:18:01 +00003616 CodeCompletionContext::CCC_Type,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003617 Results.data(),Results.size());
Douglas Gregored8d3222009-09-18 20:05:18 +00003618}
Douglas Gregor49f40bd2009-09-18 19:03:04 +00003619
Douglas Gregor0133f522010-08-28 00:00:50 +00003620void Sema::CodeCompleteConstructorInitializer(Decl *ConstructorD,
Sean Huntcbb67482011-01-08 20:30:50 +00003621 CXXCtorInitializer** Initializers,
Douglas Gregor0133f522010-08-28 00:00:50 +00003622 unsigned NumInitializers) {
3623 CXXConstructorDecl *Constructor
3624 = static_cast<CXXConstructorDecl *>(ConstructorD);
3625 if (!Constructor)
3626 return;
3627
Douglas Gregor218937c2011-02-01 19:23:04 +00003628 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00003629 CodeCompletionContext::CCC_PotentiallyQualifiedName);
Douglas Gregor0133f522010-08-28 00:00:50 +00003630 Results.EnterNewScope();
3631
3632 // Fill in any already-initialized fields or base classes.
3633 llvm::SmallPtrSet<FieldDecl *, 4> InitializedFields;
3634 llvm::SmallPtrSet<CanQualType, 4> InitializedBases;
3635 for (unsigned I = 0; I != NumInitializers; ++I) {
3636 if (Initializers[I]->isBaseInitializer())
3637 InitializedBases.insert(
3638 Context.getCanonicalType(QualType(Initializers[I]->getBaseClass(), 0)));
3639 else
Francois Pichet00eb3f92010-12-04 09:14:42 +00003640 InitializedFields.insert(cast<FieldDecl>(
3641 Initializers[I]->getAnyMember()));
Douglas Gregor0133f522010-08-28 00:00:50 +00003642 }
3643
3644 // Add completions for base classes.
Douglas Gregor218937c2011-02-01 19:23:04 +00003645 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregor0c431c82010-08-29 19:27:27 +00003646 bool SawLastInitializer = (NumInitializers == 0);
Douglas Gregor0133f522010-08-28 00:00:50 +00003647 CXXRecordDecl *ClassDecl = Constructor->getParent();
3648 for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),
3649 BaseEnd = ClassDecl->bases_end();
3650 Base != BaseEnd; ++Base) {
Douglas Gregor0c431c82010-08-29 19:27:27 +00003651 if (!InitializedBases.insert(Context.getCanonicalType(Base->getType()))) {
3652 SawLastInitializer
3653 = NumInitializers > 0 &&
3654 Initializers[NumInitializers - 1]->isBaseInitializer() &&
3655 Context.hasSameUnqualifiedType(Base->getType(),
3656 QualType(Initializers[NumInitializers - 1]->getBaseClass(), 0));
Douglas Gregor0133f522010-08-28 00:00:50 +00003657 continue;
Douglas Gregor0c431c82010-08-29 19:27:27 +00003658 }
Douglas Gregor0133f522010-08-28 00:00:50 +00003659
Douglas Gregor218937c2011-02-01 19:23:04 +00003660 Builder.AddTypedTextChunk(
3661 CopyString(Results.getAllocator(),
3662 Base->getType().getAsString(Context.PrintingPolicy)));
3663 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
3664 Builder.AddPlaceholderChunk("args");
3665 Builder.AddChunk(CodeCompletionString::CK_RightParen);
3666 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor0c431c82010-08-29 19:27:27 +00003667 SawLastInitializer? CCP_NextInitializer
3668 : CCP_MemberDeclaration));
3669 SawLastInitializer = false;
Douglas Gregor0133f522010-08-28 00:00:50 +00003670 }
3671
3672 // Add completions for virtual base classes.
3673 for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(),
3674 BaseEnd = ClassDecl->vbases_end();
3675 Base != BaseEnd; ++Base) {
Douglas Gregor0c431c82010-08-29 19:27:27 +00003676 if (!InitializedBases.insert(Context.getCanonicalType(Base->getType()))) {
3677 SawLastInitializer
3678 = NumInitializers > 0 &&
3679 Initializers[NumInitializers - 1]->isBaseInitializer() &&
3680 Context.hasSameUnqualifiedType(Base->getType(),
3681 QualType(Initializers[NumInitializers - 1]->getBaseClass(), 0));
Douglas Gregor0133f522010-08-28 00:00:50 +00003682 continue;
Douglas Gregor0c431c82010-08-29 19:27:27 +00003683 }
Douglas Gregor0133f522010-08-28 00:00:50 +00003684
Douglas Gregor218937c2011-02-01 19:23:04 +00003685 Builder.AddTypedTextChunk(
3686 CopyString(Builder.getAllocator(),
3687 Base->getType().getAsString(Context.PrintingPolicy)));
3688 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
3689 Builder.AddPlaceholderChunk("args");
3690 Builder.AddChunk(CodeCompletionString::CK_RightParen);
3691 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor0c431c82010-08-29 19:27:27 +00003692 SawLastInitializer? CCP_NextInitializer
3693 : CCP_MemberDeclaration));
3694 SawLastInitializer = false;
Douglas Gregor0133f522010-08-28 00:00:50 +00003695 }
3696
3697 // Add completions for members.
3698 for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
3699 FieldEnd = ClassDecl->field_end();
3700 Field != FieldEnd; ++Field) {
Douglas Gregor0c431c82010-08-29 19:27:27 +00003701 if (!InitializedFields.insert(cast<FieldDecl>(Field->getCanonicalDecl()))) {
3702 SawLastInitializer
3703 = NumInitializers > 0 &&
Francois Pichet00eb3f92010-12-04 09:14:42 +00003704 Initializers[NumInitializers - 1]->isAnyMemberInitializer() &&
3705 Initializers[NumInitializers - 1]->getAnyMember() == *Field;
Douglas Gregor0133f522010-08-28 00:00:50 +00003706 continue;
Douglas Gregor0c431c82010-08-29 19:27:27 +00003707 }
Douglas Gregor0133f522010-08-28 00:00:50 +00003708
3709 if (!Field->getDeclName())
3710 continue;
3711
Douglas Gregor218937c2011-02-01 19:23:04 +00003712 Builder.AddTypedTextChunk(CopyString(Builder.getAllocator(),
3713 Field->getIdentifier()->getName()));
3714 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
3715 Builder.AddPlaceholderChunk("args");
3716 Builder.AddChunk(CodeCompletionString::CK_RightParen);
3717 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor0c431c82010-08-29 19:27:27 +00003718 SawLastInitializer? CCP_NextInitializer
Douglas Gregora67e03f2010-09-09 21:42:20 +00003719 : CCP_MemberDeclaration,
3720 CXCursor_MemberRef));
Douglas Gregor0c431c82010-08-29 19:27:27 +00003721 SawLastInitializer = false;
Douglas Gregor0133f522010-08-28 00:00:50 +00003722 }
3723 Results.ExitScope();
3724
Douglas Gregor52779fb2010-09-23 23:01:17 +00003725 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor0133f522010-08-28 00:00:50 +00003726 Results.data(), Results.size());
3727}
3728
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003729// Macro that expands to @Keyword or Keyword, depending on whether NeedAt is
3730// true or false.
3731#define OBJC_AT_KEYWORD_NAME(NeedAt,Keyword) NeedAt? "@" #Keyword : #Keyword
Douglas Gregorbca403c2010-01-13 23:51:12 +00003732static void AddObjCImplementationResults(const LangOptions &LangOpts,
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003733 ResultBuilder &Results,
3734 bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00003735 typedef CodeCompletionResult Result;
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003736 // Since we have an implementation, we can end it.
Douglas Gregora4477812010-01-14 16:01:26 +00003737 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,end)));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003738
Douglas Gregor218937c2011-02-01 19:23:04 +00003739 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003740 if (LangOpts.ObjC2) {
3741 // @dynamic
Douglas Gregor218937c2011-02-01 19:23:04 +00003742 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,dynamic));
3743 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3744 Builder.AddPlaceholderChunk("property");
3745 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003746
3747 // @synthesize
Douglas Gregor218937c2011-02-01 19:23:04 +00003748 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,synthesize));
3749 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3750 Builder.AddPlaceholderChunk("property");
3751 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003752 }
3753}
3754
Douglas Gregorbca403c2010-01-13 23:51:12 +00003755static void AddObjCInterfaceResults(const LangOptions &LangOpts,
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003756 ResultBuilder &Results,
3757 bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00003758 typedef CodeCompletionResult Result;
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003759
3760 // Since we have an interface or protocol, we can end it.
Douglas Gregora4477812010-01-14 16:01:26 +00003761 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,end)));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003762
3763 if (LangOpts.ObjC2) {
3764 // @property
Douglas Gregora4477812010-01-14 16:01:26 +00003765 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,property)));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003766
3767 // @required
Douglas Gregora4477812010-01-14 16:01:26 +00003768 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,required)));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003769
3770 // @optional
Douglas Gregora4477812010-01-14 16:01:26 +00003771 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,optional)));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003772 }
3773}
3774
Douglas Gregorbca403c2010-01-13 23:51:12 +00003775static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00003776 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00003777 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003778
3779 // @class name ;
Douglas Gregor218937c2011-02-01 19:23:04 +00003780 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,class));
3781 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3782 Builder.AddPlaceholderChunk("name");
3783 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003784
Douglas Gregorc8bddde2010-05-28 00:22:41 +00003785 if (Results.includeCodePatterns()) {
3786 // @interface name
3787 // FIXME: Could introduce the whole pattern, including superclasses and
3788 // such.
Douglas Gregor218937c2011-02-01 19:23:04 +00003789 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,interface));
3790 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3791 Builder.AddPlaceholderChunk("class");
3792 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003793
Douglas Gregorc8bddde2010-05-28 00:22:41 +00003794 // @protocol name
Douglas Gregor218937c2011-02-01 19:23:04 +00003795 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,protocol));
3796 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3797 Builder.AddPlaceholderChunk("protocol");
3798 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00003799
3800 // @implementation name
Douglas Gregor218937c2011-02-01 19:23:04 +00003801 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,implementation));
3802 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3803 Builder.AddPlaceholderChunk("class");
3804 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00003805 }
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003806
3807 // @compatibility_alias name
Douglas Gregor218937c2011-02-01 19:23:04 +00003808 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,compatibility_alias));
3809 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3810 Builder.AddPlaceholderChunk("alias");
3811 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3812 Builder.AddPlaceholderChunk("class");
3813 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003814}
3815
John McCalld226f652010-08-21 09:40:31 +00003816void Sema::CodeCompleteObjCAtDirective(Scope *S, Decl *ObjCImpDecl,
Douglas Gregorc464ae82009-12-07 09:27:33 +00003817 bool InInterface) {
John McCall0a2c5e22010-08-25 06:19:51 +00003818 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00003819 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3820 CodeCompletionContext::CCC_Other);
Douglas Gregorc464ae82009-12-07 09:27:33 +00003821 Results.EnterNewScope();
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003822 if (ObjCImpDecl)
Douglas Gregorbca403c2010-01-13 23:51:12 +00003823 AddObjCImplementationResults(getLangOptions(), Results, false);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003824 else if (InInterface)
Douglas Gregorbca403c2010-01-13 23:51:12 +00003825 AddObjCInterfaceResults(getLangOptions(), Results, false);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003826 else
Douglas Gregorbca403c2010-01-13 23:51:12 +00003827 AddObjCTopLevelResults(Results, false);
Douglas Gregorc464ae82009-12-07 09:27:33 +00003828 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003829 HandleCodeCompleteResults(this, CodeCompleter,
3830 CodeCompletionContext::CCC_Other,
3831 Results.data(),Results.size());
Douglas Gregorc464ae82009-12-07 09:27:33 +00003832}
3833
Douglas Gregorbca403c2010-01-13 23:51:12 +00003834static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00003835 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00003836 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00003837
3838 // @encode ( type-name )
Douglas Gregor218937c2011-02-01 19:23:04 +00003839 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,encode));
3840 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
3841 Builder.AddPlaceholderChunk("type-name");
3842 Builder.AddChunk(CodeCompletionString::CK_RightParen);
3843 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00003844
3845 // @protocol ( protocol-name )
Douglas Gregor218937c2011-02-01 19:23:04 +00003846 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,protocol));
3847 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
3848 Builder.AddPlaceholderChunk("protocol-name");
3849 Builder.AddChunk(CodeCompletionString::CK_RightParen);
3850 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00003851
3852 // @selector ( selector )
Douglas Gregor218937c2011-02-01 19:23:04 +00003853 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,selector));
3854 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
3855 Builder.AddPlaceholderChunk("selector");
3856 Builder.AddChunk(CodeCompletionString::CK_RightParen);
3857 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00003858}
3859
Douglas Gregorbca403c2010-01-13 23:51:12 +00003860static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00003861 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00003862 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003863
Douglas Gregorc8bddde2010-05-28 00:22:41 +00003864 if (Results.includeCodePatterns()) {
3865 // @try { statements } @catch ( declaration ) { statements } @finally
3866 // { statements }
Douglas Gregor218937c2011-02-01 19:23:04 +00003867 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,try));
3868 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
3869 Builder.AddPlaceholderChunk("statements");
3870 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
3871 Builder.AddTextChunk("@catch");
3872 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
3873 Builder.AddPlaceholderChunk("parameter");
3874 Builder.AddChunk(CodeCompletionString::CK_RightParen);
3875 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
3876 Builder.AddPlaceholderChunk("statements");
3877 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
3878 Builder.AddTextChunk("@finally");
3879 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
3880 Builder.AddPlaceholderChunk("statements");
3881 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
3882 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00003883 }
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003884
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00003885 // @throw
Douglas Gregor218937c2011-02-01 19:23:04 +00003886 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,throw));
3887 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3888 Builder.AddPlaceholderChunk("expression");
3889 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003890
Douglas Gregorc8bddde2010-05-28 00:22:41 +00003891 if (Results.includeCodePatterns()) {
3892 // @synchronized ( expression ) { statements }
Douglas Gregor218937c2011-02-01 19:23:04 +00003893 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,synchronized));
3894 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3895 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
3896 Builder.AddPlaceholderChunk("expression");
3897 Builder.AddChunk(CodeCompletionString::CK_RightParen);
3898 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
3899 Builder.AddPlaceholderChunk("statements");
3900 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
3901 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00003902 }
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003903}
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00003904
Douglas Gregorbca403c2010-01-13 23:51:12 +00003905static void AddObjCVisibilityResults(const LangOptions &LangOpts,
Douglas Gregorc38c3e12010-01-13 21:54:15 +00003906 ResultBuilder &Results,
3907 bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00003908 typedef CodeCompletionResult Result;
Douglas Gregora4477812010-01-14 16:01:26 +00003909 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,private)));
3910 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,protected)));
3911 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,public)));
Douglas Gregorc38c3e12010-01-13 21:54:15 +00003912 if (LangOpts.ObjC2)
Douglas Gregora4477812010-01-14 16:01:26 +00003913 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,package)));
Douglas Gregorc38c3e12010-01-13 21:54:15 +00003914}
3915
3916void Sema::CodeCompleteObjCAtVisibility(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00003917 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3918 CodeCompletionContext::CCC_Other);
Douglas Gregorc38c3e12010-01-13 21:54:15 +00003919 Results.EnterNewScope();
Douglas Gregorbca403c2010-01-13 23:51:12 +00003920 AddObjCVisibilityResults(getLangOptions(), Results, false);
Douglas Gregorc38c3e12010-01-13 21:54:15 +00003921 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003922 HandleCodeCompleteResults(this, CodeCompleter,
3923 CodeCompletionContext::CCC_Other,
3924 Results.data(),Results.size());
Douglas Gregorc38c3e12010-01-13 21:54:15 +00003925}
3926
3927void Sema::CodeCompleteObjCAtStatement(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00003928 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3929 CodeCompletionContext::CCC_Other);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003930 Results.EnterNewScope();
Douglas Gregorbca403c2010-01-13 23:51:12 +00003931 AddObjCStatementResults(Results, false);
3932 AddObjCExpressionResults(Results, false);
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00003933 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003934 HandleCodeCompleteResults(this, CodeCompleter,
3935 CodeCompletionContext::CCC_Other,
3936 Results.data(),Results.size());
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00003937}
3938
3939void Sema::CodeCompleteObjCAtExpression(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00003940 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3941 CodeCompletionContext::CCC_Other);
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00003942 Results.EnterNewScope();
Douglas Gregorbca403c2010-01-13 23:51:12 +00003943 AddObjCExpressionResults(Results, false);
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00003944 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003945 HandleCodeCompleteResults(this, CodeCompleter,
3946 CodeCompletionContext::CCC_Other,
3947 Results.data(),Results.size());
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00003948}
3949
Douglas Gregor988358f2009-11-19 00:14:45 +00003950/// \brief Determine whether the addition of the given flag to an Objective-C
3951/// property's attributes will cause a conflict.
3952static bool ObjCPropertyFlagConflicts(unsigned Attributes, unsigned NewFlag) {
3953 // Check if we've already added this flag.
3954 if (Attributes & NewFlag)
3955 return true;
3956
3957 Attributes |= NewFlag;
3958
3959 // Check for collisions with "readonly".
3960 if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) &&
3961 (Attributes & (ObjCDeclSpec::DQ_PR_readwrite |
3962 ObjCDeclSpec::DQ_PR_assign |
3963 ObjCDeclSpec::DQ_PR_copy |
3964 ObjCDeclSpec::DQ_PR_retain)))
3965 return true;
3966
3967 // Check for more than one of { assign, copy, retain }.
3968 unsigned AssignCopyRetMask = Attributes & (ObjCDeclSpec::DQ_PR_assign |
3969 ObjCDeclSpec::DQ_PR_copy |
3970 ObjCDeclSpec::DQ_PR_retain);
3971 if (AssignCopyRetMask &&
3972 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_assign &&
3973 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_copy &&
3974 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_retain)
3975 return true;
3976
3977 return false;
3978}
3979
Douglas Gregora93b1082009-11-18 23:08:07 +00003980void Sema::CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS) {
Steve Naroffece8e712009-10-08 21:55:05 +00003981 if (!CodeCompleter)
3982 return;
Douglas Gregord3c68542009-11-19 01:08:35 +00003983
Steve Naroffece8e712009-10-08 21:55:05 +00003984 unsigned Attributes = ODS.getPropertyAttributes();
3985
John McCall0a2c5e22010-08-25 06:19:51 +00003986 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00003987 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3988 CodeCompletionContext::CCC_Other);
Steve Naroffece8e712009-10-08 21:55:05 +00003989 Results.EnterNewScope();
Douglas Gregor988358f2009-11-19 00:14:45 +00003990 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readonly))
John McCall0a2c5e22010-08-25 06:19:51 +00003991 Results.AddResult(CodeCompletionResult("readonly"));
Douglas Gregor988358f2009-11-19 00:14:45 +00003992 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_assign))
John McCall0a2c5e22010-08-25 06:19:51 +00003993 Results.AddResult(CodeCompletionResult("assign"));
Douglas Gregor988358f2009-11-19 00:14:45 +00003994 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readwrite))
John McCall0a2c5e22010-08-25 06:19:51 +00003995 Results.AddResult(CodeCompletionResult("readwrite"));
Douglas Gregor988358f2009-11-19 00:14:45 +00003996 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_retain))
John McCall0a2c5e22010-08-25 06:19:51 +00003997 Results.AddResult(CodeCompletionResult("retain"));
Douglas Gregor988358f2009-11-19 00:14:45 +00003998 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_copy))
John McCall0a2c5e22010-08-25 06:19:51 +00003999 Results.AddResult(CodeCompletionResult("copy"));
Douglas Gregor988358f2009-11-19 00:14:45 +00004000 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_nonatomic))
John McCall0a2c5e22010-08-25 06:19:51 +00004001 Results.AddResult(CodeCompletionResult("nonatomic"));
Douglas Gregor988358f2009-11-19 00:14:45 +00004002 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_setter)) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004003 CodeCompletionBuilder Setter(Results.getAllocator());
4004 Setter.AddTypedTextChunk("setter");
4005 Setter.AddTextChunk(" = ");
4006 Setter.AddPlaceholderChunk("method");
4007 Results.AddResult(CodeCompletionResult(Setter.TakeString()));
Douglas Gregor54f01612009-11-19 00:01:57 +00004008 }
Douglas Gregor988358f2009-11-19 00:14:45 +00004009 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_getter)) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004010 CodeCompletionBuilder Getter(Results.getAllocator());
4011 Getter.AddTypedTextChunk("getter");
4012 Getter.AddTextChunk(" = ");
4013 Getter.AddPlaceholderChunk("method");
4014 Results.AddResult(CodeCompletionResult(Getter.TakeString()));
Douglas Gregor54f01612009-11-19 00:01:57 +00004015 }
Steve Naroffece8e712009-10-08 21:55:05 +00004016 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004017 HandleCodeCompleteResults(this, CodeCompleter,
4018 CodeCompletionContext::CCC_Other,
4019 Results.data(),Results.size());
Steve Naroffece8e712009-10-08 21:55:05 +00004020}
Steve Naroffc4df6d22009-11-07 02:08:14 +00004021
Douglas Gregor4ad96852009-11-19 07:41:15 +00004022/// \brief Descripts the kind of Objective-C method that we want to find
4023/// via code completion.
4024enum ObjCMethodKind {
4025 MK_Any, //< Any kind of method, provided it means other specified criteria.
4026 MK_ZeroArgSelector, //< Zero-argument (unary) selector.
4027 MK_OneArgSelector //< One-argument selector.
4028};
4029
Douglas Gregor458433d2010-08-26 15:07:07 +00004030static bool isAcceptableObjCSelector(Selector Sel,
4031 ObjCMethodKind WantKind,
4032 IdentifierInfo **SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004033 unsigned NumSelIdents,
4034 bool AllowSameLength = true) {
Douglas Gregor458433d2010-08-26 15:07:07 +00004035 if (NumSelIdents > Sel.getNumArgs())
4036 return false;
4037
4038 switch (WantKind) {
4039 case MK_Any: break;
4040 case MK_ZeroArgSelector: return Sel.isUnarySelector();
4041 case MK_OneArgSelector: return Sel.getNumArgs() == 1;
4042 }
4043
Douglas Gregorcf544262010-11-17 21:36:08 +00004044 if (!AllowSameLength && NumSelIdents && NumSelIdents == Sel.getNumArgs())
4045 return false;
4046
Douglas Gregor458433d2010-08-26 15:07:07 +00004047 for (unsigned I = 0; I != NumSelIdents; ++I)
4048 if (SelIdents[I] != Sel.getIdentifierInfoForSlot(I))
4049 return false;
4050
4051 return true;
4052}
4053
Douglas Gregor4ad96852009-11-19 07:41:15 +00004054static bool isAcceptableObjCMethod(ObjCMethodDecl *Method,
4055 ObjCMethodKind WantKind,
4056 IdentifierInfo **SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004057 unsigned NumSelIdents,
4058 bool AllowSameLength = true) {
Douglas Gregor458433d2010-08-26 15:07:07 +00004059 return isAcceptableObjCSelector(Method->getSelector(), WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004060 NumSelIdents, AllowSameLength);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004061}
Douglas Gregord36adf52010-09-16 16:06:31 +00004062
4063namespace {
4064 /// \brief A set of selectors, which is used to avoid introducing multiple
4065 /// completions with the same selector into the result set.
4066 typedef llvm::SmallPtrSet<Selector, 16> VisitedSelectorSet;
4067}
4068
Douglas Gregor36ecb042009-11-17 23:22:23 +00004069/// \brief Add all of the Objective-C methods in the given Objective-C
4070/// container to the set of results.
4071///
4072/// The container will be a class, protocol, category, or implementation of
4073/// any of the above. This mether will recurse to include methods from
4074/// the superclasses of classes along with their categories, protocols, and
4075/// implementations.
4076///
4077/// \param Container the container in which we'll look to find methods.
4078///
4079/// \param WantInstance whether to add instance methods (only); if false, this
4080/// routine will add factory methods (only).
4081///
4082/// \param CurContext the context in which we're performing the lookup that
4083/// finds methods.
4084///
Douglas Gregorcf544262010-11-17 21:36:08 +00004085/// \param AllowSameLength Whether we allow a method to be added to the list
4086/// when it has the same number of parameters as we have selector identifiers.
4087///
Douglas Gregor36ecb042009-11-17 23:22:23 +00004088/// \param Results the structure into which we'll add results.
4089static void AddObjCMethods(ObjCContainerDecl *Container,
4090 bool WantInstanceMethods,
Douglas Gregor4ad96852009-11-19 07:41:15 +00004091 ObjCMethodKind WantKind,
Douglas Gregord3c68542009-11-19 01:08:35 +00004092 IdentifierInfo **SelIdents,
4093 unsigned NumSelIdents,
Douglas Gregor36ecb042009-11-17 23:22:23 +00004094 DeclContext *CurContext,
Douglas Gregord36adf52010-09-16 16:06:31 +00004095 VisitedSelectorSet &Selectors,
Douglas Gregorcf544262010-11-17 21:36:08 +00004096 bool AllowSameLength,
Douglas Gregor408be5a2010-08-25 01:08:01 +00004097 ResultBuilder &Results,
4098 bool InOriginalClass = true) {
John McCall0a2c5e22010-08-25 06:19:51 +00004099 typedef CodeCompletionResult Result;
Douglas Gregor36ecb042009-11-17 23:22:23 +00004100 for (ObjCContainerDecl::method_iterator M = Container->meth_begin(),
4101 MEnd = Container->meth_end();
4102 M != MEnd; ++M) {
Douglas Gregord3c68542009-11-19 01:08:35 +00004103 if ((*M)->isInstanceMethod() == WantInstanceMethods) {
4104 // Check whether the selector identifiers we've been given are a
4105 // subset of the identifiers for this particular method.
Douglas Gregorcf544262010-11-17 21:36:08 +00004106 if (!isAcceptableObjCMethod(*M, WantKind, SelIdents, NumSelIdents,
4107 AllowSameLength))
Douglas Gregord3c68542009-11-19 01:08:35 +00004108 continue;
Douglas Gregor4ad96852009-11-19 07:41:15 +00004109
Douglas Gregord36adf52010-09-16 16:06:31 +00004110 if (!Selectors.insert((*M)->getSelector()))
4111 continue;
4112
Douglas Gregord3c68542009-11-19 01:08:35 +00004113 Result R = Result(*M, 0);
4114 R.StartParameter = NumSelIdents;
Douglas Gregor4ad96852009-11-19 07:41:15 +00004115 R.AllParametersAreInformative = (WantKind != MK_Any);
Douglas Gregor408be5a2010-08-25 01:08:01 +00004116 if (!InOriginalClass)
4117 R.Priority += CCD_InBaseClass;
Douglas Gregord3c68542009-11-19 01:08:35 +00004118 Results.MaybeAddResult(R, CurContext);
4119 }
Douglas Gregor36ecb042009-11-17 23:22:23 +00004120 }
4121
Douglas Gregore396c7b2010-09-16 15:34:59 +00004122 // Visit the protocols of protocols.
4123 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
4124 const ObjCList<ObjCProtocolDecl> &Protocols
4125 = Protocol->getReferencedProtocols();
4126 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
4127 E = Protocols.end();
4128 I != E; ++I)
4129 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, NumSelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004130 CurContext, Selectors, AllowSameLength, Results, false);
Douglas Gregore396c7b2010-09-16 15:34:59 +00004131 }
4132
Douglas Gregor36ecb042009-11-17 23:22:23 +00004133 ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container);
4134 if (!IFace)
4135 return;
4136
4137 // Add methods in protocols.
4138 const ObjCList<ObjCProtocolDecl> &Protocols= IFace->getReferencedProtocols();
4139 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
4140 E = Protocols.end();
4141 I != E; ++I)
Douglas Gregor4ad96852009-11-19 07:41:15 +00004142 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, NumSelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004143 CurContext, Selectors, AllowSameLength, Results, false);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004144
4145 // Add methods in categories.
4146 for (ObjCCategoryDecl *CatDecl = IFace->getCategoryList(); CatDecl;
4147 CatDecl = CatDecl->getNextClassCategory()) {
Douglas Gregor4ad96852009-11-19 07:41:15 +00004148 AddObjCMethods(CatDecl, WantInstanceMethods, WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004149 NumSelIdents, CurContext, Selectors, AllowSameLength,
4150 Results, InOriginalClass);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004151
4152 // Add a categories protocol methods.
4153 const ObjCList<ObjCProtocolDecl> &Protocols
4154 = CatDecl->getReferencedProtocols();
4155 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
4156 E = Protocols.end();
4157 I != E; ++I)
Douglas Gregor4ad96852009-11-19 07:41:15 +00004158 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004159 NumSelIdents, CurContext, Selectors, AllowSameLength,
4160 Results, false);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004161
4162 // Add methods in category implementations.
4163 if (ObjCCategoryImplDecl *Impl = CatDecl->getImplementation())
Douglas Gregor4ad96852009-11-19 07:41:15 +00004164 AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004165 NumSelIdents, CurContext, Selectors, AllowSameLength,
4166 Results, InOriginalClass);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004167 }
4168
4169 // Add methods in superclass.
4170 if (IFace->getSuperClass())
Douglas Gregor4ad96852009-11-19 07:41:15 +00004171 AddObjCMethods(IFace->getSuperClass(), WantInstanceMethods, WantKind,
Douglas Gregorcf544262010-11-17 21:36:08 +00004172 SelIdents, NumSelIdents, CurContext, Selectors,
4173 AllowSameLength, Results, false);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004174
4175 // Add methods in our implementation, if any.
4176 if (ObjCImplementationDecl *Impl = IFace->getImplementation())
Douglas Gregor4ad96852009-11-19 07:41:15 +00004177 AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004178 NumSelIdents, CurContext, Selectors, AllowSameLength,
4179 Results, InOriginalClass);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004180}
4181
4182
Douglas Gregorbdb2d502010-12-21 17:34:17 +00004183void Sema::CodeCompleteObjCPropertyGetter(Scope *S, Decl *ClassDecl) {
John McCall0a2c5e22010-08-25 06:19:51 +00004184 typedef CodeCompletionResult Result;
Douglas Gregor4ad96852009-11-19 07:41:15 +00004185
4186 // Try to find the interface where getters might live.
John McCalld226f652010-08-21 09:40:31 +00004187 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(ClassDecl);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004188 if (!Class) {
4189 if (ObjCCategoryDecl *Category
John McCalld226f652010-08-21 09:40:31 +00004190 = dyn_cast_or_null<ObjCCategoryDecl>(ClassDecl))
Douglas Gregor4ad96852009-11-19 07:41:15 +00004191 Class = Category->getClassInterface();
4192
4193 if (!Class)
4194 return;
4195 }
4196
4197 // Find all of the potential getters.
Douglas Gregor218937c2011-02-01 19:23:04 +00004198 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4199 CodeCompletionContext::CCC_Other);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004200 Results.EnterNewScope();
4201
Douglas Gregord36adf52010-09-16 16:06:31 +00004202 VisitedSelectorSet Selectors;
4203 AddObjCMethods(Class, true, MK_ZeroArgSelector, 0, 0, CurContext, Selectors,
Douglas Gregorcf544262010-11-17 21:36:08 +00004204 /*AllowSameLength=*/true, Results);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004205 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004206 HandleCodeCompleteResults(this, CodeCompleter,
4207 CodeCompletionContext::CCC_Other,
4208 Results.data(),Results.size());
Douglas Gregor4ad96852009-11-19 07:41:15 +00004209}
4210
Douglas Gregorbdb2d502010-12-21 17:34:17 +00004211void Sema::CodeCompleteObjCPropertySetter(Scope *S, Decl *ObjCImplDecl) {
John McCall0a2c5e22010-08-25 06:19:51 +00004212 typedef CodeCompletionResult Result;
Douglas Gregor4ad96852009-11-19 07:41:15 +00004213
4214 // Try to find the interface where setters might live.
4215 ObjCInterfaceDecl *Class
John McCalld226f652010-08-21 09:40:31 +00004216 = dyn_cast_or_null<ObjCInterfaceDecl>(ObjCImplDecl);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004217 if (!Class) {
4218 if (ObjCCategoryDecl *Category
John McCalld226f652010-08-21 09:40:31 +00004219 = dyn_cast_or_null<ObjCCategoryDecl>(ObjCImplDecl))
Douglas Gregor4ad96852009-11-19 07:41:15 +00004220 Class = Category->getClassInterface();
4221
4222 if (!Class)
4223 return;
4224 }
4225
4226 // Find all of the potential getters.
Douglas Gregor218937c2011-02-01 19:23:04 +00004227 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4228 CodeCompletionContext::CCC_Other);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004229 Results.EnterNewScope();
4230
Douglas Gregord36adf52010-09-16 16:06:31 +00004231 VisitedSelectorSet Selectors;
4232 AddObjCMethods(Class, true, MK_OneArgSelector, 0, 0, CurContext,
Douglas Gregorcf544262010-11-17 21:36:08 +00004233 Selectors, /*AllowSameLength=*/true, Results);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004234
4235 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004236 HandleCodeCompleteResults(this, CodeCompleter,
4237 CodeCompletionContext::CCC_Other,
4238 Results.data(),Results.size());
Douglas Gregor36ecb042009-11-17 23:22:23 +00004239}
4240
Douglas Gregord32b0222010-08-24 01:06:58 +00004241void Sema::CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS) {
John McCall0a2c5e22010-08-25 06:19:51 +00004242 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00004243 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4244 CodeCompletionContext::CCC_Type);
Douglas Gregord32b0222010-08-24 01:06:58 +00004245 Results.EnterNewScope();
4246
4247 // Add context-sensitive, Objective-C parameter-passing keywords.
4248 bool AddedInOut = false;
4249 if ((DS.getObjCDeclQualifier() &
4250 (ObjCDeclSpec::DQ_In | ObjCDeclSpec::DQ_Inout)) == 0) {
4251 Results.AddResult("in");
4252 Results.AddResult("inout");
4253 AddedInOut = true;
4254 }
4255 if ((DS.getObjCDeclQualifier() &
4256 (ObjCDeclSpec::DQ_Out | ObjCDeclSpec::DQ_Inout)) == 0) {
4257 Results.AddResult("out");
4258 if (!AddedInOut)
4259 Results.AddResult("inout");
4260 }
4261 if ((DS.getObjCDeclQualifier() &
4262 (ObjCDeclSpec::DQ_Bycopy | ObjCDeclSpec::DQ_Byref |
4263 ObjCDeclSpec::DQ_Oneway)) == 0) {
4264 Results.AddResult("bycopy");
4265 Results.AddResult("byref");
4266 Results.AddResult("oneway");
4267 }
4268
4269 // Add various builtin type names and specifiers.
4270 AddOrdinaryNameResults(PCC_Type, S, *this, Results);
4271 Results.ExitScope();
4272
4273 // Add the various type names
4274 Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
4275 CodeCompletionDeclConsumer Consumer(Results, CurContext);
4276 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4277 CodeCompleter->includeGlobals());
4278
4279 if (CodeCompleter->includeMacros())
4280 AddMacroResults(PP, Results);
4281
4282 HandleCodeCompleteResults(this, CodeCompleter,
4283 CodeCompletionContext::CCC_Type,
4284 Results.data(), Results.size());
4285}
4286
Douglas Gregor22f56992010-04-06 19:22:33 +00004287/// \brief When we have an expression with type "id", we may assume
4288/// that it has some more-specific class type based on knowledge of
4289/// common uses of Objective-C. This routine returns that class type,
4290/// or NULL if no better result could be determined.
4291static ObjCInterfaceDecl *GetAssumedMessageSendExprType(Expr *E) {
Douglas Gregor78edf512010-09-15 16:23:04 +00004292 ObjCMessageExpr *Msg = dyn_cast_or_null<ObjCMessageExpr>(E);
Douglas Gregor22f56992010-04-06 19:22:33 +00004293 if (!Msg)
4294 return 0;
4295
4296 Selector Sel = Msg->getSelector();
4297 if (Sel.isNull())
4298 return 0;
4299
4300 IdentifierInfo *Id = Sel.getIdentifierInfoForSlot(0);
4301 if (!Id)
4302 return 0;
4303
4304 ObjCMethodDecl *Method = Msg->getMethodDecl();
4305 if (!Method)
4306 return 0;
4307
4308 // Determine the class that we're sending the message to.
Douglas Gregor04badcf2010-04-21 00:45:42 +00004309 ObjCInterfaceDecl *IFace = 0;
4310 switch (Msg->getReceiverKind()) {
4311 case ObjCMessageExpr::Class:
John McCallc12c5bb2010-05-15 11:32:37 +00004312 if (const ObjCObjectType *ObjType
4313 = Msg->getClassReceiver()->getAs<ObjCObjectType>())
4314 IFace = ObjType->getInterface();
Douglas Gregor04badcf2010-04-21 00:45:42 +00004315 break;
4316
4317 case ObjCMessageExpr::Instance: {
4318 QualType T = Msg->getInstanceReceiver()->getType();
4319 if (const ObjCObjectPointerType *Ptr = T->getAs<ObjCObjectPointerType>())
4320 IFace = Ptr->getInterfaceDecl();
4321 break;
4322 }
4323
4324 case ObjCMessageExpr::SuperInstance:
4325 case ObjCMessageExpr::SuperClass:
4326 break;
Douglas Gregor22f56992010-04-06 19:22:33 +00004327 }
4328
4329 if (!IFace)
4330 return 0;
4331
4332 ObjCInterfaceDecl *Super = IFace->getSuperClass();
4333 if (Method->isInstanceMethod())
4334 return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
4335 .Case("retain", IFace)
4336 .Case("autorelease", IFace)
4337 .Case("copy", IFace)
4338 .Case("copyWithZone", IFace)
4339 .Case("mutableCopy", IFace)
4340 .Case("mutableCopyWithZone", IFace)
4341 .Case("awakeFromCoder", IFace)
4342 .Case("replacementObjectFromCoder", IFace)
4343 .Case("class", IFace)
4344 .Case("classForCoder", IFace)
4345 .Case("superclass", Super)
4346 .Default(0);
4347
4348 return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
4349 .Case("new", IFace)
4350 .Case("alloc", IFace)
4351 .Case("allocWithZone", IFace)
4352 .Case("class", IFace)
4353 .Case("superclass", Super)
4354 .Default(0);
4355}
4356
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004357// Add a special completion for a message send to "super", which fills in the
4358// most likely case of forwarding all of our arguments to the superclass
4359// function.
4360///
4361/// \param S The semantic analysis object.
4362///
4363/// \param S NeedSuperKeyword Whether we need to prefix this completion with
4364/// the "super" keyword. Otherwise, we just need to provide the arguments.
4365///
4366/// \param SelIdents The identifiers in the selector that have already been
4367/// provided as arguments for a send to "super".
4368///
4369/// \param NumSelIdents The number of identifiers in \p SelIdents.
4370///
4371/// \param Results The set of results to augment.
4372///
4373/// \returns the Objective-C method declaration that would be invoked by
4374/// this "super" completion. If NULL, no completion was added.
4375static ObjCMethodDecl *AddSuperSendCompletion(Sema &S, bool NeedSuperKeyword,
4376 IdentifierInfo **SelIdents,
4377 unsigned NumSelIdents,
4378 ResultBuilder &Results) {
4379 ObjCMethodDecl *CurMethod = S.getCurMethodDecl();
4380 if (!CurMethod)
4381 return 0;
4382
4383 ObjCInterfaceDecl *Class = CurMethod->getClassInterface();
4384 if (!Class)
4385 return 0;
4386
4387 // Try to find a superclass method with the same selector.
4388 ObjCMethodDecl *SuperMethod = 0;
4389 while ((Class = Class->getSuperClass()) && !SuperMethod)
4390 SuperMethod = Class->getMethod(CurMethod->getSelector(),
4391 CurMethod->isInstanceMethod());
4392
4393 if (!SuperMethod)
4394 return 0;
4395
4396 // Check whether the superclass method has the same signature.
4397 if (CurMethod->param_size() != SuperMethod->param_size() ||
4398 CurMethod->isVariadic() != SuperMethod->isVariadic())
4399 return 0;
4400
4401 for (ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin(),
4402 CurPEnd = CurMethod->param_end(),
4403 SuperP = SuperMethod->param_begin();
4404 CurP != CurPEnd; ++CurP, ++SuperP) {
4405 // Make sure the parameter types are compatible.
4406 if (!S.Context.hasSameUnqualifiedType((*CurP)->getType(),
4407 (*SuperP)->getType()))
4408 return 0;
4409
4410 // Make sure we have a parameter name to forward!
4411 if (!(*CurP)->getIdentifier())
4412 return 0;
4413 }
4414
4415 // We have a superclass method. Now, form the send-to-super completion.
Douglas Gregor218937c2011-02-01 19:23:04 +00004416 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004417
4418 // Give this completion a return type.
Douglas Gregor218937c2011-02-01 19:23:04 +00004419 AddResultTypeChunk(S.Context, SuperMethod, Builder);
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004420
4421 // If we need the "super" keyword, add it (plus some spacing).
4422 if (NeedSuperKeyword) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004423 Builder.AddTypedTextChunk("super");
4424 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004425 }
4426
4427 Selector Sel = CurMethod->getSelector();
4428 if (Sel.isUnarySelector()) {
4429 if (NeedSuperKeyword)
Douglas Gregor218937c2011-02-01 19:23:04 +00004430 Builder.AddTextChunk(CopyString(Builder.getAllocator(),
4431 Sel.getIdentifierInfoForSlot(0)->getName()));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004432 else
Douglas Gregor218937c2011-02-01 19:23:04 +00004433 Builder.AddTypedTextChunk(CopyString(Builder.getAllocator(),
4434 Sel.getIdentifierInfoForSlot(0)->getName()));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004435 } else {
4436 ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin();
4437 for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I, ++CurP) {
4438 if (I > NumSelIdents)
Douglas Gregor218937c2011-02-01 19:23:04 +00004439 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004440
4441 if (I < NumSelIdents)
Douglas Gregor218937c2011-02-01 19:23:04 +00004442 Builder.AddInformativeChunk(
4443 CopyString(Builder.getAllocator(),
4444 Sel.getIdentifierInfoForSlot(I)->getName().str() + ":"));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004445 else if (NeedSuperKeyword || I > NumSelIdents) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004446 Builder.AddTextChunk(
4447 CopyString(Builder.getAllocator(),
4448 Sel.getIdentifierInfoForSlot(I)->getName().str() + ":"));
4449 Builder.AddPlaceholderChunk(CopyString(Builder.getAllocator(),
4450 (*CurP)->getIdentifier()->getName()));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004451 } else {
Douglas Gregor218937c2011-02-01 19:23:04 +00004452 Builder.AddTypedTextChunk(
4453 CopyString(Builder.getAllocator(),
4454 Sel.getIdentifierInfoForSlot(I)->getName().str() + ":"));
4455 Builder.AddPlaceholderChunk(CopyString(Builder.getAllocator(),
4456 (*CurP)->getIdentifier()->getName()));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004457 }
4458 }
4459 }
4460
Douglas Gregor218937c2011-02-01 19:23:04 +00004461 Results.AddResult(CodeCompletionResult(Builder.TakeString(), CCP_SuperCompletion,
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004462 SuperMethod->isInstanceMethod()
4463 ? CXCursor_ObjCInstanceMethodDecl
4464 : CXCursor_ObjCClassMethodDecl));
4465 return SuperMethod;
4466}
4467
Douglas Gregor8e254cf2010-05-27 23:06:34 +00004468void Sema::CodeCompleteObjCMessageReceiver(Scope *S) {
John McCall0a2c5e22010-08-25 06:19:51 +00004469 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00004470 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4471 CodeCompletionContext::CCC_ObjCMessageReceiver,
Douglas Gregor52779fb2010-09-23 23:01:17 +00004472 &ResultBuilder::IsObjCMessageReceiver);
Douglas Gregor8e254cf2010-05-27 23:06:34 +00004473
Douglas Gregor8e254cf2010-05-27 23:06:34 +00004474 CodeCompletionDeclConsumer Consumer(Results, CurContext);
4475 Results.EnterNewScope();
Douglas Gregor8071e422010-08-15 06:18:01 +00004476 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4477 CodeCompleter->includeGlobals());
Douglas Gregor8e254cf2010-05-27 23:06:34 +00004478
4479 // If we are in an Objective-C method inside a class that has a superclass,
4480 // add "super" as an option.
4481 if (ObjCMethodDecl *Method = getCurMethodDecl())
4482 if (ObjCInterfaceDecl *Iface = Method->getClassInterface())
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004483 if (Iface->getSuperClass()) {
Douglas Gregor8e254cf2010-05-27 23:06:34 +00004484 Results.AddResult(Result("super"));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004485
4486 AddSuperSendCompletion(*this, /*NeedSuperKeyword=*/true, 0, 0, Results);
4487 }
Douglas Gregor8e254cf2010-05-27 23:06:34 +00004488
4489 Results.ExitScope();
4490
4491 if (CodeCompleter->includeMacros())
4492 AddMacroResults(PP, Results);
Douglas Gregorcee9ff12010-09-20 22:39:41 +00004493 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004494 Results.data(), Results.size());
Douglas Gregor8e254cf2010-05-27 23:06:34 +00004495
4496}
4497
Douglas Gregor2725ca82010-04-21 19:57:20 +00004498void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc,
4499 IdentifierInfo **SelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00004500 unsigned NumSelIdents,
4501 bool AtArgumentExpression) {
Douglas Gregor2725ca82010-04-21 19:57:20 +00004502 ObjCInterfaceDecl *CDecl = 0;
4503 if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
4504 // Figure out which interface we're in.
4505 CDecl = CurMethod->getClassInterface();
4506 if (!CDecl)
4507 return;
4508
4509 // Find the superclass of this class.
4510 CDecl = CDecl->getSuperClass();
4511 if (!CDecl)
4512 return;
4513
4514 if (CurMethod->isInstanceMethod()) {
4515 // We are inside an instance method, which means that the message
4516 // send [super ...] is actually calling an instance method on the
Douglas Gregor6b0656a2010-10-13 21:24:53 +00004517 // current object.
4518 return CodeCompleteObjCInstanceMessage(S, 0,
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004519 SelIdents, NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00004520 AtArgumentExpression,
Douglas Gregor6b0656a2010-10-13 21:24:53 +00004521 CDecl);
Douglas Gregor2725ca82010-04-21 19:57:20 +00004522 }
4523
4524 // Fall through to send to the superclass in CDecl.
4525 } else {
4526 // "super" may be the name of a type or variable. Figure out which
4527 // it is.
4528 IdentifierInfo *Super = &Context.Idents.get("super");
4529 NamedDecl *ND = LookupSingleName(S, Super, SuperLoc,
4530 LookupOrdinaryName);
4531 if ((CDecl = dyn_cast_or_null<ObjCInterfaceDecl>(ND))) {
4532 // "super" names an interface. Use it.
4533 } else if (TypeDecl *TD = dyn_cast_or_null<TypeDecl>(ND)) {
John McCallc12c5bb2010-05-15 11:32:37 +00004534 if (const ObjCObjectType *Iface
4535 = Context.getTypeDeclType(TD)->getAs<ObjCObjectType>())
4536 CDecl = Iface->getInterface();
Douglas Gregor2725ca82010-04-21 19:57:20 +00004537 } else if (ND && isa<UnresolvedUsingTypenameDecl>(ND)) {
4538 // "super" names an unresolved type; we can't be more specific.
4539 } else {
4540 // Assume that "super" names some kind of value and parse that way.
4541 CXXScopeSpec SS;
4542 UnqualifiedId id;
4543 id.setIdentifier(Super, SuperLoc);
John McCall60d7b3a2010-08-24 06:29:42 +00004544 ExprResult SuperExpr = ActOnIdExpression(S, SS, id, false, false);
Douglas Gregor2725ca82010-04-21 19:57:20 +00004545 return CodeCompleteObjCInstanceMessage(S, (Expr *)SuperExpr.get(),
Douglas Gregor70c5ac72010-09-20 23:34:21 +00004546 SelIdents, NumSelIdents,
4547 AtArgumentExpression);
Douglas Gregor2725ca82010-04-21 19:57:20 +00004548 }
4549
4550 // Fall through
4551 }
4552
John McCallb3d87482010-08-24 05:47:05 +00004553 ParsedType Receiver;
Douglas Gregor2725ca82010-04-21 19:57:20 +00004554 if (CDecl)
John McCallb3d87482010-08-24 05:47:05 +00004555 Receiver = ParsedType::make(Context.getObjCInterfaceType(CDecl));
Douglas Gregor2725ca82010-04-21 19:57:20 +00004556 return CodeCompleteObjCClassMessage(S, Receiver, SelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00004557 NumSelIdents, AtArgumentExpression,
4558 /*IsSuper=*/true);
Douglas Gregor2725ca82010-04-21 19:57:20 +00004559}
4560
Douglas Gregorb9d77572010-09-21 00:03:25 +00004561/// \brief Given a set of code-completion results for the argument of a message
4562/// send, determine the preferred type (if any) for that argument expression.
4563static QualType getPreferredArgumentTypeForMessageSend(ResultBuilder &Results,
4564 unsigned NumSelIdents) {
4565 typedef CodeCompletionResult Result;
4566 ASTContext &Context = Results.getSema().Context;
4567
4568 QualType PreferredType;
4569 unsigned BestPriority = CCP_Unlikely * 2;
4570 Result *ResultsData = Results.data();
4571 for (unsigned I = 0, N = Results.size(); I != N; ++I) {
4572 Result &R = ResultsData[I];
4573 if (R.Kind == Result::RK_Declaration &&
4574 isa<ObjCMethodDecl>(R.Declaration)) {
4575 if (R.Priority <= BestPriority) {
4576 ObjCMethodDecl *Method = cast<ObjCMethodDecl>(R.Declaration);
4577 if (NumSelIdents <= Method->param_size()) {
4578 QualType MyPreferredType = Method->param_begin()[NumSelIdents - 1]
4579 ->getType();
4580 if (R.Priority < BestPriority || PreferredType.isNull()) {
4581 BestPriority = R.Priority;
4582 PreferredType = MyPreferredType;
4583 } else if (!Context.hasSameUnqualifiedType(PreferredType,
4584 MyPreferredType)) {
4585 PreferredType = QualType();
4586 }
4587 }
4588 }
4589 }
4590 }
4591
4592 return PreferredType;
4593}
4594
Douglas Gregorc7b6d882010-09-16 15:14:18 +00004595static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
4596 ParsedType Receiver,
4597 IdentifierInfo **SelIdents,
4598 unsigned NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00004599 bool AtArgumentExpression,
Douglas Gregorc7b6d882010-09-16 15:14:18 +00004600 bool IsSuper,
4601 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00004602 typedef CodeCompletionResult Result;
Douglas Gregor24a069f2009-11-17 17:59:40 +00004603 ObjCInterfaceDecl *CDecl = 0;
Douglas Gregorc7b6d882010-09-16 15:14:18 +00004604
Douglas Gregor24a069f2009-11-17 17:59:40 +00004605 // If the given name refers to an interface type, retrieve the
4606 // corresponding declaration.
Douglas Gregor2725ca82010-04-21 19:57:20 +00004607 if (Receiver) {
Douglas Gregorc7b6d882010-09-16 15:14:18 +00004608 QualType T = SemaRef.GetTypeFromParser(Receiver, 0);
Douglas Gregor2725ca82010-04-21 19:57:20 +00004609 if (!T.isNull())
John McCallc12c5bb2010-05-15 11:32:37 +00004610 if (const ObjCObjectType *Interface = T->getAs<ObjCObjectType>())
4611 CDecl = Interface->getInterface();
Douglas Gregor24a069f2009-11-17 17:59:40 +00004612 }
Douglas Gregorc7b6d882010-09-16 15:14:18 +00004613
Douglas Gregor36ecb042009-11-17 23:22:23 +00004614 // Add all of the factory methods in this Objective-C class, its protocols,
4615 // superclasses, categories, implementation, etc.
Steve Naroffc4df6d22009-11-07 02:08:14 +00004616 Results.EnterNewScope();
Douglas Gregorc7b6d882010-09-16 15:14:18 +00004617
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004618 // If this is a send-to-super, try to add the special "super" send
4619 // completion.
4620 if (IsSuper) {
4621 if (ObjCMethodDecl *SuperMethod
Douglas Gregorc7b6d882010-09-16 15:14:18 +00004622 = AddSuperSendCompletion(SemaRef, false, SelIdents, NumSelIdents,
4623 Results))
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004624 Results.Ignore(SuperMethod);
4625 }
Douglas Gregorc7b6d882010-09-16 15:14:18 +00004626
Douglas Gregor265f7492010-08-27 15:29:55 +00004627 // If we're inside an Objective-C method definition, prefer its selector to
4628 // others.
Douglas Gregorc7b6d882010-09-16 15:14:18 +00004629 if (ObjCMethodDecl *CurMethod = SemaRef.getCurMethodDecl())
Douglas Gregor265f7492010-08-27 15:29:55 +00004630 Results.setPreferredSelector(CurMethod->getSelector());
Douglas Gregorc7b6d882010-09-16 15:14:18 +00004631
Douglas Gregord36adf52010-09-16 16:06:31 +00004632 VisitedSelectorSet Selectors;
Douglas Gregor13438f92010-04-06 16:40:00 +00004633 if (CDecl)
Douglas Gregorc7b6d882010-09-16 15:14:18 +00004634 AddObjCMethods(CDecl, false, MK_Any, SelIdents, NumSelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004635 SemaRef.CurContext, Selectors, AtArgumentExpression,
4636 Results);
Douglas Gregor2725ca82010-04-21 19:57:20 +00004637 else {
Douglas Gregor13438f92010-04-06 16:40:00 +00004638 // We're messaging "id" as a type; provide all class/factory methods.
Douglas Gregorc7b6d882010-09-16 15:14:18 +00004639
Douglas Gregor719770d2010-04-06 17:30:22 +00004640 // If we have an external source, load the entire class method
Sebastian Redl3c7f4132010-08-18 23:57:06 +00004641 // pool from the AST file.
Douglas Gregorc7b6d882010-09-16 15:14:18 +00004642 if (SemaRef.ExternalSource) {
4643 for (uint32_t I = 0,
4644 N = SemaRef.ExternalSource->GetNumExternalSelectors();
John McCall76bd1f32010-06-01 09:23:16 +00004645 I != N; ++I) {
Douglas Gregorc7b6d882010-09-16 15:14:18 +00004646 Selector Sel = SemaRef.ExternalSource->GetExternalSelector(I);
4647 if (Sel.isNull() || SemaRef.MethodPool.count(Sel))
Douglas Gregor719770d2010-04-06 17:30:22 +00004648 continue;
Douglas Gregorc7b6d882010-09-16 15:14:18 +00004649
4650 SemaRef.ReadMethodPool(Sel);
Douglas Gregor719770d2010-04-06 17:30:22 +00004651 }
4652 }
Douglas Gregorc7b6d882010-09-16 15:14:18 +00004653
4654 for (Sema::GlobalMethodPool::iterator M = SemaRef.MethodPool.begin(),
4655 MEnd = SemaRef.MethodPool.end();
Sebastian Redldb9d2142010-08-02 23:18:59 +00004656 M != MEnd; ++M) {
4657 for (ObjCMethodList *MethList = &M->second.second;
4658 MethList && MethList->Method;
Douglas Gregor13438f92010-04-06 16:40:00 +00004659 MethList = MethList->Next) {
4660 if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents,
4661 NumSelIdents))
4662 continue;
Douglas Gregorc7b6d882010-09-16 15:14:18 +00004663
Douglas Gregor13438f92010-04-06 16:40:00 +00004664 Result R(MethList->Method, 0);
4665 R.StartParameter = NumSelIdents;
4666 R.AllParametersAreInformative = false;
Douglas Gregorc7b6d882010-09-16 15:14:18 +00004667 Results.MaybeAddResult(R, SemaRef.CurContext);
Douglas Gregor13438f92010-04-06 16:40:00 +00004668 }
4669 }
4670 }
Douglas Gregorc7b6d882010-09-16 15:14:18 +00004671
4672 Results.ExitScope();
4673}
Douglas Gregor13438f92010-04-06 16:40:00 +00004674
Douglas Gregorc7b6d882010-09-16 15:14:18 +00004675void Sema::CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver,
4676 IdentifierInfo **SelIdents,
4677 unsigned NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00004678 bool AtArgumentExpression,
Douglas Gregorc7b6d882010-09-16 15:14:18 +00004679 bool IsSuper) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004680 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4681 CodeCompletionContext::CCC_Other);
Douglas Gregor70c5ac72010-09-20 23:34:21 +00004682 AddClassMessageCompletions(*this, S, Receiver, SelIdents, NumSelIdents,
4683 AtArgumentExpression, IsSuper, Results);
Douglas Gregorb9d77572010-09-21 00:03:25 +00004684
4685 // If we're actually at the argument expression (rather than prior to the
4686 // selector), we're actually performing code completion for an expression.
4687 // Determine whether we have a single, best method. If so, we can
4688 // code-complete the expression using the corresponding parameter type as
4689 // our preferred type, improving completion results.
4690 if (AtArgumentExpression) {
4691 QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results,
4692 NumSelIdents);
4693 if (PreferredType.isNull())
4694 CodeCompleteOrdinaryName(S, PCC_Expression);
4695 else
4696 CodeCompleteExpression(S, PreferredType);
4697 return;
4698 }
4699
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004700 HandleCodeCompleteResults(this, CodeCompleter,
4701 CodeCompletionContext::CCC_Other,
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004702 Results.data(), Results.size());
Steve Naroffc4df6d22009-11-07 02:08:14 +00004703}
4704
Douglas Gregord3c68542009-11-19 01:08:35 +00004705void Sema::CodeCompleteObjCInstanceMessage(Scope *S, ExprTy *Receiver,
4706 IdentifierInfo **SelIdents,
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004707 unsigned NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00004708 bool AtArgumentExpression,
Douglas Gregor6b0656a2010-10-13 21:24:53 +00004709 ObjCInterfaceDecl *Super) {
John McCall0a2c5e22010-08-25 06:19:51 +00004710 typedef CodeCompletionResult Result;
Steve Naroffc4df6d22009-11-07 02:08:14 +00004711
4712 Expr *RecExpr = static_cast<Expr *>(Receiver);
Steve Naroffc4df6d22009-11-07 02:08:14 +00004713
Douglas Gregor36ecb042009-11-17 23:22:23 +00004714 // If necessary, apply function/array conversion to the receiver.
4715 // C99 6.7.5.3p[7,8].
Douglas Gregor78edf512010-09-15 16:23:04 +00004716 if (RecExpr)
4717 DefaultFunctionArrayLvalueConversion(RecExpr);
Douglas Gregor6b0656a2010-10-13 21:24:53 +00004718 QualType ReceiverType = RecExpr? RecExpr->getType()
4719 : Super? Context.getObjCObjectPointerType(
4720 Context.getObjCInterfaceType(Super))
4721 : Context.getObjCIdType();
Steve Naroffc4df6d22009-11-07 02:08:14 +00004722
Douglas Gregorda892642010-11-08 21:12:30 +00004723 // If we're messaging an expression with type "id" or "Class", check
4724 // whether we know something special about the receiver that allows
4725 // us to assume a more-specific receiver type.
4726 if (ReceiverType->isObjCIdType() || ReceiverType->isObjCClassType())
4727 if (ObjCInterfaceDecl *IFace = GetAssumedMessageSendExprType(RecExpr)) {
4728 if (ReceiverType->isObjCClassType())
4729 return CodeCompleteObjCClassMessage(S,
4730 ParsedType::make(Context.getObjCInterfaceType(IFace)),
4731 SelIdents, NumSelIdents,
4732 AtArgumentExpression, Super);
4733
4734 ReceiverType = Context.getObjCObjectPointerType(
4735 Context.getObjCInterfaceType(IFace));
4736 }
4737
Douglas Gregor36ecb042009-11-17 23:22:23 +00004738 // Build the set of methods we can see.
Douglas Gregor218937c2011-02-01 19:23:04 +00004739 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4740 CodeCompletionContext::CCC_Other);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004741 Results.EnterNewScope();
Douglas Gregor22f56992010-04-06 19:22:33 +00004742
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004743 // If this is a send-to-super, try to add the special "super" send
4744 // completion.
Douglas Gregor6b0656a2010-10-13 21:24:53 +00004745 if (Super) {
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004746 if (ObjCMethodDecl *SuperMethod
4747 = AddSuperSendCompletion(*this, false, SelIdents, NumSelIdents,
4748 Results))
4749 Results.Ignore(SuperMethod);
4750 }
4751
Douglas Gregor265f7492010-08-27 15:29:55 +00004752 // If we're inside an Objective-C method definition, prefer its selector to
4753 // others.
4754 if (ObjCMethodDecl *CurMethod = getCurMethodDecl())
4755 Results.setPreferredSelector(CurMethod->getSelector());
Douglas Gregor36ecb042009-11-17 23:22:23 +00004756
Douglas Gregord36adf52010-09-16 16:06:31 +00004757 // Keep track of the selectors we've already added.
4758 VisitedSelectorSet Selectors;
4759
Douglas Gregorf74a4192009-11-18 00:06:18 +00004760 // Handle messages to Class. This really isn't a message to an instance
4761 // method, so we treat it the same way we would treat a message send to a
4762 // class method.
4763 if (ReceiverType->isObjCClassType() ||
4764 ReceiverType->isObjCQualifiedClassType()) {
4765 if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
4766 if (ObjCInterfaceDecl *ClassDecl = CurMethod->getClassInterface())
Douglas Gregor4ad96852009-11-19 07:41:15 +00004767 AddObjCMethods(ClassDecl, false, MK_Any, SelIdents, NumSelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004768 CurContext, Selectors, AtArgumentExpression, Results);
Douglas Gregorf74a4192009-11-18 00:06:18 +00004769 }
4770 }
4771 // Handle messages to a qualified ID ("id<foo>").
4772 else if (const ObjCObjectPointerType *QualID
4773 = ReceiverType->getAsObjCQualifiedIdType()) {
4774 // Search protocols for instance methods.
4775 for (ObjCObjectPointerType::qual_iterator I = QualID->qual_begin(),
4776 E = QualID->qual_end();
4777 I != E; ++I)
Douglas Gregor4ad96852009-11-19 07:41:15 +00004778 AddObjCMethods(*I, true, MK_Any, SelIdents, NumSelIdents, CurContext,
Douglas Gregorcf544262010-11-17 21:36:08 +00004779 Selectors, AtArgumentExpression, Results);
Douglas Gregorf74a4192009-11-18 00:06:18 +00004780 }
4781 // Handle messages to a pointer to interface type.
4782 else if (const ObjCObjectPointerType *IFacePtr
4783 = ReceiverType->getAsObjCInterfacePointerType()) {
4784 // Search the class, its superclasses, etc., for instance methods.
Douglas Gregor4ad96852009-11-19 07:41:15 +00004785 AddObjCMethods(IFacePtr->getInterfaceDecl(), true, MK_Any, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004786 NumSelIdents, CurContext, Selectors, AtArgumentExpression,
4787 Results);
Douglas Gregorf74a4192009-11-18 00:06:18 +00004788
4789 // Search protocols for instance methods.
4790 for (ObjCObjectPointerType::qual_iterator I = IFacePtr->qual_begin(),
4791 E = IFacePtr->qual_end();
4792 I != E; ++I)
Douglas Gregor4ad96852009-11-19 07:41:15 +00004793 AddObjCMethods(*I, true, MK_Any, SelIdents, NumSelIdents, CurContext,
Douglas Gregorcf544262010-11-17 21:36:08 +00004794 Selectors, AtArgumentExpression, Results);
Douglas Gregorf74a4192009-11-18 00:06:18 +00004795 }
Douglas Gregor13438f92010-04-06 16:40:00 +00004796 // Handle messages to "id".
4797 else if (ReceiverType->isObjCIdType()) {
Douglas Gregor719770d2010-04-06 17:30:22 +00004798 // We're messaging "id", so provide all instance methods we know
4799 // about as code-completion results.
4800
4801 // If we have an external source, load the entire class method
Sebastian Redl3c7f4132010-08-18 23:57:06 +00004802 // pool from the AST file.
Douglas Gregor719770d2010-04-06 17:30:22 +00004803 if (ExternalSource) {
John McCall76bd1f32010-06-01 09:23:16 +00004804 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
4805 I != N; ++I) {
4806 Selector Sel = ExternalSource->GetExternalSelector(I);
Sebastian Redldb9d2142010-08-02 23:18:59 +00004807 if (Sel.isNull() || MethodPool.count(Sel))
Douglas Gregor719770d2010-04-06 17:30:22 +00004808 continue;
4809
Sebastian Redldb9d2142010-08-02 23:18:59 +00004810 ReadMethodPool(Sel);
Douglas Gregor719770d2010-04-06 17:30:22 +00004811 }
4812 }
4813
Sebastian Redldb9d2142010-08-02 23:18:59 +00004814 for (GlobalMethodPool::iterator M = MethodPool.begin(),
4815 MEnd = MethodPool.end();
4816 M != MEnd; ++M) {
4817 for (ObjCMethodList *MethList = &M->second.first;
4818 MethList && MethList->Method;
Douglas Gregor13438f92010-04-06 16:40:00 +00004819 MethList = MethList->Next) {
4820 if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents,
4821 NumSelIdents))
4822 continue;
Douglas Gregord36adf52010-09-16 16:06:31 +00004823
4824 if (!Selectors.insert(MethList->Method->getSelector()))
4825 continue;
4826
Douglas Gregor13438f92010-04-06 16:40:00 +00004827 Result R(MethList->Method, 0);
4828 R.StartParameter = NumSelIdents;
4829 R.AllParametersAreInformative = false;
4830 Results.MaybeAddResult(R, CurContext);
4831 }
4832 }
4833 }
Steve Naroffc4df6d22009-11-07 02:08:14 +00004834 Results.ExitScope();
Douglas Gregorb9d77572010-09-21 00:03:25 +00004835
4836
4837 // If we're actually at the argument expression (rather than prior to the
4838 // selector), we're actually performing code completion for an expression.
4839 // Determine whether we have a single, best method. If so, we can
4840 // code-complete the expression using the corresponding parameter type as
4841 // our preferred type, improving completion results.
4842 if (AtArgumentExpression) {
4843 QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results,
4844 NumSelIdents);
4845 if (PreferredType.isNull())
4846 CodeCompleteOrdinaryName(S, PCC_Expression);
4847 else
4848 CodeCompleteExpression(S, PreferredType);
4849 return;
4850 }
4851
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004852 HandleCodeCompleteResults(this, CodeCompleter,
4853 CodeCompletionContext::CCC_Other,
4854 Results.data(),Results.size());
Steve Naroffc4df6d22009-11-07 02:08:14 +00004855}
Douglas Gregor55385fe2009-11-18 04:19:12 +00004856
Douglas Gregorfb629412010-08-23 21:17:50 +00004857void Sema::CodeCompleteObjCForCollection(Scope *S,
4858 DeclGroupPtrTy IterationVar) {
4859 CodeCompleteExpressionData Data;
4860 Data.ObjCCollection = true;
4861
4862 if (IterationVar.getAsOpaquePtr()) {
4863 DeclGroupRef DG = IterationVar.getAsVal<DeclGroupRef>();
4864 for (DeclGroupRef::iterator I = DG.begin(), End = DG.end(); I != End; ++I) {
4865 if (*I)
4866 Data.IgnoreDecls.push_back(*I);
4867 }
4868 }
4869
4870 CodeCompleteExpression(S, Data);
4871}
4872
Douglas Gregor458433d2010-08-26 15:07:07 +00004873void Sema::CodeCompleteObjCSelector(Scope *S, IdentifierInfo **SelIdents,
4874 unsigned NumSelIdents) {
4875 // If we have an external source, load the entire class method
4876 // pool from the AST file.
4877 if (ExternalSource) {
4878 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
4879 I != N; ++I) {
4880 Selector Sel = ExternalSource->GetExternalSelector(I);
4881 if (Sel.isNull() || MethodPool.count(Sel))
4882 continue;
4883
4884 ReadMethodPool(Sel);
4885 }
4886 }
4887
Douglas Gregor218937c2011-02-01 19:23:04 +00004888 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4889 CodeCompletionContext::CCC_SelectorName);
Douglas Gregor458433d2010-08-26 15:07:07 +00004890 Results.EnterNewScope();
4891 for (GlobalMethodPool::iterator M = MethodPool.begin(),
4892 MEnd = MethodPool.end();
4893 M != MEnd; ++M) {
4894
4895 Selector Sel = M->first;
4896 if (!isAcceptableObjCSelector(Sel, MK_Any, SelIdents, NumSelIdents))
4897 continue;
4898
Douglas Gregor218937c2011-02-01 19:23:04 +00004899 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregor458433d2010-08-26 15:07:07 +00004900 if (Sel.isUnarySelector()) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004901 Builder.AddTypedTextChunk(CopyString(Builder.getAllocator(),
4902 Sel.getIdentifierInfoForSlot(0)->getName()));
4903 Results.AddResult(Builder.TakeString());
Douglas Gregor458433d2010-08-26 15:07:07 +00004904 continue;
4905 }
4906
Douglas Gregor2d9e21f2010-08-26 16:46:39 +00004907 std::string Accumulator;
Douglas Gregor458433d2010-08-26 15:07:07 +00004908 for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I) {
Douglas Gregor2d9e21f2010-08-26 16:46:39 +00004909 if (I == NumSelIdents) {
4910 if (!Accumulator.empty()) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004911 Builder.AddInformativeChunk(CopyString(Builder.getAllocator(),
4912 Accumulator));
Douglas Gregor2d9e21f2010-08-26 16:46:39 +00004913 Accumulator.clear();
4914 }
4915 }
4916
4917 Accumulator += Sel.getIdentifierInfoForSlot(I)->getName().str();
4918 Accumulator += ':';
Douglas Gregor458433d2010-08-26 15:07:07 +00004919 }
Douglas Gregor218937c2011-02-01 19:23:04 +00004920 Builder.AddTypedTextChunk(CopyString(Builder.getAllocator(), Accumulator));
4921 Results.AddResult(Builder.TakeString());
Douglas Gregor458433d2010-08-26 15:07:07 +00004922 }
4923 Results.ExitScope();
4924
4925 HandleCodeCompleteResults(this, CodeCompleter,
4926 CodeCompletionContext::CCC_SelectorName,
4927 Results.data(), Results.size());
4928}
4929
Douglas Gregor55385fe2009-11-18 04:19:12 +00004930/// \brief Add all of the protocol declarations that we find in the given
4931/// (translation unit) context.
4932static void AddProtocolResults(DeclContext *Ctx, DeclContext *CurContext,
Douglas Gregor083128f2009-11-18 04:49:41 +00004933 bool OnlyForwardDeclarations,
Douglas Gregor55385fe2009-11-18 04:19:12 +00004934 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00004935 typedef CodeCompletionResult Result;
Douglas Gregor55385fe2009-11-18 04:19:12 +00004936
4937 for (DeclContext::decl_iterator D = Ctx->decls_begin(),
4938 DEnd = Ctx->decls_end();
4939 D != DEnd; ++D) {
4940 // Record any protocols we find.
4941 if (ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>(*D))
Douglas Gregor083128f2009-11-18 04:49:41 +00004942 if (!OnlyForwardDeclarations || Proto->isForwardDecl())
Douglas Gregor608300b2010-01-14 16:14:35 +00004943 Results.AddResult(Result(Proto, 0), CurContext, 0, false);
Douglas Gregor55385fe2009-11-18 04:19:12 +00004944
4945 // Record any forward-declared protocols we find.
4946 if (ObjCForwardProtocolDecl *Forward
4947 = dyn_cast<ObjCForwardProtocolDecl>(*D)) {
4948 for (ObjCForwardProtocolDecl::protocol_iterator
4949 P = Forward->protocol_begin(),
4950 PEnd = Forward->protocol_end();
4951 P != PEnd; ++P)
Douglas Gregor083128f2009-11-18 04:49:41 +00004952 if (!OnlyForwardDeclarations || (*P)->isForwardDecl())
Douglas Gregor608300b2010-01-14 16:14:35 +00004953 Results.AddResult(Result(*P, 0), CurContext, 0, false);
Douglas Gregor55385fe2009-11-18 04:19:12 +00004954 }
4955 }
4956}
4957
4958void Sema::CodeCompleteObjCProtocolReferences(IdentifierLocPair *Protocols,
4959 unsigned NumProtocols) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004960 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4961 CodeCompletionContext::CCC_ObjCProtocolName);
Douglas Gregor55385fe2009-11-18 04:19:12 +00004962
Douglas Gregor70c23352010-12-09 21:44:02 +00004963 if (CodeCompleter && CodeCompleter->includeGlobals()) {
4964 Results.EnterNewScope();
4965
4966 // Tell the result set to ignore all of the protocols we have
4967 // already seen.
4968 // FIXME: This doesn't work when caching code-completion results.
4969 for (unsigned I = 0; I != NumProtocols; ++I)
4970 if (ObjCProtocolDecl *Protocol = LookupProtocol(Protocols[I].first,
4971 Protocols[I].second))
4972 Results.Ignore(Protocol);
Douglas Gregor55385fe2009-11-18 04:19:12 +00004973
Douglas Gregor70c23352010-12-09 21:44:02 +00004974 // Add all protocols.
4975 AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, false,
4976 Results);
Douglas Gregor083128f2009-11-18 04:49:41 +00004977
Douglas Gregor70c23352010-12-09 21:44:02 +00004978 Results.ExitScope();
4979 }
4980
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004981 HandleCodeCompleteResults(this, CodeCompleter,
4982 CodeCompletionContext::CCC_ObjCProtocolName,
4983 Results.data(),Results.size());
Douglas Gregor083128f2009-11-18 04:49:41 +00004984}
4985
4986void Sema::CodeCompleteObjCProtocolDecl(Scope *) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004987 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4988 CodeCompletionContext::CCC_ObjCProtocolName);
Douglas Gregor083128f2009-11-18 04:49:41 +00004989
Douglas Gregor70c23352010-12-09 21:44:02 +00004990 if (CodeCompleter && CodeCompleter->includeGlobals()) {
4991 Results.EnterNewScope();
4992
4993 // Add all protocols.
4994 AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, true,
4995 Results);
Douglas Gregor55385fe2009-11-18 04:19:12 +00004996
Douglas Gregor70c23352010-12-09 21:44:02 +00004997 Results.ExitScope();
4998 }
4999
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005000 HandleCodeCompleteResults(this, CodeCompleter,
5001 CodeCompletionContext::CCC_ObjCProtocolName,
5002 Results.data(),Results.size());
Douglas Gregor55385fe2009-11-18 04:19:12 +00005003}
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005004
5005/// \brief Add all of the Objective-C interface declarations that we find in
5006/// the given (translation unit) context.
5007static void AddInterfaceResults(DeclContext *Ctx, DeclContext *CurContext,
5008 bool OnlyForwardDeclarations,
5009 bool OnlyUnimplemented,
5010 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00005011 typedef CodeCompletionResult Result;
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005012
5013 for (DeclContext::decl_iterator D = Ctx->decls_begin(),
5014 DEnd = Ctx->decls_end();
5015 D != DEnd; ++D) {
Douglas Gregordeacbdc2010-08-11 12:19:30 +00005016 // Record any interfaces we find.
5017 if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(*D))
5018 if ((!OnlyForwardDeclarations || Class->isForwardDecl()) &&
5019 (!OnlyUnimplemented || !Class->getImplementation()))
5020 Results.AddResult(Result(Class, 0), CurContext, 0, false);
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005021
5022 // Record any forward-declared interfaces we find.
5023 if (ObjCClassDecl *Forward = dyn_cast<ObjCClassDecl>(*D)) {
5024 for (ObjCClassDecl::iterator C = Forward->begin(), CEnd = Forward->end();
Douglas Gregordeacbdc2010-08-11 12:19:30 +00005025 C != CEnd; ++C)
5026 if ((!OnlyForwardDeclarations || C->getInterface()->isForwardDecl()) &&
5027 (!OnlyUnimplemented || !C->getInterface()->getImplementation()))
5028 Results.AddResult(Result(C->getInterface(), 0), CurContext,
Douglas Gregor608300b2010-01-14 16:14:35 +00005029 0, false);
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005030 }
5031 }
5032}
5033
5034void Sema::CodeCompleteObjCInterfaceDecl(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005035 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5036 CodeCompletionContext::CCC_Other);
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005037 Results.EnterNewScope();
5038
5039 // Add all classes.
5040 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, true,
5041 false, Results);
5042
5043 Results.ExitScope();
Douglas Gregor52779fb2010-09-23 23:01:17 +00005044 // FIXME: Add a special context for this, use cached global completion
5045 // results.
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005046 HandleCodeCompleteResults(this, CodeCompleter,
5047 CodeCompletionContext::CCC_Other,
5048 Results.data(),Results.size());
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005049}
5050
Douglas Gregorc83c6872010-04-15 22:33:43 +00005051void Sema::CodeCompleteObjCSuperclass(Scope *S, IdentifierInfo *ClassName,
5052 SourceLocation ClassNameLoc) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005053 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5054 CodeCompletionContext::CCC_Other);
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005055 Results.EnterNewScope();
5056
5057 // Make sure that we ignore the class we're currently defining.
5058 NamedDecl *CurClass
Douglas Gregorc83c6872010-04-15 22:33:43 +00005059 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005060 if (CurClass && isa<ObjCInterfaceDecl>(CurClass))
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005061 Results.Ignore(CurClass);
5062
5063 // Add all classes.
5064 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
5065 false, Results);
5066
5067 Results.ExitScope();
Douglas Gregor52779fb2010-09-23 23:01:17 +00005068 // FIXME: Add a special context for this, use cached global completion
5069 // results.
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005070 HandleCodeCompleteResults(this, CodeCompleter,
5071 CodeCompletionContext::CCC_Other,
5072 Results.data(),Results.size());
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005073}
5074
5075void Sema::CodeCompleteObjCImplementationDecl(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005076 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5077 CodeCompletionContext::CCC_Other);
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005078 Results.EnterNewScope();
5079
5080 // Add all unimplemented classes.
5081 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
5082 true, Results);
5083
5084 Results.ExitScope();
Douglas Gregor52779fb2010-09-23 23:01:17 +00005085 // FIXME: Add a special context for this, use cached global completion
5086 // results.
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005087 HandleCodeCompleteResults(this, CodeCompleter,
5088 CodeCompletionContext::CCC_Other,
5089 Results.data(),Results.size());
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005090}
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005091
5092void Sema::CodeCompleteObjCInterfaceCategory(Scope *S,
Douglas Gregorc83c6872010-04-15 22:33:43 +00005093 IdentifierInfo *ClassName,
5094 SourceLocation ClassNameLoc) {
John McCall0a2c5e22010-08-25 06:19:51 +00005095 typedef CodeCompletionResult Result;
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005096
Douglas Gregor218937c2011-02-01 19:23:04 +00005097 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5098 CodeCompletionContext::CCC_Other);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005099
5100 // Ignore any categories we find that have already been implemented by this
5101 // interface.
5102 llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
5103 NamedDecl *CurClass
Douglas Gregorc83c6872010-04-15 22:33:43 +00005104 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005105 if (ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass))
5106 for (ObjCCategoryDecl *Category = Class->getCategoryList(); Category;
5107 Category = Category->getNextClassCategory())
5108 CategoryNames.insert(Category->getIdentifier());
5109
5110 // Add all of the categories we know about.
5111 Results.EnterNewScope();
5112 TranslationUnitDecl *TU = Context.getTranslationUnitDecl();
5113 for (DeclContext::decl_iterator D = TU->decls_begin(),
5114 DEnd = TU->decls_end();
5115 D != DEnd; ++D)
5116 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(*D))
5117 if (CategoryNames.insert(Category->getIdentifier()))
Douglas Gregor608300b2010-01-14 16:14:35 +00005118 Results.AddResult(Result(Category, 0), CurContext, 0, false);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005119 Results.ExitScope();
5120
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005121 HandleCodeCompleteResults(this, CodeCompleter,
5122 CodeCompletionContext::CCC_Other,
5123 Results.data(),Results.size());
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005124}
5125
5126void Sema::CodeCompleteObjCImplementationCategory(Scope *S,
Douglas Gregorc83c6872010-04-15 22:33:43 +00005127 IdentifierInfo *ClassName,
5128 SourceLocation ClassNameLoc) {
John McCall0a2c5e22010-08-25 06:19:51 +00005129 typedef CodeCompletionResult Result;
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005130
5131 // Find the corresponding interface. If we couldn't find the interface, the
5132 // program itself is ill-formed. However, we'll try to be helpful still by
5133 // providing the list of all of the categories we know about.
5134 NamedDecl *CurClass
Douglas Gregorc83c6872010-04-15 22:33:43 +00005135 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005136 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass);
5137 if (!Class)
Douglas Gregorc83c6872010-04-15 22:33:43 +00005138 return CodeCompleteObjCInterfaceCategory(S, ClassName, ClassNameLoc);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005139
Douglas Gregor218937c2011-02-01 19:23:04 +00005140 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5141 CodeCompletionContext::CCC_Other);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005142
5143 // Add all of the categories that have have corresponding interface
5144 // declarations in this class and any of its superclasses, except for
5145 // already-implemented categories in the class itself.
5146 llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
5147 Results.EnterNewScope();
5148 bool IgnoreImplemented = true;
5149 while (Class) {
5150 for (ObjCCategoryDecl *Category = Class->getCategoryList(); Category;
5151 Category = Category->getNextClassCategory())
5152 if ((!IgnoreImplemented || !Category->getImplementation()) &&
5153 CategoryNames.insert(Category->getIdentifier()))
Douglas Gregor608300b2010-01-14 16:14:35 +00005154 Results.AddResult(Result(Category, 0), CurContext, 0, false);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005155
5156 Class = Class->getSuperClass();
5157 IgnoreImplemented = false;
5158 }
5159 Results.ExitScope();
5160
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005161 HandleCodeCompleteResults(this, CodeCompleter,
5162 CodeCompletionContext::CCC_Other,
5163 Results.data(),Results.size());
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005164}
Douglas Gregor322328b2009-11-18 22:32:06 +00005165
John McCalld226f652010-08-21 09:40:31 +00005166void Sema::CodeCompleteObjCPropertyDefinition(Scope *S, Decl *ObjCImpDecl) {
John McCall0a2c5e22010-08-25 06:19:51 +00005167 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00005168 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5169 CodeCompletionContext::CCC_Other);
Douglas Gregor322328b2009-11-18 22:32:06 +00005170
5171 // Figure out where this @synthesize lives.
5172 ObjCContainerDecl *Container
John McCalld226f652010-08-21 09:40:31 +00005173 = dyn_cast_or_null<ObjCContainerDecl>(ObjCImpDecl);
Douglas Gregor322328b2009-11-18 22:32:06 +00005174 if (!Container ||
5175 (!isa<ObjCImplementationDecl>(Container) &&
5176 !isa<ObjCCategoryImplDecl>(Container)))
5177 return;
5178
5179 // Ignore any properties that have already been implemented.
5180 for (DeclContext::decl_iterator D = Container->decls_begin(),
5181 DEnd = Container->decls_end();
5182 D != DEnd; ++D)
5183 if (ObjCPropertyImplDecl *PropertyImpl = dyn_cast<ObjCPropertyImplDecl>(*D))
5184 Results.Ignore(PropertyImpl->getPropertyDecl());
5185
5186 // Add any properties that we find.
Douglas Gregor73449212010-12-09 23:01:55 +00005187 AddedPropertiesSet AddedProperties;
Douglas Gregor322328b2009-11-18 22:32:06 +00005188 Results.EnterNewScope();
5189 if (ObjCImplementationDecl *ClassImpl
5190 = dyn_cast<ObjCImplementationDecl>(Container))
5191 AddObjCProperties(ClassImpl->getClassInterface(), false, CurContext,
Douglas Gregor73449212010-12-09 23:01:55 +00005192 AddedProperties, Results);
Douglas Gregor322328b2009-11-18 22:32:06 +00005193 else
5194 AddObjCProperties(cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl(),
Douglas Gregor73449212010-12-09 23:01:55 +00005195 false, CurContext, AddedProperties, Results);
Douglas Gregor322328b2009-11-18 22:32:06 +00005196 Results.ExitScope();
5197
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005198 HandleCodeCompleteResults(this, CodeCompleter,
5199 CodeCompletionContext::CCC_Other,
5200 Results.data(),Results.size());
Douglas Gregor322328b2009-11-18 22:32:06 +00005201}
5202
5203void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S,
5204 IdentifierInfo *PropertyName,
John McCalld226f652010-08-21 09:40:31 +00005205 Decl *ObjCImpDecl) {
John McCall0a2c5e22010-08-25 06:19:51 +00005206 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00005207 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5208 CodeCompletionContext::CCC_Other);
Douglas Gregor322328b2009-11-18 22:32:06 +00005209
5210 // Figure out where this @synthesize lives.
5211 ObjCContainerDecl *Container
John McCalld226f652010-08-21 09:40:31 +00005212 = dyn_cast_or_null<ObjCContainerDecl>(ObjCImpDecl);
Douglas Gregor322328b2009-11-18 22:32:06 +00005213 if (!Container ||
5214 (!isa<ObjCImplementationDecl>(Container) &&
5215 !isa<ObjCCategoryImplDecl>(Container)))
5216 return;
5217
5218 // Figure out which interface we're looking into.
5219 ObjCInterfaceDecl *Class = 0;
5220 if (ObjCImplementationDecl *ClassImpl
5221 = dyn_cast<ObjCImplementationDecl>(Container))
5222 Class = ClassImpl->getClassInterface();
5223 else
5224 Class = cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl()
5225 ->getClassInterface();
5226
5227 // Add all of the instance variables in this class and its superclasses.
5228 Results.EnterNewScope();
5229 for(; Class; Class = Class->getSuperClass()) {
5230 // FIXME: We could screen the type of each ivar for compatibility with
5231 // the property, but is that being too paternal?
5232 for (ObjCInterfaceDecl::ivar_iterator IVar = Class->ivar_begin(),
5233 IVarEnd = Class->ivar_end();
5234 IVar != IVarEnd; ++IVar)
Douglas Gregor608300b2010-01-14 16:14:35 +00005235 Results.AddResult(Result(*IVar, 0), CurContext, 0, false);
Douglas Gregor322328b2009-11-18 22:32:06 +00005236 }
5237 Results.ExitScope();
5238
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005239 HandleCodeCompleteResults(this, CodeCompleter,
5240 CodeCompletionContext::CCC_Other,
5241 Results.data(),Results.size());
Douglas Gregor322328b2009-11-18 22:32:06 +00005242}
Douglas Gregore8f5a172010-04-07 00:21:17 +00005243
Douglas Gregor408be5a2010-08-25 01:08:01 +00005244// Mapping from selectors to the methods that implement that selector, along
5245// with the "in original class" flag.
5246typedef llvm::DenseMap<Selector, std::pair<ObjCMethodDecl *, bool> >
5247 KnownMethodsMap;
Douglas Gregore8f5a172010-04-07 00:21:17 +00005248
5249/// \brief Find all of the methods that reside in the given container
5250/// (and its superclasses, protocols, etc.) that meet the given
5251/// criteria. Insert those methods into the map of known methods,
5252/// indexed by selector so they can be easily found.
5253static void FindImplementableMethods(ASTContext &Context,
5254 ObjCContainerDecl *Container,
5255 bool WantInstanceMethods,
5256 QualType ReturnType,
Douglas Gregor408be5a2010-08-25 01:08:01 +00005257 KnownMethodsMap &KnownMethods,
5258 bool InOriginalClass = true) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00005259 if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)) {
5260 // Recurse into protocols.
5261 const ObjCList<ObjCProtocolDecl> &Protocols
5262 = IFace->getReferencedProtocols();
5263 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Douglas Gregorea766182010-10-18 18:21:28 +00005264 E = Protocols.end();
Douglas Gregore8f5a172010-04-07 00:21:17 +00005265 I != E; ++I)
5266 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
Douglas Gregorea766182010-10-18 18:21:28 +00005267 KnownMethods, InOriginalClass);
Douglas Gregore8f5a172010-04-07 00:21:17 +00005268
Douglas Gregorea766182010-10-18 18:21:28 +00005269 // Add methods from any class extensions and categories.
5270 for (const ObjCCategoryDecl *Cat = IFace->getCategoryList(); Cat;
5271 Cat = Cat->getNextClassCategory())
Fariborz Jahanian80aa1cd2010-06-22 23:20:40 +00005272 FindImplementableMethods(Context, const_cast<ObjCCategoryDecl*>(Cat),
5273 WantInstanceMethods, ReturnType,
Douglas Gregorea766182010-10-18 18:21:28 +00005274 KnownMethods, false);
5275
5276 // Visit the superclass.
5277 if (IFace->getSuperClass())
5278 FindImplementableMethods(Context, IFace->getSuperClass(),
5279 WantInstanceMethods, ReturnType,
5280 KnownMethods, false);
Douglas Gregore8f5a172010-04-07 00:21:17 +00005281 }
5282
5283 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(Container)) {
5284 // Recurse into protocols.
5285 const ObjCList<ObjCProtocolDecl> &Protocols
5286 = Category->getReferencedProtocols();
5287 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Douglas Gregorea766182010-10-18 18:21:28 +00005288 E = Protocols.end();
Douglas Gregore8f5a172010-04-07 00:21:17 +00005289 I != E; ++I)
5290 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
Douglas Gregorea766182010-10-18 18:21:28 +00005291 KnownMethods, InOriginalClass);
5292
5293 // If this category is the original class, jump to the interface.
5294 if (InOriginalClass && Category->getClassInterface())
5295 FindImplementableMethods(Context, Category->getClassInterface(),
5296 WantInstanceMethods, ReturnType, KnownMethods,
5297 false);
Douglas Gregore8f5a172010-04-07 00:21:17 +00005298 }
5299
5300 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
5301 // Recurse into protocols.
5302 const ObjCList<ObjCProtocolDecl> &Protocols
5303 = Protocol->getReferencedProtocols();
5304 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
5305 E = Protocols.end();
5306 I != E; ++I)
5307 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
Douglas Gregorea766182010-10-18 18:21:28 +00005308 KnownMethods, false);
Douglas Gregore8f5a172010-04-07 00:21:17 +00005309 }
5310
5311 // Add methods in this container. This operation occurs last because
5312 // we want the methods from this container to override any methods
5313 // we've previously seen with the same selector.
5314 for (ObjCContainerDecl::method_iterator M = Container->meth_begin(),
5315 MEnd = Container->meth_end();
5316 M != MEnd; ++M) {
5317 if ((*M)->isInstanceMethod() == WantInstanceMethods) {
5318 if (!ReturnType.isNull() &&
5319 !Context.hasSameUnqualifiedType(ReturnType, (*M)->getResultType()))
5320 continue;
5321
Douglas Gregor408be5a2010-08-25 01:08:01 +00005322 KnownMethods[(*M)->getSelector()] = std::make_pair(*M, InOriginalClass);
Douglas Gregore8f5a172010-04-07 00:21:17 +00005323 }
5324 }
5325}
5326
5327void Sema::CodeCompleteObjCMethodDecl(Scope *S,
5328 bool IsInstanceMethod,
John McCallb3d87482010-08-24 05:47:05 +00005329 ParsedType ReturnTy,
John McCalld226f652010-08-21 09:40:31 +00005330 Decl *IDecl) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00005331 // Determine the return type of the method we're declaring, if
5332 // provided.
5333 QualType ReturnType = GetTypeFromParser(ReturnTy);
5334
Douglas Gregorea766182010-10-18 18:21:28 +00005335 // Determine where we should start searching for methods.
5336 ObjCContainerDecl *SearchDecl = 0;
Douglas Gregore8f5a172010-04-07 00:21:17 +00005337 bool IsInImplementation = false;
John McCalld226f652010-08-21 09:40:31 +00005338 if (Decl *D = IDecl) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00005339 if (ObjCImplementationDecl *Impl = dyn_cast<ObjCImplementationDecl>(D)) {
5340 SearchDecl = Impl->getClassInterface();
Douglas Gregore8f5a172010-04-07 00:21:17 +00005341 IsInImplementation = true;
5342 } else if (ObjCCategoryImplDecl *CatImpl
Douglas Gregorea766182010-10-18 18:21:28 +00005343 = dyn_cast<ObjCCategoryImplDecl>(D)) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00005344 SearchDecl = CatImpl->getCategoryDecl();
Douglas Gregore8f5a172010-04-07 00:21:17 +00005345 IsInImplementation = true;
Douglas Gregorea766182010-10-18 18:21:28 +00005346 } else
Douglas Gregore8f5a172010-04-07 00:21:17 +00005347 SearchDecl = dyn_cast<ObjCContainerDecl>(D);
Douglas Gregore8f5a172010-04-07 00:21:17 +00005348 }
5349
5350 if (!SearchDecl && S) {
Douglas Gregorea766182010-10-18 18:21:28 +00005351 if (DeclContext *DC = static_cast<DeclContext *>(S->getEntity()))
Douglas Gregore8f5a172010-04-07 00:21:17 +00005352 SearchDecl = dyn_cast<ObjCContainerDecl>(DC);
Douglas Gregore8f5a172010-04-07 00:21:17 +00005353 }
5354
Douglas Gregorea766182010-10-18 18:21:28 +00005355 if (!SearchDecl) {
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005356 HandleCodeCompleteResults(this, CodeCompleter,
5357 CodeCompletionContext::CCC_Other,
5358 0, 0);
Douglas Gregore8f5a172010-04-07 00:21:17 +00005359 return;
5360 }
5361
5362 // Find all of the methods that we could declare/implement here.
5363 KnownMethodsMap KnownMethods;
5364 FindImplementableMethods(Context, SearchDecl, IsInstanceMethod,
Douglas Gregorea766182010-10-18 18:21:28 +00005365 ReturnType, KnownMethods);
Douglas Gregore8f5a172010-04-07 00:21:17 +00005366
Douglas Gregore8f5a172010-04-07 00:21:17 +00005367 // Add declarations or definitions for each of the known methods.
John McCall0a2c5e22010-08-25 06:19:51 +00005368 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00005369 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5370 CodeCompletionContext::CCC_Other);
Douglas Gregore8f5a172010-04-07 00:21:17 +00005371 Results.EnterNewScope();
5372 PrintingPolicy Policy(Context.PrintingPolicy);
5373 Policy.AnonymousTagLocations = false;
5374 for (KnownMethodsMap::iterator M = KnownMethods.begin(),
5375 MEnd = KnownMethods.end();
5376 M != MEnd; ++M) {
Douglas Gregor408be5a2010-08-25 01:08:01 +00005377 ObjCMethodDecl *Method = M->second.first;
Douglas Gregor218937c2011-02-01 19:23:04 +00005378 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregore8f5a172010-04-07 00:21:17 +00005379
5380 // If the result type was not already provided, add it to the
5381 // pattern as (type).
5382 if (ReturnType.isNull()) {
5383 std::string TypeStr;
5384 Method->getResultType().getAsStringInternal(TypeStr, Policy);
Douglas Gregor218937c2011-02-01 19:23:04 +00005385 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5386 // FIXME: Fast-path common type names
5387 Builder.AddTextChunk(CopyString(Builder.getAllocator(), TypeStr));
5388 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregore8f5a172010-04-07 00:21:17 +00005389 }
5390
5391 Selector Sel = Method->getSelector();
5392
5393 // Add the first part of the selector to the pattern.
Douglas Gregor218937c2011-02-01 19:23:04 +00005394 Builder.AddTypedTextChunk(CopyString(Builder.getAllocator(),
5395 Sel.getIdentifierInfoForSlot(0)->getName()));
Douglas Gregore8f5a172010-04-07 00:21:17 +00005396
5397 // Add parameters to the pattern.
5398 unsigned I = 0;
5399 for (ObjCMethodDecl::param_iterator P = Method->param_begin(),
5400 PEnd = Method->param_end();
5401 P != PEnd; (void)++P, ++I) {
5402 // Add the part of the selector name.
5403 if (I == 0)
Douglas Gregor218937c2011-02-01 19:23:04 +00005404 Builder.AddTypedTextChunk(":");
Douglas Gregore8f5a172010-04-07 00:21:17 +00005405 else if (I < Sel.getNumArgs()) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005406 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5407 Builder.AddTypedTextChunk(
5408 CopyString(Builder.getAllocator(),
5409 (Sel.getIdentifierInfoForSlot(I)->getName()
5410 + ":").str()));
Douglas Gregore8f5a172010-04-07 00:21:17 +00005411 } else
5412 break;
5413
5414 // Add the parameter type.
5415 std::string TypeStr;
5416 (*P)->getOriginalType().getAsStringInternal(TypeStr, Policy);
Douglas Gregor218937c2011-02-01 19:23:04 +00005417 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5418 // FIXME: Fast-path common type names
5419 Builder.AddTextChunk(CopyString(Builder.getAllocator(),
5420 TypeStr));
5421 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregore8f5a172010-04-07 00:21:17 +00005422
5423 if (IdentifierInfo *Id = (*P)->getIdentifier())
Douglas Gregor218937c2011-02-01 19:23:04 +00005424 Builder.AddTextChunk(CopyString(Builder.getAllocator(), Id->getName()));
Douglas Gregore8f5a172010-04-07 00:21:17 +00005425 }
5426
5427 if (Method->isVariadic()) {
5428 if (Method->param_size() > 0)
Douglas Gregor218937c2011-02-01 19:23:04 +00005429 Builder.AddChunk(CodeCompletionString::CK_Comma);
5430 Builder.AddTextChunk("...");
Douglas Gregore17794f2010-08-31 05:13:43 +00005431 }
Douglas Gregore8f5a172010-04-07 00:21:17 +00005432
Douglas Gregor447107d2010-05-28 00:57:46 +00005433 if (IsInImplementation && Results.includeCodePatterns()) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00005434 // We will be defining the method here, so add a compound statement.
Douglas Gregor218937c2011-02-01 19:23:04 +00005435 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5436 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5437 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
Douglas Gregore8f5a172010-04-07 00:21:17 +00005438 if (!Method->getResultType()->isVoidType()) {
5439 // If the result type is not void, add a return clause.
Douglas Gregor218937c2011-02-01 19:23:04 +00005440 Builder.AddTextChunk("return");
5441 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5442 Builder.AddPlaceholderChunk("expression");
5443 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Douglas Gregore8f5a172010-04-07 00:21:17 +00005444 } else
Douglas Gregor218937c2011-02-01 19:23:04 +00005445 Builder.AddPlaceholderChunk("statements");
Douglas Gregore8f5a172010-04-07 00:21:17 +00005446
Douglas Gregor218937c2011-02-01 19:23:04 +00005447 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
5448 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
Douglas Gregore8f5a172010-04-07 00:21:17 +00005449 }
5450
Douglas Gregor408be5a2010-08-25 01:08:01 +00005451 unsigned Priority = CCP_CodePattern;
5452 if (!M->second.second)
5453 Priority += CCD_InBaseClass;
5454
Douglas Gregor218937c2011-02-01 19:23:04 +00005455 Results.AddResult(Result(Builder.TakeString(), Priority,
Douglas Gregor16ed9ad2010-08-17 16:06:07 +00005456 Method->isInstanceMethod()
5457 ? CXCursor_ObjCInstanceMethodDecl
5458 : CXCursor_ObjCClassMethodDecl));
Douglas Gregore8f5a172010-04-07 00:21:17 +00005459 }
5460
5461 Results.ExitScope();
5462
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005463 HandleCodeCompleteResults(this, CodeCompleter,
5464 CodeCompletionContext::CCC_Other,
5465 Results.data(),Results.size());
Douglas Gregore8f5a172010-04-07 00:21:17 +00005466}
Douglas Gregor1f5537a2010-07-08 23:20:03 +00005467
5468void Sema::CodeCompleteObjCMethodDeclSelector(Scope *S,
5469 bool IsInstanceMethod,
Douglas Gregor40ed9a12010-07-08 23:37:41 +00005470 bool AtParameterName,
John McCallb3d87482010-08-24 05:47:05 +00005471 ParsedType ReturnTy,
Douglas Gregor1f5537a2010-07-08 23:20:03 +00005472 IdentifierInfo **SelIdents,
5473 unsigned NumSelIdents) {
Douglas Gregor1f5537a2010-07-08 23:20:03 +00005474 // If we have an external source, load the entire class method
Sebastian Redl3c7f4132010-08-18 23:57:06 +00005475 // pool from the AST file.
Douglas Gregor1f5537a2010-07-08 23:20:03 +00005476 if (ExternalSource) {
5477 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
5478 I != N; ++I) {
5479 Selector Sel = ExternalSource->GetExternalSelector(I);
Sebastian Redldb9d2142010-08-02 23:18:59 +00005480 if (Sel.isNull() || MethodPool.count(Sel))
Douglas Gregor1f5537a2010-07-08 23:20:03 +00005481 continue;
Sebastian Redldb9d2142010-08-02 23:18:59 +00005482
5483 ReadMethodPool(Sel);
Douglas Gregor1f5537a2010-07-08 23:20:03 +00005484 }
5485 }
5486
5487 // Build the set of methods we can see.
John McCall0a2c5e22010-08-25 06:19:51 +00005488 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00005489 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5490 CodeCompletionContext::CCC_Other);
Douglas Gregor1f5537a2010-07-08 23:20:03 +00005491
5492 if (ReturnTy)
5493 Results.setPreferredType(GetTypeFromParser(ReturnTy).getNonReferenceType());
Sebastian Redldb9d2142010-08-02 23:18:59 +00005494
Douglas Gregor1f5537a2010-07-08 23:20:03 +00005495 Results.EnterNewScope();
Sebastian Redldb9d2142010-08-02 23:18:59 +00005496 for (GlobalMethodPool::iterator M = MethodPool.begin(),
5497 MEnd = MethodPool.end();
5498 M != MEnd; ++M) {
5499 for (ObjCMethodList *MethList = IsInstanceMethod ? &M->second.first :
5500 &M->second.second;
5501 MethList && MethList->Method;
Douglas Gregor1f5537a2010-07-08 23:20:03 +00005502 MethList = MethList->Next) {
5503 if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents,
5504 NumSelIdents))
5505 continue;
5506
Douglas Gregor40ed9a12010-07-08 23:37:41 +00005507 if (AtParameterName) {
5508 // Suggest parameter names we've seen before.
5509 if (NumSelIdents && NumSelIdents <= MethList->Method->param_size()) {
5510 ParmVarDecl *Param = MethList->Method->param_begin()[NumSelIdents-1];
5511 if (Param->getIdentifier()) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005512 CodeCompletionBuilder Builder(Results.getAllocator());
5513 Builder.AddTypedTextChunk(CopyString(Builder.getAllocator(),
5514 Param->getIdentifier()->getName()));
5515 Results.AddResult(Builder.TakeString());
Douglas Gregor40ed9a12010-07-08 23:37:41 +00005516 }
5517 }
5518
5519 continue;
5520 }
5521
Douglas Gregor1f5537a2010-07-08 23:20:03 +00005522 Result R(MethList->Method, 0);
5523 R.StartParameter = NumSelIdents;
5524 R.AllParametersAreInformative = false;
5525 R.DeclaringEntity = true;
5526 Results.MaybeAddResult(R, CurContext);
5527 }
5528 }
5529
5530 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005531 HandleCodeCompleteResults(this, CodeCompleter,
5532 CodeCompletionContext::CCC_Other,
5533 Results.data(),Results.size());
Douglas Gregor1f5537a2010-07-08 23:20:03 +00005534}
Douglas Gregor87c08a52010-08-13 22:48:40 +00005535
Douglas Gregorf29c5232010-08-24 22:20:20 +00005536void Sema::CodeCompletePreprocessorDirective(bool InConditional) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005537 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00005538 CodeCompletionContext::CCC_PreprocessorDirective);
Douglas Gregorf44e8542010-08-24 19:08:16 +00005539 Results.EnterNewScope();
5540
5541 // #if <condition>
Douglas Gregor218937c2011-02-01 19:23:04 +00005542 CodeCompletionBuilder Builder(Results.getAllocator());
5543 Builder.AddTypedTextChunk("if");
5544 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5545 Builder.AddPlaceholderChunk("condition");
5546 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00005547
5548 // #ifdef <macro>
Douglas Gregor218937c2011-02-01 19:23:04 +00005549 Builder.AddTypedTextChunk("ifdef");
5550 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5551 Builder.AddPlaceholderChunk("macro");
5552 Results.AddResult(Builder.TakeString());
5553
Douglas Gregorf44e8542010-08-24 19:08:16 +00005554 // #ifndef <macro>
Douglas Gregor218937c2011-02-01 19:23:04 +00005555 Builder.AddTypedTextChunk("ifndef");
5556 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5557 Builder.AddPlaceholderChunk("macro");
5558 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00005559
5560 if (InConditional) {
5561 // #elif <condition>
Douglas Gregor218937c2011-02-01 19:23:04 +00005562 Builder.AddTypedTextChunk("elif");
5563 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5564 Builder.AddPlaceholderChunk("condition");
5565 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00005566
5567 // #else
Douglas Gregor218937c2011-02-01 19:23:04 +00005568 Builder.AddTypedTextChunk("else");
5569 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00005570
5571 // #endif
Douglas Gregor218937c2011-02-01 19:23:04 +00005572 Builder.AddTypedTextChunk("endif");
5573 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00005574 }
5575
5576 // #include "header"
Douglas Gregor218937c2011-02-01 19:23:04 +00005577 Builder.AddTypedTextChunk("include");
5578 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5579 Builder.AddTextChunk("\"");
5580 Builder.AddPlaceholderChunk("header");
5581 Builder.AddTextChunk("\"");
5582 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00005583
5584 // #include <header>
Douglas Gregor218937c2011-02-01 19:23:04 +00005585 Builder.AddTypedTextChunk("include");
5586 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5587 Builder.AddTextChunk("<");
5588 Builder.AddPlaceholderChunk("header");
5589 Builder.AddTextChunk(">");
5590 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00005591
5592 // #define <macro>
Douglas Gregor218937c2011-02-01 19:23:04 +00005593 Builder.AddTypedTextChunk("define");
5594 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5595 Builder.AddPlaceholderChunk("macro");
5596 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00005597
5598 // #define <macro>(<args>)
Douglas Gregor218937c2011-02-01 19:23:04 +00005599 Builder.AddTypedTextChunk("define");
5600 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5601 Builder.AddPlaceholderChunk("macro");
5602 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5603 Builder.AddPlaceholderChunk("args");
5604 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5605 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00005606
5607 // #undef <macro>
Douglas Gregor218937c2011-02-01 19:23:04 +00005608 Builder.AddTypedTextChunk("undef");
5609 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5610 Builder.AddPlaceholderChunk("macro");
5611 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00005612
5613 // #line <number>
Douglas Gregor218937c2011-02-01 19:23:04 +00005614 Builder.AddTypedTextChunk("line");
5615 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5616 Builder.AddPlaceholderChunk("number");
5617 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00005618
5619 // #line <number> "filename"
Douglas Gregor218937c2011-02-01 19:23:04 +00005620 Builder.AddTypedTextChunk("line");
5621 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5622 Builder.AddPlaceholderChunk("number");
5623 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5624 Builder.AddTextChunk("\"");
5625 Builder.AddPlaceholderChunk("filename");
5626 Builder.AddTextChunk("\"");
5627 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00005628
5629 // #error <message>
Douglas Gregor218937c2011-02-01 19:23:04 +00005630 Builder.AddTypedTextChunk("error");
5631 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5632 Builder.AddPlaceholderChunk("message");
5633 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00005634
5635 // #pragma <arguments>
Douglas Gregor218937c2011-02-01 19:23:04 +00005636 Builder.AddTypedTextChunk("pragma");
5637 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5638 Builder.AddPlaceholderChunk("arguments");
5639 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00005640
5641 if (getLangOptions().ObjC1) {
5642 // #import "header"
Douglas Gregor218937c2011-02-01 19:23:04 +00005643 Builder.AddTypedTextChunk("import");
5644 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5645 Builder.AddTextChunk("\"");
5646 Builder.AddPlaceholderChunk("header");
5647 Builder.AddTextChunk("\"");
5648 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00005649
5650 // #import <header>
Douglas Gregor218937c2011-02-01 19:23:04 +00005651 Builder.AddTypedTextChunk("import");
5652 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5653 Builder.AddTextChunk("<");
5654 Builder.AddPlaceholderChunk("header");
5655 Builder.AddTextChunk(">");
5656 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00005657 }
5658
5659 // #include_next "header"
Douglas Gregor218937c2011-02-01 19:23:04 +00005660 Builder.AddTypedTextChunk("include_next");
5661 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5662 Builder.AddTextChunk("\"");
5663 Builder.AddPlaceholderChunk("header");
5664 Builder.AddTextChunk("\"");
5665 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00005666
5667 // #include_next <header>
Douglas Gregor218937c2011-02-01 19:23:04 +00005668 Builder.AddTypedTextChunk("include_next");
5669 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5670 Builder.AddTextChunk("<");
5671 Builder.AddPlaceholderChunk("header");
5672 Builder.AddTextChunk(">");
5673 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00005674
5675 // #warning <message>
Douglas Gregor218937c2011-02-01 19:23:04 +00005676 Builder.AddTypedTextChunk("warning");
5677 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5678 Builder.AddPlaceholderChunk("message");
5679 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00005680
5681 // Note: #ident and #sccs are such crazy anachronisms that we don't provide
5682 // completions for them. And __include_macros is a Clang-internal extension
5683 // that we don't want to encourage anyone to use.
5684
5685 // FIXME: we don't support #assert or #unassert, so don't suggest them.
5686 Results.ExitScope();
5687
Douglas Gregorf44e8542010-08-24 19:08:16 +00005688 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor721f3592010-08-25 18:41:16 +00005689 CodeCompletionContext::CCC_PreprocessorDirective,
Douglas Gregorf44e8542010-08-24 19:08:16 +00005690 Results.data(), Results.size());
5691}
5692
5693void Sema::CodeCompleteInPreprocessorConditionalExclusion(Scope *S) {
Douglas Gregorf29c5232010-08-24 22:20:20 +00005694 CodeCompleteOrdinaryName(S,
John McCallf312b1e2010-08-26 23:41:50 +00005695 S->getFnParent()? Sema::PCC_RecoveryInFunction
5696 : Sema::PCC_Namespace);
Douglas Gregorf44e8542010-08-24 19:08:16 +00005697}
5698
Douglas Gregorf29c5232010-08-24 22:20:20 +00005699void Sema::CodeCompletePreprocessorMacroName(bool IsDefinition) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005700 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00005701 IsDefinition? CodeCompletionContext::CCC_MacroName
5702 : CodeCompletionContext::CCC_MacroNameUse);
Douglas Gregor1fbb4472010-08-24 20:21:13 +00005703 if (!IsDefinition && (!CodeCompleter || CodeCompleter->includeMacros())) {
5704 // Add just the names of macros, not their arguments.
Douglas Gregor218937c2011-02-01 19:23:04 +00005705 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregor1fbb4472010-08-24 20:21:13 +00005706 Results.EnterNewScope();
5707 for (Preprocessor::macro_iterator M = PP.macro_begin(),
5708 MEnd = PP.macro_end();
5709 M != MEnd; ++M) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005710 Builder.AddTypedTextChunk(CopyString(Builder.getAllocator(),
5711 M->first->getName()));
5712 Results.AddResult(Builder.TakeString());
Douglas Gregor1fbb4472010-08-24 20:21:13 +00005713 }
5714 Results.ExitScope();
5715 } else if (IsDefinition) {
5716 // FIXME: Can we detect when the user just wrote an include guard above?
5717 }
5718
Douglas Gregor52779fb2010-09-23 23:01:17 +00005719 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor1fbb4472010-08-24 20:21:13 +00005720 Results.data(), Results.size());
5721}
5722
Douglas Gregorf29c5232010-08-24 22:20:20 +00005723void Sema::CodeCompletePreprocessorExpression() {
Douglas Gregor218937c2011-02-01 19:23:04 +00005724 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00005725 CodeCompletionContext::CCC_PreprocessorExpression);
Douglas Gregorf29c5232010-08-24 22:20:20 +00005726
5727 if (!CodeCompleter || CodeCompleter->includeMacros())
5728 AddMacroResults(PP, Results);
5729
5730 // defined (<macro>)
5731 Results.EnterNewScope();
Douglas Gregor218937c2011-02-01 19:23:04 +00005732 CodeCompletionBuilder Builder(Results.getAllocator());
5733 Builder.AddTypedTextChunk("defined");
5734 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5735 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5736 Builder.AddPlaceholderChunk("macro");
5737 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5738 Results.AddResult(Builder.TakeString());
Douglas Gregorf29c5232010-08-24 22:20:20 +00005739 Results.ExitScope();
5740
5741 HandleCodeCompleteResults(this, CodeCompleter,
5742 CodeCompletionContext::CCC_PreprocessorExpression,
5743 Results.data(), Results.size());
5744}
5745
5746void Sema::CodeCompletePreprocessorMacroArgument(Scope *S,
5747 IdentifierInfo *Macro,
5748 MacroInfo *MacroInfo,
5749 unsigned Argument) {
5750 // FIXME: In the future, we could provide "overload" results, much like we
5751 // do for function calls.
5752
5753 CodeCompleteOrdinaryName(S,
John McCallf312b1e2010-08-26 23:41:50 +00005754 S->getFnParent()? Sema::PCC_RecoveryInFunction
5755 : Sema::PCC_Namespace);
Douglas Gregorf29c5232010-08-24 22:20:20 +00005756}
5757
Douglas Gregor55817af2010-08-25 17:04:25 +00005758void Sema::CodeCompleteNaturalLanguage() {
Douglas Gregor55817af2010-08-25 17:04:25 +00005759 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregoraf1c6b52010-08-25 17:10:00 +00005760 CodeCompletionContext::CCC_NaturalLanguage,
Douglas Gregor55817af2010-08-25 17:04:25 +00005761 0, 0);
5762}
5763
Douglas Gregor218937c2011-02-01 19:23:04 +00005764void Sema::GatherGlobalCodeCompletions(llvm::BumpPtrAllocator &Allocator,
John McCall0a2c5e22010-08-25 06:19:51 +00005765 llvm::SmallVectorImpl<CodeCompletionResult> &Results) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005766 ResultBuilder Builder(*this, Allocator, CodeCompletionContext::CCC_Recovery);
Douglas Gregor8071e422010-08-15 06:18:01 +00005767 if (!CodeCompleter || CodeCompleter->includeGlobals()) {
5768 CodeCompletionDeclConsumer Consumer(Builder,
5769 Context.getTranslationUnitDecl());
5770 LookupVisibleDecls(Context.getTranslationUnitDecl(), LookupAnyName,
5771 Consumer);
5772 }
Douglas Gregor87c08a52010-08-13 22:48:40 +00005773
5774 if (!CodeCompleter || CodeCompleter->includeMacros())
5775 AddMacroResults(PP, Builder);
5776
5777 Results.clear();
5778 Results.insert(Results.end(),
5779 Builder.data(), Builder.data() + Builder.size());
5780}