blob: 5bc428a04aea4ff5dfb61533ba4edf4400066057 [file] [log] [blame]
Douglas Gregor2436e712009-09-17 21:32:03 +00001//===---------------- SemaCodeComplete.cpp - Code Completion ----*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file defines the code-completion semantic actions.
11//
12//===----------------------------------------------------------------------===//
Ilya Biryukov4e7a6fe2017-09-22 19:07:37 +000013#include "clang/AST/DeclCXX.h"
John McCallde6836a2010-08-24 07:21:54 +000014#include "clang/AST/DeclObjC.h"
Douglas Gregorf2510672009-09-21 19:57:38 +000015#include "clang/AST/ExprCXX.h"
Douglas Gregor8ce33212009-11-17 17:59:40 +000016#include "clang/AST/ExprObjC.h"
Ilya Biryukovb5da91c2017-11-08 10:39:09 +000017#include "clang/AST/QualTypeNames.h"
Jordan Rose4938f272013-02-09 10:09:43 +000018#include "clang/Basic/CharInfo.h"
Douglas Gregor07f43572012-01-29 18:15:03 +000019#include "clang/Lex/HeaderSearch.h"
Douglas Gregorf329c7c2009-10-30 16:50:04 +000020#include "clang/Lex/MacroInfo.h"
21#include "clang/Lex/Preprocessor.h"
Chandler Carruth3a022472012-12-04 09:13:33 +000022#include "clang/Sema/CodeCompleteConsumer.h"
Chandler Carruth3a022472012-12-04 09:13:33 +000023#include "clang/Sema/Lookup.h"
24#include "clang/Sema/Overload.h"
25#include "clang/Sema/Scope.h"
26#include "clang/Sema/ScopeInfo.h"
Ilya Biryukov4e7a6fe2017-09-22 19:07:37 +000027#include "clang/Sema/SemaInternal.h"
Douglas Gregor1154e272010-09-16 16:06:31 +000028#include "llvm/ADT/DenseSet.h"
Benjamin Kramere0513cb2012-01-30 16:17:39 +000029#include "llvm/ADT/SmallBitVector.h"
Douglas Gregor3545ff42009-09-21 16:56:56 +000030#include "llvm/ADT/SmallPtrSet.h"
Benjamin Kramer49038022012-02-04 13:45:25 +000031#include "llvm/ADT/SmallString.h"
Douglas Gregore6688e62009-09-28 03:51:44 +000032#include "llvm/ADT/StringExtras.h"
Douglas Gregor9d2ddb22010-04-06 19:22:33 +000033#include "llvm/ADT/StringSwitch.h"
Douglas Gregor67c692c2010-08-26 15:07:07 +000034#include "llvm/ADT/Twine.h"
Douglas Gregor3545ff42009-09-21 16:56:56 +000035#include <list>
36#include <map>
37#include <vector>
Douglas Gregor2436e712009-09-17 21:32:03 +000038
39using namespace clang;
John McCallaab3e412010-08-25 08:40:02 +000040using namespace sema;
Douglas Gregor2436e712009-09-17 21:32:03 +000041
Douglas Gregor3545ff42009-09-21 16:56:56 +000042namespace {
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000043 /// A container of code-completion results.
Douglas Gregor3545ff42009-09-21 16:56:56 +000044 class ResultBuilder {
45 public:
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000046 /// The type of a name-lookup filter, which can be provided to the
Douglas Gregor3545ff42009-09-21 16:56:56 +000047 /// name-lookup routines to specify which declarations should be included in
48 /// the result set (when it returns true) and which declarations should be
49 /// filtered out (returns false).
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +000050 typedef bool (ResultBuilder::*LookupFilter)(const NamedDecl *) const;
Ivan Donchevskii13d90542017-10-27 11:05:40 +000051
John McCall276321a2010-08-25 06:19:51 +000052 typedef CodeCompletionResult Result;
Douglas Gregor3545ff42009-09-21 16:56:56 +000053
54 private:
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000055 /// The actual results we have found.
Douglas Gregor3545ff42009-09-21 16:56:56 +000056 std::vector<Result> Results;
57
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000058 /// A record of all of the declarations we have found and placed
Douglas Gregor3545ff42009-09-21 16:56:56 +000059 /// into the result set, used to ensure that no declaration ever gets into
60 /// the result set twice.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +000061 llvm::SmallPtrSet<const Decl*, 16> AllDeclsFound;
Douglas Gregor3545ff42009-09-21 16:56:56 +000062
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +000063 typedef std::pair<const NamedDecl *, unsigned> DeclIndexPair;
Douglas Gregor05e7ca32009-12-06 20:23:50 +000064
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000065 /// An entry in the shadow map, which is optimized to store
Douglas Gregor05e7ca32009-12-06 20:23:50 +000066 /// a single (declaration, index) mapping (the common case) but
67 /// can also store a list of (declaration, index) mappings.
68 class ShadowMapEntry {
Chris Lattner0e62c1c2011-07-23 10:55:15 +000069 typedef SmallVector<DeclIndexPair, 4> DeclIndexPairVector;
Douglas Gregor05e7ca32009-12-06 20:23:50 +000070
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000071 /// Contains either the solitary NamedDecl * or a vector
Douglas Gregor05e7ca32009-12-06 20:23:50 +000072 /// of (declaration, index) pairs.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +000073 llvm::PointerUnion<const NamedDecl *, DeclIndexPairVector*> DeclOrVector;
Douglas Gregor05e7ca32009-12-06 20:23:50 +000074
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000075 /// When the entry contains a single declaration, this is
Douglas Gregor05e7ca32009-12-06 20:23:50 +000076 /// the index associated with that entry.
77 unsigned SingleDeclIndex;
78
79 public:
80 ShadowMapEntry() : DeclOrVector(), SingleDeclIndex(0) { }
81
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +000082 void Add(const NamedDecl *ND, unsigned Index) {
Douglas Gregor05e7ca32009-12-06 20:23:50 +000083 if (DeclOrVector.isNull()) {
84 // 0 - > 1 elements: just set the single element information.
85 DeclOrVector = ND;
86 SingleDeclIndex = Index;
87 return;
88 }
89
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +000090 if (const NamedDecl *PrevND =
91 DeclOrVector.dyn_cast<const NamedDecl *>()) {
Douglas Gregor05e7ca32009-12-06 20:23:50 +000092 // 1 -> 2 elements: create the vector of results and push in the
93 // existing declaration.
94 DeclIndexPairVector *Vec = new DeclIndexPairVector;
95 Vec->push_back(DeclIndexPair(PrevND, SingleDeclIndex));
96 DeclOrVector = Vec;
97 }
98
99 // Add the new element to the end of the vector.
100 DeclOrVector.get<DeclIndexPairVector*>()->push_back(
101 DeclIndexPair(ND, Index));
102 }
103
104 void Destroy() {
105 if (DeclIndexPairVector *Vec
106 = DeclOrVector.dyn_cast<DeclIndexPairVector *>()) {
107 delete Vec;
Craig Topperc3ec1492014-05-26 06:22:03 +0000108 DeclOrVector = ((NamedDecl *)nullptr);
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000109 }
110 }
111
112 // Iteration.
113 class iterator;
114 iterator begin() const;
115 iterator end() const;
116 };
117
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000118 /// A mapping from declaration names to the declarations that have
Douglas Gregor3545ff42009-09-21 16:56:56 +0000119 /// this name within a particular scope and their index within the list of
120 /// results.
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000121 typedef llvm::DenseMap<DeclarationName, ShadowMapEntry> ShadowMap;
Douglas Gregor3545ff42009-09-21 16:56:56 +0000122
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000123 /// The semantic analysis object for which results are being
Douglas Gregor3545ff42009-09-21 16:56:56 +0000124 /// produced.
125 Sema &SemaRef;
Douglas Gregorb278aaf2011-02-01 19:23:04 +0000126
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000127 /// The allocator used to allocate new code-completion strings.
Douglas Gregorbcbf46c2011-02-01 22:57:45 +0000128 CodeCompletionAllocator &Allocator;
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +0000129
130 CodeCompletionTUInfo &CCTUInfo;
Douglas Gregor3545ff42009-09-21 16:56:56 +0000131
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000132 /// If non-NULL, a filter function used to remove any code-completion
Douglas Gregor3545ff42009-09-21 16:56:56 +0000133 /// results that are not desirable.
134 LookupFilter Filter;
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000135
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000136 /// Whether we should allow declarations as
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000137 /// nested-name-specifiers that would otherwise be filtered out.
138 bool AllowNestedNameSpecifiers;
139
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000140 /// If set, the type that we would prefer our resulting value
Douglas Gregor7aa6b222010-05-30 01:49:25 +0000141 /// declarations to have.
142 ///
143 /// Closely matching the preferred type gives a boost to a result's
144 /// priority.
145 CanQualType PreferredType;
146
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000147 /// A list of shadow maps, which is used to model name hiding at
Douglas Gregor3545ff42009-09-21 16:56:56 +0000148 /// different levels of, e.g., the inheritance hierarchy.
149 std::list<ShadowMap> ShadowMaps;
150
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000151 /// If we're potentially referring to a C++ member function, the set
Douglas Gregor9be0ed42010-08-26 16:36:48 +0000152 /// of qualifiers applied to the object type.
153 Qualifiers ObjectTypeQualifiers;
154
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000155 /// Whether the \p ObjectTypeQualifiers field is active.
Douglas Gregor9be0ed42010-08-26 16:36:48 +0000156 bool HasObjectTypeQualifiers;
157
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000158 /// The selector that we prefer.
Douglas Gregorc2cb2e22010-08-27 15:29:55 +0000159 Selector PreferredSelector;
160
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000161 /// The completion context in which we are gathering results.
Douglas Gregor50832e02010-09-20 22:39:41 +0000162 CodeCompletionContext CompletionContext;
163
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000164 /// If we are in an instance method definition, the \@implementation
Douglas Gregor05fcf842010-11-02 20:36:02 +0000165 /// object.
166 ObjCImplementationDecl *ObjCImplementation;
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000167
Douglas Gregor50832e02010-09-20 22:39:41 +0000168 void AdjustResultPriorityForDecl(Result &R);
Douglas Gregor95887f92010-07-08 23:20:03 +0000169
Douglas Gregor0212fd72010-09-21 16:06:22 +0000170 void MaybeAddConstructorResults(Result R);
171
Douglas Gregor3545ff42009-09-21 16:56:56 +0000172 public:
Douglas Gregorbcbf46c2011-02-01 22:57:45 +0000173 explicit ResultBuilder(Sema &SemaRef, CodeCompletionAllocator &Allocator,
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +0000174 CodeCompletionTUInfo &CCTUInfo,
Douglas Gregor0ac41382010-09-23 23:01:17 +0000175 const CodeCompletionContext &CompletionContext,
Craig Topperc3ec1492014-05-26 06:22:03 +0000176 LookupFilter Filter = nullptr)
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +0000177 : SemaRef(SemaRef), Allocator(Allocator), CCTUInfo(CCTUInfo),
178 Filter(Filter),
Douglas Gregorb278aaf2011-02-01 19:23:04 +0000179 AllowNestedNameSpecifiers(false), HasObjectTypeQualifiers(false),
Douglas Gregor05fcf842010-11-02 20:36:02 +0000180 CompletionContext(CompletionContext),
Craig Topperc3ec1492014-05-26 06:22:03 +0000181 ObjCImplementation(nullptr)
Douglas Gregor05fcf842010-11-02 20:36:02 +0000182 {
183 // If this is an Objective-C instance method definition, dig out the
184 // corresponding implementation.
185 switch (CompletionContext.getKind()) {
186 case CodeCompletionContext::CCC_Expression:
187 case CodeCompletionContext::CCC_ObjCMessageReceiver:
188 case CodeCompletionContext::CCC_ParenthesizedExpression:
189 case CodeCompletionContext::CCC_Statement:
190 case CodeCompletionContext::CCC_Recovery:
191 if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl())
192 if (Method->isInstanceMethod())
193 if (ObjCInterfaceDecl *Interface = Method->getClassInterface())
194 ObjCImplementation = Interface->getImplementation();
195 break;
196
197 default:
198 break;
199 }
200 }
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000201
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000202 /// Determine the priority for a reference to the given declaration.
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000203 unsigned getBasePriority(const NamedDecl *D);
204
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000205 /// Whether we should include code patterns in the completion
Douglas Gregorf64acca2010-05-25 21:41:55 +0000206 /// results.
207 bool includeCodePatterns() const {
208 return SemaRef.CodeCompleter &&
Douglas Gregorac322ec2010-08-27 21:18:54 +0000209 SemaRef.CodeCompleter->includeCodePatterns();
Douglas Gregorf64acca2010-05-25 21:41:55 +0000210 }
211
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000212 /// Set the filter used for code-completion results.
Douglas Gregor3545ff42009-09-21 16:56:56 +0000213 void setFilter(LookupFilter Filter) {
214 this->Filter = Filter;
215 }
Craig Topperc3ec1492014-05-26 06:22:03 +0000216
217 Result *data() { return Results.empty()? nullptr : &Results.front(); }
Douglas Gregor3545ff42009-09-21 16:56:56 +0000218 unsigned size() const { return Results.size(); }
219 bool empty() const { return Results.empty(); }
220
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000221 /// Specify the preferred type.
Douglas Gregor7aa6b222010-05-30 01:49:25 +0000222 void setPreferredType(QualType T) {
223 PreferredType = SemaRef.Context.getCanonicalType(T);
224 }
225
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000226 /// Set the cv-qualifiers on the object type, for us in filtering
Douglas Gregor9be0ed42010-08-26 16:36:48 +0000227 /// calls to member functions.
228 ///
229 /// When there are qualifiers in this set, they will be used to filter
230 /// out member functions that aren't available (because there will be a
231 /// cv-qualifier mismatch) or prefer functions with an exact qualifier
232 /// match.
233 void setObjectTypeQualifiers(Qualifiers Quals) {
234 ObjectTypeQualifiers = Quals;
235 HasObjectTypeQualifiers = true;
236 }
237
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000238 /// Set the preferred selector.
Douglas Gregorc2cb2e22010-08-27 15:29:55 +0000239 ///
240 /// When an Objective-C method declaration result is added, and that
241 /// method's selector matches this preferred selector, we give that method
242 /// a slight priority boost.
243 void setPreferredSelector(Selector Sel) {
244 PreferredSelector = Sel;
245 }
Douglas Gregor05fcf842010-11-02 20:36:02 +0000246
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000247 /// Retrieve the code-completion context for which results are
Douglas Gregor50832e02010-09-20 22:39:41 +0000248 /// being collected.
249 const CodeCompletionContext &getCompletionContext() const {
250 return CompletionContext;
251 }
252
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000253 /// Specify whether nested-name-specifiers are allowed.
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000254 void allowNestedNameSpecifiers(bool Allow = true) {
255 AllowNestedNameSpecifiers = Allow;
256 }
257
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000258 /// Return the semantic analysis object for which we are collecting
Douglas Gregor74661272010-09-21 00:03:25 +0000259 /// code completion results.
260 Sema &getSema() const { return SemaRef; }
261
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000262 /// Retrieve the allocator used to allocate code completion strings.
Douglas Gregorbcbf46c2011-02-01 22:57:45 +0000263 CodeCompletionAllocator &getAllocator() const { return Allocator; }
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +0000264
265 CodeCompletionTUInfo &getCodeCompletionTUInfo() const { return CCTUInfo; }
Douglas Gregorb278aaf2011-02-01 19:23:04 +0000266
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000267 /// Determine whether the given declaration is at all interesting
Douglas Gregor7c208612010-01-14 00:20:49 +0000268 /// as a code-completion result.
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000269 ///
270 /// \param ND the declaration that we are inspecting.
271 ///
272 /// \param AsNestedNameSpecifier will be set true if this declaration is
273 /// only interesting when it is a nested-name-specifier.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000274 bool isInterestingDecl(const NamedDecl *ND,
275 bool &AsNestedNameSpecifier) const;
Douglas Gregore0717ab2010-01-14 00:41:07 +0000276
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000277 /// Check whether the result is hidden by the Hiding declaration.
Douglas Gregore0717ab2010-01-14 00:41:07 +0000278 ///
279 /// \returns true if the result is hidden and cannot be found, false if
280 /// the hidden result could still be found. When false, \p R may be
281 /// modified to describe how the result can be found (e.g., via extra
282 /// qualification).
283 bool CheckHiddenResult(Result &R, DeclContext *CurContext,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000284 const NamedDecl *Hiding);
Douglas Gregore0717ab2010-01-14 00:41:07 +0000285
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000286 /// Add a new result to this result set (if it isn't already in one
Douglas Gregor3545ff42009-09-21 16:56:56 +0000287 /// of the shadow maps), or replace an existing result (for, e.g., a
288 /// redeclaration).
Douglas Gregor2af2f672009-09-21 20:12:40 +0000289 ///
Douglas Gregord8c61782012-02-15 15:34:24 +0000290 /// \param R the result to add (if it is unique).
Douglas Gregor2af2f672009-09-21 20:12:40 +0000291 ///
Douglas Gregord8c61782012-02-15 15:34:24 +0000292 /// \param CurContext the context in which this result will be named.
Craig Topperc3ec1492014-05-26 06:22:03 +0000293 void MaybeAddResult(Result R, DeclContext *CurContext = nullptr);
294
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000295 /// Add a new result to this result set, where we already know
Yaron Keren8fbe43982014-11-14 18:33:42 +0000296 /// the hiding declaration (if any).
Douglas Gregorc580c522010-01-14 01:09:38 +0000297 ///
298 /// \param R the result to add (if it is unique).
299 ///
300 /// \param CurContext the context in which this result will be named.
301 ///
302 /// \param Hiding the declaration that hides the result.
Douglas Gregor09bbc652010-01-14 15:47:35 +0000303 ///
304 /// \param InBaseClass whether the result was found in a base
305 /// class of the searched context.
306 void AddResult(Result R, DeclContext *CurContext, NamedDecl *Hiding,
307 bool InBaseClass);
Douglas Gregorc580c522010-01-14 01:09:38 +0000308
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000309 /// Add a new non-declaration result to this result set.
Douglas Gregor78a21012010-01-14 16:01:26 +0000310 void AddResult(Result R);
311
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000312 /// Enter into a new scope.
Douglas Gregor3545ff42009-09-21 16:56:56 +0000313 void EnterNewScope();
314
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000315 /// Exit from the current scope.
Douglas Gregor3545ff42009-09-21 16:56:56 +0000316 void ExitScope();
317
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000318 /// Ignore this declaration, if it is seen again.
Dmitri Gribenko6cfb1532013-02-14 13:53:30 +0000319 void Ignore(const Decl *D) { AllDeclsFound.insert(D->getCanonicalDecl()); }
Douglas Gregorbaf69612009-11-18 04:19:12 +0000320
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000321 /// Add a visited context.
Haojian Wu10d95c52018-01-17 14:29:25 +0000322 void addVisitedContext(DeclContext *Ctx) {
323 CompletionContext.addVisitedContext(Ctx);
324 }
325
Douglas Gregor3545ff42009-09-21 16:56:56 +0000326 /// \name Name lookup predicates
327 ///
328 /// These predicates can be passed to the name lookup functions to filter the
329 /// results of name lookup. All of the predicates have the same type, so that
330 ///
331 //@{
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000332 bool IsOrdinaryName(const NamedDecl *ND) const;
333 bool IsOrdinaryNonTypeName(const NamedDecl *ND) const;
334 bool IsIntegralConstantValue(const NamedDecl *ND) const;
335 bool IsOrdinaryNonValueName(const NamedDecl *ND) const;
336 bool IsNestedNameSpecifier(const NamedDecl *ND) const;
337 bool IsEnum(const NamedDecl *ND) const;
338 bool IsClassOrStruct(const NamedDecl *ND) const;
339 bool IsUnion(const NamedDecl *ND) const;
340 bool IsNamespace(const NamedDecl *ND) const;
341 bool IsNamespaceOrAlias(const NamedDecl *ND) const;
342 bool IsType(const NamedDecl *ND) const;
343 bool IsMember(const NamedDecl *ND) const;
344 bool IsObjCIvar(const NamedDecl *ND) const;
345 bool IsObjCMessageReceiver(const NamedDecl *ND) const;
346 bool IsObjCMessageReceiverOrLambdaCapture(const NamedDecl *ND) const;
347 bool IsObjCCollection(const NamedDecl *ND) const;
348 bool IsImpossibleToSatisfy(const NamedDecl *ND) const;
Douglas Gregor3545ff42009-09-21 16:56:56 +0000349 //@}
350 };
Alexander Kornienkoab9db512015-06-22 23:07:51 +0000351}
Douglas Gregor3545ff42009-09-21 16:56:56 +0000352
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000353class ResultBuilder::ShadowMapEntry::iterator {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000354 llvm::PointerUnion<const NamedDecl *, const DeclIndexPair *> DeclOrIterator;
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000355 unsigned SingleDeclIndex;
356
357public:
358 typedef DeclIndexPair value_type;
359 typedef value_type reference;
360 typedef std::ptrdiff_t difference_type;
361 typedef std::input_iterator_tag iterator_category;
362
363 class pointer {
364 DeclIndexPair Value;
365
366 public:
367 pointer(const DeclIndexPair &Value) : Value(Value) { }
368
369 const DeclIndexPair *operator->() const {
370 return &Value;
371 }
372 };
Craig Topperc3ec1492014-05-26 06:22:03 +0000373
374 iterator() : DeclOrIterator((NamedDecl *)nullptr), SingleDeclIndex(0) {}
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000375
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000376 iterator(const NamedDecl *SingleDecl, unsigned Index)
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000377 : DeclOrIterator(SingleDecl), SingleDeclIndex(Index) { }
378
379 iterator(const DeclIndexPair *Iterator)
380 : DeclOrIterator(Iterator), SingleDeclIndex(0) { }
381
382 iterator &operator++() {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000383 if (DeclOrIterator.is<const NamedDecl *>()) {
Craig Topperc3ec1492014-05-26 06:22:03 +0000384 DeclOrIterator = (NamedDecl *)nullptr;
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000385 SingleDeclIndex = 0;
386 return *this;
387 }
388
389 const DeclIndexPair *I = DeclOrIterator.get<const DeclIndexPair*>();
390 ++I;
391 DeclOrIterator = I;
392 return *this;
393 }
394
Chris Lattner9795b392010-09-04 18:12:20 +0000395 /*iterator operator++(int) {
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000396 iterator tmp(*this);
397 ++(*this);
398 return tmp;
Chris Lattner9795b392010-09-04 18:12:20 +0000399 }*/
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000400
401 reference operator*() const {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000402 if (const NamedDecl *ND = DeclOrIterator.dyn_cast<const NamedDecl *>())
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000403 return reference(ND, SingleDeclIndex);
404
Douglas Gregor94bb5e82009-12-06 21:27:58 +0000405 return *DeclOrIterator.get<const DeclIndexPair*>();
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000406 }
407
408 pointer operator->() const {
409 return pointer(**this);
410 }
411
412 friend bool operator==(const iterator &X, const iterator &Y) {
Douglas Gregor94bb5e82009-12-06 21:27:58 +0000413 return X.DeclOrIterator.getOpaqueValue()
414 == Y.DeclOrIterator.getOpaqueValue() &&
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000415 X.SingleDeclIndex == Y.SingleDeclIndex;
416 }
417
418 friend bool operator!=(const iterator &X, const iterator &Y) {
Douglas Gregor94bb5e82009-12-06 21:27:58 +0000419 return !(X == Y);
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000420 }
421};
422
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000423ResultBuilder::ShadowMapEntry::iterator
424ResultBuilder::ShadowMapEntry::begin() const {
425 if (DeclOrVector.isNull())
426 return iterator();
427
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000428 if (const NamedDecl *ND = DeclOrVector.dyn_cast<const NamedDecl *>())
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000429 return iterator(ND, SingleDeclIndex);
430
431 return iterator(DeclOrVector.get<DeclIndexPairVector *>()->begin());
432}
433
434ResultBuilder::ShadowMapEntry::iterator
435ResultBuilder::ShadowMapEntry::end() const {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000436 if (DeclOrVector.is<const NamedDecl *>() || DeclOrVector.isNull())
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000437 return iterator();
438
439 return iterator(DeclOrVector.get<DeclIndexPairVector *>()->end());
440}
441
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000442/// Compute the qualification required to get from the current context
Douglas Gregor2af2f672009-09-21 20:12:40 +0000443/// (\p CurContext) to the target context (\p TargetContext).
444///
445/// \param Context the AST context in which the qualification will be used.
446///
447/// \param CurContext the context where an entity is being named, which is
448/// typically based on the current scope.
449///
450/// \param TargetContext the context in which the named entity actually
451/// resides.
452///
453/// \returns a nested name specifier that refers into the target context, or
454/// NULL if no qualification is needed.
455static NestedNameSpecifier *
456getRequiredQualification(ASTContext &Context,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000457 const DeclContext *CurContext,
458 const DeclContext *TargetContext) {
459 SmallVector<const DeclContext *, 4> TargetParents;
Douglas Gregor2af2f672009-09-21 20:12:40 +0000460
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000461 for (const DeclContext *CommonAncestor = TargetContext;
Douglas Gregor2af2f672009-09-21 20:12:40 +0000462 CommonAncestor && !CommonAncestor->Encloses(CurContext);
463 CommonAncestor = CommonAncestor->getLookupParent()) {
464 if (CommonAncestor->isTransparentContext() ||
465 CommonAncestor->isFunctionOrMethod())
466 continue;
467
468 TargetParents.push_back(CommonAncestor);
469 }
Craig Topperc3ec1492014-05-26 06:22:03 +0000470
471 NestedNameSpecifier *Result = nullptr;
Douglas Gregor2af2f672009-09-21 20:12:40 +0000472 while (!TargetParents.empty()) {
Robert Wilhelm25284cc2013-08-23 16:11:15 +0000473 const DeclContext *Parent = TargetParents.pop_back_val();
474
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000475 if (const NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Parent)) {
Douglas Gregor68762e72010-08-23 21:17:50 +0000476 if (!Namespace->getIdentifier())
477 continue;
478
Douglas Gregor2af2f672009-09-21 20:12:40 +0000479 Result = NestedNameSpecifier::Create(Context, Result, Namespace);
Douglas Gregor68762e72010-08-23 21:17:50 +0000480 }
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000481 else if (const TagDecl *TD = dyn_cast<TagDecl>(Parent))
Douglas Gregor2af2f672009-09-21 20:12:40 +0000482 Result = NestedNameSpecifier::Create(Context, Result,
483 false,
484 Context.getTypeDeclType(TD).getTypePtr());
Douglas Gregor9eb77012009-11-07 00:00:49 +0000485 }
Douglas Gregor2af2f672009-09-21 20:12:40 +0000486 return Result;
487}
488
Alp Toker034bbd52014-06-30 01:33:53 +0000489/// Determine whether \p Id is a name reserved for the implementation (C99
490/// 7.1.3, C++ [lib.global.names]).
Argyrios Kyrtzidis5d8006d2016-07-01 01:17:02 +0000491static bool isReservedName(const IdentifierInfo *Id,
492 bool doubleUnderscoreOnly = false) {
Alp Toker034bbd52014-06-30 01:33:53 +0000493 if (Id->getLength() < 2)
494 return false;
495 const char *Name = Id->getNameStart();
496 return Name[0] == '_' &&
Argyrios Kyrtzidis5d8006d2016-07-01 01:17:02 +0000497 (Name[1] == '_' || (Name[1] >= 'A' && Name[1] <= 'Z' &&
498 !doubleUnderscoreOnly));
499}
500
501// Some declarations have reserved names that we don't want to ever show.
502// Filter out names reserved for the implementation if they come from a
503// system header.
504static bool shouldIgnoreDueToReservedName(const NamedDecl *ND, Sema &SemaRef) {
505 const IdentifierInfo *Id = ND->getIdentifier();
506 if (!Id)
507 return false;
508
509 // Ignore reserved names for compiler provided decls.
510 if (isReservedName(Id) && ND->getLocation().isInvalid())
511 return true;
512
513 // For system headers ignore only double-underscore names.
514 // This allows for system headers providing private symbols with a single
515 // underscore.
516 if (isReservedName(Id, /*doubleUnderscoreOnly=*/true) &&
517 SemaRef.SourceMgr.isInSystemHeader(
518 SemaRef.SourceMgr.getSpellingLoc(ND->getLocation())))
519 return true;
520
521 return false;
Alp Toker034bbd52014-06-30 01:33:53 +0000522}
523
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000524bool ResultBuilder::isInterestingDecl(const NamedDecl *ND,
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000525 bool &AsNestedNameSpecifier) const {
526 AsNestedNameSpecifier = false;
527
Richard Smithf2005d32015-12-29 23:34:32 +0000528 auto *Named = ND;
Douglas Gregor7c208612010-01-14 00:20:49 +0000529 ND = ND->getUnderlyingDecl();
Douglas Gregor58acf322009-10-09 22:16:47 +0000530
531 // Skip unnamed entities.
Douglas Gregor7c208612010-01-14 00:20:49 +0000532 if (!ND->getDeclName())
533 return false;
Douglas Gregor3545ff42009-09-21 16:56:56 +0000534
535 // Friend declarations and declarations introduced due to friends are never
536 // added as results.
Richard Smith6eece292015-01-15 02:27:20 +0000537 if (ND->getFriendObjectKind() == Decl::FOK_Undeclared)
Douglas Gregor7c208612010-01-14 00:20:49 +0000538 return false;
539
Douglas Gregor99fe2ad2009-12-11 17:31:05 +0000540 // Class template (partial) specializations are never added as results.
Douglas Gregor7c208612010-01-14 00:20:49 +0000541 if (isa<ClassTemplateSpecializationDecl>(ND) ||
542 isa<ClassTemplatePartialSpecializationDecl>(ND))
543 return false;
Douglas Gregor3545ff42009-09-21 16:56:56 +0000544
Douglas Gregor99fe2ad2009-12-11 17:31:05 +0000545 // Using declarations themselves are never added as results.
Douglas Gregor7c208612010-01-14 00:20:49 +0000546 if (isa<UsingDecl>(ND))
547 return false;
Argyrios Kyrtzidis5d8006d2016-07-01 01:17:02 +0000548
549 if (shouldIgnoreDueToReservedName(ND, SemaRef))
550 return false;
Douglas Gregor2927c0c2010-11-09 03:59:40 +0000551
Douglas Gregor59cab552010-08-16 23:05:20 +0000552 if (Filter == &ResultBuilder::IsNestedNameSpecifier ||
Richard Smithf2005d32015-12-29 23:34:32 +0000553 (isa<NamespaceDecl>(ND) &&
Douglas Gregor59cab552010-08-16 23:05:20 +0000554 Filter != &ResultBuilder::IsNamespace &&
Douglas Gregor0ac41382010-09-23 23:01:17 +0000555 Filter != &ResultBuilder::IsNamespaceOrAlias &&
Craig Topperc3ec1492014-05-26 06:22:03 +0000556 Filter != nullptr))
Douglas Gregor59cab552010-08-16 23:05:20 +0000557 AsNestedNameSpecifier = true;
558
Douglas Gregor3545ff42009-09-21 16:56:56 +0000559 // Filter out any unwanted results.
Richard Smithf2005d32015-12-29 23:34:32 +0000560 if (Filter && !(this->*Filter)(Named)) {
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000561 // Check whether it is interesting as a nested-name-specifier.
David Blaikiebbafb8a2012-03-11 07:00:24 +0000562 if (AllowNestedNameSpecifiers && SemaRef.getLangOpts().CPlusPlus &&
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000563 IsNestedNameSpecifier(ND) &&
564 (Filter != &ResultBuilder::IsMember ||
565 (isa<CXXRecordDecl>(ND) &&
566 cast<CXXRecordDecl>(ND)->isInjectedClassName()))) {
567 AsNestedNameSpecifier = true;
568 return true;
569 }
570
Douglas Gregor7c208612010-01-14 00:20:49 +0000571 return false;
Douglas Gregor59cab552010-08-16 23:05:20 +0000572 }
Douglas Gregor7c208612010-01-14 00:20:49 +0000573 // ... then it must be interesting!
574 return true;
575}
576
Douglas Gregore0717ab2010-01-14 00:41:07 +0000577bool ResultBuilder::CheckHiddenResult(Result &R, DeclContext *CurContext,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000578 const NamedDecl *Hiding) {
Douglas Gregore0717ab2010-01-14 00:41:07 +0000579 // In C, there is no way to refer to a hidden name.
580 // FIXME: This isn't true; we can find a tag name hidden by an ordinary
581 // name if we introduce the tag type.
David Blaikiebbafb8a2012-03-11 07:00:24 +0000582 if (!SemaRef.getLangOpts().CPlusPlus)
Douglas Gregore0717ab2010-01-14 00:41:07 +0000583 return true;
584
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000585 const DeclContext *HiddenCtx =
586 R.Declaration->getDeclContext()->getRedeclContext();
Douglas Gregore0717ab2010-01-14 00:41:07 +0000587
588 // There is no way to qualify a name declared in a function or method.
589 if (HiddenCtx->isFunctionOrMethod())
590 return true;
591
Sebastian Redl50c68252010-08-31 00:36:30 +0000592 if (HiddenCtx == Hiding->getDeclContext()->getRedeclContext())
Douglas Gregore0717ab2010-01-14 00:41:07 +0000593 return true;
594
595 // We can refer to the result with the appropriate qualification. Do it.
596 R.Hidden = true;
597 R.QualifierIsInformative = false;
598
599 if (!R.Qualifier)
600 R.Qualifier = getRequiredQualification(SemaRef.Context,
601 CurContext,
602 R.Declaration->getDeclContext());
603 return false;
604}
605
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000606/// A simplified classification of types used to determine whether two
Douglas Gregor95887f92010-07-08 23:20:03 +0000607/// types are "similar enough" when adjusting priorities.
Douglas Gregor6e240332010-08-16 16:18:59 +0000608SimplifiedTypeClass clang::getSimplifiedTypeClass(CanQualType T) {
Douglas Gregor95887f92010-07-08 23:20:03 +0000609 switch (T->getTypeClass()) {
610 case Type::Builtin:
611 switch (cast<BuiltinType>(T)->getKind()) {
612 case BuiltinType::Void:
613 return STC_Void;
614
615 case BuiltinType::NullPtr:
616 return STC_Pointer;
617
618 case BuiltinType::Overload:
619 case BuiltinType::Dependent:
Douglas Gregor95887f92010-07-08 23:20:03 +0000620 return STC_Other;
621
622 case BuiltinType::ObjCId:
623 case BuiltinType::ObjCClass:
624 case BuiltinType::ObjCSel:
625 return STC_ObjectiveC;
626
627 default:
628 return STC_Arithmetic;
629 }
David Blaikie8a40f702012-01-17 06:56:22 +0000630
Douglas Gregor95887f92010-07-08 23:20:03 +0000631 case Type::Complex:
632 return STC_Arithmetic;
633
634 case Type::Pointer:
635 return STC_Pointer;
636
637 case Type::BlockPointer:
638 return STC_Block;
639
640 case Type::LValueReference:
641 case Type::RValueReference:
642 return getSimplifiedTypeClass(T->getAs<ReferenceType>()->getPointeeType());
643
644 case Type::ConstantArray:
645 case Type::IncompleteArray:
646 case Type::VariableArray:
647 case Type::DependentSizedArray:
648 return STC_Array;
649
650 case Type::DependentSizedExtVector:
651 case Type::Vector:
652 case Type::ExtVector:
653 return STC_Arithmetic;
654
655 case Type::FunctionProto:
656 case Type::FunctionNoProto:
657 return STC_Function;
658
659 case Type::Record:
660 return STC_Record;
661
662 case Type::Enum:
663 return STC_Arithmetic;
664
665 case Type::ObjCObject:
666 case Type::ObjCInterface:
667 case Type::ObjCObjectPointer:
668 return STC_ObjectiveC;
669
670 default:
671 return STC_Other;
672 }
673}
674
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000675/// Get the type that a given expression will have if this declaration
Douglas Gregor95887f92010-07-08 23:20:03 +0000676/// is used as an expression in its "typical" code-completion form.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000677QualType clang::getDeclUsageType(ASTContext &C, const NamedDecl *ND) {
George Burgess IV00f70bd2018-03-01 05:43:23 +0000678 ND = ND->getUnderlyingDecl();
Douglas Gregor95887f92010-07-08 23:20:03 +0000679
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000680 if (const TypeDecl *Type = dyn_cast<TypeDecl>(ND))
Douglas Gregor95887f92010-07-08 23:20:03 +0000681 return C.getTypeDeclType(Type);
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000682 if (const ObjCInterfaceDecl *Iface = dyn_cast<ObjCInterfaceDecl>(ND))
Douglas Gregor95887f92010-07-08 23:20:03 +0000683 return C.getObjCInterfaceType(Iface);
684
685 QualType T;
Alp Tokera2794f92014-01-22 07:29:52 +0000686 if (const FunctionDecl *Function = ND->getAsFunction())
Douglas Gregor603d81b2010-07-13 08:18:22 +0000687 T = Function->getCallResultType();
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000688 else if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND))
Douglas Gregor603d81b2010-07-13 08:18:22 +0000689 T = Method->getSendResultType();
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000690 else if (const EnumConstantDecl *Enumerator = dyn_cast<EnumConstantDecl>(ND))
Douglas Gregor95887f92010-07-08 23:20:03 +0000691 T = C.getTypeDeclType(cast<EnumDecl>(Enumerator->getDeclContext()));
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000692 else if (const ObjCPropertyDecl *Property = dyn_cast<ObjCPropertyDecl>(ND))
Douglas Gregor95887f92010-07-08 23:20:03 +0000693 T = Property->getType();
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000694 else if (const ValueDecl *Value = dyn_cast<ValueDecl>(ND))
Douglas Gregor95887f92010-07-08 23:20:03 +0000695 T = Value->getType();
696 else
697 return QualType();
Douglas Gregoraf670a82011-04-14 20:33:34 +0000698
699 // Dig through references, function pointers, and block pointers to
700 // get down to the likely type of an expression when the entity is
701 // used.
702 do {
703 if (const ReferenceType *Ref = T->getAs<ReferenceType>()) {
704 T = Ref->getPointeeType();
705 continue;
706 }
707
708 if (const PointerType *Pointer = T->getAs<PointerType>()) {
709 if (Pointer->getPointeeType()->isFunctionType()) {
710 T = Pointer->getPointeeType();
711 continue;
712 }
713
714 break;
715 }
716
717 if (const BlockPointerType *Block = T->getAs<BlockPointerType>()) {
718 T = Block->getPointeeType();
719 continue;
720 }
721
722 if (const FunctionType *Function = T->getAs<FunctionType>()) {
Alp Toker314cc812014-01-25 16:55:45 +0000723 T = Function->getReturnType();
Douglas Gregoraf670a82011-04-14 20:33:34 +0000724 continue;
725 }
726
727 break;
728 } while (true);
729
730 return T;
Douglas Gregor95887f92010-07-08 23:20:03 +0000731}
732
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000733unsigned ResultBuilder::getBasePriority(const NamedDecl *ND) {
734 if (!ND)
735 return CCP_Unlikely;
736
737 // Context-based decisions.
Richard Smith541b38b2013-09-20 01:15:31 +0000738 const DeclContext *LexicalDC = ND->getLexicalDeclContext();
739 if (LexicalDC->isFunctionOrMethod()) {
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000740 // _cmd is relatively rare
741 if (const ImplicitParamDecl *ImplicitParam =
742 dyn_cast<ImplicitParamDecl>(ND))
743 if (ImplicitParam->getIdentifier() &&
744 ImplicitParam->getIdentifier()->isStr("_cmd"))
745 return CCP_ObjC_cmd;
746
747 return CCP_LocalDeclaration;
748 }
Richard Smith541b38b2013-09-20 01:15:31 +0000749
750 const DeclContext *DC = ND->getDeclContext()->getRedeclContext();
Ilya Biryukov4e7a6fe2017-09-22 19:07:37 +0000751 if (DC->isRecord() || isa<ObjCContainerDecl>(DC)) {
752 // Explicit destructor calls are very rare.
753 if (isa<CXXDestructorDecl>(ND))
754 return CCP_Unlikely;
755 // Explicit operator and conversion function calls are also very rare.
756 auto DeclNameKind = ND->getDeclName().getNameKind();
757 if (DeclNameKind == DeclarationName::CXXOperatorName ||
758 DeclNameKind == DeclarationName::CXXLiteralOperatorName ||
759 DeclNameKind == DeclarationName::CXXConversionFunctionName)
760 return CCP_Unlikely;
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000761 return CCP_MemberDeclaration;
Ilya Biryukov4e7a6fe2017-09-22 19:07:37 +0000762 }
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000763
764 // Content-based decisions.
765 if (isa<EnumConstantDecl>(ND))
766 return CCP_Constant;
767
Douglas Gregor52e0de42013-01-31 05:03:46 +0000768 // Use CCP_Type for type declarations unless we're in a statement, Objective-C
769 // message receiver, or parenthesized expression context. There, it's as
770 // likely that the user will want to write a type as other declarations.
771 if ((isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND)) &&
772 !(CompletionContext.getKind() == CodeCompletionContext::CCC_Statement ||
773 CompletionContext.getKind()
774 == CodeCompletionContext::CCC_ObjCMessageReceiver ||
775 CompletionContext.getKind()
776 == CodeCompletionContext::CCC_ParenthesizedExpression))
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000777 return CCP_Type;
778
779 return CCP_Declaration;
780}
781
Douglas Gregor50832e02010-09-20 22:39:41 +0000782void ResultBuilder::AdjustResultPriorityForDecl(Result &R) {
783 // If this is an Objective-C method declaration whose selector matches our
784 // preferred selector, give it a priority boost.
785 if (!PreferredSelector.isNull())
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000786 if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(R.Declaration))
Douglas Gregor50832e02010-09-20 22:39:41 +0000787 if (PreferredSelector == Method->getSelector())
788 R.Priority += CCD_SelectorMatch;
Douglas Gregor5fb901d2010-09-20 23:11:55 +0000789
Douglas Gregor50832e02010-09-20 22:39:41 +0000790 // If we have a preferred type, adjust the priority for results with exactly-
791 // matching or nearly-matching types.
792 if (!PreferredType.isNull()) {
793 QualType T = getDeclUsageType(SemaRef.Context, R.Declaration);
794 if (!T.isNull()) {
795 CanQualType TC = SemaRef.Context.getCanonicalType(T);
796 // Check for exactly-matching types (modulo qualifiers).
797 if (SemaRef.Context.hasSameUnqualifiedType(PreferredType, TC))
798 R.Priority /= CCF_ExactTypeMatch;
799 // Check for nearly-matching types, based on classification of each.
800 else if ((getSimplifiedTypeClass(PreferredType)
Douglas Gregor95887f92010-07-08 23:20:03 +0000801 == getSimplifiedTypeClass(TC)) &&
Douglas Gregor50832e02010-09-20 22:39:41 +0000802 !(PreferredType->isEnumeralType() && TC->isEnumeralType()))
803 R.Priority /= CCF_SimilarTypeMatch;
804 }
805 }
Douglas Gregor95887f92010-07-08 23:20:03 +0000806}
807
Douglas Gregor0212fd72010-09-21 16:06:22 +0000808void ResultBuilder::MaybeAddConstructorResults(Result R) {
David Blaikiebbafb8a2012-03-11 07:00:24 +0000809 if (!SemaRef.getLangOpts().CPlusPlus || !R.Declaration ||
Douglas Gregor0212fd72010-09-21 16:06:22 +0000810 !CompletionContext.wantConstructorResults())
811 return;
812
813 ASTContext &Context = SemaRef.Context;
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000814 const NamedDecl *D = R.Declaration;
Craig Topperc3ec1492014-05-26 06:22:03 +0000815 const CXXRecordDecl *Record = nullptr;
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000816 if (const ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(D))
Douglas Gregor0212fd72010-09-21 16:06:22 +0000817 Record = ClassTemplate->getTemplatedDecl();
818 else if ((Record = dyn_cast<CXXRecordDecl>(D))) {
819 // Skip specializations and partial specializations.
820 if (isa<ClassTemplateSpecializationDecl>(Record))
821 return;
822 } else {
823 // There are no constructors here.
824 return;
825 }
826
827 Record = Record->getDefinition();
828 if (!Record)
829 return;
830
831
832 QualType RecordTy = Context.getTypeDeclType(Record);
833 DeclarationName ConstructorName
834 = Context.DeclarationNames.getCXXConstructorName(
835 Context.getCanonicalType(RecordTy));
Richard Smithcf4bdde2015-02-21 02:45:19 +0000836 DeclContext::lookup_result Ctors = Record->lookup(ConstructorName);
837 for (DeclContext::lookup_iterator I = Ctors.begin(),
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000838 E = Ctors.end();
839 I != E; ++I) {
David Blaikieff7d47a2012-12-19 00:45:41 +0000840 R.Declaration = *I;
Douglas Gregor0212fd72010-09-21 16:06:22 +0000841 R.CursorKind = getCursorKindForDecl(R.Declaration);
842 Results.push_back(R);
843 }
844}
845
Sam McCall63c59722018-01-22 20:44:47 +0000846static bool isConstructor(const Decl *ND) {
847 if (const auto *Tmpl = dyn_cast<FunctionTemplateDecl>(ND))
848 ND = Tmpl->getTemplatedDecl();
849 return isa<CXXConstructorDecl>(ND);
850}
851
Douglas Gregor7c208612010-01-14 00:20:49 +0000852void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) {
853 assert(!ShadowMaps.empty() && "Must enter into a results scope");
854
855 if (R.Kind != Result::RK_Declaration) {
856 // For non-declaration results, just add the result.
857 Results.push_back(R);
858 return;
859 }
860
861 // Look through using declarations.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000862 if (const UsingShadowDecl *Using =
863 dyn_cast<UsingShadowDecl>(R.Declaration)) {
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000864 MaybeAddResult(Result(Using->getTargetDecl(),
865 getBasePriority(Using->getTargetDecl()),
866 R.Qualifier),
867 CurContext);
Douglas Gregor7c208612010-01-14 00:20:49 +0000868 return;
869 }
870
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000871 const Decl *CanonDecl = R.Declaration->getCanonicalDecl();
Douglas Gregor7c208612010-01-14 00:20:49 +0000872 unsigned IDNS = CanonDecl->getIdentifierNamespace();
873
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000874 bool AsNestedNameSpecifier = false;
875 if (!isInterestingDecl(R.Declaration, AsNestedNameSpecifier))
Douglas Gregor7c208612010-01-14 00:20:49 +0000876 return;
877
Douglas Gregor0212fd72010-09-21 16:06:22 +0000878 // C++ constructors are never found by name lookup.
Sam McCall63c59722018-01-22 20:44:47 +0000879 if (isConstructor(R.Declaration))
Douglas Gregor0212fd72010-09-21 16:06:22 +0000880 return;
881
Douglas Gregor3545ff42009-09-21 16:56:56 +0000882 ShadowMap &SMap = ShadowMaps.back();
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000883 ShadowMapEntry::iterator I, IEnd;
884 ShadowMap::iterator NamePos = SMap.find(R.Declaration->getDeclName());
885 if (NamePos != SMap.end()) {
886 I = NamePos->second.begin();
887 IEnd = NamePos->second.end();
888 }
889
890 for (; I != IEnd; ++I) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000891 const NamedDecl *ND = I->first;
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000892 unsigned Index = I->second;
Douglas Gregor3545ff42009-09-21 16:56:56 +0000893 if (ND->getCanonicalDecl() == CanonDecl) {
894 // This is a redeclaration. Always pick the newer declaration.
Douglas Gregor3545ff42009-09-21 16:56:56 +0000895 Results[Index].Declaration = R.Declaration;
896
Douglas Gregor3545ff42009-09-21 16:56:56 +0000897 // We're done.
898 return;
899 }
900 }
901
902 // This is a new declaration in this scope. However, check whether this
903 // declaration name is hidden by a similarly-named declaration in an outer
904 // scope.
905 std::list<ShadowMap>::iterator SM, SMEnd = ShadowMaps.end();
906 --SMEnd;
907 for (SM = ShadowMaps.begin(); SM != SMEnd; ++SM) {
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000908 ShadowMapEntry::iterator I, IEnd;
909 ShadowMap::iterator NamePos = SM->find(R.Declaration->getDeclName());
910 if (NamePos != SM->end()) {
911 I = NamePos->second.begin();
912 IEnd = NamePos->second.end();
913 }
914 for (; I != IEnd; ++I) {
Douglas Gregor3545ff42009-09-21 16:56:56 +0000915 // A tag declaration does not hide a non-tag declaration.
John McCalle87beb22010-04-23 18:46:30 +0000916 if (I->first->hasTagIdentifierNamespace() &&
Richard Smith541b38b2013-09-20 01:15:31 +0000917 (IDNS & (Decl::IDNS_Member | Decl::IDNS_Ordinary |
918 Decl::IDNS_LocalExtern | Decl::IDNS_ObjCProtocol)))
Douglas Gregor3545ff42009-09-21 16:56:56 +0000919 continue;
920
921 // Protocols are in distinct namespaces from everything else.
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000922 if (((I->first->getIdentifierNamespace() & Decl::IDNS_ObjCProtocol)
Douglas Gregor3545ff42009-09-21 16:56:56 +0000923 || (IDNS & Decl::IDNS_ObjCProtocol)) &&
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000924 I->first->getIdentifierNamespace() != IDNS)
Douglas Gregor3545ff42009-09-21 16:56:56 +0000925 continue;
926
927 // The newly-added result is hidden by an entry in the shadow map.
Douglas Gregore0717ab2010-01-14 00:41:07 +0000928 if (CheckHiddenResult(R, CurContext, I->first))
Douglas Gregor3545ff42009-09-21 16:56:56 +0000929 return;
Douglas Gregor3545ff42009-09-21 16:56:56 +0000930
931 break;
932 }
933 }
934
935 // Make sure that any given declaration only shows up in the result set once.
David Blaikie82e95a32014-11-19 07:49:47 +0000936 if (!AllDeclsFound.insert(CanonDecl).second)
Douglas Gregor3545ff42009-09-21 16:56:56 +0000937 return;
Douglas Gregorc2cb2e22010-08-27 15:29:55 +0000938
Douglas Gregore412a5a2009-09-23 22:26:46 +0000939 // If the filter is for nested-name-specifiers, then this result starts a
940 // nested-name-specifier.
Douglas Gregora2db7932010-05-26 22:00:08 +0000941 if (AsNestedNameSpecifier) {
Douglas Gregore412a5a2009-09-23 22:26:46 +0000942 R.StartsNestedNameSpecifier = true;
Douglas Gregora2db7932010-05-26 22:00:08 +0000943 R.Priority = CCP_NestedNameSpecifier;
Douglas Gregor50832e02010-09-20 22:39:41 +0000944 } else
945 AdjustResultPriorityForDecl(R);
Douglas Gregorc2cb2e22010-08-27 15:29:55 +0000946
Douglas Gregor5bf52692009-09-22 23:15:58 +0000947 // If this result is supposed to have an informative qualifier, add one.
Douglas Gregore412a5a2009-09-23 22:26:46 +0000948 if (R.QualifierIsInformative && !R.Qualifier &&
949 !R.StartsNestedNameSpecifier) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000950 const DeclContext *Ctx = R.Declaration->getDeclContext();
951 if (const NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Ctx))
Craig Topperc3ec1492014-05-26 06:22:03 +0000952 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, nullptr,
953 Namespace);
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000954 else if (const TagDecl *Tag = dyn_cast<TagDecl>(Ctx))
Craig Topperc3ec1492014-05-26 06:22:03 +0000955 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, nullptr,
956 false, SemaRef.Context.getTypeDeclType(Tag).getTypePtr());
Douglas Gregor5bf52692009-09-22 23:15:58 +0000957 else
958 R.QualifierIsInformative = false;
959 }
Douglas Gregore412a5a2009-09-23 22:26:46 +0000960
Douglas Gregor3545ff42009-09-21 16:56:56 +0000961 // Insert this result into the set of results and into the current shadow
962 // map.
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000963 SMap[R.Declaration->getDeclName()].Add(R.Declaration, Results.size());
Douglas Gregor3545ff42009-09-21 16:56:56 +0000964 Results.push_back(R);
Douglas Gregor0212fd72010-09-21 16:06:22 +0000965
966 if (!AsNestedNameSpecifier)
967 MaybeAddConstructorResults(R);
Douglas Gregor3545ff42009-09-21 16:56:56 +0000968}
969
Douglas Gregorc580c522010-01-14 01:09:38 +0000970void ResultBuilder::AddResult(Result R, DeclContext *CurContext,
Douglas Gregor09bbc652010-01-14 15:47:35 +0000971 NamedDecl *Hiding, bool InBaseClass = false) {
Douglas Gregor78a21012010-01-14 16:01:26 +0000972 if (R.Kind != Result::RK_Declaration) {
973 // For non-declaration results, just add the result.
974 Results.push_back(R);
975 return;
976 }
977
Douglas Gregorc580c522010-01-14 01:09:38 +0000978 // Look through using declarations.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000979 if (const UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(R.Declaration)) {
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000980 AddResult(Result(Using->getTargetDecl(),
981 getBasePriority(Using->getTargetDecl()),
982 R.Qualifier),
983 CurContext, Hiding);
Douglas Gregorc580c522010-01-14 01:09:38 +0000984 return;
985 }
986
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000987 bool AsNestedNameSpecifier = false;
988 if (!isInterestingDecl(R.Declaration, AsNestedNameSpecifier))
Douglas Gregorc580c522010-01-14 01:09:38 +0000989 return;
990
Douglas Gregor0212fd72010-09-21 16:06:22 +0000991 // C++ constructors are never found by name lookup.
Sam McCall63c59722018-01-22 20:44:47 +0000992 if (isConstructor(R.Declaration))
Douglas Gregor0212fd72010-09-21 16:06:22 +0000993 return;
994
Douglas Gregorc580c522010-01-14 01:09:38 +0000995 if (Hiding && CheckHiddenResult(R, CurContext, Hiding))
996 return;
Nick Lewyckyc3921482012-04-03 21:44:08 +0000997
Douglas Gregorc580c522010-01-14 01:09:38 +0000998 // Make sure that any given declaration only shows up in the result set once.
David Blaikie82e95a32014-11-19 07:49:47 +0000999 if (!AllDeclsFound.insert(R.Declaration->getCanonicalDecl()).second)
Douglas Gregorc580c522010-01-14 01:09:38 +00001000 return;
1001
1002 // If the filter is for nested-name-specifiers, then this result starts a
1003 // nested-name-specifier.
Douglas Gregora2db7932010-05-26 22:00:08 +00001004 if (AsNestedNameSpecifier) {
Douglas Gregorc580c522010-01-14 01:09:38 +00001005 R.StartsNestedNameSpecifier = true;
Douglas Gregora2db7932010-05-26 22:00:08 +00001006 R.Priority = CCP_NestedNameSpecifier;
1007 }
Douglas Gregor09bbc652010-01-14 15:47:35 +00001008 else if (Filter == &ResultBuilder::IsMember && !R.Qualifier && InBaseClass &&
1009 isa<CXXRecordDecl>(R.Declaration->getDeclContext()
Sebastian Redl50c68252010-08-31 00:36:30 +00001010 ->getRedeclContext()))
Douglas Gregor09bbc652010-01-14 15:47:35 +00001011 R.QualifierIsInformative = true;
1012
Douglas Gregorc580c522010-01-14 01:09:38 +00001013 // If this result is supposed to have an informative qualifier, add one.
1014 if (R.QualifierIsInformative && !R.Qualifier &&
1015 !R.StartsNestedNameSpecifier) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001016 const DeclContext *Ctx = R.Declaration->getDeclContext();
1017 if (const NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Ctx))
Craig Topperc3ec1492014-05-26 06:22:03 +00001018 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, nullptr,
1019 Namespace);
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001020 else if (const TagDecl *Tag = dyn_cast<TagDecl>(Ctx))
Craig Topperc3ec1492014-05-26 06:22:03 +00001021 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, nullptr, false,
Douglas Gregor6ae4c522010-01-14 03:21:49 +00001022 SemaRef.Context.getTypeDeclType(Tag).getTypePtr());
Douglas Gregorc580c522010-01-14 01:09:38 +00001023 else
1024 R.QualifierIsInformative = false;
1025 }
1026
Douglas Gregora2db7932010-05-26 22:00:08 +00001027 // Adjust the priority if this result comes from a base class.
1028 if (InBaseClass)
1029 R.Priority += CCD_InBaseClass;
1030
Douglas Gregor50832e02010-09-20 22:39:41 +00001031 AdjustResultPriorityForDecl(R);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00001032
Douglas Gregor9be0ed42010-08-26 16:36:48 +00001033 if (HasObjectTypeQualifiers)
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001034 if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(R.Declaration))
Douglas Gregor9be0ed42010-08-26 16:36:48 +00001035 if (Method->isInstance()) {
1036 Qualifiers MethodQuals
1037 = Qualifiers::fromCVRMask(Method->getTypeQualifiers());
1038 if (ObjectTypeQualifiers == MethodQuals)
1039 R.Priority += CCD_ObjectQualifierMatch;
1040 else if (ObjectTypeQualifiers - MethodQuals) {
1041 // The method cannot be invoked, because doing so would drop
1042 // qualifiers.
1043 return;
1044 }
1045 }
1046
Douglas Gregorc580c522010-01-14 01:09:38 +00001047 // Insert this result into the set of results.
1048 Results.push_back(R);
Douglas Gregor0212fd72010-09-21 16:06:22 +00001049
1050 if (!AsNestedNameSpecifier)
1051 MaybeAddConstructorResults(R);
Douglas Gregorc580c522010-01-14 01:09:38 +00001052}
1053
Douglas Gregor78a21012010-01-14 16:01:26 +00001054void ResultBuilder::AddResult(Result R) {
1055 assert(R.Kind != Result::RK_Declaration &&
1056 "Declaration results need more context");
1057 Results.push_back(R);
1058}
1059
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001060/// Enter into a new scope.
Benjamin Kramer3204b152015-05-29 19:42:19 +00001061void ResultBuilder::EnterNewScope() { ShadowMaps.emplace_back(); }
Douglas Gregor3545ff42009-09-21 16:56:56 +00001062
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001063/// Exit from the current scope.
Douglas Gregor3545ff42009-09-21 16:56:56 +00001064void ResultBuilder::ExitScope() {
Douglas Gregor05e7ca32009-12-06 20:23:50 +00001065 for (ShadowMap::iterator E = ShadowMaps.back().begin(),
1066 EEnd = ShadowMaps.back().end();
1067 E != EEnd;
1068 ++E)
1069 E->second.Destroy();
1070
Douglas Gregor3545ff42009-09-21 16:56:56 +00001071 ShadowMaps.pop_back();
1072}
1073
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001074/// Determines whether this given declaration will be found by
Douglas Gregor9d64c5e2009-09-21 20:51:25 +00001075/// ordinary name lookup.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001076bool ResultBuilder::IsOrdinaryName(const NamedDecl *ND) const {
George Burgess IV00f70bd2018-03-01 05:43:23 +00001077 ND = ND->getUnderlyingDecl();
Douglas Gregor70febae2010-05-28 00:49:12 +00001078
Richard Smith541b38b2013-09-20 01:15:31 +00001079 // If name lookup finds a local extern declaration, then we are in a
1080 // context where it behaves like an ordinary name.
1081 unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_LocalExtern;
David Blaikiebbafb8a2012-03-11 07:00:24 +00001082 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregor9858ed52010-06-15 20:26:51 +00001083 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member;
David Blaikiebbafb8a2012-03-11 07:00:24 +00001084 else if (SemaRef.getLangOpts().ObjC1) {
Douglas Gregor05fcf842010-11-02 20:36:02 +00001085 if (isa<ObjCIvarDecl>(ND))
1086 return true;
Douglas Gregor05fcf842010-11-02 20:36:02 +00001087 }
1088
Douglas Gregor9d64c5e2009-09-21 20:51:25 +00001089 return ND->getIdentifierNamespace() & IDNS;
1090}
1091
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001092/// Determines whether this given declaration will be found by
Douglas Gregor70febae2010-05-28 00:49:12 +00001093/// ordinary name lookup but is not a type name.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001094bool ResultBuilder::IsOrdinaryNonTypeName(const NamedDecl *ND) const {
George Burgess IV00f70bd2018-03-01 05:43:23 +00001095 ND = ND->getUnderlyingDecl();
Alex Lorenzf3df1f72017-11-14 01:46:24 +00001096 if (isa<TypeDecl>(ND))
Douglas Gregor70febae2010-05-28 00:49:12 +00001097 return false;
Alex Lorenzf3df1f72017-11-14 01:46:24 +00001098 // Objective-C interfaces names are not filtered by this method because they
1099 // can be used in a class property expression. We can still filter out
1100 // @class declarations though.
1101 if (const auto *ID = dyn_cast<ObjCInterfaceDecl>(ND)) {
1102 if (!ID->getDefinition())
1103 return false;
1104 }
1105
Richard Smith541b38b2013-09-20 01:15:31 +00001106 unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_LocalExtern;
David Blaikiebbafb8a2012-03-11 07:00:24 +00001107 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregor9858ed52010-06-15 20:26:51 +00001108 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member;
David Blaikiebbafb8a2012-03-11 07:00:24 +00001109 else if (SemaRef.getLangOpts().ObjC1) {
Douglas Gregor05fcf842010-11-02 20:36:02 +00001110 if (isa<ObjCIvarDecl>(ND))
1111 return true;
Douglas Gregor05fcf842010-11-02 20:36:02 +00001112 }
1113
Douglas Gregor70febae2010-05-28 00:49:12 +00001114 return ND->getIdentifierNamespace() & IDNS;
1115}
1116
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001117bool ResultBuilder::IsIntegralConstantValue(const NamedDecl *ND) const {
Douglas Gregor85b50632010-07-28 21:50:18 +00001118 if (!IsOrdinaryNonTypeName(ND))
1119 return 0;
1120
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001121 if (const ValueDecl *VD = dyn_cast<ValueDecl>(ND->getUnderlyingDecl()))
Douglas Gregor85b50632010-07-28 21:50:18 +00001122 if (VD->getType()->isIntegralOrEnumerationType())
1123 return true;
1124
1125 return false;
1126}
1127
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001128/// Determines whether this given declaration will be found by
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001129/// ordinary name lookup.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001130bool ResultBuilder::IsOrdinaryNonValueName(const NamedDecl *ND) const {
George Burgess IV00f70bd2018-03-01 05:43:23 +00001131 ND = ND->getUnderlyingDecl();
Douglas Gregor70febae2010-05-28 00:49:12 +00001132
Richard Smith541b38b2013-09-20 01:15:31 +00001133 unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_LocalExtern;
David Blaikiebbafb8a2012-03-11 07:00:24 +00001134 if (SemaRef.getLangOpts().CPlusPlus)
John McCalle87beb22010-04-23 18:46:30 +00001135 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001136
1137 return (ND->getIdentifierNamespace() & IDNS) &&
Douglas Gregor70febae2010-05-28 00:49:12 +00001138 !isa<ValueDecl>(ND) && !isa<FunctionTemplateDecl>(ND) &&
1139 !isa<ObjCPropertyDecl>(ND);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001140}
1141
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001142/// Determines whether the given declaration is suitable as the
Douglas Gregor3545ff42009-09-21 16:56:56 +00001143/// start of a C++ nested-name-specifier, e.g., a class or namespace.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001144bool ResultBuilder::IsNestedNameSpecifier(const NamedDecl *ND) const {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001145 // Allow us to find class templates, too.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001146 if (const ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
Douglas Gregor3545ff42009-09-21 16:56:56 +00001147 ND = ClassTemplate->getTemplatedDecl();
1148
1149 return SemaRef.isAcceptableNestedNameSpecifier(ND);
1150}
1151
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001152/// Determines whether the given declaration is an enumeration.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001153bool ResultBuilder::IsEnum(const NamedDecl *ND) const {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001154 return isa<EnumDecl>(ND);
1155}
1156
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001157/// Determines whether the given declaration is a class or struct.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001158bool ResultBuilder::IsClassOrStruct(const NamedDecl *ND) const {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001159 // Allow us to find class templates, too.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001160 if (const ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
Douglas Gregor3545ff42009-09-21 16:56:56 +00001161 ND = ClassTemplate->getTemplatedDecl();
Joao Matosdc86f942012-08-31 18:45:21 +00001162
1163 // For purposes of this check, interfaces match too.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001164 if (const RecordDecl *RD = dyn_cast<RecordDecl>(ND))
Abramo Bagnara6150c882010-05-11 21:36:43 +00001165 return RD->getTagKind() == TTK_Class ||
Joao Matosdc86f942012-08-31 18:45:21 +00001166 RD->getTagKind() == TTK_Struct ||
1167 RD->getTagKind() == TTK_Interface;
Douglas Gregor3545ff42009-09-21 16:56:56 +00001168
1169 return false;
1170}
1171
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001172/// Determines whether the given declaration is a union.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001173bool ResultBuilder::IsUnion(const NamedDecl *ND) const {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001174 // Allow us to find class templates, too.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001175 if (const ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
Douglas Gregor3545ff42009-09-21 16:56:56 +00001176 ND = ClassTemplate->getTemplatedDecl();
1177
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001178 if (const RecordDecl *RD = dyn_cast<RecordDecl>(ND))
Abramo Bagnara6150c882010-05-11 21:36:43 +00001179 return RD->getTagKind() == TTK_Union;
Douglas Gregor3545ff42009-09-21 16:56:56 +00001180
1181 return false;
1182}
1183
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001184/// Determines whether the given declaration is a namespace.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001185bool ResultBuilder::IsNamespace(const NamedDecl *ND) const {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001186 return isa<NamespaceDecl>(ND);
1187}
1188
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001189/// Determines whether the given declaration is a namespace or
Douglas Gregor3545ff42009-09-21 16:56:56 +00001190/// namespace alias.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001191bool ResultBuilder::IsNamespaceOrAlias(const NamedDecl *ND) const {
Richard Smithf2005d32015-12-29 23:34:32 +00001192 return isa<NamespaceDecl>(ND->getUnderlyingDecl());
Douglas Gregor3545ff42009-09-21 16:56:56 +00001193}
1194
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001195/// Determines whether the given declaration is a type.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001196bool ResultBuilder::IsType(const NamedDecl *ND) const {
Richard Smithf2005d32015-12-29 23:34:32 +00001197 ND = ND->getUnderlyingDecl();
Douglas Gregor99fa2642010-08-24 01:06:58 +00001198 return isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND);
Douglas Gregor3545ff42009-09-21 16:56:56 +00001199}
1200
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001201/// Determines which members of a class should be visible via
Douglas Gregor99fe2ad2009-12-11 17:31:05 +00001202/// "." or "->". Only value declarations, nested name specifiers, and
1203/// using declarations thereof should show up.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001204bool ResultBuilder::IsMember(const NamedDecl *ND) const {
Richard Smithf2005d32015-12-29 23:34:32 +00001205 ND = ND->getUnderlyingDecl();
Douglas Gregor70788392009-12-11 18:14:22 +00001206 return isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND) ||
Richard Smithf2005d32015-12-29 23:34:32 +00001207 isa<ObjCPropertyDecl>(ND);
Douglas Gregore412a5a2009-09-23 22:26:46 +00001208}
1209
Douglas Gregora817a192010-05-27 23:06:34 +00001210static bool isObjCReceiverType(ASTContext &C, QualType T) {
1211 T = C.getCanonicalType(T);
1212 switch (T->getTypeClass()) {
1213 case Type::ObjCObject:
1214 case Type::ObjCInterface:
1215 case Type::ObjCObjectPointer:
1216 return true;
1217
1218 case Type::Builtin:
1219 switch (cast<BuiltinType>(T)->getKind()) {
1220 case BuiltinType::ObjCId:
1221 case BuiltinType::ObjCClass:
1222 case BuiltinType::ObjCSel:
1223 return true;
1224
1225 default:
1226 break;
1227 }
1228 return false;
1229
1230 default:
1231 break;
1232 }
1233
David Blaikiebbafb8a2012-03-11 07:00:24 +00001234 if (!C.getLangOpts().CPlusPlus)
Douglas Gregora817a192010-05-27 23:06:34 +00001235 return false;
1236
1237 // FIXME: We could perform more analysis here to determine whether a
1238 // particular class type has any conversions to Objective-C types. For now,
1239 // just accept all class types.
1240 return T->isDependentType() || T->isRecordType();
1241}
1242
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001243bool ResultBuilder::IsObjCMessageReceiver(const NamedDecl *ND) const {
Douglas Gregora817a192010-05-27 23:06:34 +00001244 QualType T = getDeclUsageType(SemaRef.Context, ND);
1245 if (T.isNull())
1246 return false;
1247
1248 T = SemaRef.Context.getBaseElementType(T);
1249 return isObjCReceiverType(SemaRef.Context, T);
1250}
1251
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001252bool ResultBuilder::IsObjCMessageReceiverOrLambdaCapture(const NamedDecl *ND) const {
Douglas Gregord8c61782012-02-15 15:34:24 +00001253 if (IsObjCMessageReceiver(ND))
1254 return true;
1255
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001256 const VarDecl *Var = dyn_cast<VarDecl>(ND);
Douglas Gregord8c61782012-02-15 15:34:24 +00001257 if (!Var)
1258 return false;
1259
1260 return Var->hasLocalStorage() && !Var->hasAttr<BlocksAttr>();
1261}
1262
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001263bool ResultBuilder::IsObjCCollection(const NamedDecl *ND) const {
David Blaikiebbafb8a2012-03-11 07:00:24 +00001264 if ((SemaRef.getLangOpts().CPlusPlus && !IsOrdinaryName(ND)) ||
1265 (!SemaRef.getLangOpts().CPlusPlus && !IsOrdinaryNonTypeName(ND)))
Douglas Gregor68762e72010-08-23 21:17:50 +00001266 return false;
1267
1268 QualType T = getDeclUsageType(SemaRef.Context, ND);
1269 if (T.isNull())
1270 return false;
1271
1272 T = SemaRef.Context.getBaseElementType(T);
1273 return T->isObjCObjectType() || T->isObjCObjectPointerType() ||
1274 T->isObjCIdType() ||
David Blaikiebbafb8a2012-03-11 07:00:24 +00001275 (SemaRef.getLangOpts().CPlusPlus && T->isRecordType());
Douglas Gregor68762e72010-08-23 21:17:50 +00001276}
Douglas Gregora817a192010-05-27 23:06:34 +00001277
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001278bool ResultBuilder::IsImpossibleToSatisfy(const NamedDecl *ND) const {
Douglas Gregor0ac41382010-09-23 23:01:17 +00001279 return false;
1280}
1281
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001282/// Determines whether the given declaration is an Objective-C
Douglas Gregor2b8162b2010-01-14 16:08:12 +00001283/// instance variable.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001284bool ResultBuilder::IsObjCIvar(const NamedDecl *ND) const {
Douglas Gregor2b8162b2010-01-14 16:08:12 +00001285 return isa<ObjCIvarDecl>(ND);
1286}
1287
Douglas Gregorc580c522010-01-14 01:09:38 +00001288namespace {
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001289 /// Visible declaration consumer that adds a code-completion result
Douglas Gregorc580c522010-01-14 01:09:38 +00001290 /// for each visible declaration.
1291 class CodeCompletionDeclConsumer : public VisibleDeclConsumer {
1292 ResultBuilder &Results;
1293 DeclContext *CurContext;
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00001294 std::vector<FixItHint> FixIts;
Haojian Wu10d95c52018-01-17 14:29:25 +00001295
Douglas Gregorc580c522010-01-14 01:09:38 +00001296 public:
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00001297 CodeCompletionDeclConsumer(
1298 ResultBuilder &Results, DeclContext *CurContext,
1299 std::vector<FixItHint> FixIts = std::vector<FixItHint>())
1300 : Results(Results), CurContext(CurContext), FixIts(std::move(FixIts)) {}
Craig Toppere14c0f82014-03-12 04:55:44 +00001301
1302 void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx,
1303 bool InBaseClass) override {
Erik Verbruggen2e657ff2011-10-06 07:27:49 +00001304 bool Accessible = true;
Douglas Gregor03ba1882011-11-03 16:51:37 +00001305 if (Ctx)
1306 Accessible = Results.getSema().IsSimplyAccessible(ND, Ctx);
Craig Topperc3ec1492014-05-26 06:22:03 +00001307
1308 ResultBuilder::Result Result(ND, Results.getBasePriority(ND), nullptr,
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00001309 false, Accessible, FixIts);
Erik Verbruggen2e657ff2011-10-06 07:27:49 +00001310 Results.AddResult(Result, CurContext, Hiding, InBaseClass);
Douglas Gregorc580c522010-01-14 01:09:38 +00001311 }
Haojian Wu10d95c52018-01-17 14:29:25 +00001312
1313 void EnteredContext(DeclContext* Ctx) override {
1314 Results.addVisitedContext(Ctx);
1315 }
Douglas Gregorc580c522010-01-14 01:09:38 +00001316 };
Alexander Kornienkoab9db512015-06-22 23:07:51 +00001317}
Douglas Gregorc580c522010-01-14 01:09:38 +00001318
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001319/// Add type specifiers for the current language as keyword results.
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001320static void AddTypeSpecifierResults(const LangOptions &LangOpts,
Douglas Gregor3545ff42009-09-21 16:56:56 +00001321 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00001322 typedef CodeCompletionResult Result;
Douglas Gregora2db7932010-05-26 22:00:08 +00001323 Results.AddResult(Result("short", CCP_Type));
1324 Results.AddResult(Result("long", CCP_Type));
1325 Results.AddResult(Result("signed", CCP_Type));
1326 Results.AddResult(Result("unsigned", CCP_Type));
1327 Results.AddResult(Result("void", CCP_Type));
1328 Results.AddResult(Result("char", CCP_Type));
1329 Results.AddResult(Result("int", CCP_Type));
1330 Results.AddResult(Result("float", CCP_Type));
1331 Results.AddResult(Result("double", CCP_Type));
1332 Results.AddResult(Result("enum", CCP_Type));
1333 Results.AddResult(Result("struct", CCP_Type));
1334 Results.AddResult(Result("union", CCP_Type));
1335 Results.AddResult(Result("const", CCP_Type));
1336 Results.AddResult(Result("volatile", CCP_Type));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001337
Douglas Gregor3545ff42009-09-21 16:56:56 +00001338 if (LangOpts.C99) {
1339 // C99-specific
Douglas Gregora2db7932010-05-26 22:00:08 +00001340 Results.AddResult(Result("_Complex", CCP_Type));
1341 Results.AddResult(Result("_Imaginary", CCP_Type));
1342 Results.AddResult(Result("_Bool", CCP_Type));
1343 Results.AddResult(Result("restrict", CCP_Type));
Douglas Gregor3545ff42009-09-21 16:56:56 +00001344 }
1345
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00001346 CodeCompletionBuilder Builder(Results.getAllocator(),
1347 Results.getCodeCompletionTUInfo());
Douglas Gregor3545ff42009-09-21 16:56:56 +00001348 if (LangOpts.CPlusPlus) {
1349 // C++-specific
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00001350 Results.AddResult(Result("bool", CCP_Type +
1351 (LangOpts.ObjC1? CCD_bool_in_ObjC : 0)));
Douglas Gregora2db7932010-05-26 22:00:08 +00001352 Results.AddResult(Result("class", CCP_Type));
1353 Results.AddResult(Result("wchar_t", CCP_Type));
Douglas Gregor3545ff42009-09-21 16:56:56 +00001354
Douglas Gregorf4c33342010-05-28 00:22:41 +00001355 // typename qualified-id
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001356 Builder.AddTypedTextChunk("typename");
1357 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1358 Builder.AddPlaceholderChunk("qualifier");
1359 Builder.AddTextChunk("::");
1360 Builder.AddPlaceholderChunk("name");
1361 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf64acca2010-05-25 21:41:55 +00001362
Richard Smith2bf7fdb2013-01-02 11:42:31 +00001363 if (LangOpts.CPlusPlus11) {
Douglas Gregora2db7932010-05-26 22:00:08 +00001364 Results.AddResult(Result("auto", CCP_Type));
1365 Results.AddResult(Result("char16_t", CCP_Type));
1366 Results.AddResult(Result("char32_t", CCP_Type));
Douglas Gregorf4c33342010-05-28 00:22:41 +00001367
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001368 Builder.AddTypedTextChunk("decltype");
1369 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1370 Builder.AddPlaceholderChunk("expression");
1371 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1372 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor3545ff42009-09-21 16:56:56 +00001373 }
Alex Lorenz46eed9d2017-02-13 23:35:59 +00001374 } else
1375 Results.AddResult(Result("__auto_type", CCP_Type));
1376
Richard Smith7b301e22018-05-24 21:51:52 +00001377 // GNU keywords
1378 if (LangOpts.GNUKeywords) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001379 // FIXME: Enable when we actually support decimal floating point.
Douglas Gregor78a21012010-01-14 16:01:26 +00001380 // Results.AddResult(Result("_Decimal32"));
1381 // Results.AddResult(Result("_Decimal64"));
1382 // Results.AddResult(Result("_Decimal128"));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001383
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001384 Builder.AddTypedTextChunk("typeof");
1385 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1386 Builder.AddPlaceholderChunk("expression");
1387 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00001388
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001389 Builder.AddTypedTextChunk("typeof");
1390 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1391 Builder.AddPlaceholderChunk("type");
1392 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1393 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor3545ff42009-09-21 16:56:56 +00001394 }
Douglas Gregor86b42682015-06-19 18:27:52 +00001395
1396 // Nullability
Douglas Gregoraea7afd2015-06-24 22:02:08 +00001397 Results.AddResult(Result("_Nonnull", CCP_Type));
1398 Results.AddResult(Result("_Null_unspecified", CCP_Type));
1399 Results.AddResult(Result("_Nullable", CCP_Type));
Douglas Gregor3545ff42009-09-21 16:56:56 +00001400}
1401
John McCallfaf5fb42010-08-26 23:41:50 +00001402static void AddStorageSpecifiers(Sema::ParserCompletionContext CCC,
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001403 const LangOptions &LangOpts,
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001404 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00001405 typedef CodeCompletionResult Result;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001406 // Note: we don't suggest either "auto" or "register", because both
1407 // are pointless as storage specifiers. Elsewhere, we suggest "auto"
1408 // in C++0x as a type specifier.
Douglas Gregor78a21012010-01-14 16:01:26 +00001409 Results.AddResult(Result("extern"));
1410 Results.AddResult(Result("static"));
Alex Lorenz8f4d3992017-02-13 23:19:40 +00001411
1412 if (LangOpts.CPlusPlus11) {
1413 CodeCompletionAllocator &Allocator = Results.getAllocator();
1414 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
1415
1416 // alignas
1417 Builder.AddTypedTextChunk("alignas");
1418 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1419 Builder.AddPlaceholderChunk("expression");
1420 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1421 Results.AddResult(Result(Builder.TakeString()));
1422
1423 Results.AddResult(Result("constexpr"));
1424 Results.AddResult(Result("thread_local"));
1425 }
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001426}
1427
John McCallfaf5fb42010-08-26 23:41:50 +00001428static void AddFunctionSpecifiers(Sema::ParserCompletionContext CCC,
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001429 const LangOptions &LangOpts,
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001430 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00001431 typedef CodeCompletionResult Result;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001432 switch (CCC) {
John McCallfaf5fb42010-08-26 23:41:50 +00001433 case Sema::PCC_Class:
1434 case Sema::PCC_MemberTemplate:
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001435 if (LangOpts.CPlusPlus) {
Douglas Gregor78a21012010-01-14 16:01:26 +00001436 Results.AddResult(Result("explicit"));
1437 Results.AddResult(Result("friend"));
1438 Results.AddResult(Result("mutable"));
1439 Results.AddResult(Result("virtual"));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001440 }
Adrian Prantlf3b3ccd2017-12-19 22:06:11 +00001441 LLVM_FALLTHROUGH;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001442
John McCallfaf5fb42010-08-26 23:41:50 +00001443 case Sema::PCC_ObjCInterface:
1444 case Sema::PCC_ObjCImplementation:
1445 case Sema::PCC_Namespace:
1446 case Sema::PCC_Template:
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001447 if (LangOpts.CPlusPlus || LangOpts.C99)
Douglas Gregor78a21012010-01-14 16:01:26 +00001448 Results.AddResult(Result("inline"));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001449 break;
1450
John McCallfaf5fb42010-08-26 23:41:50 +00001451 case Sema::PCC_ObjCInstanceVariableList:
1452 case Sema::PCC_Expression:
1453 case Sema::PCC_Statement:
1454 case Sema::PCC_ForInit:
1455 case Sema::PCC_Condition:
1456 case Sema::PCC_RecoveryInFunction:
1457 case Sema::PCC_Type:
Douglas Gregor5e35d592010-09-14 23:59:36 +00001458 case Sema::PCC_ParenthesizedExpression:
Douglas Gregor80039242011-02-15 20:33:25 +00001459 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001460 break;
1461 }
1462}
1463
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001464static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt);
1465static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt);
1466static void AddObjCVisibilityResults(const LangOptions &LangOpts,
Douglas Gregor48d46252010-01-13 21:54:15 +00001467 ResultBuilder &Results,
1468 bool NeedAt);
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001469static void AddObjCImplementationResults(const LangOptions &LangOpts,
Douglas Gregorf1934162010-01-13 21:24:21 +00001470 ResultBuilder &Results,
1471 bool NeedAt);
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001472static void AddObjCInterfaceResults(const LangOptions &LangOpts,
Douglas Gregorf1934162010-01-13 21:24:21 +00001473 ResultBuilder &Results,
1474 bool NeedAt);
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001475static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt);
Douglas Gregorf1934162010-01-13 21:24:21 +00001476
Douglas Gregorf4c33342010-05-28 00:22:41 +00001477static void AddTypedefResult(ResultBuilder &Results) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00001478 CodeCompletionBuilder Builder(Results.getAllocator(),
1479 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001480 Builder.AddTypedTextChunk("typedef");
1481 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1482 Builder.AddPlaceholderChunk("type");
1483 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1484 Builder.AddPlaceholderChunk("name");
1485 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00001486}
1487
John McCallfaf5fb42010-08-26 23:41:50 +00001488static bool WantTypesInContext(Sema::ParserCompletionContext CCC,
Douglas Gregor70febae2010-05-28 00:49:12 +00001489 const LangOptions &LangOpts) {
Douglas Gregor70febae2010-05-28 00:49:12 +00001490 switch (CCC) {
John McCallfaf5fb42010-08-26 23:41:50 +00001491 case Sema::PCC_Namespace:
1492 case Sema::PCC_Class:
1493 case Sema::PCC_ObjCInstanceVariableList:
1494 case Sema::PCC_Template:
1495 case Sema::PCC_MemberTemplate:
1496 case Sema::PCC_Statement:
1497 case Sema::PCC_RecoveryInFunction:
1498 case Sema::PCC_Type:
Douglas Gregor5e35d592010-09-14 23:59:36 +00001499 case Sema::PCC_ParenthesizedExpression:
Douglas Gregor80039242011-02-15 20:33:25 +00001500 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregor70febae2010-05-28 00:49:12 +00001501 return true;
1502
John McCallfaf5fb42010-08-26 23:41:50 +00001503 case Sema::PCC_Expression:
1504 case Sema::PCC_Condition:
Douglas Gregor5e35d592010-09-14 23:59:36 +00001505 return LangOpts.CPlusPlus;
1506
1507 case Sema::PCC_ObjCInterface:
1508 case Sema::PCC_ObjCImplementation:
Douglas Gregor70febae2010-05-28 00:49:12 +00001509 return false;
1510
John McCallfaf5fb42010-08-26 23:41:50 +00001511 case Sema::PCC_ForInit:
Douglas Gregor5e35d592010-09-14 23:59:36 +00001512 return LangOpts.CPlusPlus || LangOpts.ObjC1 || LangOpts.C99;
Douglas Gregor70febae2010-05-28 00:49:12 +00001513 }
David Blaikie8a40f702012-01-17 06:56:22 +00001514
1515 llvm_unreachable("Invalid ParserCompletionContext!");
Douglas Gregor70febae2010-05-28 00:49:12 +00001516}
1517
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00001518static PrintingPolicy getCompletionPrintingPolicy(const ASTContext &Context,
1519 const Preprocessor &PP) {
1520 PrintingPolicy Policy = Sema::getPrintingPolicy(Context, PP);
Douglas Gregore5c79d52011-10-18 21:20:17 +00001521 Policy.AnonymousTagLocations = false;
1522 Policy.SuppressStrongLifetime = true;
Douglas Gregor2e10cf92011-11-03 00:16:13 +00001523 Policy.SuppressUnwrittenScope = true;
Ilya Biryukovb5da91c2017-11-08 10:39:09 +00001524 Policy.SuppressScope = true;
Douglas Gregore5c79d52011-10-18 21:20:17 +00001525 return Policy;
1526}
1527
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001528/// Retrieve a printing policy suitable for code completion.
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00001529static PrintingPolicy getCompletionPrintingPolicy(Sema &S) {
1530 return getCompletionPrintingPolicy(S.Context, S.PP);
1531}
1532
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001533/// Retrieve the string representation of the given type as a string
Douglas Gregore5c79d52011-10-18 21:20:17 +00001534/// that has the appropriate lifetime for code completion.
1535///
1536/// This routine provides a fast path where we provide constant strings for
1537/// common type names.
1538static const char *GetCompletionTypeString(QualType T,
1539 ASTContext &Context,
1540 const PrintingPolicy &Policy,
1541 CodeCompletionAllocator &Allocator) {
1542 if (!T.getLocalQualifiers()) {
1543 // Built-in type names are constant strings.
1544 if (const BuiltinType *BT = dyn_cast<BuiltinType>(T))
Argyrios Kyrtzidisbbff3da2012-05-05 04:20:28 +00001545 return BT->getNameAsCString(Policy);
Douglas Gregore5c79d52011-10-18 21:20:17 +00001546
1547 // Anonymous tag types are constant strings.
1548 if (const TagType *TagT = dyn_cast<TagType>(T))
1549 if (TagDecl *Tag = TagT->getDecl())
John McCall5ea95772013-03-09 00:54:27 +00001550 if (!Tag->hasNameForLinkage()) {
Douglas Gregore5c79d52011-10-18 21:20:17 +00001551 switch (Tag->getTagKind()) {
1552 case TTK_Struct: return "struct <anonymous>";
Joao Matosdc86f942012-08-31 18:45:21 +00001553 case TTK_Interface: return "__interface <anonymous>";
1554 case TTK_Class: return "class <anonymous>";
Douglas Gregore5c79d52011-10-18 21:20:17 +00001555 case TTK_Union: return "union <anonymous>";
1556 case TTK_Enum: return "enum <anonymous>";
1557 }
1558 }
1559 }
1560
1561 // Slow path: format the type as a string.
1562 std::string Result;
1563 T.getAsStringInternal(Result, Policy);
1564 return Allocator.CopyString(Result);
1565}
1566
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001567/// Add a completion for "this", if we're in a member function.
Douglas Gregord8c61782012-02-15 15:34:24 +00001568static void addThisCompletion(Sema &S, ResultBuilder &Results) {
1569 QualType ThisTy = S.getCurrentThisType();
1570 if (ThisTy.isNull())
1571 return;
1572
1573 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00001574 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Douglas Gregord8c61782012-02-15 15:34:24 +00001575 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
1576 Builder.AddResultTypeChunk(GetCompletionTypeString(ThisTy,
1577 S.Context,
1578 Policy,
1579 Allocator));
1580 Builder.AddTypedTextChunk("this");
Joao Matosdc86f942012-08-31 18:45:21 +00001581 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
Douglas Gregord8c61782012-02-15 15:34:24 +00001582}
1583
Alex Lorenz8f4d3992017-02-13 23:19:40 +00001584static void AddStaticAssertResult(CodeCompletionBuilder &Builder,
1585 ResultBuilder &Results,
1586 const LangOptions &LangOpts) {
1587 if (!LangOpts.CPlusPlus11)
1588 return;
1589
1590 Builder.AddTypedTextChunk("static_assert");
1591 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1592 Builder.AddPlaceholderChunk("expression");
1593 Builder.AddChunk(CodeCompletionString::CK_Comma);
1594 Builder.AddPlaceholderChunk("message");
1595 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1596 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
1597}
1598
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001599/// Add language constructs that show up for "ordinary" names.
John McCallfaf5fb42010-08-26 23:41:50 +00001600static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001601 Scope *S,
1602 Sema &SemaRef,
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001603 ResultBuilder &Results) {
Douglas Gregore5c79d52011-10-18 21:20:17 +00001604 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00001605 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001606
John McCall276321a2010-08-25 06:19:51 +00001607 typedef CodeCompletionResult Result;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001608 switch (CCC) {
John McCallfaf5fb42010-08-26 23:41:50 +00001609 case Sema::PCC_Namespace:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001610 if (SemaRef.getLangOpts().CPlusPlus) {
Douglas Gregorf4c33342010-05-28 00:22:41 +00001611 if (Results.includeCodePatterns()) {
1612 // namespace <identifier> { declarations }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001613 Builder.AddTypedTextChunk("namespace");
1614 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1615 Builder.AddPlaceholderChunk("identifier");
1616 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1617 Builder.AddPlaceholderChunk("declarations");
1618 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1619 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1620 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00001621 }
1622
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001623 // namespace identifier = identifier ;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001624 Builder.AddTypedTextChunk("namespace");
1625 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1626 Builder.AddPlaceholderChunk("name");
1627 Builder.AddChunk(CodeCompletionString::CK_Equal);
1628 Builder.AddPlaceholderChunk("namespace");
1629 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001630
1631 // Using directives
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001632 Builder.AddTypedTextChunk("using");
1633 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1634 Builder.AddTextChunk("namespace");
1635 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1636 Builder.AddPlaceholderChunk("identifier");
1637 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001638
1639 // asm(string-literal)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001640 Builder.AddTypedTextChunk("asm");
1641 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1642 Builder.AddPlaceholderChunk("string-literal");
1643 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1644 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001645
Douglas Gregorf4c33342010-05-28 00:22:41 +00001646 if (Results.includeCodePatterns()) {
1647 // Explicit template instantiation
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001648 Builder.AddTypedTextChunk("template");
1649 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1650 Builder.AddPlaceholderChunk("declaration");
1651 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00001652 }
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001653 }
Douglas Gregorf1934162010-01-13 21:24:21 +00001654
David Blaikiebbafb8a2012-03-11 07:00:24 +00001655 if (SemaRef.getLangOpts().ObjC1)
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001656 AddObjCTopLevelResults(Results, true);
Douglas Gregorf1934162010-01-13 21:24:21 +00001657
Douglas Gregorf4c33342010-05-28 00:22:41 +00001658 AddTypedefResult(Results);
Adrian Prantlf3b3ccd2017-12-19 22:06:11 +00001659 LLVM_FALLTHROUGH;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001660
John McCallfaf5fb42010-08-26 23:41:50 +00001661 case Sema::PCC_Class:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001662 if (SemaRef.getLangOpts().CPlusPlus) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001663 // Using declaration
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001664 Builder.AddTypedTextChunk("using");
1665 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1666 Builder.AddPlaceholderChunk("qualifier");
1667 Builder.AddTextChunk("::");
1668 Builder.AddPlaceholderChunk("name");
1669 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001670
Douglas Gregorf4c33342010-05-28 00:22:41 +00001671 // using typename qualifier::name (only in a dependent context)
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001672 if (SemaRef.CurContext->isDependentContext()) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001673 Builder.AddTypedTextChunk("using");
1674 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1675 Builder.AddTextChunk("typename");
1676 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1677 Builder.AddPlaceholderChunk("qualifier");
1678 Builder.AddTextChunk("::");
1679 Builder.AddPlaceholderChunk("name");
1680 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001681 }
1682
Alex Lorenz8f4d3992017-02-13 23:19:40 +00001683 AddStaticAssertResult(Builder, Results, SemaRef.getLangOpts());
1684
John McCallfaf5fb42010-08-26 23:41:50 +00001685 if (CCC == Sema::PCC_Class) {
Douglas Gregorf4c33342010-05-28 00:22:41 +00001686 AddTypedefResult(Results);
1687
Erik Verbruggen6524c052017-10-24 13:46:58 +00001688 bool IsNotInheritanceScope =
1689 !(S->getFlags() & Scope::ClassInheritanceScope);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001690 // public:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001691 Builder.AddTypedTextChunk("public");
Erik Verbruggen6524c052017-10-24 13:46:58 +00001692 if (IsNotInheritanceScope && Results.includeCodePatterns())
Douglas Gregor9489cdf2012-04-10 17:56:28 +00001693 Builder.AddChunk(CodeCompletionString::CK_Colon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001694 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001695
1696 // protected:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001697 Builder.AddTypedTextChunk("protected");
Erik Verbruggen6524c052017-10-24 13:46:58 +00001698 if (IsNotInheritanceScope && Results.includeCodePatterns())
Douglas Gregor9489cdf2012-04-10 17:56:28 +00001699 Builder.AddChunk(CodeCompletionString::CK_Colon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001700 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001701
1702 // private:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001703 Builder.AddTypedTextChunk("private");
Erik Verbruggen6524c052017-10-24 13:46:58 +00001704 if (IsNotInheritanceScope && Results.includeCodePatterns())
Douglas Gregor9489cdf2012-04-10 17:56:28 +00001705 Builder.AddChunk(CodeCompletionString::CK_Colon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001706 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001707 }
1708 }
Adrian Prantlf3b3ccd2017-12-19 22:06:11 +00001709 LLVM_FALLTHROUGH;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001710
John McCallfaf5fb42010-08-26 23:41:50 +00001711 case Sema::PCC_Template:
1712 case Sema::PCC_MemberTemplate:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001713 if (SemaRef.getLangOpts().CPlusPlus && Results.includeCodePatterns()) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001714 // template < parameters >
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001715 Builder.AddTypedTextChunk("template");
1716 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1717 Builder.AddPlaceholderChunk("parameters");
1718 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1719 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001720 }
1721
David Blaikiebbafb8a2012-03-11 07:00:24 +00001722 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
1723 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001724 break;
1725
John McCallfaf5fb42010-08-26 23:41:50 +00001726 case Sema::PCC_ObjCInterface:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001727 AddObjCInterfaceResults(SemaRef.getLangOpts(), Results, true);
1728 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
1729 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregorf1934162010-01-13 21:24:21 +00001730 break;
1731
John McCallfaf5fb42010-08-26 23:41:50 +00001732 case Sema::PCC_ObjCImplementation:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001733 AddObjCImplementationResults(SemaRef.getLangOpts(), Results, true);
1734 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
1735 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregorf1934162010-01-13 21:24:21 +00001736 break;
1737
John McCallfaf5fb42010-08-26 23:41:50 +00001738 case Sema::PCC_ObjCInstanceVariableList:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001739 AddObjCVisibilityResults(SemaRef.getLangOpts(), Results, true);
Douglas Gregor48d46252010-01-13 21:54:15 +00001740 break;
1741
John McCallfaf5fb42010-08-26 23:41:50 +00001742 case Sema::PCC_RecoveryInFunction:
1743 case Sema::PCC_Statement: {
Douglas Gregorf4c33342010-05-28 00:22:41 +00001744 AddTypedefResult(Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001745
David Blaikiebbafb8a2012-03-11 07:00:24 +00001746 if (SemaRef.getLangOpts().CPlusPlus && Results.includeCodePatterns() &&
1747 SemaRef.getLangOpts().CXXExceptions) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001748 Builder.AddTypedTextChunk("try");
1749 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1750 Builder.AddPlaceholderChunk("statements");
1751 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1752 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1753 Builder.AddTextChunk("catch");
1754 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1755 Builder.AddPlaceholderChunk("declaration");
1756 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1757 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1758 Builder.AddPlaceholderChunk("statements");
1759 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1760 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1761 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001762 }
David Blaikiebbafb8a2012-03-11 07:00:24 +00001763 if (SemaRef.getLangOpts().ObjC1)
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001764 AddObjCStatementResults(Results, true);
Douglas Gregorf1934162010-01-13 21:24:21 +00001765
Douglas Gregorf64acca2010-05-25 21:41:55 +00001766 if (Results.includeCodePatterns()) {
1767 // if (condition) { statements }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001768 Builder.AddTypedTextChunk("if");
1769 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00001770 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001771 Builder.AddPlaceholderChunk("condition");
Douglas Gregorf64acca2010-05-25 21:41:55 +00001772 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001773 Builder.AddPlaceholderChunk("expression");
1774 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1775 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1776 Builder.AddPlaceholderChunk("statements");
1777 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1778 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1779 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001780
Douglas Gregorf64acca2010-05-25 21:41:55 +00001781 // switch (condition) { }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001782 Builder.AddTypedTextChunk("switch");
1783 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00001784 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001785 Builder.AddPlaceholderChunk("condition");
Douglas Gregorf64acca2010-05-25 21:41:55 +00001786 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001787 Builder.AddPlaceholderChunk("expression");
1788 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1789 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1790 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1791 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1792 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf64acca2010-05-25 21:41:55 +00001793 }
1794
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001795 // Switch-specific statements.
John McCallaab3e412010-08-25 08:40:02 +00001796 if (!SemaRef.getCurFunction()->SwitchStack.empty()) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001797 // case expression:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001798 Builder.AddTypedTextChunk("case");
1799 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1800 Builder.AddPlaceholderChunk("expression");
1801 Builder.AddChunk(CodeCompletionString::CK_Colon);
1802 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001803
1804 // default:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001805 Builder.AddTypedTextChunk("default");
1806 Builder.AddChunk(CodeCompletionString::CK_Colon);
1807 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001808 }
1809
Douglas Gregorf64acca2010-05-25 21:41:55 +00001810 if (Results.includeCodePatterns()) {
1811 /// while (condition) { statements }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001812 Builder.AddTypedTextChunk("while");
1813 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00001814 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001815 Builder.AddPlaceholderChunk("condition");
Douglas Gregorf64acca2010-05-25 21:41:55 +00001816 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001817 Builder.AddPlaceholderChunk("expression");
1818 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1819 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1820 Builder.AddPlaceholderChunk("statements");
1821 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1822 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1823 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf64acca2010-05-25 21:41:55 +00001824
1825 // do { statements } while ( expression );
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001826 Builder.AddTypedTextChunk("do");
1827 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1828 Builder.AddPlaceholderChunk("statements");
1829 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1830 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1831 Builder.AddTextChunk("while");
1832 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1833 Builder.AddPlaceholderChunk("expression");
1834 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1835 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001836
Douglas Gregorf64acca2010-05-25 21:41:55 +00001837 // for ( for-init-statement ; condition ; expression ) { statements }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001838 Builder.AddTypedTextChunk("for");
1839 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00001840 if (SemaRef.getLangOpts().CPlusPlus || SemaRef.getLangOpts().C99)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001841 Builder.AddPlaceholderChunk("init-statement");
Douglas Gregorf64acca2010-05-25 21:41:55 +00001842 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001843 Builder.AddPlaceholderChunk("init-expression");
1844 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
1845 Builder.AddPlaceholderChunk("condition");
1846 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
1847 Builder.AddPlaceholderChunk("inc-expression");
1848 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1849 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1850 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1851 Builder.AddPlaceholderChunk("statements");
1852 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1853 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1854 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf64acca2010-05-25 21:41:55 +00001855 }
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001856
1857 if (S->getContinueParent()) {
1858 // continue ;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001859 Builder.AddTypedTextChunk("continue");
1860 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001861 }
1862
1863 if (S->getBreakParent()) {
1864 // break ;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001865 Builder.AddTypedTextChunk("break");
1866 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001867 }
1868
1869 // "return expression ;" or "return ;", depending on whether we
1870 // know the function is void or not.
1871 bool isVoid = false;
1872 if (FunctionDecl *Function = dyn_cast<FunctionDecl>(SemaRef.CurContext))
Alp Toker314cc812014-01-25 16:55:45 +00001873 isVoid = Function->getReturnType()->isVoidType();
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001874 else if (ObjCMethodDecl *Method
1875 = dyn_cast<ObjCMethodDecl>(SemaRef.CurContext))
Alp Toker314cc812014-01-25 16:55:45 +00001876 isVoid = Method->getReturnType()->isVoidType();
Douglas Gregor9a28e842010-03-01 23:15:13 +00001877 else if (SemaRef.getCurBlock() &&
1878 !SemaRef.getCurBlock()->ReturnType.isNull())
1879 isVoid = SemaRef.getCurBlock()->ReturnType->isVoidType();
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001880 Builder.AddTypedTextChunk("return");
Douglas Gregor44272ca2010-02-18 04:06:48 +00001881 if (!isVoid) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001882 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1883 Builder.AddPlaceholderChunk("expression");
Douglas Gregor44272ca2010-02-18 04:06:48 +00001884 }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001885 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001886
Douglas Gregorf4c33342010-05-28 00:22:41 +00001887 // goto identifier ;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001888 Builder.AddTypedTextChunk("goto");
1889 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1890 Builder.AddPlaceholderChunk("label");
1891 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001892
Douglas Gregorf4c33342010-05-28 00:22:41 +00001893 // Using directives
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001894 Builder.AddTypedTextChunk("using");
1895 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1896 Builder.AddTextChunk("namespace");
1897 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1898 Builder.AddPlaceholderChunk("identifier");
1899 Results.AddResult(Result(Builder.TakeString()));
Alex Lorenz8f4d3992017-02-13 23:19:40 +00001900
1901 AddStaticAssertResult(Builder, Results, SemaRef.getLangOpts());
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001902 }
Galina Kistanovabe3ba9da2017-06-07 06:31:55 +00001903 LLVM_FALLTHROUGH;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001904
1905 // Fall through (for statement expressions).
John McCallfaf5fb42010-08-26 23:41:50 +00001906 case Sema::PCC_ForInit:
1907 case Sema::PCC_Condition:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001908 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001909 // Fall through: conditions and statements can have expressions.
Galina Kistanova33399112017-06-03 06:35:06 +00001910 LLVM_FALLTHROUGH;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001911
Douglas Gregor5e35d592010-09-14 23:59:36 +00001912 case Sema::PCC_ParenthesizedExpression:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001913 if (SemaRef.getLangOpts().ObjCAutoRefCount &&
John McCall31168b02011-06-15 23:02:42 +00001914 CCC == Sema::PCC_ParenthesizedExpression) {
1915 // (__bridge <type>)<expression>
1916 Builder.AddTypedTextChunk("__bridge");
1917 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1918 Builder.AddPlaceholderChunk("type");
1919 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1920 Builder.AddPlaceholderChunk("expression");
1921 Results.AddResult(Result(Builder.TakeString()));
1922
1923 // (__bridge_transfer <Objective-C type>)<expression>
1924 Builder.AddTypedTextChunk("__bridge_transfer");
1925 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1926 Builder.AddPlaceholderChunk("Objective-C type");
1927 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1928 Builder.AddPlaceholderChunk("expression");
1929 Results.AddResult(Result(Builder.TakeString()));
1930
1931 // (__bridge_retained <CF type>)<expression>
1932 Builder.AddTypedTextChunk("__bridge_retained");
1933 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1934 Builder.AddPlaceholderChunk("CF type");
1935 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1936 Builder.AddPlaceholderChunk("expression");
1937 Results.AddResult(Result(Builder.TakeString()));
1938 }
1939 // Fall through
Galina Kistanova33399112017-06-03 06:35:06 +00001940 LLVM_FALLTHROUGH;
John McCall31168b02011-06-15 23:02:42 +00001941
John McCallfaf5fb42010-08-26 23:41:50 +00001942 case Sema::PCC_Expression: {
David Blaikiebbafb8a2012-03-11 07:00:24 +00001943 if (SemaRef.getLangOpts().CPlusPlus) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001944 // 'this', if we're in a non-static member function.
Douglas Gregord8c61782012-02-15 15:34:24 +00001945 addThisCompletion(SemaRef, Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001946
Douglas Gregore5c79d52011-10-18 21:20:17 +00001947 // true
1948 Builder.AddResultTypeChunk("bool");
1949 Builder.AddTypedTextChunk("true");
1950 Results.AddResult(Result(Builder.TakeString()));
1951
1952 // false
1953 Builder.AddResultTypeChunk("bool");
1954 Builder.AddTypedTextChunk("false");
1955 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001956
David Blaikiebbafb8a2012-03-11 07:00:24 +00001957 if (SemaRef.getLangOpts().RTTI) {
Douglas Gregorc05f6572011-04-12 02:47:21 +00001958 // dynamic_cast < type-id > ( expression )
1959 Builder.AddTypedTextChunk("dynamic_cast");
1960 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1961 Builder.AddPlaceholderChunk("type");
1962 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1963 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1964 Builder.AddPlaceholderChunk("expression");
1965 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1966 Results.AddResult(Result(Builder.TakeString()));
1967 }
Douglas Gregorf4c33342010-05-28 00:22:41 +00001968
1969 // static_cast < type-id > ( expression )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001970 Builder.AddTypedTextChunk("static_cast");
1971 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1972 Builder.AddPlaceholderChunk("type");
1973 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1974 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1975 Builder.AddPlaceholderChunk("expression");
1976 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1977 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001978
Douglas Gregorf4c33342010-05-28 00:22:41 +00001979 // reinterpret_cast < type-id > ( expression )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001980 Builder.AddTypedTextChunk("reinterpret_cast");
1981 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1982 Builder.AddPlaceholderChunk("type");
1983 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1984 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1985 Builder.AddPlaceholderChunk("expression");
1986 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1987 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001988
Douglas Gregorf4c33342010-05-28 00:22:41 +00001989 // const_cast < type-id > ( expression )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001990 Builder.AddTypedTextChunk("const_cast");
1991 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1992 Builder.AddPlaceholderChunk("type");
1993 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1994 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1995 Builder.AddPlaceholderChunk("expression");
1996 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1997 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001998
David Blaikiebbafb8a2012-03-11 07:00:24 +00001999 if (SemaRef.getLangOpts().RTTI) {
Douglas Gregorc05f6572011-04-12 02:47:21 +00002000 // typeid ( expression-or-type )
Douglas Gregore5c79d52011-10-18 21:20:17 +00002001 Builder.AddResultTypeChunk("std::type_info");
Douglas Gregorc05f6572011-04-12 02:47:21 +00002002 Builder.AddTypedTextChunk("typeid");
2003 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2004 Builder.AddPlaceholderChunk("expression-or-type");
2005 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2006 Results.AddResult(Result(Builder.TakeString()));
2007 }
2008
Douglas Gregorf4c33342010-05-28 00:22:41 +00002009 // new T ( ... )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002010 Builder.AddTypedTextChunk("new");
2011 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2012 Builder.AddPlaceholderChunk("type");
2013 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2014 Builder.AddPlaceholderChunk("expressions");
2015 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2016 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002017
Douglas Gregorf4c33342010-05-28 00:22:41 +00002018 // new T [ ] ( ... )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002019 Builder.AddTypedTextChunk("new");
2020 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2021 Builder.AddPlaceholderChunk("type");
2022 Builder.AddChunk(CodeCompletionString::CK_LeftBracket);
2023 Builder.AddPlaceholderChunk("size");
2024 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
2025 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2026 Builder.AddPlaceholderChunk("expressions");
2027 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2028 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002029
Douglas Gregorf4c33342010-05-28 00:22:41 +00002030 // delete expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00002031 Builder.AddResultTypeChunk("void");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002032 Builder.AddTypedTextChunk("delete");
2033 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2034 Builder.AddPlaceholderChunk("expression");
2035 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002036
Douglas Gregorf4c33342010-05-28 00:22:41 +00002037 // delete [] expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00002038 Builder.AddResultTypeChunk("void");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002039 Builder.AddTypedTextChunk("delete");
2040 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2041 Builder.AddChunk(CodeCompletionString::CK_LeftBracket);
2042 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
2043 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2044 Builder.AddPlaceholderChunk("expression");
2045 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002046
David Blaikiebbafb8a2012-03-11 07:00:24 +00002047 if (SemaRef.getLangOpts().CXXExceptions) {
Douglas Gregorc05f6572011-04-12 02:47:21 +00002048 // throw expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00002049 Builder.AddResultTypeChunk("void");
Douglas Gregorc05f6572011-04-12 02:47:21 +00002050 Builder.AddTypedTextChunk("throw");
2051 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2052 Builder.AddPlaceholderChunk("expression");
2053 Results.AddResult(Result(Builder.TakeString()));
2054 }
Douglas Gregor4205fef2011-10-18 16:29:03 +00002055
Douglas Gregora2db7932010-05-26 22:00:08 +00002056 // FIXME: Rethrow?
Douglas Gregor4205fef2011-10-18 16:29:03 +00002057
Richard Smith2bf7fdb2013-01-02 11:42:31 +00002058 if (SemaRef.getLangOpts().CPlusPlus11) {
Douglas Gregor4205fef2011-10-18 16:29:03 +00002059 // nullptr
Douglas Gregore5c79d52011-10-18 21:20:17 +00002060 Builder.AddResultTypeChunk("std::nullptr_t");
Douglas Gregor4205fef2011-10-18 16:29:03 +00002061 Builder.AddTypedTextChunk("nullptr");
2062 Results.AddResult(Result(Builder.TakeString()));
2063
2064 // alignof
Douglas Gregore5c79d52011-10-18 21:20:17 +00002065 Builder.AddResultTypeChunk("size_t");
Douglas Gregor4205fef2011-10-18 16:29:03 +00002066 Builder.AddTypedTextChunk("alignof");
2067 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2068 Builder.AddPlaceholderChunk("type");
2069 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2070 Results.AddResult(Result(Builder.TakeString()));
2071
2072 // noexcept
Douglas Gregore5c79d52011-10-18 21:20:17 +00002073 Builder.AddResultTypeChunk("bool");
Douglas Gregor4205fef2011-10-18 16:29:03 +00002074 Builder.AddTypedTextChunk("noexcept");
2075 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2076 Builder.AddPlaceholderChunk("expression");
2077 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2078 Results.AddResult(Result(Builder.TakeString()));
2079
2080 // sizeof... expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00002081 Builder.AddResultTypeChunk("size_t");
Douglas Gregor4205fef2011-10-18 16:29:03 +00002082 Builder.AddTypedTextChunk("sizeof...");
2083 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2084 Builder.AddPlaceholderChunk("parameter-pack");
2085 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2086 Results.AddResult(Result(Builder.TakeString()));
2087 }
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002088 }
2089
David Blaikiebbafb8a2012-03-11 07:00:24 +00002090 if (SemaRef.getLangOpts().ObjC1) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002091 // Add "super", if we're in an Objective-C class with a superclass.
Ted Kremenek305a0a72010-05-31 21:43:10 +00002092 if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl()) {
2093 // The interface can be NULL.
2094 if (ObjCInterfaceDecl *ID = Method->getClassInterface())
Douglas Gregore5c79d52011-10-18 21:20:17 +00002095 if (ID->getSuperClass()) {
2096 std::string SuperType;
2097 SuperType = ID->getSuperClass()->getNameAsString();
2098 if (Method->isInstanceMethod())
2099 SuperType += " *";
2100
2101 Builder.AddResultTypeChunk(Allocator.CopyString(SuperType));
2102 Builder.AddTypedTextChunk("super");
2103 Results.AddResult(Result(Builder.TakeString()));
2104 }
Ted Kremenek305a0a72010-05-31 21:43:10 +00002105 }
2106
Douglas Gregorf98e6a22010-01-13 23:51:12 +00002107 AddObjCExpressionResults(Results, true);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002108 }
2109
Jordan Rose58d54722012-06-30 21:33:57 +00002110 if (SemaRef.getLangOpts().C11) {
2111 // _Alignof
2112 Builder.AddResultTypeChunk("size_t");
Richard Smith20e883e2015-04-29 23:20:19 +00002113 if (SemaRef.PP.isMacroDefined("alignof"))
Jordan Rose58d54722012-06-30 21:33:57 +00002114 Builder.AddTypedTextChunk("alignof");
2115 else
2116 Builder.AddTypedTextChunk("_Alignof");
2117 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2118 Builder.AddPlaceholderChunk("type");
2119 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2120 Results.AddResult(Result(Builder.TakeString()));
2121 }
2122
Douglas Gregorf4c33342010-05-28 00:22:41 +00002123 // sizeof expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00002124 Builder.AddResultTypeChunk("size_t");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002125 Builder.AddTypedTextChunk("sizeof");
2126 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2127 Builder.AddPlaceholderChunk("expression-or-type");
2128 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2129 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002130 break;
2131 }
Douglas Gregor99fa2642010-08-24 01:06:58 +00002132
John McCallfaf5fb42010-08-26 23:41:50 +00002133 case Sema::PCC_Type:
Douglas Gregor80039242011-02-15 20:33:25 +00002134 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregor99fa2642010-08-24 01:06:58 +00002135 break;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002136 }
2137
David Blaikiebbafb8a2012-03-11 07:00:24 +00002138 if (WantTypesInContext(CCC, SemaRef.getLangOpts()))
2139 AddTypeSpecifierResults(SemaRef.getLangOpts(), Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002140
David Blaikiebbafb8a2012-03-11 07:00:24 +00002141 if (SemaRef.getLangOpts().CPlusPlus && CCC != Sema::PCC_Type)
Douglas Gregor78a21012010-01-14 16:01:26 +00002142 Results.AddResult(Result("operator"));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002143}
2144
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002145/// If the given declaration has an associated type, add it as a result
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002146/// type chunk.
2147static void AddResultTypeChunk(ASTContext &Context,
Douglas Gregor75acd922011-09-27 23:30:47 +00002148 const PrintingPolicy &Policy,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002149 const NamedDecl *ND,
Douglas Gregorc3425b12015-07-07 06:20:19 +00002150 QualType BaseType,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002151 CodeCompletionBuilder &Result) {
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002152 if (!ND)
2153 return;
Douglas Gregor0212fd72010-09-21 16:06:22 +00002154
2155 // Skip constructors and conversion functions, which have their return types
2156 // built into their names.
Sam McCall63c59722018-01-22 20:44:47 +00002157 if (isConstructor(ND) || isa<CXXConversionDecl>(ND))
Douglas Gregor0212fd72010-09-21 16:06:22 +00002158 return;
2159
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002160 // Determine the type of the declaration (if it has a type).
Alp Tokera2794f92014-01-22 07:29:52 +00002161 QualType T;
2162 if (const FunctionDecl *Function = ND->getAsFunction())
Alp Toker314cc812014-01-25 16:55:45 +00002163 T = Function->getReturnType();
Douglas Gregorc3425b12015-07-07 06:20:19 +00002164 else if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND)) {
2165 if (!BaseType.isNull())
2166 T = Method->getSendResultType(BaseType);
2167 else
2168 T = Method->getReturnType();
Ilya Biryukovb5da91c2017-11-08 10:39:09 +00002169 } else if (const EnumConstantDecl *Enumerator = dyn_cast<EnumConstantDecl>(ND)) {
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002170 T = Context.getTypeDeclType(cast<TypeDecl>(Enumerator->getDeclContext()));
Ilya Biryukovb5da91c2017-11-08 10:39:09 +00002171 T = clang::TypeName::getFullyQualifiedType(T, Context);
2172 } else if (isa<UnresolvedUsingValueDecl>(ND)) {
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002173 /* Do nothing: ignore unresolved using declarations*/
Douglas Gregorc3425b12015-07-07 06:20:19 +00002174 } else if (const ObjCIvarDecl *Ivar = dyn_cast<ObjCIvarDecl>(ND)) {
2175 if (!BaseType.isNull())
2176 T = Ivar->getUsageType(BaseType);
2177 else
2178 T = Ivar->getType();
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002179 } else if (const ValueDecl *Value = dyn_cast<ValueDecl>(ND)) {
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002180 T = Value->getType();
Douglas Gregorc3425b12015-07-07 06:20:19 +00002181 } else if (const ObjCPropertyDecl *Property = dyn_cast<ObjCPropertyDecl>(ND)) {
2182 if (!BaseType.isNull())
2183 T = Property->getUsageType(BaseType);
2184 else
2185 T = Property->getType();
2186 }
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002187
2188 if (T.isNull() || Context.hasSameType(T, Context.DependentTy))
2189 return;
2190
Douglas Gregor75acd922011-09-27 23:30:47 +00002191 Result.AddResultTypeChunk(GetCompletionTypeString(T, Context, Policy,
Douglas Gregor304f9b02011-02-01 21:15:40 +00002192 Result.getAllocator()));
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002193}
2194
Richard Smith20e883e2015-04-29 23:20:19 +00002195static void MaybeAddSentinel(Preprocessor &PP,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002196 const NamedDecl *FunctionOrMethod,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002197 CodeCompletionBuilder &Result) {
Douglas Gregordbb71db2010-08-23 23:51:41 +00002198 if (SentinelAttr *Sentinel = FunctionOrMethod->getAttr<SentinelAttr>())
2199 if (Sentinel->getSentinel() == 0) {
Richard Smith20e883e2015-04-29 23:20:19 +00002200 if (PP.getLangOpts().ObjC1 && PP.isMacroDefined("nil"))
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002201 Result.AddTextChunk(", nil");
Richard Smith20e883e2015-04-29 23:20:19 +00002202 else if (PP.isMacroDefined("NULL"))
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002203 Result.AddTextChunk(", NULL");
Douglas Gregordbb71db2010-08-23 23:51:41 +00002204 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002205 Result.AddTextChunk(", (void*)0");
Douglas Gregordbb71db2010-08-23 23:51:41 +00002206 }
2207}
2208
Douglas Gregor86b42682015-06-19 18:27:52 +00002209static std::string formatObjCParamQualifiers(unsigned ObjCQuals,
2210 QualType &Type) {
Douglas Gregor8f08d742011-07-30 07:55:26 +00002211 std::string Result;
2212 if (ObjCQuals & Decl::OBJC_TQ_In)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002213 Result += "in ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002214 else if (ObjCQuals & Decl::OBJC_TQ_Inout)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002215 Result += "inout ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002216 else if (ObjCQuals & Decl::OBJC_TQ_Out)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002217 Result += "out ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002218 if (ObjCQuals & Decl::OBJC_TQ_Bycopy)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002219 Result += "bycopy ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002220 else if (ObjCQuals & Decl::OBJC_TQ_Byref)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002221 Result += "byref ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002222 if (ObjCQuals & Decl::OBJC_TQ_Oneway)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002223 Result += "oneway ";
Douglas Gregor86b42682015-06-19 18:27:52 +00002224 if (ObjCQuals & Decl::OBJC_TQ_CSNullability) {
2225 if (auto nullability = AttributedType::stripOuterNullability(Type)) {
2226 switch (*nullability) {
2227 case NullabilityKind::NonNull:
2228 Result += "nonnull ";
2229 break;
2230
2231 case NullabilityKind::Nullable:
2232 Result += "nullable ";
2233 break;
2234
2235 case NullabilityKind::Unspecified:
2236 Result += "null_unspecified ";
2237 break;
2238 }
2239 }
2240 }
Douglas Gregor8f08d742011-07-30 07:55:26 +00002241 return Result;
2242}
2243
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002244/// Tries to find the most appropriate type location for an Objective-C
Alex Lorenza1951202016-10-18 10:35:27 +00002245/// block placeholder.
2246///
2247/// This function ignores things like typedefs and qualifiers in order to
2248/// present the most relevant and accurate block placeholders in code completion
2249/// results.
2250static void findTypeLocationForBlockDecl(const TypeSourceInfo *TSInfo,
2251 FunctionTypeLoc &Block,
2252 FunctionProtoTypeLoc &BlockProto,
2253 bool SuppressBlock = false) {
2254 if (!TSInfo)
2255 return;
2256 TypeLoc TL = TSInfo->getTypeLoc().getUnqualifiedLoc();
2257 while (true) {
2258 // Look through typedefs.
2259 if (!SuppressBlock) {
2260 if (TypedefTypeLoc TypedefTL = TL.getAs<TypedefTypeLoc>()) {
2261 if (TypeSourceInfo *InnerTSInfo =
2262 TypedefTL.getTypedefNameDecl()->getTypeSourceInfo()) {
2263 TL = InnerTSInfo->getTypeLoc().getUnqualifiedLoc();
2264 continue;
2265 }
2266 }
2267
2268 // Look through qualified types
2269 if (QualifiedTypeLoc QualifiedTL = TL.getAs<QualifiedTypeLoc>()) {
2270 TL = QualifiedTL.getUnqualifiedLoc();
2271 continue;
2272 }
2273
2274 if (AttributedTypeLoc AttrTL = TL.getAs<AttributedTypeLoc>()) {
2275 TL = AttrTL.getModifiedLoc();
2276 continue;
2277 }
2278 }
2279
2280 // Try to get the function prototype behind the block pointer type,
2281 // then we're done.
2282 if (BlockPointerTypeLoc BlockPtr = TL.getAs<BlockPointerTypeLoc>()) {
2283 TL = BlockPtr.getPointeeLoc().IgnoreParens();
2284 Block = TL.getAs<FunctionTypeLoc>();
2285 BlockProto = TL.getAs<FunctionProtoTypeLoc>();
2286 }
2287 break;
2288 }
2289}
2290
Alex Lorenz920ae142016-10-18 10:38:58 +00002291static std::string
2292formatBlockPlaceholder(const PrintingPolicy &Policy, const NamedDecl *BlockDecl,
2293 FunctionTypeLoc &Block, FunctionProtoTypeLoc &BlockProto,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002294 bool SuppressBlockName = false,
Alex Lorenz920ae142016-10-18 10:38:58 +00002295 bool SuppressBlock = false,
2296 Optional<ArrayRef<QualType>> ObjCSubsts = None);
2297
Richard Smith20e883e2015-04-29 23:20:19 +00002298static std::string FormatFunctionParameter(const PrintingPolicy &Policy,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002299 const ParmVarDecl *Param,
Douglas Gregord793e7c2011-10-18 04:23:19 +00002300 bool SuppressName = false,
Douglas Gregorc3425b12015-07-07 06:20:19 +00002301 bool SuppressBlock = false,
2302 Optional<ArrayRef<QualType>> ObjCSubsts = None) {
Douglas Gregore90dd002010-08-24 16:15:59 +00002303 bool ObjCMethodParam = isa<ObjCMethodDecl>(Param->getDeclContext());
2304 if (Param->getType()->isDependentType() ||
2305 !Param->getType()->isBlockPointerType()) {
2306 // The argument for a dependent or non-block parameter is a placeholder
2307 // containing that parameter's type.
2308 std::string Result;
2309
Douglas Gregor981a0c42010-08-29 19:47:46 +00002310 if (Param->getIdentifier() && !ObjCMethodParam && !SuppressName)
Douglas Gregore90dd002010-08-24 16:15:59 +00002311 Result = Param->getIdentifier()->getName();
2312
Douglas Gregor86b42682015-06-19 18:27:52 +00002313 QualType Type = Param->getType();
Douglas Gregorc3425b12015-07-07 06:20:19 +00002314 if (ObjCSubsts)
2315 Type = Type.substObjCTypeArgs(Param->getASTContext(), *ObjCSubsts,
2316 ObjCSubstitutionContext::Parameter);
Douglas Gregore90dd002010-08-24 16:15:59 +00002317 if (ObjCMethodParam) {
Douglas Gregor86b42682015-06-19 18:27:52 +00002318 Result = "(" + formatObjCParamQualifiers(Param->getObjCDeclQualifier(),
2319 Type);
2320 Result += Type.getAsString(Policy) + ")";
Douglas Gregor981a0c42010-08-29 19:47:46 +00002321 if (Param->getIdentifier() && !SuppressName)
Douglas Gregore90dd002010-08-24 16:15:59 +00002322 Result += Param->getIdentifier()->getName();
Douglas Gregor86b42682015-06-19 18:27:52 +00002323 } else {
2324 Type.getAsStringInternal(Result, Policy);
Douglas Gregore90dd002010-08-24 16:15:59 +00002325 }
2326 return Result;
2327 }
Alex Lorenza1951202016-10-18 10:35:27 +00002328
Douglas Gregore90dd002010-08-24 16:15:59 +00002329 // The argument for a block pointer parameter is a block literal with
2330 // the appropriate type.
David Blaikie6adc78e2013-02-18 22:06:02 +00002331 FunctionTypeLoc Block;
2332 FunctionProtoTypeLoc BlockProto;
Alex Lorenza1951202016-10-18 10:35:27 +00002333 findTypeLocationForBlockDecl(Param->getTypeSourceInfo(), Block, BlockProto,
2334 SuppressBlock);
Alex Lorenz6bf4a582017-03-13 15:43:42 +00002335 // Try to retrieve the block type information from the property if this is a
2336 // parameter in a setter.
2337 if (!Block && ObjCMethodParam &&
2338 cast<ObjCMethodDecl>(Param->getDeclContext())->isPropertyAccessor()) {
2339 if (const auto *PD = cast<ObjCMethodDecl>(Param->getDeclContext())
2340 ->findPropertyDecl(/*CheckOverrides=*/false))
2341 findTypeLocationForBlockDecl(PD->getTypeSourceInfo(), Block, BlockProto,
2342 SuppressBlock);
2343 }
Douglas Gregore90dd002010-08-24 16:15:59 +00002344
2345 if (!Block) {
2346 // We were unable to find a FunctionProtoTypeLoc with parameter names
2347 // for the block; just use the parameter type as a placeholder.
2348 std::string Result;
Douglas Gregord793e7c2011-10-18 04:23:19 +00002349 if (!ObjCMethodParam && Param->getIdentifier())
2350 Result = Param->getIdentifier()->getName();
2351
Douglas Gregor86b42682015-06-19 18:27:52 +00002352 QualType Type = Param->getType().getUnqualifiedType();
Douglas Gregore90dd002010-08-24 16:15:59 +00002353
2354 if (ObjCMethodParam) {
Alex Lorenz01bcfc12016-11-23 16:28:34 +00002355 Result = Type.getAsString(Policy);
2356 std::string Quals =
2357 formatObjCParamQualifiers(Param->getObjCDeclQualifier(), Type);
2358 if (!Quals.empty())
2359 Result = "(" + Quals + " " + Result + ")";
2360 if (Result.back() != ')')
2361 Result += " ";
Douglas Gregore90dd002010-08-24 16:15:59 +00002362 if (Param->getIdentifier())
2363 Result += Param->getIdentifier()->getName();
Douglas Gregor86b42682015-06-19 18:27:52 +00002364 } else {
2365 Type.getAsStringInternal(Result, Policy);
Douglas Gregore90dd002010-08-24 16:15:59 +00002366 }
2367
2368 return Result;
2369 }
Alex Lorenz01bcfc12016-11-23 16:28:34 +00002370
Douglas Gregore90dd002010-08-24 16:15:59 +00002371 // We have the function prototype behind the block pointer type, as it was
2372 // written in the source.
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002373 return formatBlockPlaceholder(Policy, Param, Block, BlockProto,
2374 /*SuppressBlockName=*/false, SuppressBlock,
Alex Lorenz920ae142016-10-18 10:38:58 +00002375 ObjCSubsts);
2376}
2377
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002378/// Returns a placeholder string that corresponds to an Objective-C block
Alex Lorenz920ae142016-10-18 10:38:58 +00002379/// declaration.
2380///
2381/// \param BlockDecl A declaration with an Objective-C block type.
2382///
2383/// \param Block The most relevant type location for that block type.
2384///
Alexander Kornienko2a8c18d2018-04-06 15:14:32 +00002385/// \param SuppressBlockName Determines whether or not the name of the block
Alex Lorenz920ae142016-10-18 10:38:58 +00002386/// declaration is included in the resulting string.
2387static std::string
2388formatBlockPlaceholder(const PrintingPolicy &Policy, const NamedDecl *BlockDecl,
2389 FunctionTypeLoc &Block, FunctionProtoTypeLoc &BlockProto,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002390 bool SuppressBlockName, bool SuppressBlock,
Alex Lorenz920ae142016-10-18 10:38:58 +00002391 Optional<ArrayRef<QualType>> ObjCSubsts) {
Douglas Gregor67da50e2010-09-08 22:47:51 +00002392 std::string Result;
Alp Toker314cc812014-01-25 16:55:45 +00002393 QualType ResultType = Block.getTypePtr()->getReturnType();
Douglas Gregorc3425b12015-07-07 06:20:19 +00002394 if (ObjCSubsts)
Alex Lorenz920ae142016-10-18 10:38:58 +00002395 ResultType =
2396 ResultType.substObjCTypeArgs(BlockDecl->getASTContext(), *ObjCSubsts,
2397 ObjCSubstitutionContext::Result);
Douglas Gregord793e7c2011-10-18 04:23:19 +00002398 if (!ResultType->isVoidType() || SuppressBlock)
John McCall31168b02011-06-15 23:02:42 +00002399 ResultType.getAsStringInternal(Result, Policy);
Douglas Gregord793e7c2011-10-18 04:23:19 +00002400
2401 // Format the parameter list.
2402 std::string Params;
Alp Tokerb3fd5cf2014-01-21 00:32:38 +00002403 if (!BlockProto || Block.getNumParams() == 0) {
David Blaikie6adc78e2013-02-18 22:06:02 +00002404 if (BlockProto && BlockProto.getTypePtr()->isVariadic())
Douglas Gregord793e7c2011-10-18 04:23:19 +00002405 Params = "(...)";
Douglas Gregoraf25cfa2010-10-02 23:49:58 +00002406 else
Douglas Gregord793e7c2011-10-18 04:23:19 +00002407 Params = "(void)";
Douglas Gregor67da50e2010-09-08 22:47:51 +00002408 } else {
Douglas Gregord793e7c2011-10-18 04:23:19 +00002409 Params += "(";
Alp Tokerb3fd5cf2014-01-21 00:32:38 +00002410 for (unsigned I = 0, N = Block.getNumParams(); I != N; ++I) {
Douglas Gregor67da50e2010-09-08 22:47:51 +00002411 if (I)
Douglas Gregord793e7c2011-10-18 04:23:19 +00002412 Params += ", ";
Richard Smith20e883e2015-04-29 23:20:19 +00002413 Params += FormatFunctionParameter(Policy, Block.getParam(I),
Alp Tokerb3fd5cf2014-01-21 00:32:38 +00002414 /*SuppressName=*/false,
Alex Lorenz920ae142016-10-18 10:38:58 +00002415 /*SuppressBlock=*/true, ObjCSubsts);
Alp Tokerb3fd5cf2014-01-21 00:32:38 +00002416
David Blaikie6adc78e2013-02-18 22:06:02 +00002417 if (I == N - 1 && BlockProto.getTypePtr()->isVariadic())
Douglas Gregord793e7c2011-10-18 04:23:19 +00002418 Params += ", ...";
Douglas Gregor67da50e2010-09-08 22:47:51 +00002419 }
Douglas Gregord793e7c2011-10-18 04:23:19 +00002420 Params += ")";
Douglas Gregor400f5972010-08-31 05:13:43 +00002421 }
Alex Lorenz920ae142016-10-18 10:38:58 +00002422
Douglas Gregord793e7c2011-10-18 04:23:19 +00002423 if (SuppressBlock) {
2424 // Format as a parameter.
2425 Result = Result + " (^";
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002426 if (!SuppressBlockName && BlockDecl->getIdentifier())
Alex Lorenz920ae142016-10-18 10:38:58 +00002427 Result += BlockDecl->getIdentifier()->getName();
Douglas Gregord793e7c2011-10-18 04:23:19 +00002428 Result += ")";
2429 Result += Params;
2430 } else {
2431 // Format as a block literal argument.
2432 Result = '^' + Result;
2433 Result += Params;
Alex Lorenz920ae142016-10-18 10:38:58 +00002434
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002435 if (!SuppressBlockName && BlockDecl->getIdentifier())
Alex Lorenz920ae142016-10-18 10:38:58 +00002436 Result += BlockDecl->getIdentifier()->getName();
Douglas Gregord793e7c2011-10-18 04:23:19 +00002437 }
Alex Lorenz920ae142016-10-18 10:38:58 +00002438
Douglas Gregore90dd002010-08-24 16:15:59 +00002439 return Result;
2440}
2441
Erik Verbruggen11338c52017-07-19 10:45:40 +00002442static std::string GetDefaultValueString(const ParmVarDecl *Param,
2443 const SourceManager &SM,
2444 const LangOptions &LangOpts) {
Ilya Biryukovb6d1ec82017-07-21 09:24:00 +00002445 const SourceRange SrcRange = Param->getDefaultArgRange();
Erik Verbruggen11338c52017-07-19 10:45:40 +00002446 CharSourceRange CharSrcRange = CharSourceRange::getTokenRange(SrcRange);
2447 bool Invalid = CharSrcRange.isInvalid();
2448 if (Invalid)
2449 return "";
2450 StringRef srcText = Lexer::getSourceText(CharSrcRange, SM, LangOpts, &Invalid);
2451 if (Invalid)
2452 return "";
2453
2454 if (srcText.empty() || srcText == "=") {
2455 // Lexer can't determine the value.
2456 // This happens if the code is incorrect (for example class is forward declared).
2457 return "";
2458 }
Erik Verbruggen797980e2017-07-19 11:15:36 +00002459 std::string DefValue(srcText.str());
Erik Verbruggen11338c52017-07-19 10:45:40 +00002460 // FIXME: remove this check if the Lexer::getSourceText value is fixed and
2461 // this value always has (or always does not have) '=' in front of it
2462 if (DefValue.at(0) != '=') {
2463 // If we don't have '=' in front of value.
2464 // Lexer returns built-in types values without '=' and user-defined types values with it.
2465 return " = " + DefValue;
2466 }
2467 return " " + DefValue;
2468}
2469
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002470/// Add function parameter chunks to the given code completion string.
Richard Smith20e883e2015-04-29 23:20:19 +00002471static void AddFunctionParameterChunks(Preprocessor &PP,
Douglas Gregor75acd922011-09-27 23:30:47 +00002472 const PrintingPolicy &Policy,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002473 const FunctionDecl *Function,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002474 CodeCompletionBuilder &Result,
2475 unsigned Start = 0,
2476 bool InOptional = false) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002477 bool FirstParameter = true;
Douglas Gregor9eb77012009-11-07 00:00:49 +00002478
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002479 for (unsigned P = Start, N = Function->getNumParams(); P != N; ++P) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002480 const ParmVarDecl *Param = Function->getParamDecl(P);
Douglas Gregor3545ff42009-09-21 16:56:56 +00002481
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002482 if (Param->hasDefaultArg() && !InOptional) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002483 // When we see an optional default argument, put that argument and
2484 // the remaining default arguments into a new, optional string.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00002485 CodeCompletionBuilder Opt(Result.getAllocator(),
2486 Result.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002487 if (!FirstParameter)
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002488 Opt.AddChunk(CodeCompletionString::CK_Comma);
Richard Smith20e883e2015-04-29 23:20:19 +00002489 AddFunctionParameterChunks(PP, Policy, Function, Opt, P, true);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002490 Result.AddOptionalChunk(Opt.TakeString());
2491 break;
Douglas Gregor3545ff42009-09-21 16:56:56 +00002492 }
2493
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002494 if (FirstParameter)
2495 FirstParameter = false;
2496 else
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002497 Result.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002498
2499 InOptional = false;
Douglas Gregor3545ff42009-09-21 16:56:56 +00002500
2501 // Format the placeholder string.
Richard Smith20e883e2015-04-29 23:20:19 +00002502 std::string PlaceholderStr = FormatFunctionParameter(Policy, Param);
Erik Verbruggen11338c52017-07-19 10:45:40 +00002503 if (Param->hasDefaultArg())
2504 PlaceholderStr += GetDefaultValueString(Param, PP.getSourceManager(), PP.getLangOpts());
Richard Smith20e883e2015-04-29 23:20:19 +00002505
Douglas Gregor400f5972010-08-31 05:13:43 +00002506 if (Function->isVariadic() && P == N - 1)
2507 PlaceholderStr += ", ...";
2508
Douglas Gregor3545ff42009-09-21 16:56:56 +00002509 // Add the placeholder string.
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002510 Result.AddPlaceholderChunk(
2511 Result.getAllocator().CopyString(PlaceholderStr));
Douglas Gregor3545ff42009-09-21 16:56:56 +00002512 }
Douglas Gregorba449032009-09-22 21:42:17 +00002513
2514 if (const FunctionProtoType *Proto
2515 = Function->getType()->getAs<FunctionProtoType>())
Douglas Gregordbb71db2010-08-23 23:51:41 +00002516 if (Proto->isVariadic()) {
Alp Toker9cacbab2014-01-20 20:26:09 +00002517 if (Proto->getNumParams() == 0)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002518 Result.AddPlaceholderChunk("...");
Douglas Gregordbb71db2010-08-23 23:51:41 +00002519
Richard Smith20e883e2015-04-29 23:20:19 +00002520 MaybeAddSentinel(PP, Function, Result);
Douglas Gregordbb71db2010-08-23 23:51:41 +00002521 }
Douglas Gregor3545ff42009-09-21 16:56:56 +00002522}
2523
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002524/// Add template parameter chunks to the given code completion string.
Douglas Gregor3545ff42009-09-21 16:56:56 +00002525static void AddTemplateParameterChunks(ASTContext &Context,
Douglas Gregor75acd922011-09-27 23:30:47 +00002526 const PrintingPolicy &Policy,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002527 const TemplateDecl *Template,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002528 CodeCompletionBuilder &Result,
2529 unsigned MaxParameters = 0,
2530 unsigned Start = 0,
2531 bool InDefaultArg = false) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002532 bool FirstParameter = true;
Richard Smith6eece292015-01-15 02:27:20 +00002533
2534 // Prefer to take the template parameter names from the first declaration of
2535 // the template.
2536 Template = cast<TemplateDecl>(Template->getCanonicalDecl());
2537
Douglas Gregor3545ff42009-09-21 16:56:56 +00002538 TemplateParameterList *Params = Template->getTemplateParameters();
2539 TemplateParameterList::iterator PEnd = Params->end();
2540 if (MaxParameters)
2541 PEnd = Params->begin() + MaxParameters;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002542 for (TemplateParameterList::iterator P = Params->begin() + Start;
2543 P != PEnd; ++P) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002544 bool HasDefaultArg = false;
2545 std::string PlaceholderStr;
2546 if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*P)) {
2547 if (TTP->wasDeclaredWithTypename())
2548 PlaceholderStr = "typename";
2549 else
2550 PlaceholderStr = "class";
2551
2552 if (TTP->getIdentifier()) {
2553 PlaceholderStr += ' ';
2554 PlaceholderStr += TTP->getIdentifier()->getName();
2555 }
2556
2557 HasDefaultArg = TTP->hasDefaultArgument();
2558 } else if (NonTypeTemplateParmDecl *NTTP
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002559 = dyn_cast<NonTypeTemplateParmDecl>(*P)) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002560 if (NTTP->getIdentifier())
2561 PlaceholderStr = NTTP->getIdentifier()->getName();
John McCall31168b02011-06-15 23:02:42 +00002562 NTTP->getType().getAsStringInternal(PlaceholderStr, Policy);
Douglas Gregor3545ff42009-09-21 16:56:56 +00002563 HasDefaultArg = NTTP->hasDefaultArgument();
2564 } else {
2565 assert(isa<TemplateTemplateParmDecl>(*P));
2566 TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*P);
2567
2568 // Since putting the template argument list into the placeholder would
2569 // be very, very long, we just use an abbreviation.
2570 PlaceholderStr = "template<...> class";
2571 if (TTP->getIdentifier()) {
2572 PlaceholderStr += ' ';
2573 PlaceholderStr += TTP->getIdentifier()->getName();
2574 }
2575
2576 HasDefaultArg = TTP->hasDefaultArgument();
2577 }
2578
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002579 if (HasDefaultArg && !InDefaultArg) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002580 // When we see an optional default argument, put that argument and
2581 // the remaining default arguments into a new, optional string.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00002582 CodeCompletionBuilder Opt(Result.getAllocator(),
2583 Result.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002584 if (!FirstParameter)
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002585 Opt.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor75acd922011-09-27 23:30:47 +00002586 AddTemplateParameterChunks(Context, Policy, Template, Opt, MaxParameters,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002587 P - Params->begin(), true);
2588 Result.AddOptionalChunk(Opt.TakeString());
2589 break;
Douglas Gregor3545ff42009-09-21 16:56:56 +00002590 }
2591
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002592 InDefaultArg = false;
2593
Douglas Gregor3545ff42009-09-21 16:56:56 +00002594 if (FirstParameter)
2595 FirstParameter = false;
2596 else
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002597 Result.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor3545ff42009-09-21 16:56:56 +00002598
2599 // Add the placeholder string.
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002600 Result.AddPlaceholderChunk(
2601 Result.getAllocator().CopyString(PlaceholderStr));
Douglas Gregor3545ff42009-09-21 16:56:56 +00002602 }
2603}
2604
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002605/// Add a qualifier to the given code-completion string, if the
Douglas Gregorf2510672009-09-21 19:57:38 +00002606/// provided nested-name-specifier is non-NULL.
Douglas Gregor0f622362009-12-11 18:44:16 +00002607static void
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002608AddQualifierToCompletionString(CodeCompletionBuilder &Result,
Douglas Gregor0f622362009-12-11 18:44:16 +00002609 NestedNameSpecifier *Qualifier,
2610 bool QualifierIsInformative,
Douglas Gregor75acd922011-09-27 23:30:47 +00002611 ASTContext &Context,
2612 const PrintingPolicy &Policy) {
Douglas Gregorf2510672009-09-21 19:57:38 +00002613 if (!Qualifier)
2614 return;
2615
2616 std::string PrintedNNS;
2617 {
2618 llvm::raw_string_ostream OS(PrintedNNS);
Douglas Gregor75acd922011-09-27 23:30:47 +00002619 Qualifier->print(OS, Policy);
Douglas Gregorf2510672009-09-21 19:57:38 +00002620 }
Douglas Gregor5bf52692009-09-22 23:15:58 +00002621 if (QualifierIsInformative)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002622 Result.AddInformativeChunk(Result.getAllocator().CopyString(PrintedNNS));
Douglas Gregor5bf52692009-09-22 23:15:58 +00002623 else
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002624 Result.AddTextChunk(Result.getAllocator().CopyString(PrintedNNS));
Douglas Gregorf2510672009-09-21 19:57:38 +00002625}
2626
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002627static void
2628AddFunctionTypeQualsToCompletionString(CodeCompletionBuilder &Result,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002629 const FunctionDecl *Function) {
Douglas Gregor0f622362009-12-11 18:44:16 +00002630 const FunctionProtoType *Proto
2631 = Function->getType()->getAs<FunctionProtoType>();
2632 if (!Proto || !Proto->getTypeQuals())
2633 return;
2634
Douglas Gregor304f9b02011-02-01 21:15:40 +00002635 // FIXME: Add ref-qualifier!
2636
2637 // Handle single qualifiers without copying
2638 if (Proto->getTypeQuals() == Qualifiers::Const) {
2639 Result.AddInformativeChunk(" const");
2640 return;
2641 }
2642
2643 if (Proto->getTypeQuals() == Qualifiers::Volatile) {
2644 Result.AddInformativeChunk(" volatile");
2645 return;
2646 }
2647
2648 if (Proto->getTypeQuals() == Qualifiers::Restrict) {
2649 Result.AddInformativeChunk(" restrict");
2650 return;
2651 }
2652
2653 // Handle multiple qualifiers.
Douglas Gregor0f622362009-12-11 18:44:16 +00002654 std::string QualsStr;
David Blaikief5697e52012-08-10 00:55:35 +00002655 if (Proto->isConst())
Douglas Gregor0f622362009-12-11 18:44:16 +00002656 QualsStr += " const";
David Blaikief5697e52012-08-10 00:55:35 +00002657 if (Proto->isVolatile())
Douglas Gregor0f622362009-12-11 18:44:16 +00002658 QualsStr += " volatile";
David Blaikief5697e52012-08-10 00:55:35 +00002659 if (Proto->isRestrict())
Douglas Gregor0f622362009-12-11 18:44:16 +00002660 QualsStr += " restrict";
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002661 Result.AddInformativeChunk(Result.getAllocator().CopyString(QualsStr));
Douglas Gregor0f622362009-12-11 18:44:16 +00002662}
2663
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002664/// Add the name of the given declaration
Douglas Gregor75acd922011-09-27 23:30:47 +00002665static void AddTypedNameChunk(ASTContext &Context, const PrintingPolicy &Policy,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002666 const NamedDecl *ND,
2667 CodeCompletionBuilder &Result) {
Douglas Gregor0212fd72010-09-21 16:06:22 +00002668 DeclarationName Name = ND->getDeclName();
2669 if (!Name)
2670 return;
2671
2672 switch (Name.getNameKind()) {
Douglas Gregor304f9b02011-02-01 21:15:40 +00002673 case DeclarationName::CXXOperatorName: {
Craig Topperc3ec1492014-05-26 06:22:03 +00002674 const char *OperatorName = nullptr;
Douglas Gregor304f9b02011-02-01 21:15:40 +00002675 switch (Name.getCXXOverloadedOperator()) {
2676 case OO_None:
2677 case OO_Conditional:
2678 case NUM_OVERLOADED_OPERATORS:
2679 OperatorName = "operator";
2680 break;
2681
2682#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
2683 case OO_##Name: OperatorName = "operator" Spelling; break;
2684#define OVERLOADED_OPERATOR_MULTI(Name,Spelling,Unary,Binary,MemberOnly)
2685#include "clang/Basic/OperatorKinds.def"
2686
2687 case OO_New: OperatorName = "operator new"; break;
2688 case OO_Delete: OperatorName = "operator delete"; break;
2689 case OO_Array_New: OperatorName = "operator new[]"; break;
2690 case OO_Array_Delete: OperatorName = "operator delete[]"; break;
2691 case OO_Call: OperatorName = "operator()"; break;
2692 case OO_Subscript: OperatorName = "operator[]"; break;
2693 }
2694 Result.AddTypedTextChunk(OperatorName);
2695 break;
2696 }
2697
Douglas Gregor0212fd72010-09-21 16:06:22 +00002698 case DeclarationName::Identifier:
2699 case DeclarationName::CXXConversionFunctionName:
Douglas Gregor0212fd72010-09-21 16:06:22 +00002700 case DeclarationName::CXXDestructorName:
2701 case DeclarationName::CXXLiteralOperatorName:
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002702 Result.AddTypedTextChunk(
2703 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor0212fd72010-09-21 16:06:22 +00002704 break;
2705
Richard Smith35845152017-02-07 01:37:30 +00002706 case DeclarationName::CXXDeductionGuideName:
Douglas Gregor0212fd72010-09-21 16:06:22 +00002707 case DeclarationName::CXXUsingDirective:
2708 case DeclarationName::ObjCZeroArgSelector:
2709 case DeclarationName::ObjCOneArgSelector:
2710 case DeclarationName::ObjCMultiArgSelector:
2711 break;
2712
2713 case DeclarationName::CXXConstructorName: {
Craig Topperc3ec1492014-05-26 06:22:03 +00002714 CXXRecordDecl *Record = nullptr;
Douglas Gregor0212fd72010-09-21 16:06:22 +00002715 QualType Ty = Name.getCXXNameType();
2716 if (const RecordType *RecordTy = Ty->getAs<RecordType>())
2717 Record = cast<CXXRecordDecl>(RecordTy->getDecl());
2718 else if (const InjectedClassNameType *InjectedTy
2719 = Ty->getAs<InjectedClassNameType>())
2720 Record = InjectedTy->getDecl();
2721 else {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002722 Result.AddTypedTextChunk(
2723 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor0212fd72010-09-21 16:06:22 +00002724 break;
2725 }
2726
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002727 Result.AddTypedTextChunk(
2728 Result.getAllocator().CopyString(Record->getNameAsString()));
Douglas Gregor0212fd72010-09-21 16:06:22 +00002729 if (ClassTemplateDecl *Template = Record->getDescribedClassTemplate()) {
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002730 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Douglas Gregor75acd922011-09-27 23:30:47 +00002731 AddTemplateParameterChunks(Context, Policy, Template, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002732 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregor0212fd72010-09-21 16:06:22 +00002733 }
2734 break;
2735 }
2736 }
2737}
2738
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002739CodeCompletionString *CodeCompletionResult::CreateCodeCompletionString(Sema &S,
Douglas Gregorc3425b12015-07-07 06:20:19 +00002740 const CodeCompletionContext &CCContext,
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00002741 CodeCompletionAllocator &Allocator,
Dmitri Gribenko3292d062012-07-02 17:35:10 +00002742 CodeCompletionTUInfo &CCTUInfo,
2743 bool IncludeBriefComments) {
Douglas Gregorc3425b12015-07-07 06:20:19 +00002744 return CreateCodeCompletionString(S.Context, S.PP, CCContext, Allocator,
2745 CCTUInfo, IncludeBriefComments);
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002746}
2747
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002748/// If possible, create a new code completion string for the given
Douglas Gregor3545ff42009-09-21 16:56:56 +00002749/// result.
2750///
2751/// \returns Either a new, heap-allocated code completion string describing
2752/// how to use this result, or NULL to indicate that the string or name of the
2753/// result is all that is needed.
2754CodeCompletionString *
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002755CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx,
2756 Preprocessor &PP,
Douglas Gregorc3425b12015-07-07 06:20:19 +00002757 const CodeCompletionContext &CCContext,
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00002758 CodeCompletionAllocator &Allocator,
Dmitri Gribenko3292d062012-07-02 17:35:10 +00002759 CodeCompletionTUInfo &CCTUInfo,
2760 bool IncludeBriefComments) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00002761 CodeCompletionBuilder Result(Allocator, CCTUInfo, Priority, Availability);
Douglas Gregor9eb77012009-11-07 00:00:49 +00002762
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002763 PrintingPolicy Policy = getCompletionPrintingPolicy(Ctx, PP);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002764 if (Kind == RK_Pattern) {
2765 Pattern->Priority = Priority;
2766 Pattern->Availability = Availability;
Douglas Gregor78254c82012-03-27 23:34:16 +00002767
2768 if (Declaration) {
2769 Result.addParentContext(Declaration->getDeclContext());
Douglas Gregor78254c82012-03-27 23:34:16 +00002770 Pattern->ParentName = Result.getParentName();
Ilya Biryukova3f955b2018-05-16 12:30:01 +00002771 if (const RawComment *RC =
2772 getPatternCompletionComment(Ctx, Declaration)) {
2773 Result.addBriefComment(RC->getBriefText(Ctx));
2774 Pattern->BriefComment = Result.getBriefComment();
2775 }
Douglas Gregor78254c82012-03-27 23:34:16 +00002776 }
2777
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002778 return Pattern;
2779 }
Douglas Gregorf09935f2009-12-01 05:55:20 +00002780
Douglas Gregorf09935f2009-12-01 05:55:20 +00002781 if (Kind == RK_Keyword) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002782 Result.AddTypedTextChunk(Keyword);
2783 return Result.TakeString();
Douglas Gregorf09935f2009-12-01 05:55:20 +00002784 }
Douglas Gregor3545ff42009-09-21 16:56:56 +00002785
Douglas Gregorf329c7c2009-10-30 16:50:04 +00002786 if (Kind == RK_Macro) {
Richard Smith20e883e2015-04-29 23:20:19 +00002787 const MacroInfo *MI = PP.getMacroInfo(Macro);
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002788 Result.AddTypedTextChunk(
2789 Result.getAllocator().CopyString(Macro->getName()));
Douglas Gregorf09935f2009-12-01 05:55:20 +00002790
Ben Langmuirc28ce3a2014-09-30 20:00:18 +00002791 if (!MI || !MI->isFunctionLike())
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002792 return Result.TakeString();
Douglas Gregorf329c7c2009-10-30 16:50:04 +00002793
2794 // Format a function-like macro with placeholders for the arguments.
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002795 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Faisal Valiac506d72017-07-17 17:18:43 +00002796 MacroInfo::param_iterator A = MI->param_begin(), AEnd = MI->param_end();
Douglas Gregor3aa55262012-01-21 00:43:38 +00002797
2798 // C99 variadic macros add __VA_ARGS__ at the end. Skip it.
2799 if (MI->isC99Varargs()) {
2800 --AEnd;
2801
2802 if (A == AEnd) {
2803 Result.AddPlaceholderChunk("...");
2804 }
Douglas Gregor0c505312011-07-30 08:17:44 +00002805 }
Douglas Gregor3aa55262012-01-21 00:43:38 +00002806
Faisal Valiac506d72017-07-17 17:18:43 +00002807 for (MacroInfo::param_iterator A = MI->param_begin(); A != AEnd; ++A) {
2808 if (A != MI->param_begin())
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002809 Result.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor3aa55262012-01-21 00:43:38 +00002810
2811 if (MI->isVariadic() && (A+1) == AEnd) {
Dylan Noblesmith2c1dd272012-02-05 02:13:05 +00002812 SmallString<32> Arg = (*A)->getName();
Douglas Gregor3aa55262012-01-21 00:43:38 +00002813 if (MI->isC99Varargs())
2814 Arg += ", ...";
2815 else
2816 Arg += "...";
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002817 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregor3aa55262012-01-21 00:43:38 +00002818 break;
Douglas Gregorf329c7c2009-10-30 16:50:04 +00002819 }
Douglas Gregor3aa55262012-01-21 00:43:38 +00002820
2821 // Non-variadic macros are simple.
2822 Result.AddPlaceholderChunk(
2823 Result.getAllocator().CopyString((*A)->getName()));
Douglas Gregor0c505312011-07-30 08:17:44 +00002824 }
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002825 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002826 return Result.TakeString();
Douglas Gregorf329c7c2009-10-30 16:50:04 +00002827 }
2828
Douglas Gregorf64acca2010-05-25 21:41:55 +00002829 assert(Kind == RK_Declaration && "Missed a result kind?");
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002830 const NamedDecl *ND = Declaration;
Douglas Gregor78254c82012-03-27 23:34:16 +00002831 Result.addParentContext(ND->getDeclContext());
Dmitri Gribenko3292d062012-07-02 17:35:10 +00002832
2833 if (IncludeBriefComments) {
2834 // Add documentation comment, if it exists.
Ilya Biryukova3f955b2018-05-16 12:30:01 +00002835 if (const RawComment *RC = getCompletionComment(Ctx, Declaration)) {
Dmitri Gribenko3292d062012-07-02 17:35:10 +00002836 Result.addBriefComment(RC->getBriefText(Ctx));
Fariborz Jahanian15a0b552013-02-28 17:47:14 +00002837 }
Dmitri Gribenko3292d062012-07-02 17:35:10 +00002838 }
2839
Douglas Gregor9eb77012009-11-07 00:00:49 +00002840 if (StartsNestedNameSpecifier) {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002841 Result.AddTypedTextChunk(
2842 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002843 Result.AddTextChunk("::");
2844 return Result.TakeString();
Douglas Gregor9eb77012009-11-07 00:00:49 +00002845 }
Erik Verbruggen98ea7f62011-10-14 15:31:08 +00002846
Aaron Ballmanbe22bcb2014-03-10 17:08:28 +00002847 for (const auto *I : ND->specific_attrs<AnnotateAttr>())
2848 Result.AddAnnotation(Result.getAllocator().CopyString(I->getAnnotation()));
Aaron Ballmanb97112e2014-03-08 22:19:01 +00002849
Douglas Gregorc3425b12015-07-07 06:20:19 +00002850 AddResultTypeChunk(Ctx, Policy, ND, CCContext.getBaseType(), Result);
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002851
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002852 if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(ND)) {
Douglas Gregor5bf52692009-09-22 23:15:58 +00002853 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002854 Ctx, Policy);
2855 AddTypedNameChunk(Ctx, Policy, ND, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002856 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Richard Smith20e883e2015-04-29 23:20:19 +00002857 AddFunctionParameterChunks(PP, Policy, Function, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002858 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor0f622362009-12-11 18:44:16 +00002859 AddFunctionTypeQualsToCompletionString(Result, Function);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002860 return Result.TakeString();
Douglas Gregor3545ff42009-09-21 16:56:56 +00002861 }
2862
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002863 if (const FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND)) {
Douglas Gregor5bf52692009-09-22 23:15:58 +00002864 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002865 Ctx, Policy);
Douglas Gregor3545ff42009-09-21 16:56:56 +00002866 FunctionDecl *Function = FunTmpl->getTemplatedDecl();
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002867 AddTypedNameChunk(Ctx, Policy, Function, Result);
Douglas Gregor0212fd72010-09-21 16:06:22 +00002868
Douglas Gregor3545ff42009-09-21 16:56:56 +00002869 // Figure out which template parameters are deduced (or have default
2870 // arguments).
Benjamin Kramere0513cb2012-01-30 16:17:39 +00002871 llvm::SmallBitVector Deduced;
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002872 Sema::MarkDeducedTemplateParameters(Ctx, FunTmpl, Deduced);
Douglas Gregor3545ff42009-09-21 16:56:56 +00002873 unsigned LastDeducibleArgument;
2874 for (LastDeducibleArgument = Deduced.size(); LastDeducibleArgument > 0;
2875 --LastDeducibleArgument) {
2876 if (!Deduced[LastDeducibleArgument - 1]) {
2877 // C++0x: Figure out if the template argument has a default. If so,
2878 // the user doesn't need to type this argument.
2879 // FIXME: We need to abstract template parameters better!
2880 bool HasDefaultArg = false;
2881 NamedDecl *Param = FunTmpl->getTemplateParameters()->getParam(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002882 LastDeducibleArgument - 1);
Douglas Gregor3545ff42009-09-21 16:56:56 +00002883 if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param))
2884 HasDefaultArg = TTP->hasDefaultArgument();
2885 else if (NonTypeTemplateParmDecl *NTTP
2886 = dyn_cast<NonTypeTemplateParmDecl>(Param))
2887 HasDefaultArg = NTTP->hasDefaultArgument();
2888 else {
2889 assert(isa<TemplateTemplateParmDecl>(Param));
2890 HasDefaultArg
Douglas Gregor9eb77012009-11-07 00:00:49 +00002891 = cast<TemplateTemplateParmDecl>(Param)->hasDefaultArgument();
Douglas Gregor3545ff42009-09-21 16:56:56 +00002892 }
2893
2894 if (!HasDefaultArg)
2895 break;
2896 }
2897 }
2898
2899 if (LastDeducibleArgument) {
2900 // Some of the function template arguments cannot be deduced from a
2901 // function call, so we introduce an explicit template argument list
2902 // containing all of the arguments up to the first deducible argument.
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002903 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002904 AddTemplateParameterChunks(Ctx, Policy, FunTmpl, Result,
Douglas Gregor3545ff42009-09-21 16:56:56 +00002905 LastDeducibleArgument);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002906 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregor3545ff42009-09-21 16:56:56 +00002907 }
2908
2909 // Add the function parameters
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002910 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Richard Smith20e883e2015-04-29 23:20:19 +00002911 AddFunctionParameterChunks(PP, Policy, Function, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002912 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor0f622362009-12-11 18:44:16 +00002913 AddFunctionTypeQualsToCompletionString(Result, Function);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002914 return Result.TakeString();
Douglas Gregor3545ff42009-09-21 16:56:56 +00002915 }
2916
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002917 if (const TemplateDecl *Template = dyn_cast<TemplateDecl>(ND)) {
Douglas Gregor5bf52692009-09-22 23:15:58 +00002918 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002919 Ctx, Policy);
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002920 Result.AddTypedTextChunk(
2921 Result.getAllocator().CopyString(Template->getNameAsString()));
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002922 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002923 AddTemplateParameterChunks(Ctx, Policy, Template, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002924 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002925 return Result.TakeString();
Douglas Gregor3545ff42009-09-21 16:56:56 +00002926 }
2927
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002928 if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND)) {
Douglas Gregord3c5d792009-11-17 16:44:22 +00002929 Selector Sel = Method->getSelector();
2930 if (Sel.isUnarySelector()) {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002931 Result.AddTypedTextChunk(Result.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00002932 Sel.getNameForSlot(0)));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002933 return Result.TakeString();
Douglas Gregord3c5d792009-11-17 16:44:22 +00002934 }
2935
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00002936 std::string SelName = Sel.getNameForSlot(0).str();
Douglas Gregor1b605f72009-11-19 01:08:35 +00002937 SelName += ':';
2938 if (StartParameter == 0)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002939 Result.AddTypedTextChunk(Result.getAllocator().CopyString(SelName));
Douglas Gregor1b605f72009-11-19 01:08:35 +00002940 else {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002941 Result.AddInformativeChunk(Result.getAllocator().CopyString(SelName));
Douglas Gregor1b605f72009-11-19 01:08:35 +00002942
2943 // If there is only one parameter, and we're past it, add an empty
2944 // typed-text chunk since there is nothing to type.
2945 if (Method->param_size() == 1)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002946 Result.AddTypedTextChunk("");
Douglas Gregor1b605f72009-11-19 01:08:35 +00002947 }
Douglas Gregord3c5d792009-11-17 16:44:22 +00002948 unsigned Idx = 0;
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002949 for (ObjCMethodDecl::param_const_iterator P = Method->param_begin(),
2950 PEnd = Method->param_end();
Douglas Gregord3c5d792009-11-17 16:44:22 +00002951 P != PEnd; (void)++P, ++Idx) {
2952 if (Idx > 0) {
Douglas Gregor1b605f72009-11-19 01:08:35 +00002953 std::string Keyword;
2954 if (Idx > StartParameter)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002955 Result.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregord3c5d792009-11-17 16:44:22 +00002956 if (IdentifierInfo *II = Sel.getIdentifierInfoForSlot(Idx))
Benjamin Kramer632500c2011-07-26 16:59:25 +00002957 Keyword += II->getName();
Douglas Gregord3c5d792009-11-17 16:44:22 +00002958 Keyword += ":";
Douglas Gregor95887f92010-07-08 23:20:03 +00002959 if (Idx < StartParameter || AllParametersAreInformative)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002960 Result.AddInformativeChunk(Result.getAllocator().CopyString(Keyword));
Douglas Gregor8e3e8742010-10-18 21:05:04 +00002961 else
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002962 Result.AddTypedTextChunk(Result.getAllocator().CopyString(Keyword));
Douglas Gregord3c5d792009-11-17 16:44:22 +00002963 }
Douglas Gregor1b605f72009-11-19 01:08:35 +00002964
2965 // If we're before the starting parameter, skip the placeholder.
2966 if (Idx < StartParameter)
2967 continue;
Douglas Gregord3c5d792009-11-17 16:44:22 +00002968
2969 std::string Arg;
Douglas Gregorc3425b12015-07-07 06:20:19 +00002970 QualType ParamType = (*P)->getType();
2971 Optional<ArrayRef<QualType>> ObjCSubsts;
2972 if (!CCContext.getBaseType().isNull())
2973 ObjCSubsts = CCContext.getBaseType()->getObjCSubstitutions(Method);
2974
2975 if (ParamType->isBlockPointerType() && !DeclaringEntity)
2976 Arg = FormatFunctionParameter(Policy, *P, true,
2977 /*SuppressBlock=*/false,
2978 ObjCSubsts);
Douglas Gregore90dd002010-08-24 16:15:59 +00002979 else {
Douglas Gregorc3425b12015-07-07 06:20:19 +00002980 if (ObjCSubsts)
2981 ParamType = ParamType.substObjCTypeArgs(Ctx, *ObjCSubsts,
2982 ObjCSubstitutionContext::Parameter);
Douglas Gregor86b42682015-06-19 18:27:52 +00002983 Arg = "(" + formatObjCParamQualifiers((*P)->getObjCDeclQualifier(),
Douglas Gregorc3425b12015-07-07 06:20:19 +00002984 ParamType);
2985 Arg += ParamType.getAsString(Policy) + ")";
Douglas Gregore90dd002010-08-24 16:15:59 +00002986 if (IdentifierInfo *II = (*P)->getIdentifier())
Douglas Gregor981a0c42010-08-29 19:47:46 +00002987 if (DeclaringEntity || AllParametersAreInformative)
Benjamin Kramer632500c2011-07-26 16:59:25 +00002988 Arg += II->getName();
Douglas Gregore90dd002010-08-24 16:15:59 +00002989 }
2990
Douglas Gregor400f5972010-08-31 05:13:43 +00002991 if (Method->isVariadic() && (P + 1) == PEnd)
2992 Arg += ", ...";
2993
Douglas Gregor95887f92010-07-08 23:20:03 +00002994 if (DeclaringEntity)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002995 Result.AddTextChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregor95887f92010-07-08 23:20:03 +00002996 else if (AllParametersAreInformative)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002997 Result.AddInformativeChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregorc8537c52009-11-19 07:41:15 +00002998 else
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002999 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregord3c5d792009-11-17 16:44:22 +00003000 }
3001
Douglas Gregor04c5f972009-12-23 00:21:46 +00003002 if (Method->isVariadic()) {
Douglas Gregor400f5972010-08-31 05:13:43 +00003003 if (Method->param_size() == 0) {
3004 if (DeclaringEntity)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003005 Result.AddTextChunk(", ...");
Douglas Gregor400f5972010-08-31 05:13:43 +00003006 else if (AllParametersAreInformative)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003007 Result.AddInformativeChunk(", ...");
Douglas Gregor400f5972010-08-31 05:13:43 +00003008 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003009 Result.AddPlaceholderChunk(", ...");
Douglas Gregor400f5972010-08-31 05:13:43 +00003010 }
Douglas Gregordbb71db2010-08-23 23:51:41 +00003011
Richard Smith20e883e2015-04-29 23:20:19 +00003012 MaybeAddSentinel(PP, Method, Result);
Douglas Gregor04c5f972009-12-23 00:21:46 +00003013 }
3014
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003015 return Result.TakeString();
Douglas Gregord3c5d792009-11-17 16:44:22 +00003016 }
3017
Douglas Gregorf09935f2009-12-01 05:55:20 +00003018 if (Qualifier)
Douglas Gregor5bf52692009-09-22 23:15:58 +00003019 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003020 Ctx, Policy);
Douglas Gregorf09935f2009-12-01 05:55:20 +00003021
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003022 Result.AddTypedTextChunk(
3023 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003024 return Result.TakeString();
Douglas Gregor3545ff42009-09-21 16:56:56 +00003025}
3026
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003027const RawComment *clang::getCompletionComment(const ASTContext &Ctx,
3028 const NamedDecl *ND) {
3029 if (!ND)
3030 return nullptr;
3031 if (auto *RC = Ctx.getRawCommentForAnyRedecl(ND))
3032 return RC;
3033
3034 // Try to find comment from a property for ObjC methods.
3035 const ObjCMethodDecl *M = dyn_cast<ObjCMethodDecl>(ND);
3036 if (!M)
3037 return nullptr;
3038 const ObjCPropertyDecl *PDecl = M->findPropertyDecl();
3039 if (!PDecl)
3040 return nullptr;
3041
3042 return Ctx.getRawCommentForAnyRedecl(PDecl);
3043}
3044
3045const RawComment *clang::getPatternCompletionComment(const ASTContext &Ctx,
3046 const NamedDecl *ND) {
3047 const ObjCMethodDecl *M = dyn_cast_or_null<ObjCMethodDecl>(ND);
3048 if (!M || !M->isPropertyAccessor())
3049 return nullptr;
3050
3051 // Provide code completion comment for self.GetterName where
3052 // GetterName is the getter method for a property with name
3053 // different from the property name (declared via a property
3054 // getter attribute.
3055 const ObjCPropertyDecl *PDecl = M->findPropertyDecl();
3056 if (!PDecl)
3057 return nullptr;
3058 if (PDecl->getGetterName() == M->getSelector() &&
3059 PDecl->getIdentifier() != M->getIdentifier()) {
3060 if (auto *RC = Ctx.getRawCommentForAnyRedecl(M))
3061 return RC;
3062 if (auto *RC = Ctx.getRawCommentForAnyRedecl(PDecl))
3063 return RC;
3064 }
3065 return nullptr;
3066}
3067
3068const RawComment *clang::getParameterComment(
3069 const ASTContext &Ctx,
3070 const CodeCompleteConsumer::OverloadCandidate &Result,
3071 unsigned ArgIndex) {
3072 auto FDecl = Result.getFunction();
3073 if (!FDecl)
3074 return nullptr;
3075 if (ArgIndex < FDecl->getNumParams())
3076 return Ctx.getRawCommentForAnyRedecl(FDecl->getParamDecl(ArgIndex));
3077 return nullptr;
3078}
3079
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003080/// Add function overload parameter chunks to the given code completion
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003081/// string.
3082static void AddOverloadParameterChunks(ASTContext &Context,
3083 const PrintingPolicy &Policy,
3084 const FunctionDecl *Function,
3085 const FunctionProtoType *Prototype,
3086 CodeCompletionBuilder &Result,
3087 unsigned CurrentArg,
3088 unsigned Start = 0,
3089 bool InOptional = false) {
3090 bool FirstParameter = true;
3091 unsigned NumParams = Function ? Function->getNumParams()
3092 : Prototype->getNumParams();
3093
3094 for (unsigned P = Start; P != NumParams; ++P) {
3095 if (Function && Function->getParamDecl(P)->hasDefaultArg() && !InOptional) {
3096 // When we see an optional default argument, put that argument and
3097 // the remaining default arguments into a new, optional string.
3098 CodeCompletionBuilder Opt(Result.getAllocator(),
3099 Result.getCodeCompletionTUInfo());
3100 if (!FirstParameter)
3101 Opt.AddChunk(CodeCompletionString::CK_Comma);
3102 // Optional sections are nested.
3103 AddOverloadParameterChunks(Context, Policy, Function, Prototype, Opt,
3104 CurrentArg, P, /*InOptional=*/true);
3105 Result.AddOptionalChunk(Opt.TakeString());
3106 return;
3107 }
3108
3109 if (FirstParameter)
3110 FirstParameter = false;
3111 else
3112 Result.AddChunk(CodeCompletionString::CK_Comma);
3113
3114 InOptional = false;
3115
3116 // Format the placeholder string.
3117 std::string Placeholder;
Erik Verbruggen11338c52017-07-19 10:45:40 +00003118 if (Function) {
3119 const ParmVarDecl *Param = Function->getParamDecl(P);
3120 Placeholder = FormatFunctionParameter(Policy, Param);
3121 if (Param->hasDefaultArg())
3122 Placeholder += GetDefaultValueString(Param, Context.getSourceManager(), Context.getLangOpts());
3123 } else {
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003124 Placeholder = Prototype->getParamType(P).getAsString(Policy);
Erik Verbruggen11338c52017-07-19 10:45:40 +00003125 }
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003126
3127 if (P == CurrentArg)
3128 Result.AddCurrentParameterChunk(
3129 Result.getAllocator().CopyString(Placeholder));
3130 else
3131 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Placeholder));
3132 }
3133
3134 if (Prototype && Prototype->isVariadic()) {
3135 CodeCompletionBuilder Opt(Result.getAllocator(),
3136 Result.getCodeCompletionTUInfo());
3137 if (!FirstParameter)
3138 Opt.AddChunk(CodeCompletionString::CK_Comma);
3139
3140 if (CurrentArg < NumParams)
3141 Opt.AddPlaceholderChunk("...");
3142 else
3143 Opt.AddCurrentParameterChunk("...");
3144
3145 Result.AddOptionalChunk(Opt.TakeString());
3146 }
3147}
3148
Douglas Gregorf0f51982009-09-23 00:34:09 +00003149CodeCompletionString *
3150CodeCompleteConsumer::OverloadCandidate::CreateSignatureString(
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003151 unsigned CurrentArg, Sema &S,
3152 CodeCompletionAllocator &Allocator,
3153 CodeCompletionTUInfo &CCTUInfo,
3154 bool IncludeBriefComments) const {
Douglas Gregor75acd922011-09-27 23:30:47 +00003155 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
John McCall31168b02011-06-15 23:02:42 +00003156
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003157 // FIXME: Set priority, availability appropriately.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003158 CodeCompletionBuilder Result(Allocator,CCTUInfo, 1, CXAvailability_Available);
Douglas Gregorf0f51982009-09-23 00:34:09 +00003159 FunctionDecl *FDecl = getFunction();
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003160 const FunctionProtoType *Proto
Douglas Gregorf0f51982009-09-23 00:34:09 +00003161 = dyn_cast<FunctionProtoType>(getFunctionType());
3162 if (!FDecl && !Proto) {
3163 // Function without a prototype. Just give the return type and a
3164 // highlighted ellipsis.
3165 const FunctionType *FT = getFunctionType();
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003166 Result.AddResultTypeChunk(Result.getAllocator().CopyString(
3167 FT->getReturnType().getAsString(Policy)));
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003168 Result.AddChunk(CodeCompletionString::CK_LeftParen);
3169 Result.AddChunk(CodeCompletionString::CK_CurrentParameter, "...");
3170 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003171 return Result.TakeString();
Douglas Gregorf0f51982009-09-23 00:34:09 +00003172 }
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003173
3174 if (FDecl) {
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003175 if (IncludeBriefComments) {
3176 if (auto RC = getParameterComment(S.getASTContext(), *this, CurrentArg))
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003177 Result.addBriefComment(RC->getBriefText(S.getASTContext()));
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003178 }
Douglas Gregorc3425b12015-07-07 06:20:19 +00003179 AddResultTypeChunk(S.Context, Policy, FDecl, QualType(), Result);
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003180 Result.AddTextChunk(
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003181 Result.getAllocator().CopyString(FDecl->getNameAsString()));
3182 } else {
3183 Result.AddResultTypeChunk(
3184 Result.getAllocator().CopyString(
Alp Toker314cc812014-01-25 16:55:45 +00003185 Proto->getReturnType().getAsString(Policy)));
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003186 }
Alp Toker314cc812014-01-25 16:55:45 +00003187
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003188 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003189 AddOverloadParameterChunks(S.getASTContext(), Policy, FDecl, Proto, Result,
3190 CurrentArg);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003191 Result.AddChunk(CodeCompletionString::CK_RightParen);
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003192
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003193 return Result.TakeString();
Douglas Gregorf0f51982009-09-23 00:34:09 +00003194}
3195
Chris Lattner0e62c1c2011-07-23 10:55:15 +00003196unsigned clang::getMacroUsagePriority(StringRef MacroName,
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00003197 const LangOptions &LangOpts,
Douglas Gregor6e240332010-08-16 16:18:59 +00003198 bool PreferredTypeIsPointer) {
3199 unsigned Priority = CCP_Macro;
3200
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00003201 // Treat the "nil", "Nil" and "NULL" macros as null pointer constants.
3202 if (MacroName.equals("nil") || MacroName.equals("NULL") ||
3203 MacroName.equals("Nil")) {
Douglas Gregor6e240332010-08-16 16:18:59 +00003204 Priority = CCP_Constant;
3205 if (PreferredTypeIsPointer)
3206 Priority = Priority / CCF_SimilarTypeMatch;
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00003207 }
3208 // Treat "YES", "NO", "true", and "false" as constants.
3209 else if (MacroName.equals("YES") || MacroName.equals("NO") ||
3210 MacroName.equals("true") || MacroName.equals("false"))
3211 Priority = CCP_Constant;
3212 // Treat "bool" as a type.
3213 else if (MacroName.equals("bool"))
3214 Priority = CCP_Type + (LangOpts.ObjC1? CCD_bool_in_ObjC : 0);
3215
Douglas Gregor6e240332010-08-16 16:18:59 +00003216
3217 return Priority;
3218}
3219
Dmitri Gribenkobdc80de2013-01-11 20:32:41 +00003220CXCursorKind clang::getCursorKindForDecl(const Decl *D) {
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003221 if (!D)
3222 return CXCursor_UnexposedDecl;
3223
3224 switch (D->getKind()) {
3225 case Decl::Enum: return CXCursor_EnumDecl;
3226 case Decl::EnumConstant: return CXCursor_EnumConstantDecl;
3227 case Decl::Field: return CXCursor_FieldDecl;
3228 case Decl::Function:
3229 return CXCursor_FunctionDecl;
3230 case Decl::ObjCCategory: return CXCursor_ObjCCategoryDecl;
3231 case Decl::ObjCCategoryImpl: return CXCursor_ObjCCategoryImplDecl;
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003232 case Decl::ObjCImplementation: return CXCursor_ObjCImplementationDecl;
Douglas Gregordeafd0b2011-12-27 22:43:10 +00003233
Argyrios Kyrtzidis3698cef2012-01-24 21:39:26 +00003234 case Decl::ObjCInterface: return CXCursor_ObjCInterfaceDecl;
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003235 case Decl::ObjCIvar: return CXCursor_ObjCIvarDecl;
3236 case Decl::ObjCMethod:
3237 return cast<ObjCMethodDecl>(D)->isInstanceMethod()
3238 ? CXCursor_ObjCInstanceMethodDecl : CXCursor_ObjCClassMethodDecl;
3239 case Decl::CXXMethod: return CXCursor_CXXMethod;
3240 case Decl::CXXConstructor: return CXCursor_Constructor;
3241 case Decl::CXXDestructor: return CXCursor_Destructor;
3242 case Decl::CXXConversion: return CXCursor_ConversionFunction;
3243 case Decl::ObjCProperty: return CXCursor_ObjCPropertyDecl;
Argyrios Kyrtzidis3698cef2012-01-24 21:39:26 +00003244 case Decl::ObjCProtocol: return CXCursor_ObjCProtocolDecl;
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003245 case Decl::ParmVar: return CXCursor_ParmDecl;
3246 case Decl::Typedef: return CXCursor_TypedefDecl;
Richard Smithdda56e42011-04-15 14:24:37 +00003247 case Decl::TypeAlias: return CXCursor_TypeAliasDecl;
Sergey Kalinichev8f3b1872015-11-15 13:48:32 +00003248 case Decl::TypeAliasTemplate: return CXCursor_TypeAliasTemplateDecl;
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003249 case Decl::Var: return CXCursor_VarDecl;
3250 case Decl::Namespace: return CXCursor_Namespace;
3251 case Decl::NamespaceAlias: return CXCursor_NamespaceAlias;
3252 case Decl::TemplateTypeParm: return CXCursor_TemplateTypeParameter;
3253 case Decl::NonTypeTemplateParm:return CXCursor_NonTypeTemplateParameter;
3254 case Decl::TemplateTemplateParm:return CXCursor_TemplateTemplateParameter;
3255 case Decl::FunctionTemplate: return CXCursor_FunctionTemplate;
3256 case Decl::ClassTemplate: return CXCursor_ClassTemplate;
Argyrios Kyrtzidis12afd702011-09-30 17:58:23 +00003257 case Decl::AccessSpec: return CXCursor_CXXAccessSpecifier;
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003258 case Decl::ClassTemplatePartialSpecialization:
3259 return CXCursor_ClassTemplatePartialSpecialization;
3260 case Decl::UsingDirective: return CXCursor_UsingDirective;
Olivier Goffart81978012016-06-09 16:15:55 +00003261 case Decl::StaticAssert: return CXCursor_StaticAssert;
Olivier Goffartd211c642016-11-04 06:29:27 +00003262 case Decl::Friend: return CXCursor_FriendDecl;
Douglas Gregor3e653b32012-04-30 23:41:16 +00003263 case Decl::TranslationUnit: return CXCursor_TranslationUnit;
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003264
3265 case Decl::Using:
3266 case Decl::UnresolvedUsingValue:
3267 case Decl::UnresolvedUsingTypename:
3268 return CXCursor_UsingDeclaration;
3269
Douglas Gregor4cd65962011-06-03 23:08:58 +00003270 case Decl::ObjCPropertyImpl:
3271 switch (cast<ObjCPropertyImplDecl>(D)->getPropertyImplementation()) {
3272 case ObjCPropertyImplDecl::Dynamic:
3273 return CXCursor_ObjCDynamicDecl;
3274
3275 case ObjCPropertyImplDecl::Synthesize:
3276 return CXCursor_ObjCSynthesizeDecl;
3277 }
Argyrios Kyrtzidis50e5b1d2012-10-05 00:22:24 +00003278
3279 case Decl::Import:
3280 return CXCursor_ModuleImportDecl;
Douglas Gregor85f3f952015-07-07 03:57:15 +00003281
3282 case Decl::ObjCTypeParam: return CXCursor_TemplateTypeParameter;
3283
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003284 default:
Dmitri Gribenkobdc80de2013-01-11 20:32:41 +00003285 if (const TagDecl *TD = dyn_cast<TagDecl>(D)) {
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003286 switch (TD->getTagKind()) {
Joao Matosdc86f942012-08-31 18:45:21 +00003287 case TTK_Interface: // fall through
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003288 case TTK_Struct: return CXCursor_StructDecl;
3289 case TTK_Class: return CXCursor_ClassDecl;
3290 case TTK_Union: return CXCursor_UnionDecl;
3291 case TTK_Enum: return CXCursor_EnumDecl;
3292 }
3293 }
3294 }
3295
3296 return CXCursor_UnexposedDecl;
3297}
3298
Douglas Gregor55b037b2010-07-08 20:55:51 +00003299static void AddMacroResults(Preprocessor &PP, ResultBuilder &Results,
Douglas Gregor8cb17462012-10-09 16:01:50 +00003300 bool IncludeUndefined,
Douglas Gregor55b037b2010-07-08 20:55:51 +00003301 bool TargetTypeIsPointer = false) {
John McCall276321a2010-08-25 06:19:51 +00003302 typedef CodeCompletionResult Result;
Douglas Gregor55b037b2010-07-08 20:55:51 +00003303
Douglas Gregorf329c7c2009-10-30 16:50:04 +00003304 Results.EnterNewScope();
Douglas Gregor8e3e8742010-10-18 21:05:04 +00003305
Douglas Gregor9eb77012009-11-07 00:00:49 +00003306 for (Preprocessor::macro_iterator M = PP.macro_begin(),
3307 MEnd = PP.macro_end();
Douglas Gregor55b037b2010-07-08 20:55:51 +00003308 M != MEnd; ++M) {
Richard Smith20e883e2015-04-29 23:20:19 +00003309 auto MD = PP.getMacroDefinition(M->first);
3310 if (IncludeUndefined || MD) {
3311 if (MacroInfo *MI = MD.getMacroInfo())
Argyrios Kyrtzidis9ef53ce2014-04-09 18:21:23 +00003312 if (MI->isUsedForHeaderGuard())
3313 continue;
3314
Douglas Gregor8cb17462012-10-09 16:01:50 +00003315 Results.AddResult(Result(M->first,
Douglas Gregor6e240332010-08-16 16:18:59 +00003316 getMacroUsagePriority(M->first->getName(),
David Blaikiebbafb8a2012-03-11 07:00:24 +00003317 PP.getLangOpts(),
Douglas Gregor6e240332010-08-16 16:18:59 +00003318 TargetTypeIsPointer)));
Argyrios Kyrtzidis9ef53ce2014-04-09 18:21:23 +00003319 }
Douglas Gregor55b037b2010-07-08 20:55:51 +00003320 }
Douglas Gregor8e3e8742010-10-18 21:05:04 +00003321
Douglas Gregorf329c7c2009-10-30 16:50:04 +00003322 Results.ExitScope();
Douglas Gregor8e3e8742010-10-18 21:05:04 +00003323
Douglas Gregorf329c7c2009-10-30 16:50:04 +00003324}
3325
Douglas Gregorce0e8562010-08-23 21:54:33 +00003326static void AddPrettyFunctionResults(const LangOptions &LangOpts,
3327 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00003328 typedef CodeCompletionResult Result;
Douglas Gregorce0e8562010-08-23 21:54:33 +00003329
3330 Results.EnterNewScope();
Douglas Gregor8e3e8742010-10-18 21:05:04 +00003331
Douglas Gregorce0e8562010-08-23 21:54:33 +00003332 Results.AddResult(Result("__PRETTY_FUNCTION__", CCP_Constant));
3333 Results.AddResult(Result("__FUNCTION__", CCP_Constant));
Richard Smith2bf7fdb2013-01-02 11:42:31 +00003334 if (LangOpts.C99 || LangOpts.CPlusPlus11)
Douglas Gregorce0e8562010-08-23 21:54:33 +00003335 Results.AddResult(Result("__func__", CCP_Constant));
3336 Results.ExitScope();
3337}
3338
Daniel Dunbar242ea9a2009-11-13 08:58:20 +00003339static void HandleCodeCompleteResults(Sema *S,
3340 CodeCompleteConsumer *CodeCompleter,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003341 CodeCompletionContext Context,
John McCall276321a2010-08-25 06:19:51 +00003342 CodeCompletionResult *Results,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003343 unsigned NumResults) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00003344 if (CodeCompleter)
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003345 CodeCompleter->ProcessCodeCompleteResults(*S, Context, Results, NumResults);
Douglas Gregor3545ff42009-09-21 16:56:56 +00003346}
3347
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003348static enum CodeCompletionContext::Kind mapCodeCompletionContext(Sema &S,
3349 Sema::ParserCompletionContext PCC) {
3350 switch (PCC) {
John McCallfaf5fb42010-08-26 23:41:50 +00003351 case Sema::PCC_Namespace:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003352 return CodeCompletionContext::CCC_TopLevel;
3353
John McCallfaf5fb42010-08-26 23:41:50 +00003354 case Sema::PCC_Class:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003355 return CodeCompletionContext::CCC_ClassStructUnion;
3356
John McCallfaf5fb42010-08-26 23:41:50 +00003357 case Sema::PCC_ObjCInterface:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003358 return CodeCompletionContext::CCC_ObjCInterface;
3359
John McCallfaf5fb42010-08-26 23:41:50 +00003360 case Sema::PCC_ObjCImplementation:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003361 return CodeCompletionContext::CCC_ObjCImplementation;
3362
John McCallfaf5fb42010-08-26 23:41:50 +00003363 case Sema::PCC_ObjCInstanceVariableList:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003364 return CodeCompletionContext::CCC_ObjCIvarList;
3365
John McCallfaf5fb42010-08-26 23:41:50 +00003366 case Sema::PCC_Template:
3367 case Sema::PCC_MemberTemplate:
Douglas Gregor0ac41382010-09-23 23:01:17 +00003368 if (S.CurContext->isFileContext())
3369 return CodeCompletionContext::CCC_TopLevel;
David Blaikie8a40f702012-01-17 06:56:22 +00003370 if (S.CurContext->isRecord())
Douglas Gregor0ac41382010-09-23 23:01:17 +00003371 return CodeCompletionContext::CCC_ClassStructUnion;
David Blaikie8a40f702012-01-17 06:56:22 +00003372 return CodeCompletionContext::CCC_Other;
Douglas Gregor0ac41382010-09-23 23:01:17 +00003373
John McCallfaf5fb42010-08-26 23:41:50 +00003374 case Sema::PCC_RecoveryInFunction:
Douglas Gregor0ac41382010-09-23 23:01:17 +00003375 return CodeCompletionContext::CCC_Recovery;
Douglas Gregorc769d6e2010-10-18 22:01:46 +00003376
John McCallfaf5fb42010-08-26 23:41:50 +00003377 case Sema::PCC_ForInit:
David Blaikiebbafb8a2012-03-11 07:00:24 +00003378 if (S.getLangOpts().CPlusPlus || S.getLangOpts().C99 ||
3379 S.getLangOpts().ObjC1)
Douglas Gregorc769d6e2010-10-18 22:01:46 +00003380 return CodeCompletionContext::CCC_ParenthesizedExpression;
3381 else
3382 return CodeCompletionContext::CCC_Expression;
3383
3384 case Sema::PCC_Expression:
John McCallfaf5fb42010-08-26 23:41:50 +00003385 case Sema::PCC_Condition:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003386 return CodeCompletionContext::CCC_Expression;
3387
John McCallfaf5fb42010-08-26 23:41:50 +00003388 case Sema::PCC_Statement:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003389 return CodeCompletionContext::CCC_Statement;
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003390
John McCallfaf5fb42010-08-26 23:41:50 +00003391 case Sema::PCC_Type:
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003392 return CodeCompletionContext::CCC_Type;
Douglas Gregor5e35d592010-09-14 23:59:36 +00003393
3394 case Sema::PCC_ParenthesizedExpression:
3395 return CodeCompletionContext::CCC_ParenthesizedExpression;
Douglas Gregor80039242011-02-15 20:33:25 +00003396
3397 case Sema::PCC_LocalDeclarationSpecifiers:
3398 return CodeCompletionContext::CCC_Type;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003399 }
David Blaikie8a40f702012-01-17 06:56:22 +00003400
3401 llvm_unreachable("Invalid ParserCompletionContext!");
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003402}
3403
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003404/// If we're in a C++ virtual member function, add completion results
Douglas Gregorac322ec2010-08-27 21:18:54 +00003405/// that invoke the functions we override, since it's common to invoke the
3406/// overridden function as well as adding new functionality.
3407///
3408/// \param S The semantic analysis object for which we are generating results.
3409///
3410/// \param InContext This context in which the nested-name-specifier preceding
3411/// the code-completion point
3412static void MaybeAddOverrideCalls(Sema &S, DeclContext *InContext,
3413 ResultBuilder &Results) {
3414 // Look through blocks.
3415 DeclContext *CurContext = S.CurContext;
3416 while (isa<BlockDecl>(CurContext))
3417 CurContext = CurContext->getParent();
3418
3419
3420 CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(CurContext);
3421 if (!Method || !Method->isVirtual())
3422 return;
3423
3424 // We need to have names for all of the parameters, if we're going to
3425 // generate a forwarding call.
David Majnemer59f77922016-06-24 04:05:48 +00003426 for (auto P : Method->parameters())
Aaron Ballman43b68be2014-03-07 17:50:17 +00003427 if (!P->getDeclName())
Douglas Gregorac322ec2010-08-27 21:18:54 +00003428 return;
Douglas Gregorac322ec2010-08-27 21:18:54 +00003429
Douglas Gregor75acd922011-09-27 23:30:47 +00003430 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
Benjamin Krameracfa3392017-12-17 23:52:45 +00003431 for (const CXXMethodDecl *Overridden : Method->overridden_methods()) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003432 CodeCompletionBuilder Builder(Results.getAllocator(),
3433 Results.getCodeCompletionTUInfo());
Douglas Gregorac322ec2010-08-27 21:18:54 +00003434 if (Overridden->getCanonicalDecl() == Method->getCanonicalDecl())
3435 continue;
3436
3437 // If we need a nested-name-specifier, add one now.
3438 if (!InContext) {
3439 NestedNameSpecifier *NNS
3440 = getRequiredQualification(S.Context, CurContext,
3441 Overridden->getDeclContext());
3442 if (NNS) {
3443 std::string Str;
3444 llvm::raw_string_ostream OS(Str);
Douglas Gregor75acd922011-09-27 23:30:47 +00003445 NNS->print(OS, Policy);
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003446 Builder.AddTextChunk(Results.getAllocator().CopyString(OS.str()));
Douglas Gregorac322ec2010-08-27 21:18:54 +00003447 }
3448 } else if (!InContext->Equals(Overridden->getDeclContext()))
3449 continue;
3450
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003451 Builder.AddTypedTextChunk(Results.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003452 Overridden->getNameAsString()));
3453 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregorac322ec2010-08-27 21:18:54 +00003454 bool FirstParam = true;
David Majnemer59f77922016-06-24 04:05:48 +00003455 for (auto P : Method->parameters()) {
Douglas Gregorac322ec2010-08-27 21:18:54 +00003456 if (FirstParam)
3457 FirstParam = false;
3458 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003459 Builder.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregorac322ec2010-08-27 21:18:54 +00003460
Aaron Ballman43b68be2014-03-07 17:50:17 +00003461 Builder.AddPlaceholderChunk(
3462 Results.getAllocator().CopyString(P->getIdentifier()->getName()));
Douglas Gregorac322ec2010-08-27 21:18:54 +00003463 }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003464 Builder.AddChunk(CodeCompletionString::CK_RightParen);
3465 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregorac322ec2010-08-27 21:18:54 +00003466 CCP_SuperCompletion,
Douglas Gregor78254c82012-03-27 23:34:16 +00003467 CXCursor_CXXMethod,
3468 CXAvailability_Available,
3469 Overridden));
Douglas Gregorac322ec2010-08-27 21:18:54 +00003470 Results.Ignore(Overridden);
3471 }
3472}
3473
Douglas Gregor07f43572012-01-29 18:15:03 +00003474void Sema::CodeCompleteModuleImport(SourceLocation ImportLoc,
3475 ModuleIdPath Path) {
3476 typedef CodeCompletionResult Result;
3477 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003478 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor07f43572012-01-29 18:15:03 +00003479 CodeCompletionContext::CCC_Other);
3480 Results.EnterNewScope();
3481
3482 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003483 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Douglas Gregor07f43572012-01-29 18:15:03 +00003484 typedef CodeCompletionResult Result;
3485 if (Path.empty()) {
3486 // Enumerate all top-level modules.
Dmitri Gribenkof8579502013-01-12 19:30:44 +00003487 SmallVector<Module *, 8> Modules;
Douglas Gregor07f43572012-01-29 18:15:03 +00003488 PP.getHeaderSearchInfo().collectAllModules(Modules);
3489 for (unsigned I = 0, N = Modules.size(); I != N; ++I) {
3490 Builder.AddTypedTextChunk(
3491 Builder.getAllocator().CopyString(Modules[I]->Name));
3492 Results.AddResult(Result(Builder.TakeString(),
3493 CCP_Declaration,
Argyrios Kyrtzidis345d05f2013-05-29 18:50:15 +00003494 CXCursor_ModuleImportDecl,
Douglas Gregor07f43572012-01-29 18:15:03 +00003495 Modules[I]->isAvailable()
3496 ? CXAvailability_Available
3497 : CXAvailability_NotAvailable));
3498 }
Daniel Jasper07e6c402013-08-05 20:26:17 +00003499 } else if (getLangOpts().Modules) {
Douglas Gregor07f43572012-01-29 18:15:03 +00003500 // Load the named module.
3501 Module *Mod = PP.getModuleLoader().loadModule(ImportLoc, Path,
3502 Module::AllVisible,
3503 /*IsInclusionDirective=*/false);
3504 // Enumerate submodules.
3505 if (Mod) {
3506 for (Module::submodule_iterator Sub = Mod->submodule_begin(),
3507 SubEnd = Mod->submodule_end();
3508 Sub != SubEnd; ++Sub) {
3509
3510 Builder.AddTypedTextChunk(
3511 Builder.getAllocator().CopyString((*Sub)->Name));
3512 Results.AddResult(Result(Builder.TakeString(),
3513 CCP_Declaration,
Argyrios Kyrtzidis345d05f2013-05-29 18:50:15 +00003514 CXCursor_ModuleImportDecl,
Douglas Gregor07f43572012-01-29 18:15:03 +00003515 (*Sub)->isAvailable()
3516 ? CXAvailability_Available
3517 : CXAvailability_NotAvailable));
3518 }
3519 }
3520 }
3521 Results.ExitScope();
3522 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
3523 Results.data(),Results.size());
3524}
3525
Douglas Gregor504a6ae2010-01-10 23:08:15 +00003526void Sema::CodeCompleteOrdinaryName(Scope *S,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003527 ParserCompletionContext CompletionContext) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003528 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003529 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00003530 mapCodeCompletionContext(*this, CompletionContext));
Douglas Gregorac322ec2010-08-27 21:18:54 +00003531 Results.EnterNewScope();
Douglas Gregor50832e02010-09-20 22:39:41 +00003532
Douglas Gregor504a6ae2010-01-10 23:08:15 +00003533 // Determine how to filter results, e.g., so that the names of
3534 // values (functions, enumerators, function templates, etc.) are
3535 // only allowed where we can have an expression.
3536 switch (CompletionContext) {
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003537 case PCC_Namespace:
3538 case PCC_Class:
3539 case PCC_ObjCInterface:
3540 case PCC_ObjCImplementation:
3541 case PCC_ObjCInstanceVariableList:
3542 case PCC_Template:
3543 case PCC_MemberTemplate:
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003544 case PCC_Type:
Douglas Gregor80039242011-02-15 20:33:25 +00003545 case PCC_LocalDeclarationSpecifiers:
Douglas Gregor504a6ae2010-01-10 23:08:15 +00003546 Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
3547 break;
3548
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003549 case PCC_Statement:
Douglas Gregor5e35d592010-09-14 23:59:36 +00003550 case PCC_ParenthesizedExpression:
Douglas Gregor4d755e82010-08-24 23:58:17 +00003551 case PCC_Expression:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003552 case PCC_ForInit:
3553 case PCC_Condition:
David Blaikiebbafb8a2012-03-11 07:00:24 +00003554 if (WantTypesInContext(CompletionContext, getLangOpts()))
Douglas Gregor70febae2010-05-28 00:49:12 +00003555 Results.setFilter(&ResultBuilder::IsOrdinaryName);
3556 else
3557 Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
Douglas Gregorac322ec2010-08-27 21:18:54 +00003558
David Blaikiebbafb8a2012-03-11 07:00:24 +00003559 if (getLangOpts().CPlusPlus)
Craig Topperc3ec1492014-05-26 06:22:03 +00003560 MaybeAddOverrideCalls(*this, /*InContext=*/nullptr, Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00003561 break;
Douglas Gregor6da3db42010-05-25 05:58:43 +00003562
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003563 case PCC_RecoveryInFunction:
Douglas Gregor6da3db42010-05-25 05:58:43 +00003564 // Unfiltered
3565 break;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00003566 }
3567
Douglas Gregor9be0ed42010-08-26 16:36:48 +00003568 // If we are in a C++ non-static member function, check the qualifiers on
3569 // the member function to filter/prioritize the results list.
3570 if (CXXMethodDecl *CurMethod = dyn_cast<CXXMethodDecl>(CurContext))
3571 if (CurMethod->isInstance())
3572 Results.setObjectTypeQualifiers(
3573 Qualifiers::fromCVRMask(CurMethod->getTypeQualifiers()));
3574
Douglas Gregorc580c522010-01-14 01:09:38 +00003575 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00003576 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00003577 CodeCompleter->includeGlobals(),
3578 CodeCompleter->loadExternal());
Douglas Gregor92253692009-12-07 09:54:55 +00003579
Douglas Gregorf98e6a22010-01-13 23:51:12 +00003580 AddOrdinaryNameResults(CompletionContext, S, *this, Results);
Douglas Gregor92253692009-12-07 09:54:55 +00003581 Results.ExitScope();
3582
Douglas Gregorce0e8562010-08-23 21:54:33 +00003583 switch (CompletionContext) {
Douglas Gregor5e35d592010-09-14 23:59:36 +00003584 case PCC_ParenthesizedExpression:
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003585 case PCC_Expression:
3586 case PCC_Statement:
3587 case PCC_RecoveryInFunction:
3588 if (S->getFnParent())
Craig Topper12126262015-11-15 17:27:57 +00003589 AddPrettyFunctionResults(getLangOpts(), Results);
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003590 break;
3591
3592 case PCC_Namespace:
3593 case PCC_Class:
3594 case PCC_ObjCInterface:
3595 case PCC_ObjCImplementation:
3596 case PCC_ObjCInstanceVariableList:
3597 case PCC_Template:
3598 case PCC_MemberTemplate:
3599 case PCC_ForInit:
3600 case PCC_Condition:
3601 case PCC_Type:
Douglas Gregor80039242011-02-15 20:33:25 +00003602 case PCC_LocalDeclarationSpecifiers:
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003603 break;
Douglas Gregorce0e8562010-08-23 21:54:33 +00003604 }
3605
Douglas Gregor9eb77012009-11-07 00:00:49 +00003606 if (CodeCompleter->includeMacros())
Douglas Gregor8cb17462012-10-09 16:01:50 +00003607 AddMacroResults(PP, Results, false);
Douglas Gregorce0e8562010-08-23 21:54:33 +00003608
Douglas Gregor50832e02010-09-20 22:39:41 +00003609 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003610 Results.data(),Results.size());
Douglas Gregor9d64c5e2009-09-21 20:51:25 +00003611}
3612
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003613static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
3614 ParsedType Receiver,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00003615 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00003616 bool AtArgumentExpression,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003617 bool IsSuper,
3618 ResultBuilder &Results);
3619
3620void Sema::CodeCompleteDeclSpec(Scope *S, DeclSpec &DS,
3621 bool AllowNonIdentifiers,
3622 bool AllowNestedNameSpecifiers) {
John McCall276321a2010-08-25 06:19:51 +00003623 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003624 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003625 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00003626 AllowNestedNameSpecifiers
3627 ? CodeCompletionContext::CCC_PotentiallyQualifiedName
3628 : CodeCompletionContext::CCC_Name);
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003629 Results.EnterNewScope();
3630
3631 // Type qualifiers can come after names.
3632 Results.AddResult(Result("const"));
3633 Results.AddResult(Result("volatile"));
David Blaikiebbafb8a2012-03-11 07:00:24 +00003634 if (getLangOpts().C99)
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003635 Results.AddResult(Result("restrict"));
3636
David Blaikiebbafb8a2012-03-11 07:00:24 +00003637 if (getLangOpts().CPlusPlus) {
Alex Lorenz8f4d3992017-02-13 23:19:40 +00003638 if (getLangOpts().CPlusPlus11 &&
3639 (DS.getTypeSpecType() == DeclSpec::TST_class ||
3640 DS.getTypeSpecType() == DeclSpec::TST_struct))
3641 Results.AddResult("final");
3642
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003643 if (AllowNonIdentifiers) {
3644 Results.AddResult(Result("operator"));
3645 }
3646
3647 // Add nested-name-specifiers.
3648 if (AllowNestedNameSpecifiers) {
3649 Results.allowNestedNameSpecifiers();
Douglas Gregor0ac41382010-09-23 23:01:17 +00003650 Results.setFilter(&ResultBuilder::IsImpossibleToSatisfy);
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003651 CodeCompletionDeclConsumer Consumer(Results, CurContext);
3652 LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00003653 CodeCompleter->includeGlobals(),
3654 CodeCompleter->loadExternal());
Craig Topperc3ec1492014-05-26 06:22:03 +00003655 Results.setFilter(nullptr);
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003656 }
3657 }
3658 Results.ExitScope();
3659
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003660 // If we're in a context where we might have an expression (rather than a
3661 // declaration), and what we've seen so far is an Objective-C type that could
3662 // be a receiver of a class message, this may be a class message send with
3663 // the initial opening bracket '[' missing. Add appropriate completions.
3664 if (AllowNonIdentifiers && !AllowNestedNameSpecifiers &&
Richard Smithb4a9e862013-04-12 22:46:28 +00003665 DS.getParsedSpecifiers() == DeclSpec::PQ_TypeSpecifier &&
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003666 DS.getTypeSpecType() == DeclSpec::TST_typename &&
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003667 DS.getTypeSpecComplex() == DeclSpec::TSC_unspecified &&
3668 DS.getTypeSpecSign() == DeclSpec::TSS_unspecified &&
Richard Smithb4a9e862013-04-12 22:46:28 +00003669 !DS.isTypeAltiVecVector() &&
3670 S &&
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003671 (S->getFlags() & Scope::DeclScope) != 0 &&
3672 (S->getFlags() & (Scope::ClassScope | Scope::TemplateParamScope |
3673 Scope::FunctionPrototypeScope |
3674 Scope::AtCatchScope)) == 0) {
3675 ParsedType T = DS.getRepAsType();
3676 if (!T.get().isNull() && T.get()->isObjCObjectOrInterfaceType())
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00003677 AddClassMessageCompletions(*this, S, T, None, false, false, Results);
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003678 }
3679
Douglas Gregor56ccce02010-08-24 04:59:56 +00003680 // Note that we intentionally suppress macro results here, since we do not
3681 // encourage using macros to produce the names of entities.
3682
Douglas Gregor0ac41382010-09-23 23:01:17 +00003683 HandleCodeCompleteResults(this, CodeCompleter,
3684 Results.getCompletionContext(),
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003685 Results.data(), Results.size());
3686}
3687
Douglas Gregor68762e72010-08-23 21:17:50 +00003688struct Sema::CodeCompleteExpressionData {
3689 CodeCompleteExpressionData(QualType PreferredType = QualType())
3690 : PreferredType(PreferredType), IntegralConstantExpression(false),
3691 ObjCCollection(false) { }
3692
3693 QualType PreferredType;
3694 bool IntegralConstantExpression;
3695 bool ObjCCollection;
Chris Lattner0e62c1c2011-07-23 10:55:15 +00003696 SmallVector<Decl *, 4> IgnoreDecls;
Douglas Gregor68762e72010-08-23 21:17:50 +00003697};
3698
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003699/// Perform code-completion in an expression context when we know what
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003700/// type we're looking for.
Douglas Gregor68762e72010-08-23 21:17:50 +00003701void Sema::CodeCompleteExpression(Scope *S,
3702 const CodeCompleteExpressionData &Data) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003703 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003704 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003705 CodeCompletionContext::CCC_Expression);
Douglas Gregor68762e72010-08-23 21:17:50 +00003706 if (Data.ObjCCollection)
3707 Results.setFilter(&ResultBuilder::IsObjCCollection);
3708 else if (Data.IntegralConstantExpression)
Douglas Gregor85b50632010-07-28 21:50:18 +00003709 Results.setFilter(&ResultBuilder::IsIntegralConstantValue);
David Blaikiebbafb8a2012-03-11 07:00:24 +00003710 else if (WantTypesInContext(PCC_Expression, getLangOpts()))
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003711 Results.setFilter(&ResultBuilder::IsOrdinaryName);
3712 else
3713 Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
Douglas Gregor68762e72010-08-23 21:17:50 +00003714
3715 if (!Data.PreferredType.isNull())
3716 Results.setPreferredType(Data.PreferredType.getNonReferenceType());
3717
3718 // Ignore any declarations that we were told that we don't care about.
3719 for (unsigned I = 0, N = Data.IgnoreDecls.size(); I != N; ++I)
3720 Results.Ignore(Data.IgnoreDecls[I]);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003721
3722 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00003723 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00003724 CodeCompleter->includeGlobals(),
3725 CodeCompleter->loadExternal());
3726
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003727 Results.EnterNewScope();
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003728 AddOrdinaryNameResults(PCC_Expression, S, *this, Results);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003729 Results.ExitScope();
3730
Douglas Gregor55b037b2010-07-08 20:55:51 +00003731 bool PreferredTypeIsPointer = false;
Douglas Gregor68762e72010-08-23 21:17:50 +00003732 if (!Data.PreferredType.isNull())
3733 PreferredTypeIsPointer = Data.PreferredType->isAnyPointerType()
3734 || Data.PreferredType->isMemberPointerType()
3735 || Data.PreferredType->isBlockPointerType();
Douglas Gregor55b037b2010-07-08 20:55:51 +00003736
Douglas Gregorce0e8562010-08-23 21:54:33 +00003737 if (S->getFnParent() &&
3738 !Data.ObjCCollection &&
3739 !Data.IntegralConstantExpression)
Craig Topper12126262015-11-15 17:27:57 +00003740 AddPrettyFunctionResults(getLangOpts(), Results);
Douglas Gregorce0e8562010-08-23 21:54:33 +00003741
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003742 if (CodeCompleter->includeMacros())
Douglas Gregor8cb17462012-10-09 16:01:50 +00003743 AddMacroResults(PP, Results, false, PreferredTypeIsPointer);
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003744 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor68762e72010-08-23 21:17:50 +00003745 CodeCompletionContext(CodeCompletionContext::CCC_Expression,
3746 Data.PreferredType),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003747 Results.data(),Results.size());
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003748}
3749
Douglas Gregoreda7e542010-09-18 01:28:11 +00003750void Sema::CodeCompletePostfixExpression(Scope *S, ExprResult E) {
3751 if (E.isInvalid())
3752 CodeCompleteOrdinaryName(S, PCC_RecoveryInFunction);
David Blaikiebbafb8a2012-03-11 07:00:24 +00003753 else if (getLangOpts().ObjC1)
Nikola Smiljanic01a75982014-05-29 10:55:11 +00003754 CodeCompleteObjCInstanceMessage(S, E.get(), None, false);
Douglas Gregored0b69d2010-09-15 16:23:04 +00003755}
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003756
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003757/// The set of properties that have already been added, referenced by
Douglas Gregorb888acf2010-12-09 23:01:55 +00003758/// property name.
3759typedef llvm::SmallPtrSet<IdentifierInfo*, 16> AddedPropertiesSet;
3760
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003761/// Retrieve the container definition, if any?
Douglas Gregor9b4f3702012-06-12 13:44:08 +00003762static ObjCContainerDecl *getContainerDef(ObjCContainerDecl *Container) {
3763 if (ObjCInterfaceDecl *Interface = dyn_cast<ObjCInterfaceDecl>(Container)) {
3764 if (Interface->hasDefinition())
3765 return Interface->getDefinition();
3766
3767 return Interface;
3768 }
3769
3770 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
3771 if (Protocol->hasDefinition())
3772 return Protocol->getDefinition();
3773
3774 return Protocol;
3775 }
3776 return Container;
3777}
3778
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003779/// Adds a block invocation code completion result for the given block
Alex Lorenzbaef8022016-11-09 13:43:18 +00003780/// declaration \p BD.
3781static void AddObjCBlockCall(ASTContext &Context, const PrintingPolicy &Policy,
3782 CodeCompletionBuilder &Builder,
3783 const NamedDecl *BD,
3784 const FunctionTypeLoc &BlockLoc,
3785 const FunctionProtoTypeLoc &BlockProtoLoc) {
3786 Builder.AddResultTypeChunk(
3787 GetCompletionTypeString(BlockLoc.getReturnLoc().getType(), Context,
3788 Policy, Builder.getAllocator()));
3789
3790 AddTypedNameChunk(Context, Policy, BD, Builder);
3791 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
3792
3793 if (BlockProtoLoc && BlockProtoLoc.getTypePtr()->isVariadic()) {
3794 Builder.AddPlaceholderChunk("...");
3795 } else {
3796 for (unsigned I = 0, N = BlockLoc.getNumParams(); I != N; ++I) {
3797 if (I)
3798 Builder.AddChunk(CodeCompletionString::CK_Comma);
3799
3800 // Format the placeholder string.
3801 std::string PlaceholderStr =
3802 FormatFunctionParameter(Policy, BlockLoc.getParam(I));
3803
3804 if (I == N - 1 && BlockProtoLoc &&
3805 BlockProtoLoc.getTypePtr()->isVariadic())
3806 PlaceholderStr += ", ...";
3807
3808 // Add the placeholder string.
3809 Builder.AddPlaceholderChunk(
3810 Builder.getAllocator().CopyString(PlaceholderStr));
3811 }
3812 }
3813
3814 Builder.AddChunk(CodeCompletionString::CK_RightParen);
3815}
3816
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003817static void AddObjCProperties(
3818 const CodeCompletionContext &CCContext, ObjCContainerDecl *Container,
3819 bool AllowCategories, bool AllowNullaryMethods, DeclContext *CurContext,
3820 AddedPropertiesSet &AddedProperties, ResultBuilder &Results,
3821 bool IsBaseExprStatement = false, bool IsClassProperty = false) {
John McCall276321a2010-08-25 06:19:51 +00003822 typedef CodeCompletionResult Result;
Douglas Gregor9291bad2009-11-18 01:29:26 +00003823
Douglas Gregor9b4f3702012-06-12 13:44:08 +00003824 // Retrieve the definition.
3825 Container = getContainerDef(Container);
3826
Douglas Gregor9291bad2009-11-18 01:29:26 +00003827 // Add properties in this container.
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003828 const auto AddProperty = [&](const ObjCPropertyDecl *P) {
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003829 if (!AddedProperties.insert(P->getIdentifier()).second)
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003830 return;
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003831
Alex Lorenzbaef8022016-11-09 13:43:18 +00003832 // FIXME: Provide block invocation completion for non-statement
3833 // expressions.
3834 if (!P->getType().getTypePtr()->isBlockPointerType() ||
3835 !IsBaseExprStatement) {
3836 Results.MaybeAddResult(Result(P, Results.getBasePriority(P), nullptr),
3837 CurContext);
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003838 return;
Alex Lorenzbaef8022016-11-09 13:43:18 +00003839 }
3840
3841 // Block setter and invocation completion is provided only when we are able
3842 // to find the FunctionProtoTypeLoc with parameter names for the block.
3843 FunctionTypeLoc BlockLoc;
3844 FunctionProtoTypeLoc BlockProtoLoc;
3845 findTypeLocationForBlockDecl(P->getTypeSourceInfo(), BlockLoc,
3846 BlockProtoLoc);
3847 if (!BlockLoc) {
3848 Results.MaybeAddResult(Result(P, Results.getBasePriority(P), nullptr),
3849 CurContext);
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003850 return;
Alex Lorenzbaef8022016-11-09 13:43:18 +00003851 }
3852
3853 // The default completion result for block properties should be the block
3854 // invocation completion when the base expression is a statement.
3855 CodeCompletionBuilder Builder(Results.getAllocator(),
3856 Results.getCodeCompletionTUInfo());
3857 AddObjCBlockCall(Container->getASTContext(),
3858 getCompletionPrintingPolicy(Results.getSema()), Builder, P,
3859 BlockLoc, BlockProtoLoc);
3860 Results.MaybeAddResult(
3861 Result(Builder.TakeString(), P, Results.getBasePriority(P)),
3862 CurContext);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003863
3864 // Provide additional block setter completion iff the base expression is a
Alex Lorenzbaef8022016-11-09 13:43:18 +00003865 // statement and the block property is mutable.
3866 if (!P->isReadOnly()) {
3867 CodeCompletionBuilder Builder(Results.getAllocator(),
3868 Results.getCodeCompletionTUInfo());
3869 AddResultTypeChunk(Container->getASTContext(),
3870 getCompletionPrintingPolicy(Results.getSema()), P,
3871 CCContext.getBaseType(), Builder);
3872 Builder.AddTypedTextChunk(
3873 Results.getAllocator().CopyString(P->getName()));
3874 Builder.AddChunk(CodeCompletionString::CK_Equal);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003875
Alex Lorenzbaef8022016-11-09 13:43:18 +00003876 std::string PlaceholderStr = formatBlockPlaceholder(
3877 getCompletionPrintingPolicy(Results.getSema()), P, BlockLoc,
3878 BlockProtoLoc, /*SuppressBlockName=*/true);
3879 // Add the placeholder string.
3880 Builder.AddPlaceholderChunk(
3881 Builder.getAllocator().CopyString(PlaceholderStr));
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003882
Alex Lorenz6e0f3932017-01-06 12:00:44 +00003883 // When completing blocks properties that return void the default
3884 // property completion result should show up before the setter,
3885 // otherwise the setter completion should show up before the default
3886 // property completion, as we normally want to use the result of the
3887 // call.
Alex Lorenzbaef8022016-11-09 13:43:18 +00003888 Results.MaybeAddResult(
3889 Result(Builder.TakeString(), P,
Alex Lorenz6e0f3932017-01-06 12:00:44 +00003890 Results.getBasePriority(P) +
3891 (BlockLoc.getTypePtr()->getReturnType()->isVoidType()
3892 ? CCD_BlockPropertySetter
3893 : -CCD_BlockPropertySetter)),
Alex Lorenzbaef8022016-11-09 13:43:18 +00003894 CurContext);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003895 }
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003896 };
3897
3898 if (IsClassProperty) {
3899 for (const auto *P : Container->class_properties())
3900 AddProperty(P);
3901 } else {
3902 for (const auto *P : Container->instance_properties())
3903 AddProperty(P);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003904 }
Craig Topperc3ec1492014-05-26 06:22:03 +00003905
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003906 // Add nullary methods or implicit class properties
Douglas Gregor95147142011-05-05 15:50:42 +00003907 if (AllowNullaryMethods) {
3908 ASTContext &Context = Container->getASTContext();
Douglas Gregor75acd922011-09-27 23:30:47 +00003909 PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema());
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003910 // Adds a method result
3911 const auto AddMethod = [&](const ObjCMethodDecl *M) {
3912 IdentifierInfo *Name = M->getSelector().getIdentifierInfoForSlot(0);
3913 if (!Name)
3914 return;
3915 if (!AddedProperties.insert(Name).second)
3916 return;
3917 CodeCompletionBuilder Builder(Results.getAllocator(),
3918 Results.getCodeCompletionTUInfo());
3919 AddResultTypeChunk(Context, Policy, M, CCContext.getBaseType(), Builder);
3920 Builder.AddTypedTextChunk(
3921 Results.getAllocator().CopyString(Name->getName()));
3922 Results.MaybeAddResult(
3923 Result(Builder.TakeString(), M,
3924 CCP_MemberDeclaration + CCD_MethodAsProperty),
3925 CurContext);
3926 };
3927
3928 if (IsClassProperty) {
3929 for (const auto *M : Container->methods()) {
3930 // Gather the class method that can be used as implicit property
3931 // getters. Methods with arguments or methods that return void aren't
3932 // added to the results as they can't be used as a getter.
3933 if (!M->getSelector().isUnarySelector() ||
3934 M->getReturnType()->isVoidType() || M->isInstanceMethod())
3935 continue;
3936 AddMethod(M);
3937 }
3938 } else {
3939 for (auto *M : Container->methods()) {
3940 if (M->getSelector().isUnarySelector())
3941 AddMethod(M);
3942 }
Douglas Gregor95147142011-05-05 15:50:42 +00003943 }
3944 }
Douglas Gregor95147142011-05-05 15:50:42 +00003945
Douglas Gregor9291bad2009-11-18 01:29:26 +00003946 // Add properties in referenced protocols.
3947 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Aaron Ballman0f6e64d2014-03-13 22:58:06 +00003948 for (auto *P : Protocol->protocols())
Douglas Gregorc3425b12015-07-07 06:20:19 +00003949 AddObjCProperties(CCContext, P, AllowCategories, AllowNullaryMethods,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003950 CurContext, AddedProperties, Results,
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003951 IsBaseExprStatement, IsClassProperty);
Douglas Gregor9291bad2009-11-18 01:29:26 +00003952 } else if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)){
Douglas Gregor5d649882009-11-18 22:32:06 +00003953 if (AllowCategories) {
3954 // Look through categories.
Aaron Ballman15063e12014-03-13 21:35:02 +00003955 for (auto *Cat : IFace->known_categories())
Douglas Gregorc3425b12015-07-07 06:20:19 +00003956 AddObjCProperties(CCContext, Cat, AllowCategories, AllowNullaryMethods,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003957 CurContext, AddedProperties, Results,
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003958 IsBaseExprStatement, IsClassProperty);
Douglas Gregor5d649882009-11-18 22:32:06 +00003959 }
Aaron Ballman15063e12014-03-13 21:35:02 +00003960
Douglas Gregor9291bad2009-11-18 01:29:26 +00003961 // Look through protocols.
Aaron Ballmana9f49e32014-03-13 20:55:22 +00003962 for (auto *I : IFace->all_referenced_protocols())
Douglas Gregorc3425b12015-07-07 06:20:19 +00003963 AddObjCProperties(CCContext, I, AllowCategories, AllowNullaryMethods,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003964 CurContext, AddedProperties, Results,
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003965 IsBaseExprStatement, IsClassProperty);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003966
Douglas Gregor9291bad2009-11-18 01:29:26 +00003967 // Look in the superclass.
3968 if (IFace->getSuperClass())
Douglas Gregorc3425b12015-07-07 06:20:19 +00003969 AddObjCProperties(CCContext, IFace->getSuperClass(), AllowCategories,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003970 AllowNullaryMethods, CurContext, AddedProperties,
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003971 Results, IsBaseExprStatement, IsClassProperty);
Douglas Gregor9291bad2009-11-18 01:29:26 +00003972 } else if (const ObjCCategoryDecl *Category
3973 = dyn_cast<ObjCCategoryDecl>(Container)) {
3974 // Look through protocols.
Aaron Ballman19a41762014-03-14 12:55:57 +00003975 for (auto *P : Category->protocols())
Douglas Gregorc3425b12015-07-07 06:20:19 +00003976 AddObjCProperties(CCContext, P, AllowCategories, AllowNullaryMethods,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003977 CurContext, AddedProperties, Results,
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003978 IsBaseExprStatement, IsClassProperty);
Douglas Gregor9291bad2009-11-18 01:29:26 +00003979 }
3980}
3981
Alex Lorenz0fe0d982017-05-11 13:41:00 +00003982static void AddRecordMembersCompletionResults(Sema &SemaRef,
3983 ResultBuilder &Results, Scope *S,
3984 QualType BaseType,
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00003985 RecordDecl *RD,
3986 Optional<FixItHint> AccessOpFixIt) {
Alex Lorenz0fe0d982017-05-11 13:41:00 +00003987 // Indicate that we are performing a member access, and the cv-qualifiers
3988 // for the base object type.
3989 Results.setObjectTypeQualifiers(BaseType.getQualifiers());
3990
3991 // Access to a C/C++ class, struct, or union.
3992 Results.allowNestedNameSpecifiers();
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00003993 std::vector<FixItHint> FixIts;
3994 if (AccessOpFixIt)
3995 FixIts.emplace_back(AccessOpFixIt.getValue());
3996 CodeCompletionDeclConsumer Consumer(Results, SemaRef.CurContext, std::move(FixIts));
Alex Lorenz0fe0d982017-05-11 13:41:00 +00003997 SemaRef.LookupVisibleDecls(RD, Sema::LookupMemberName, Consumer,
Alex Lorenze6afa392017-05-11 13:48:57 +00003998 SemaRef.CodeCompleter->includeGlobals(),
Sam McCallbb2cf632018-01-12 14:51:47 +00003999 /*IncludeDependentBases=*/true,
4000 SemaRef.CodeCompleter->loadExternal());
Alex Lorenz0fe0d982017-05-11 13:41:00 +00004001
4002 if (SemaRef.getLangOpts().CPlusPlus) {
4003 if (!Results.empty()) {
4004 // The "template" keyword can follow "->" or "." in the grammar.
4005 // However, we only want to suggest the template keyword if something
4006 // is dependent.
4007 bool IsDependent = BaseType->isDependentType();
4008 if (!IsDependent) {
4009 for (Scope *DepScope = S; DepScope; DepScope = DepScope->getParent())
4010 if (DeclContext *Ctx = DepScope->getEntity()) {
4011 IsDependent = Ctx->isDependentContext();
4012 break;
4013 }
4014 }
4015
4016 if (IsDependent)
4017 Results.AddResult(CodeCompletionResult("template"));
4018 }
4019 }
4020}
4021
Douglas Gregor1cc88a92012-01-23 15:59:30 +00004022void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base,
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004023 Expr *OtherOpBase,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004024 SourceLocation OpLoc, bool IsArrow,
4025 bool IsBaseExprStatement) {
Douglas Gregor1cc88a92012-01-23 15:59:30 +00004026 if (!Base || !CodeCompleter)
Douglas Gregor2436e712009-09-17 21:32:03 +00004027 return;
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004028
Douglas Gregor1cc88a92012-01-23 15:59:30 +00004029 ExprResult ConvertedBase = PerformMemberExprBaseConversion(Base, IsArrow);
4030 if (ConvertedBase.isInvalid())
4031 return;
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004032 QualType ConvertedBaseType = ConvertedBase.get()->getType();
4033
4034 enum CodeCompletionContext::Kind contextKind;
Douglas Gregor3545ff42009-09-21 16:56:56 +00004035
4036 if (IsArrow) {
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004037 if (const PointerType *Ptr = ConvertedBaseType->getAs<PointerType>())
4038 ConvertedBaseType = Ptr->getPointeeType();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004039 }
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004040
Douglas Gregor21325842011-07-07 16:03:39 +00004041 if (IsArrow) {
4042 contextKind = CodeCompletionContext::CCC_ArrowMemberAccess;
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004043 } else {
4044 if (ConvertedBaseType->isObjCObjectPointerType() ||
4045 ConvertedBaseType->isObjCObjectOrInterfaceType()) {
Douglas Gregor21325842011-07-07 16:03:39 +00004046 contextKind = CodeCompletionContext::CCC_ObjCPropertyAccess;
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004047 } else {
Douglas Gregor21325842011-07-07 16:03:39 +00004048 contextKind = CodeCompletionContext::CCC_DotMemberAccess;
4049 }
4050 }
Douglas Gregorc3425b12015-07-07 06:20:19 +00004051
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004052 CodeCompletionContext CCContext(contextKind, ConvertedBaseType);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004053 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004054 CodeCompleter->getCodeCompletionTUInfo(), CCContext,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004055 &ResultBuilder::IsMember);
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004056
4057 auto DoCompletion = [&](Expr *Base, bool IsArrow, Optional<FixItHint> AccessOpFixIt) -> bool {
4058 if (!Base)
4059 return false;
4060
4061 ExprResult ConvertedBase = PerformMemberExprBaseConversion(Base, IsArrow);
4062 if (ConvertedBase.isInvalid())
4063 return false;
4064 Base = ConvertedBase.get();
4065
4066 QualType BaseType = Base->getType();
4067
4068 if (IsArrow) {
4069 if (const PointerType *Ptr = BaseType->getAs<PointerType>())
4070 BaseType = Ptr->getPointeeType();
4071 else if (BaseType->isObjCObjectPointerType())
4072 /*Do nothing*/;
4073 else
4074 return false;
4075 }
4076
4077 if (const RecordType *Record = BaseType->getAs<RecordType>()) {
4078 AddRecordMembersCompletionResults(*this, Results, S, BaseType,
4079 Record->getDecl(),
4080 std::move(AccessOpFixIt));
4081 } else if (const auto *TST =
4082 BaseType->getAs<TemplateSpecializationType>()) {
4083 TemplateName TN = TST->getTemplateName();
4084 if (const auto *TD =
4085 dyn_cast_or_null<ClassTemplateDecl>(TN.getAsTemplateDecl())) {
4086 CXXRecordDecl *RD = TD->getTemplatedDecl();
4087 AddRecordMembersCompletionResults(*this, Results, S, BaseType, RD,
4088 std::move(AccessOpFixIt));
4089 }
4090 } else if (const auto *ICNT = BaseType->getAs<InjectedClassNameType>()) {
4091 if (auto *RD = ICNT->getDecl())
4092 AddRecordMembersCompletionResults(*this, Results, S, BaseType, RD,
4093 std::move(AccessOpFixIt));
4094 } else if (!IsArrow && BaseType->isObjCObjectPointerType()) {
4095 // Objective-C property reference.
4096 AddedPropertiesSet AddedProperties;
4097
4098 if (const ObjCObjectPointerType *ObjCPtr =
4099 BaseType->getAsObjCInterfacePointerType()) {
4100 // Add property results based on our interface.
4101 assert(ObjCPtr && "Non-NULL pointer guaranteed above!");
4102 AddObjCProperties(CCContext, ObjCPtr->getInterfaceDecl(), true,
4103 /*AllowNullaryMethods=*/true, CurContext,
4104 AddedProperties, Results, IsBaseExprStatement);
4105 }
4106
4107 // Add properties from the protocols in a qualified interface.
4108 for (auto *I : BaseType->getAs<ObjCObjectPointerType>()->quals())
4109 AddObjCProperties(CCContext, I, true, /*AllowNullaryMethods=*/true,
4110 CurContext, AddedProperties, Results,
4111 IsBaseExprStatement);
4112 } else if ((IsArrow && BaseType->isObjCObjectPointerType()) ||
4113 (!IsArrow && BaseType->isObjCObjectType())) {
4114 // Objective-C instance variable access.
4115 ObjCInterfaceDecl *Class = nullptr;
4116 if (const ObjCObjectPointerType *ObjCPtr =
4117 BaseType->getAs<ObjCObjectPointerType>())
4118 Class = ObjCPtr->getInterfaceDecl();
4119 else
4120 Class = BaseType->getAs<ObjCObjectType>()->getInterface();
4121
4122 // Add all ivars from this class and its superclasses.
4123 if (Class) {
4124 CodeCompletionDeclConsumer Consumer(Results, CurContext);
4125 Results.setFilter(&ResultBuilder::IsObjCIvar);
4126 LookupVisibleDecls(
4127 Class, LookupMemberName, Consumer, CodeCompleter->includeGlobals(),
4128 /*IncludeDependentBases=*/false, CodeCompleter->loadExternal());
4129 }
4130 }
4131
4132 // FIXME: How do we cope with isa?
4133 return true;
4134 };
4135
Douglas Gregor9291bad2009-11-18 01:29:26 +00004136 Results.EnterNewScope();
Alex Lorenz06cfa992016-10-12 11:40:15 +00004137
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004138 bool CompletionSucceded = DoCompletion(Base, IsArrow, None);
4139 if (CodeCompleter->includeFixIts()) {
4140 const CharSourceRange OpRange =
4141 CharSourceRange::getTokenRange(OpLoc, OpLoc);
4142 CompletionSucceded |= DoCompletion(
4143 OtherOpBase, !IsArrow,
4144 FixItHint::CreateReplacement(OpRange, IsArrow ? "." : "->"));
Douglas Gregor3545ff42009-09-21 16:56:56 +00004145 }
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004146
Douglas Gregor9291bad2009-11-18 01:29:26 +00004147 Results.ExitScope();
Daniel Dunbar242ea9a2009-11-13 08:58:20 +00004148
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004149 if (!CompletionSucceded)
4150 return;
4151
Daniel Dunbar242ea9a2009-11-13 08:58:20 +00004152 // Hand off the results found for code completion.
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004153 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4154 Results.data(), Results.size());
Douglas Gregor2436e712009-09-17 21:32:03 +00004155}
4156
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004157void Sema::CodeCompleteObjCClassPropertyRefExpr(Scope *S,
4158 IdentifierInfo &ClassName,
4159 SourceLocation ClassNameLoc,
4160 bool IsBaseExprStatement) {
4161 IdentifierInfo *ClassNamePtr = &ClassName;
4162 ObjCInterfaceDecl *IFace = getObjCInterfaceDecl(ClassNamePtr, ClassNameLoc);
4163 if (!IFace)
4164 return;
4165 CodeCompletionContext CCContext(
4166 CodeCompletionContext::CCC_ObjCPropertyAccess);
4167 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4168 CodeCompleter->getCodeCompletionTUInfo(), CCContext,
4169 &ResultBuilder::IsMember);
4170 Results.EnterNewScope();
4171 AddedPropertiesSet AddedProperties;
4172 AddObjCProperties(CCContext, IFace, true,
4173 /*AllowNullaryMethods=*/true, CurContext, AddedProperties,
4174 Results, IsBaseExprStatement,
4175 /*IsClassProperty=*/true);
4176 Results.ExitScope();
4177 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4178 Results.data(), Results.size());
4179}
4180
Faisal Vali090da2d2018-01-01 18:23:28 +00004181void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) {
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004182 if (!CodeCompleter)
4183 return;
Craig Topperc3ec1492014-05-26 06:22:03 +00004184
4185 ResultBuilder::LookupFilter Filter = nullptr;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004186 enum CodeCompletionContext::Kind ContextKind
4187 = CodeCompletionContext::CCC_Other;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004188 switch ((DeclSpec::TST)TagSpec) {
4189 case DeclSpec::TST_enum:
Douglas Gregor3545ff42009-09-21 16:56:56 +00004190 Filter = &ResultBuilder::IsEnum;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004191 ContextKind = CodeCompletionContext::CCC_EnumTag;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004192 break;
4193
4194 case DeclSpec::TST_union:
Douglas Gregor3545ff42009-09-21 16:56:56 +00004195 Filter = &ResultBuilder::IsUnion;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004196 ContextKind = CodeCompletionContext::CCC_UnionTag;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004197 break;
4198
4199 case DeclSpec::TST_struct:
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004200 case DeclSpec::TST_class:
Joao Matosdc86f942012-08-31 18:45:21 +00004201 case DeclSpec::TST_interface:
Douglas Gregor3545ff42009-09-21 16:56:56 +00004202 Filter = &ResultBuilder::IsClassOrStruct;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004203 ContextKind = CodeCompletionContext::CCC_ClassOrStructTag;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004204 break;
4205
4206 default:
David Blaikie83d382b2011-09-23 05:06:16 +00004207 llvm_unreachable("Unknown type specifier kind in CodeCompleteTag");
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004208 }
Douglas Gregor3545ff42009-09-21 16:56:56 +00004209
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004210 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4211 CodeCompleter->getCodeCompletionTUInfo(), ContextKind);
Douglas Gregora6e2edc2010-01-14 03:27:13 +00004212 CodeCompletionDeclConsumer Consumer(Results, CurContext);
John McCalle87beb22010-04-23 18:46:30 +00004213
4214 // First pass: look for tags.
4215 Results.setFilter(Filter);
Douglas Gregor39982192010-08-15 06:18:01 +00004216 LookupVisibleDecls(S, LookupTagName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00004217 CodeCompleter->includeGlobals(),
4218 CodeCompleter->loadExternal());
John McCalle87beb22010-04-23 18:46:30 +00004219
Douglas Gregor39982192010-08-15 06:18:01 +00004220 if (CodeCompleter->includeGlobals()) {
4221 // Second pass: look for nested name specifiers.
4222 Results.setFilter(&ResultBuilder::IsNestedNameSpecifier);
Sam McCallbb2cf632018-01-12 14:51:47 +00004223 LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer,
4224 CodeCompleter->includeGlobals(),
4225 CodeCompleter->loadExternal());
Douglas Gregor39982192010-08-15 06:18:01 +00004226 }
Douglas Gregor3545ff42009-09-21 16:56:56 +00004227
Douglas Gregor0ac41382010-09-23 23:01:17 +00004228 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004229 Results.data(),Results.size());
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004230}
4231
Alex Lorenz8f4d3992017-02-13 23:19:40 +00004232static void AddTypeQualifierResults(DeclSpec &DS, ResultBuilder &Results,
4233 const LangOptions &LangOpts) {
4234 if (!(DS.getTypeQualifiers() & DeclSpec::TQ_const))
4235 Results.AddResult("const");
4236 if (!(DS.getTypeQualifiers() & DeclSpec::TQ_volatile))
4237 Results.AddResult("volatile");
4238 if (LangOpts.C99 && !(DS.getTypeQualifiers() & DeclSpec::TQ_restrict))
4239 Results.AddResult("restrict");
4240 if (LangOpts.C11 && !(DS.getTypeQualifiers() & DeclSpec::TQ_atomic))
4241 Results.AddResult("_Atomic");
4242 if (LangOpts.MSVCCompat && !(DS.getTypeQualifiers() & DeclSpec::TQ_unaligned))
4243 Results.AddResult("__unaligned");
4244}
4245
Douglas Gregor28c78432010-08-27 17:35:51 +00004246void Sema::CodeCompleteTypeQualifiers(DeclSpec &DS) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004247 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004248 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004249 CodeCompletionContext::CCC_TypeQualifiers);
Douglas Gregor28c78432010-08-27 17:35:51 +00004250 Results.EnterNewScope();
Alex Lorenz8f4d3992017-02-13 23:19:40 +00004251 AddTypeQualifierResults(DS, Results, LangOpts);
Douglas Gregor28c78432010-08-27 17:35:51 +00004252 Results.ExitScope();
4253 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004254 Results.getCompletionContext(),
Douglas Gregor28c78432010-08-27 17:35:51 +00004255 Results.data(), Results.size());
4256}
4257
Alex Lorenz8f4d3992017-02-13 23:19:40 +00004258void Sema::CodeCompleteFunctionQualifiers(DeclSpec &DS, Declarator &D,
4259 const VirtSpecifiers *VS) {
4260 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4261 CodeCompleter->getCodeCompletionTUInfo(),
4262 CodeCompletionContext::CCC_TypeQualifiers);
4263 Results.EnterNewScope();
4264 AddTypeQualifierResults(DS, Results, LangOpts);
4265 if (LangOpts.CPlusPlus11) {
4266 Results.AddResult("noexcept");
Faisal Vali421b2d12017-12-29 05:41:00 +00004267 if (D.getContext() == DeclaratorContext::MemberContext &&
4268 !D.isCtorOrDtor() && !D.isStaticMember()) {
Alex Lorenz8f4d3992017-02-13 23:19:40 +00004269 if (!VS || !VS->isFinalSpecified())
4270 Results.AddResult("final");
4271 if (!VS || !VS->isOverrideSpecified())
4272 Results.AddResult("override");
4273 }
4274 }
4275 Results.ExitScope();
4276 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4277 Results.data(), Results.size());
4278}
4279
Benjamin Kramer72dae622016-02-18 15:30:24 +00004280void Sema::CodeCompleteBracketDeclarator(Scope *S) {
4281 CodeCompleteExpression(S, QualType(getASTContext().getSizeType()));
4282}
4283
Douglas Gregord328d572009-09-21 18:10:23 +00004284void Sema::CodeCompleteCase(Scope *S) {
John McCallaab3e412010-08-25 08:40:02 +00004285 if (getCurFunction()->SwitchStack.empty() || !CodeCompleter)
Douglas Gregord328d572009-09-21 18:10:23 +00004286 return;
John McCall5939b162011-08-06 07:30:58 +00004287
John McCallaab3e412010-08-25 08:40:02 +00004288 SwitchStmt *Switch = getCurFunction()->SwitchStack.back();
John McCall5939b162011-08-06 07:30:58 +00004289 QualType type = Switch->getCond()->IgnoreImplicit()->getType();
4290 if (!type->isEnumeralType()) {
4291 CodeCompleteExpressionData Data(type);
Douglas Gregor68762e72010-08-23 21:17:50 +00004292 Data.IntegralConstantExpression = true;
4293 CodeCompleteExpression(S, Data);
Douglas Gregord328d572009-09-21 18:10:23 +00004294 return;
Douglas Gregor85b50632010-07-28 21:50:18 +00004295 }
Douglas Gregord328d572009-09-21 18:10:23 +00004296
4297 // Code-complete the cases of a switch statement over an enumeration type
4298 // by providing the list of
John McCall5939b162011-08-06 07:30:58 +00004299 EnumDecl *Enum = type->castAs<EnumType>()->getDecl();
Douglas Gregor9b4f3702012-06-12 13:44:08 +00004300 if (EnumDecl *Def = Enum->getDefinition())
4301 Enum = Def;
Douglas Gregord328d572009-09-21 18:10:23 +00004302
4303 // Determine which enumerators we have already seen in the switch statement.
4304 // FIXME: Ideally, we would also be able to look *past* the code-completion
4305 // token, in case we are code-completing in the middle of the switch and not
4306 // at the end. However, we aren't able to do so at the moment.
4307 llvm::SmallPtrSet<EnumConstantDecl *, 8> EnumeratorsSeen;
Craig Topperc3ec1492014-05-26 06:22:03 +00004308 NestedNameSpecifier *Qualifier = nullptr;
Douglas Gregord328d572009-09-21 18:10:23 +00004309 for (SwitchCase *SC = Switch->getSwitchCaseList(); SC;
4310 SC = SC->getNextSwitchCase()) {
4311 CaseStmt *Case = dyn_cast<CaseStmt>(SC);
4312 if (!Case)
4313 continue;
4314
4315 Expr *CaseVal = Case->getLHS()->IgnoreParenCasts();
4316 if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CaseVal))
4317 if (EnumConstantDecl *Enumerator
4318 = dyn_cast<EnumConstantDecl>(DRE->getDecl())) {
4319 // We look into the AST of the case statement to determine which
4320 // enumerator was named. Alternatively, we could compute the value of
4321 // the integral constant expression, then compare it against the
4322 // values of each enumerator. However, value-based approach would not
4323 // work as well with C++ templates where enumerators declared within a
4324 // template are type- and value-dependent.
4325 EnumeratorsSeen.insert(Enumerator);
4326
Douglas Gregorf2510672009-09-21 19:57:38 +00004327 // If this is a qualified-id, keep track of the nested-name-specifier
4328 // so that we can reproduce it as part of code completion, e.g.,
Douglas Gregord328d572009-09-21 18:10:23 +00004329 //
4330 // switch (TagD.getKind()) {
4331 // case TagDecl::TK_enum:
4332 // break;
4333 // case XXX
4334 //
Douglas Gregorf2510672009-09-21 19:57:38 +00004335 // At the XXX, our completions are TagDecl::TK_union,
Douglas Gregord328d572009-09-21 18:10:23 +00004336 // TagDecl::TK_struct, and TagDecl::TK_class, rather than TK_union,
4337 // TK_struct, and TK_class.
Douglas Gregor4bd90e52009-10-23 18:54:35 +00004338 Qualifier = DRE->getQualifier();
Douglas Gregord328d572009-09-21 18:10:23 +00004339 }
4340 }
4341
David Blaikiebbafb8a2012-03-11 07:00:24 +00004342 if (getLangOpts().CPlusPlus && !Qualifier && EnumeratorsSeen.empty()) {
Douglas Gregorf2510672009-09-21 19:57:38 +00004343 // If there are no prior enumerators in C++, check whether we have to
4344 // qualify the names of the enumerators that we suggest, because they
4345 // may not be visible in this scope.
Douglas Gregord3cebdb2012-02-01 05:02:47 +00004346 Qualifier = getRequiredQualification(Context, CurContext, Enum);
Douglas Gregorf2510672009-09-21 19:57:38 +00004347 }
4348
Douglas Gregord328d572009-09-21 18:10:23 +00004349 // Add any enumerators that have not yet been mentioned.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004350 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004351 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004352 CodeCompletionContext::CCC_Expression);
Douglas Gregord328d572009-09-21 18:10:23 +00004353 Results.EnterNewScope();
Aaron Ballman23a6dcb2014-03-08 18:45:14 +00004354 for (auto *E : Enum->enumerators()) {
4355 if (EnumeratorsSeen.count(E))
Douglas Gregord328d572009-09-21 18:10:23 +00004356 continue;
4357
Aaron Ballman23a6dcb2014-03-08 18:45:14 +00004358 CodeCompletionResult R(E, CCP_EnumInCase, Qualifier);
Craig Topperc3ec1492014-05-26 06:22:03 +00004359 Results.AddResult(R, CurContext, nullptr, false);
Douglas Gregord328d572009-09-21 18:10:23 +00004360 }
4361 Results.ExitScope();
Douglas Gregor285560922010-04-06 20:02:15 +00004362
Douglas Gregor21325842011-07-07 16:03:39 +00004363 //We need to make sure we're setting the right context,
4364 //so only say we include macros if the code completer says we do
4365 enum CodeCompletionContext::Kind kind = CodeCompletionContext::CCC_Other;
4366 if (CodeCompleter->includeMacros()) {
Douglas Gregor8cb17462012-10-09 16:01:50 +00004367 AddMacroResults(PP, Results, false);
Douglas Gregor21325842011-07-07 16:03:39 +00004368 kind = CodeCompletionContext::CCC_OtherWithMacros;
4369 }
4370
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004371 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor21325842011-07-07 16:03:39 +00004372 kind,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004373 Results.data(),Results.size());
Douglas Gregord328d572009-09-21 18:10:23 +00004374}
4375
Robert Wilhelm16e94b92013-08-09 18:02:13 +00004376static bool anyNullArguments(ArrayRef<Expr *> Args) {
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00004377 if (Args.size() && !Args.data())
Douglas Gregor6ed3eb82010-05-30 06:10:08 +00004378 return true;
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00004379
4380 for (unsigned I = 0; I != Args.size(); ++I)
Douglas Gregor6ed3eb82010-05-30 06:10:08 +00004381 if (!Args[I])
4382 return true;
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00004383
Douglas Gregor6ed3eb82010-05-30 06:10:08 +00004384 return false;
4385}
4386
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004387typedef CodeCompleteConsumer::OverloadCandidate ResultCandidate;
4388
Francisco Lopes da Silva8cafefa2015-01-29 05:54:59 +00004389static void mergeCandidatesWithResults(Sema &SemaRef,
4390 SmallVectorImpl<ResultCandidate> &Results,
4391 OverloadCandidateSet &CandidateSet,
4392 SourceLocation Loc) {
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004393 if (!CandidateSet.empty()) {
4394 // Sort the overload candidate set by placing the best overloads first.
4395 std::stable_sort(
4396 CandidateSet.begin(), CandidateSet.end(),
4397 [&](const OverloadCandidate &X, const OverloadCandidate &Y) {
Richard Smith67ef14f2017-09-26 18:37:55 +00004398 return isBetterOverloadCandidate(SemaRef, X, Y, Loc,
4399 CandidateSet.getKind());
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004400 });
4401
4402 // Add the remaining viable overload candidates as code-completion results.
Erik Verbruggen7ec91072017-09-08 10:23:08 +00004403 for (auto &Candidate : CandidateSet) {
4404 if (Candidate.Function && Candidate.Function->isDeleted())
4405 continue;
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004406 if (Candidate.Viable)
4407 Results.push_back(ResultCandidate(Candidate.Function));
Erik Verbruggen7ec91072017-09-08 10:23:08 +00004408 }
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004409 }
4410}
4411
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00004412/// Get the type of the Nth parameter from a given set of overload
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004413/// candidates.
Francisco Lopes da Silva8cafefa2015-01-29 05:54:59 +00004414static QualType getParamType(Sema &SemaRef,
4415 ArrayRef<ResultCandidate> Candidates,
4416 unsigned N) {
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004417
4418 // Given the overloads 'Candidates' for a function call matching all arguments
4419 // up to N, return the type of the Nth parameter if it is the same for all
4420 // overload candidates.
4421 QualType ParamType;
4422 for (auto &Candidate : Candidates) {
4423 if (auto FType = Candidate.getFunctionType())
4424 if (auto Proto = dyn_cast<FunctionProtoType>(FType))
4425 if (N < Proto->getNumParams()) {
4426 if (ParamType.isNull())
4427 ParamType = Proto->getParamType(N);
4428 else if (!SemaRef.Context.hasSameUnqualifiedType(
4429 ParamType.getNonReferenceType(),
4430 Proto->getParamType(N).getNonReferenceType()))
4431 // Otherwise return a default-constructed QualType.
4432 return QualType();
4433 }
4434 }
4435
4436 return ParamType;
4437}
4438
Francisco Lopes da Silva8cafefa2015-01-29 05:54:59 +00004439static void CodeCompleteOverloadResults(Sema &SemaRef, Scope *S,
4440 MutableArrayRef<ResultCandidate> Candidates,
4441 unsigned CurrentArg,
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004442 bool CompleteExpressionWithCurrentArg = true) {
4443 QualType ParamType;
4444 if (CompleteExpressionWithCurrentArg)
4445 ParamType = getParamType(SemaRef, Candidates, CurrentArg);
4446
4447 if (ParamType.isNull())
4448 SemaRef.CodeCompleteOrdinaryName(S, Sema::PCC_Expression);
4449 else
4450 SemaRef.CodeCompleteExpression(S, ParamType);
4451
4452 if (!Candidates.empty())
4453 SemaRef.CodeCompleter->ProcessOverloadCandidates(SemaRef, CurrentArg,
4454 Candidates.data(),
4455 Candidates.size());
4456}
4457
4458void Sema::CodeCompleteCall(Scope *S, Expr *Fn, ArrayRef<Expr *> Args) {
Douglas Gregorcabea402009-09-22 15:41:20 +00004459 if (!CodeCompleter)
4460 return;
Douglas Gregor3ef59522009-12-11 19:06:04 +00004461
4462 // When we're code-completing for a call, we fall back to ordinary
4463 // name code-completion whenever we can't produce specific
4464 // results. We may want to revisit this strategy in the future,
4465 // e.g., by merging the two kinds of results.
4466
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004467 // FIXME: Provide support for variadic template functions.
Douglas Gregor3ef59522009-12-11 19:06:04 +00004468
Douglas Gregorcabea402009-09-22 15:41:20 +00004469 // Ignore type-dependent call expressions entirely.
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00004470 if (!Fn || Fn->isTypeDependent() || anyNullArguments(Args) ||
4471 Expr::hasAnyTypeDependentArguments(Args)) {
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004472 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregorcabea402009-09-22 15:41:20 +00004473 return;
Douglas Gregor3ef59522009-12-11 19:06:04 +00004474 }
Douglas Gregorcabea402009-09-22 15:41:20 +00004475
John McCall57500772009-12-16 12:17:52 +00004476 // Build an overload candidate set based on the functions we find.
John McCallbc077cf2010-02-08 23:07:23 +00004477 SourceLocation Loc = Fn->getExprLoc();
Richard Smith100b24a2014-04-17 01:52:14 +00004478 OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal);
John McCall57500772009-12-16 12:17:52 +00004479
Chris Lattner0e62c1c2011-07-23 10:55:15 +00004480 SmallVector<ResultCandidate, 8> Results;
Douglas Gregorff59f672010-01-21 15:46:19 +00004481
John McCall57500772009-12-16 12:17:52 +00004482 Expr *NakedFn = Fn->IgnoreParenCasts();
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004483 if (auto ULE = dyn_cast<UnresolvedLookupExpr>(NakedFn))
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00004484 AddOverloadedCallCandidates(ULE, Args, CandidateSet,
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004485 /*PartialOverloading=*/true);
4486 else if (auto UME = dyn_cast<UnresolvedMemberExpr>(NakedFn)) {
4487 TemplateArgumentListInfo TemplateArgsBuffer, *TemplateArgs = nullptr;
4488 if (UME->hasExplicitTemplateArgs()) {
4489 UME->copyTemplateArgumentsInto(TemplateArgsBuffer);
4490 TemplateArgs = &TemplateArgsBuffer;
Douglas Gregorff59f672010-01-21 15:46:19 +00004491 }
Erik Verbruggenf1898cf2017-03-28 07:22:21 +00004492
4493 // Add the base as first argument (use a nullptr if the base is implicit).
4494 SmallVector<Expr *, 12> ArgExprs(
4495 1, UME->isImplicitAccess() ? nullptr : UME->getBase());
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004496 ArgExprs.append(Args.begin(), Args.end());
4497 UnresolvedSet<8> Decls;
4498 Decls.append(UME->decls_begin(), UME->decls_end());
Benjamin Kramere3962ae2017-10-26 08:41:28 +00004499 const bool FirstArgumentIsBase = !UME->isImplicitAccess() && UME->getBase();
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004500 AddFunctionCandidates(Decls, ArgExprs, CandidateSet, TemplateArgs,
4501 /*SuppressUsedConversions=*/false,
Benjamin Kramere3962ae2017-10-26 08:41:28 +00004502 /*PartialOverloading=*/true,
4503 FirstArgumentIsBase);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004504 } else {
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004505 FunctionDecl *FD = nullptr;
4506 if (auto MCE = dyn_cast<MemberExpr>(NakedFn))
4507 FD = dyn_cast<FunctionDecl>(MCE->getMemberDecl());
4508 else if (auto DRE = dyn_cast<DeclRefExpr>(NakedFn))
4509 FD = dyn_cast<FunctionDecl>(DRE->getDecl());
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00004510 if (FD) { // We check whether it's a resolved function declaration.
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00004511 if (!getLangOpts().CPlusPlus ||
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004512 !FD->getType()->getAs<FunctionProtoType>())
4513 Results.push_back(ResultCandidate(FD));
4514 else
4515 AddOverloadCandidate(FD, DeclAccessPair::make(FD, FD->getAccess()),
4516 Args, CandidateSet,
4517 /*SuppressUsedConversions=*/false,
4518 /*PartialOverloading=*/true);
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00004519
4520 } else if (auto DC = NakedFn->getType()->getAsCXXRecordDecl()) {
4521 // If expression's type is CXXRecordDecl, it may overload the function
4522 // call operator, so we check if it does and add them as candidates.
Francisco Lopes da Silvaa349a8a2015-01-25 08:47:59 +00004523 // A complete type is needed to lookup for member function call operators.
Richard Smithdb0ac552015-12-18 22:40:25 +00004524 if (isCompleteType(Loc, NakedFn->getType())) {
Francisco Lopes da Silvaa349a8a2015-01-25 08:47:59 +00004525 DeclarationName OpName = Context.DeclarationNames
4526 .getCXXOperatorName(OO_Call);
4527 LookupResult R(*this, OpName, Loc, LookupOrdinaryName);
4528 LookupQualifiedName(R, DC);
4529 R.suppressDiagnostics();
4530 SmallVector<Expr *, 12> ArgExprs(1, NakedFn);
4531 ArgExprs.append(Args.begin(), Args.end());
4532 AddFunctionCandidates(R.asUnresolvedSet(), ArgExprs, CandidateSet,
4533 /*ExplicitArgs=*/nullptr,
4534 /*SuppressUsedConversions=*/false,
4535 /*PartialOverloading=*/true);
4536 }
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00004537 } else {
4538 // Lastly we check whether expression's type is function pointer or
4539 // function.
4540 QualType T = NakedFn->getType();
4541 if (!T->getPointeeType().isNull())
4542 T = T->getPointeeType();
4543
4544 if (auto FP = T->getAs<FunctionProtoType>()) {
4545 if (!TooManyArguments(FP->getNumParams(), Args.size(),
Francisco Lopes da Silva62a9a4f2015-01-23 13:17:51 +00004546 /*PartialOverloading=*/true) ||
4547 FP->isVariadic())
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00004548 Results.push_back(ResultCandidate(FP));
4549 } else if (auto FT = T->getAs<FunctionType>())
Francisco Lopes da Silva62a9a4f2015-01-23 13:17:51 +00004550 // No prototype and declaration, it may be a K & R style function.
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00004551 Results.push_back(ResultCandidate(FT));
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004552 }
Douglas Gregorcabea402009-09-22 15:41:20 +00004553 }
Douglas Gregor3ef59522009-12-11 19:06:04 +00004554
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004555 mergeCandidatesWithResults(*this, Results, CandidateSet, Loc);
4556 CodeCompleteOverloadResults(*this, S, Results, Args.size(),
4557 !CandidateSet.empty());
4558}
4559
4560void Sema::CodeCompleteConstructor(Scope *S, QualType Type, SourceLocation Loc,
4561 ArrayRef<Expr *> Args) {
4562 if (!CodeCompleter)
4563 return;
4564
4565 // A complete type is needed to lookup for constructors.
Ilya Biryukovfb9dde72018-05-14 13:50:36 +00004566 CXXRecordDecl *RD =
4567 isCompleteType(Loc, Type) ? Type->getAsCXXRecordDecl() : nullptr;
Argyrios Kyrtzidisee1d76f2015-03-13 07:39:30 +00004568 if (!RD) {
4569 CodeCompleteExpression(S, Type);
4570 return;
4571 }
4572
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004573 // FIXME: Provide support for member initializers.
4574 // FIXME: Provide support for variadic template constructors.
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004575
4576 OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal);
4577
Argyrios Kyrtzidisee1d76f2015-03-13 07:39:30 +00004578 for (auto C : LookupConstructors(RD)) {
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004579 if (auto FD = dyn_cast<FunctionDecl>(C)) {
4580 AddOverloadCandidate(FD, DeclAccessPair::make(FD, C->getAccess()),
4581 Args, CandidateSet,
4582 /*SuppressUsedConversions=*/false,
4583 /*PartialOverloading=*/true);
4584 } else if (auto FTD = dyn_cast<FunctionTemplateDecl>(C)) {
4585 AddTemplateOverloadCandidate(FTD,
4586 DeclAccessPair::make(FTD, C->getAccess()),
4587 /*ExplicitTemplateArgs=*/nullptr,
4588 Args, CandidateSet,
4589 /*SuppressUsedConversions=*/false,
4590 /*PartialOverloading=*/true);
4591 }
4592 }
4593
4594 SmallVector<ResultCandidate, 8> Results;
4595 mergeCandidatesWithResults(*this, Results, CandidateSet, Loc);
4596 CodeCompleteOverloadResults(*this, S, Results, Args.size());
Douglas Gregorcabea402009-09-22 15:41:20 +00004597}
4598
John McCall48871652010-08-21 09:40:31 +00004599void Sema::CodeCompleteInitializer(Scope *S, Decl *D) {
4600 ValueDecl *VD = dyn_cast_or_null<ValueDecl>(D);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004601 if (!VD) {
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004602 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004603 return;
4604 }
4605
4606 CodeCompleteExpression(S, VD->getType());
4607}
4608
4609void Sema::CodeCompleteReturn(Scope *S) {
4610 QualType ResultType;
4611 if (isa<BlockDecl>(CurContext)) {
4612 if (BlockScopeInfo *BSI = getCurBlock())
4613 ResultType = BSI->ReturnType;
4614 } else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(CurContext))
Alp Toker314cc812014-01-25 16:55:45 +00004615 ResultType = Function->getReturnType();
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004616 else if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(CurContext))
Alp Toker314cc812014-01-25 16:55:45 +00004617 ResultType = Method->getReturnType();
4618
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004619 if (ResultType.isNull())
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004620 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004621 else
4622 CodeCompleteExpression(S, ResultType);
4623}
4624
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004625void Sema::CodeCompleteAfterIf(Scope *S) {
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004626 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004627 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004628 mapCodeCompletionContext(*this, PCC_Statement));
4629 Results.setFilter(&ResultBuilder::IsOrdinaryName);
4630 Results.EnterNewScope();
4631
4632 CodeCompletionDeclConsumer Consumer(Results, CurContext);
4633 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00004634 CodeCompleter->includeGlobals(),
4635 CodeCompleter->loadExternal());
4636
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004637 AddOrdinaryNameResults(PCC_Statement, S, *this, Results);
4638
4639 // "else" block
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004640 CodeCompletionBuilder Builder(Results.getAllocator(),
4641 Results.getCodeCompletionTUInfo());
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004642 Builder.AddTypedTextChunk("else");
Douglas Gregor3a5d6c22012-02-16 17:49:04 +00004643 if (Results.includeCodePatterns()) {
4644 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4645 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4646 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
4647 Builder.AddPlaceholderChunk("statements");
4648 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
4649 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4650 }
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004651 Results.AddResult(Builder.TakeString());
4652
4653 // "else if" block
4654 Builder.AddTypedTextChunk("else");
4655 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4656 Builder.AddTextChunk("if");
4657 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4658 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00004659 if (getLangOpts().CPlusPlus)
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004660 Builder.AddPlaceholderChunk("condition");
4661 else
4662 Builder.AddPlaceholderChunk("expression");
4663 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor3a5d6c22012-02-16 17:49:04 +00004664 if (Results.includeCodePatterns()) {
4665 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4666 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4667 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
4668 Builder.AddPlaceholderChunk("statements");
4669 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
4670 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4671 }
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004672 Results.AddResult(Builder.TakeString());
4673
4674 Results.ExitScope();
4675
4676 if (S->getFnParent())
Craig Topper12126262015-11-15 17:27:57 +00004677 AddPrettyFunctionResults(getLangOpts(), Results);
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004678
4679 if (CodeCompleter->includeMacros())
Douglas Gregor8cb17462012-10-09 16:01:50 +00004680 AddMacroResults(PP, Results, false);
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004681
4682 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4683 Results.data(),Results.size());
4684}
4685
Richard Trieu2bd04012011-09-09 02:00:50 +00004686void Sema::CodeCompleteAssignmentRHS(Scope *S, Expr *LHS) {
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004687 if (LHS)
4688 CodeCompleteExpression(S, static_cast<Expr *>(LHS)->getType());
4689 else
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004690 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004691}
4692
Jeffrey Yasskinc76498d2010-04-08 16:38:48 +00004693void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS,
Douglas Gregor2436e712009-09-17 21:32:03 +00004694 bool EnteringContext) {
Eric Liu06d34022017-12-12 11:35:46 +00004695 if (SS.isEmpty() || !CodeCompleter)
Douglas Gregor2436e712009-09-17 21:32:03 +00004696 return;
Alex Lorenz8a7a4cf2017-06-15 21:40:54 +00004697
Eric Liu06d34022017-12-12 11:35:46 +00004698 // We want to keep the scope specifier even if it's invalid (e.g. the scope
4699 // "a::b::" is not corresponding to any context/namespace in the AST), since
4700 // it can be useful for global code completion which have information about
4701 // contexts/symbols that are not in the AST.
4702 if (SS.isInvalid()) {
4703 CodeCompletionContext CC(CodeCompletionContext::CCC_Name);
4704 CC.setCXXScopeSpecifier(SS);
4705 HandleCodeCompleteResults(this, CodeCompleter, CC, nullptr, 0);
4706 return;
4707 }
Alex Lorenz8a7a4cf2017-06-15 21:40:54 +00004708 // Always pretend to enter a context to ensure that a dependent type
4709 // resolves to a dependent record.
4710 DeclContext *Ctx = computeDeclContext(SS, /*EnteringContext=*/true);
Douglas Gregor3545ff42009-09-21 16:56:56 +00004711 if (!Ctx)
4712 return;
Douglas Gregor800f2f02009-12-11 18:28:39 +00004713
4714 // Try to instantiate any non-dependent declaration contexts before
4715 // we look in them.
John McCall0b66eb32010-05-01 00:40:08 +00004716 if (!isDependentScopeSpecifier(SS) && RequireCompleteDeclContext(SS, Ctx))
Douglas Gregor800f2f02009-12-11 18:28:39 +00004717 return;
4718
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004719 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004720 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004721 CodeCompletionContext::CCC_Name);
Douglas Gregorac322ec2010-08-27 21:18:54 +00004722 Results.EnterNewScope();
Eric Liu06d34022017-12-12 11:35:46 +00004723
Douglas Gregor3545ff42009-09-21 16:56:56 +00004724 // The "template" keyword can follow "::" in the grammar, but only
4725 // put it into the grammar if the nested-name-specifier is dependent.
Aaron Ballman4a979672014-01-03 13:56:08 +00004726 NestedNameSpecifier *NNS = SS.getScopeRep();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004727 if (!Results.empty() && NNS->isDependent())
Douglas Gregor78a21012010-01-14 16:01:26 +00004728 Results.AddResult("template");
Douglas Gregorac322ec2010-08-27 21:18:54 +00004729
4730 // Add calls to overridden virtual functions, if there are any.
4731 //
4732 // FIXME: This isn't wonderful, because we don't know whether we're actually
4733 // in a context that permits expressions. This is a general issue with
4734 // qualified-id completions.
4735 if (!EnteringContext)
4736 MaybeAddOverrideCalls(*this, Ctx, Results);
Eric Liu06d34022017-12-12 11:35:46 +00004737 Results.ExitScope();
4738
Eric Liufead6ae2017-12-13 10:26:49 +00004739 if (CodeCompleter->includeNamespaceLevelDecls() ||
4740 (!Ctx->isNamespace() && !Ctx->isTranslationUnit())) {
4741 CodeCompletionDeclConsumer Consumer(Results, CurContext);
4742 LookupVisibleDecls(Ctx, LookupOrdinaryName, Consumer,
4743 /*IncludeGlobalScope=*/true,
Sam McCallbb2cf632018-01-12 14:51:47 +00004744 /*IncludeDependentBases=*/true,
4745 CodeCompleter->loadExternal());
Eric Liufead6ae2017-12-13 10:26:49 +00004746 }
Douglas Gregorac322ec2010-08-27 21:18:54 +00004747
Eric Liu06d34022017-12-12 11:35:46 +00004748 auto CC = Results.getCompletionContext();
4749 CC.setCXXScopeSpecifier(SS);
4750
4751 HandleCodeCompleteResults(this, CodeCompleter, CC, Results.data(),
4752 Results.size());
Douglas Gregor2436e712009-09-17 21:32:03 +00004753}
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00004754
4755void Sema::CodeCompleteUsing(Scope *S) {
4756 if (!CodeCompleter)
4757 return;
4758
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004759 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004760 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00004761 CodeCompletionContext::CCC_PotentiallyQualifiedName,
4762 &ResultBuilder::IsNestedNameSpecifier);
Douglas Gregor64b12b52009-09-22 23:31:26 +00004763 Results.EnterNewScope();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004764
4765 // If we aren't in class scope, we could see the "namespace" keyword.
4766 if (!S->isClassScope())
John McCall276321a2010-08-25 06:19:51 +00004767 Results.AddResult(CodeCompletionResult("namespace"));
Douglas Gregor3545ff42009-09-21 16:56:56 +00004768
4769 // After "using", we can see anything that would start a
4770 // nested-name-specifier.
Douglas Gregora6e2edc2010-01-14 03:27:13 +00004771 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00004772 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00004773 CodeCompleter->includeGlobals(),
4774 CodeCompleter->loadExternal());
Douglas Gregor64b12b52009-09-22 23:31:26 +00004775 Results.ExitScope();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004776
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004777 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004778 CodeCompletionContext::CCC_PotentiallyQualifiedName,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004779 Results.data(),Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00004780}
4781
4782void Sema::CodeCompleteUsingDirective(Scope *S) {
4783 if (!CodeCompleter)
4784 return;
4785
Douglas Gregor3545ff42009-09-21 16:56:56 +00004786 // After "using namespace", we expect to see a namespace name or namespace
4787 // alias.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004788 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004789 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004790 CodeCompletionContext::CCC_Namespace,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004791 &ResultBuilder::IsNamespaceOrAlias);
Douglas Gregor64b12b52009-09-22 23:31:26 +00004792 Results.EnterNewScope();
Douglas Gregora6e2edc2010-01-14 03:27:13 +00004793 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00004794 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00004795 CodeCompleter->includeGlobals(),
4796 CodeCompleter->loadExternal());
Douglas Gregor64b12b52009-09-22 23:31:26 +00004797 Results.ExitScope();
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004798 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor39982192010-08-15 06:18:01 +00004799 CodeCompletionContext::CCC_Namespace,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004800 Results.data(),Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00004801}
4802
4803void Sema::CodeCompleteNamespaceDecl(Scope *S) {
4804 if (!CodeCompleter)
4805 return;
4806
Ted Kremenekc37877d2013-10-08 17:08:03 +00004807 DeclContext *Ctx = S->getEntity();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004808 if (!S->getParent())
4809 Ctx = Context.getTranslationUnitDecl();
4810
Douglas Gregor0ac41382010-09-23 23:01:17 +00004811 bool SuppressedGlobalResults
4812 = Ctx && !CodeCompleter->includeGlobals() && isa<TranslationUnitDecl>(Ctx);
4813
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004814 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004815 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00004816 SuppressedGlobalResults
4817 ? CodeCompletionContext::CCC_Namespace
4818 : CodeCompletionContext::CCC_Other,
4819 &ResultBuilder::IsNamespace);
4820
4821 if (Ctx && Ctx->isFileContext() && !SuppressedGlobalResults) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00004822 // We only want to see those namespaces that have already been defined
4823 // within this scope, because its likely that the user is creating an
4824 // extended namespace declaration. Keep track of the most recent
4825 // definition of each namespace.
4826 std::map<NamespaceDecl *, NamespaceDecl *> OrigToLatest;
4827 for (DeclContext::specific_decl_iterator<NamespaceDecl>
4828 NS(Ctx->decls_begin()), NSEnd(Ctx->decls_end());
4829 NS != NSEnd; ++NS)
David Blaikie40ed2972012-06-06 20:45:41 +00004830 OrigToLatest[NS->getOriginalNamespace()] = *NS;
Douglas Gregor3545ff42009-09-21 16:56:56 +00004831
4832 // Add the most recent definition (or extended definition) of each
4833 // namespace to the list of results.
Douglas Gregor64b12b52009-09-22 23:31:26 +00004834 Results.EnterNewScope();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004835 for (std::map<NamespaceDecl *, NamespaceDecl *>::iterator
Douglas Gregor78254c82012-03-27 23:34:16 +00004836 NS = OrigToLatest.begin(),
4837 NSEnd = OrigToLatest.end();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004838 NS != NSEnd; ++NS)
Douglas Gregor0a0e2b32013-01-31 04:52:16 +00004839 Results.AddResult(CodeCompletionResult(
Craig Topperc3ec1492014-05-26 06:22:03 +00004840 NS->second, Results.getBasePriority(NS->second),
4841 nullptr),
4842 CurContext, nullptr, false);
Douglas Gregor64b12b52009-09-22 23:31:26 +00004843 Results.ExitScope();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004844 }
4845
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004846 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004847 Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004848 Results.data(),Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00004849}
4850
4851void Sema::CodeCompleteNamespaceAliasDecl(Scope *S) {
4852 if (!CodeCompleter)
4853 return;
4854
Douglas Gregor3545ff42009-09-21 16:56:56 +00004855 // After "namespace", we expect to see a namespace or alias.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004856 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004857 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004858 CodeCompletionContext::CCC_Namespace,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004859 &ResultBuilder::IsNamespaceOrAlias);
Douglas Gregora6e2edc2010-01-14 03:27:13 +00004860 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00004861 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00004862 CodeCompleter->includeGlobals(),
4863 CodeCompleter->loadExternal());
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004864 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004865 Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004866 Results.data(),Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00004867}
4868
Douglas Gregorc811ede2009-09-18 20:05:18 +00004869void Sema::CodeCompleteOperatorName(Scope *S) {
4870 if (!CodeCompleter)
4871 return;
Douglas Gregor3545ff42009-09-21 16:56:56 +00004872
John McCall276321a2010-08-25 06:19:51 +00004873 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004874 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004875 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004876 CodeCompletionContext::CCC_Type,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004877 &ResultBuilder::IsType);
Douglas Gregor64b12b52009-09-22 23:31:26 +00004878 Results.EnterNewScope();
Douglas Gregorc811ede2009-09-18 20:05:18 +00004879
Douglas Gregor3545ff42009-09-21 16:56:56 +00004880 // Add the names of overloadable operators.
4881#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
4882 if (std::strcmp(Spelling, "?")) \
Douglas Gregor78a21012010-01-14 16:01:26 +00004883 Results.AddResult(Result(Spelling));
Douglas Gregor3545ff42009-09-21 16:56:56 +00004884#include "clang/Basic/OperatorKinds.def"
4885
4886 // Add any type names visible from the current scope
Douglas Gregor6ae4c522010-01-14 03:21:49 +00004887 Results.allowNestedNameSpecifiers();
Douglas Gregora6e2edc2010-01-14 03:27:13 +00004888 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00004889 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00004890 CodeCompleter->includeGlobals(),
4891 CodeCompleter->loadExternal());
4892
Douglas Gregor3545ff42009-09-21 16:56:56 +00004893 // Add any type specifiers
David Blaikiebbafb8a2012-03-11 07:00:24 +00004894 AddTypeSpecifierResults(getLangOpts(), Results);
Douglas Gregor64b12b52009-09-22 23:31:26 +00004895 Results.ExitScope();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004896
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004897 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor39982192010-08-15 06:18:01 +00004898 CodeCompletionContext::CCC_Type,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004899 Results.data(),Results.size());
Douglas Gregorc811ede2009-09-18 20:05:18 +00004900}
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00004901
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00004902void Sema::CodeCompleteConstructorInitializer(
4903 Decl *ConstructorD,
4904 ArrayRef <CXXCtorInitializer *> Initializers) {
Benjamin Kramera4f8df02015-07-09 15:31:10 +00004905 if (!ConstructorD)
4906 return;
4907
4908 AdjustDeclIfTemplate(ConstructorD);
4909
4910 CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(ConstructorD);
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004911 if (!Constructor)
4912 return;
4913
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004914 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004915 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00004916 CodeCompletionContext::CCC_PotentiallyQualifiedName);
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004917 Results.EnterNewScope();
4918
4919 // Fill in any already-initialized fields or base classes.
4920 llvm::SmallPtrSet<FieldDecl *, 4> InitializedFields;
4921 llvm::SmallPtrSet<CanQualType, 4> InitializedBases;
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00004922 for (unsigned I = 0, E = Initializers.size(); I != E; ++I) {
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004923 if (Initializers[I]->isBaseInitializer())
4924 InitializedBases.insert(
4925 Context.getCanonicalType(QualType(Initializers[I]->getBaseClass(), 0)));
4926 else
Francois Pichetd583da02010-12-04 09:14:42 +00004927 InitializedFields.insert(cast<FieldDecl>(
4928 Initializers[I]->getAnyMember()));
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004929 }
4930
4931 // Add completions for base classes.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004932 CodeCompletionBuilder Builder(Results.getAllocator(),
4933 Results.getCodeCompletionTUInfo());
Benjamin Kramera4f8df02015-07-09 15:31:10 +00004934 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00004935 bool SawLastInitializer = Initializers.empty();
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004936 CXXRecordDecl *ClassDecl = Constructor->getParent();
Aaron Ballman574705e2014-03-13 15:41:46 +00004937 for (const auto &Base : ClassDecl->bases()) {
David Blaikie82e95a32014-11-19 07:49:47 +00004938 if (!InitializedBases.insert(Context.getCanonicalType(Base.getType()))
4939 .second) {
Douglas Gregor99129ef2010-08-29 19:27:27 +00004940 SawLastInitializer
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00004941 = !Initializers.empty() &&
4942 Initializers.back()->isBaseInitializer() &&
Aaron Ballman574705e2014-03-13 15:41:46 +00004943 Context.hasSameUnqualifiedType(Base.getType(),
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00004944 QualType(Initializers.back()->getBaseClass(), 0));
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004945 continue;
Douglas Gregor99129ef2010-08-29 19:27:27 +00004946 }
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004947
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004948 Builder.AddTypedTextChunk(
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00004949 Results.getAllocator().CopyString(
Aaron Ballman574705e2014-03-13 15:41:46 +00004950 Base.getType().getAsString(Policy)));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004951 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4952 Builder.AddPlaceholderChunk("args");
4953 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4954 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor99129ef2010-08-29 19:27:27 +00004955 SawLastInitializer? CCP_NextInitializer
4956 : CCP_MemberDeclaration));
4957 SawLastInitializer = false;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004958 }
4959
4960 // Add completions for virtual base classes.
Aaron Ballman445a9392014-03-13 16:15:17 +00004961 for (const auto &Base : ClassDecl->vbases()) {
David Blaikie82e95a32014-11-19 07:49:47 +00004962 if (!InitializedBases.insert(Context.getCanonicalType(Base.getType()))
4963 .second) {
Douglas Gregor99129ef2010-08-29 19:27:27 +00004964 SawLastInitializer
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00004965 = !Initializers.empty() &&
4966 Initializers.back()->isBaseInitializer() &&
Aaron Ballman445a9392014-03-13 16:15:17 +00004967 Context.hasSameUnqualifiedType(Base.getType(),
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00004968 QualType(Initializers.back()->getBaseClass(), 0));
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004969 continue;
Douglas Gregor99129ef2010-08-29 19:27:27 +00004970 }
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004971
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004972 Builder.AddTypedTextChunk(
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00004973 Builder.getAllocator().CopyString(
Aaron Ballman445a9392014-03-13 16:15:17 +00004974 Base.getType().getAsString(Policy)));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004975 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4976 Builder.AddPlaceholderChunk("args");
4977 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4978 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor99129ef2010-08-29 19:27:27 +00004979 SawLastInitializer? CCP_NextInitializer
4980 : CCP_MemberDeclaration));
4981 SawLastInitializer = false;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004982 }
4983
4984 // Add completions for members.
Aaron Ballmane8a8bae2014-03-08 20:12:42 +00004985 for (auto *Field : ClassDecl->fields()) {
David Blaikie82e95a32014-11-19 07:49:47 +00004986 if (!InitializedFields.insert(cast<FieldDecl>(Field->getCanonicalDecl()))
4987 .second) {
Douglas Gregor99129ef2010-08-29 19:27:27 +00004988 SawLastInitializer
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00004989 = !Initializers.empty() &&
4990 Initializers.back()->isAnyMemberInitializer() &&
Aaron Ballmane8a8bae2014-03-08 20:12:42 +00004991 Initializers.back()->getAnyMember() == Field;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004992 continue;
Douglas Gregor99129ef2010-08-29 19:27:27 +00004993 }
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004994
4995 if (!Field->getDeclName())
4996 continue;
4997
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00004998 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004999 Field->getIdentifier()->getName()));
5000 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5001 Builder.AddPlaceholderChunk("args");
5002 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5003 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor99129ef2010-08-29 19:27:27 +00005004 SawLastInitializer? CCP_NextInitializer
Douglas Gregorf3af3112010-09-09 21:42:20 +00005005 : CCP_MemberDeclaration,
Douglas Gregor78254c82012-03-27 23:34:16 +00005006 CXCursor_MemberRef,
5007 CXAvailability_Available,
Aaron Ballmane8a8bae2014-03-08 20:12:42 +00005008 Field));
Douglas Gregor99129ef2010-08-29 19:27:27 +00005009 SawLastInitializer = false;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005010 }
5011 Results.ExitScope();
5012
Douglas Gregor0ac41382010-09-23 23:01:17 +00005013 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005014 Results.data(), Results.size());
5015}
5016
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00005017/// Determine whether this scope denotes a namespace.
Douglas Gregord8c61782012-02-15 15:34:24 +00005018static bool isNamespaceScope(Scope *S) {
Ted Kremenekc37877d2013-10-08 17:08:03 +00005019 DeclContext *DC = S->getEntity();
Douglas Gregord8c61782012-02-15 15:34:24 +00005020 if (!DC)
5021 return false;
5022
5023 return DC->isFileContext();
5024}
5025
5026void Sema::CodeCompleteLambdaIntroducer(Scope *S, LambdaIntroducer &Intro,
5027 bool AfterAmpersand) {
5028 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005029 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregord8c61782012-02-15 15:34:24 +00005030 CodeCompletionContext::CCC_Other);
5031 Results.EnterNewScope();
5032
5033 // Note what has already been captured.
5034 llvm::SmallPtrSet<IdentifierInfo *, 4> Known;
5035 bool IncludedThis = false;
Benjamin Kramerf3ca26982014-05-10 16:31:55 +00005036 for (const auto &C : Intro.Captures) {
5037 if (C.Kind == LCK_This) {
Douglas Gregord8c61782012-02-15 15:34:24 +00005038 IncludedThis = true;
5039 continue;
5040 }
5041
Benjamin Kramerf3ca26982014-05-10 16:31:55 +00005042 Known.insert(C.Id);
Douglas Gregord8c61782012-02-15 15:34:24 +00005043 }
5044
5045 // Look for other capturable variables.
5046 for (; S && !isNamespaceScope(S); S = S->getParent()) {
Aaron Ballman35c54952014-03-17 16:55:25 +00005047 for (const auto *D : S->decls()) {
5048 const auto *Var = dyn_cast<VarDecl>(D);
Douglas Gregord8c61782012-02-15 15:34:24 +00005049 if (!Var ||
5050 !Var->hasLocalStorage() ||
5051 Var->hasAttr<BlocksAttr>())
5052 continue;
5053
David Blaikie82e95a32014-11-19 07:49:47 +00005054 if (Known.insert(Var->getIdentifier()).second)
Douglas Gregor0a0e2b32013-01-31 04:52:16 +00005055 Results.AddResult(CodeCompletionResult(Var, CCP_LocalDeclaration),
Craig Topperc3ec1492014-05-26 06:22:03 +00005056 CurContext, nullptr, false);
Douglas Gregord8c61782012-02-15 15:34:24 +00005057 }
5058 }
5059
5060 // Add 'this', if it would be valid.
5061 if (!IncludedThis && !AfterAmpersand && Intro.Default != LCD_ByCopy)
5062 addThisCompletion(*this, Results);
5063
5064 Results.ExitScope();
5065
5066 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5067 Results.data(), Results.size());
5068}
5069
James Dennett596e4752012-06-14 03:11:41 +00005070/// Macro that optionally prepends an "@" to the string literal passed in via
5071/// Keyword, depending on whether NeedAt is true or false.
5072#define OBJC_AT_KEYWORD_NAME(NeedAt,Keyword) ((NeedAt)? "@" Keyword : Keyword)
5073
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005074static void AddObjCImplementationResults(const LangOptions &LangOpts,
Douglas Gregorf1934162010-01-13 21:24:21 +00005075 ResultBuilder &Results,
5076 bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005077 typedef CodeCompletionResult Result;
Douglas Gregorf1934162010-01-13 21:24:21 +00005078 // Since we have an implementation, we can end it.
James Dennett596e4752012-06-14 03:11:41 +00005079 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"end")));
Douglas Gregorf1934162010-01-13 21:24:21 +00005080
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005081 CodeCompletionBuilder Builder(Results.getAllocator(),
5082 Results.getCodeCompletionTUInfo());
Douglas Gregorf1934162010-01-13 21:24:21 +00005083 if (LangOpts.ObjC2) {
5084 // @dynamic
James Dennett596e4752012-06-14 03:11:41 +00005085 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"dynamic"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005086 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5087 Builder.AddPlaceholderChunk("property");
5088 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf1934162010-01-13 21:24:21 +00005089
5090 // @synthesize
James Dennett596e4752012-06-14 03:11:41 +00005091 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"synthesize"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005092 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5093 Builder.AddPlaceholderChunk("property");
5094 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf1934162010-01-13 21:24:21 +00005095 }
5096}
5097
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005098static void AddObjCInterfaceResults(const LangOptions &LangOpts,
Douglas Gregorf1934162010-01-13 21:24:21 +00005099 ResultBuilder &Results,
5100 bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005101 typedef CodeCompletionResult Result;
Douglas Gregorf1934162010-01-13 21:24:21 +00005102
5103 // Since we have an interface or protocol, we can end it.
James Dennett596e4752012-06-14 03:11:41 +00005104 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"end")));
Douglas Gregorf1934162010-01-13 21:24:21 +00005105
5106 if (LangOpts.ObjC2) {
5107 // @property
James Dennett596e4752012-06-14 03:11:41 +00005108 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"property")));
Douglas Gregorf1934162010-01-13 21:24:21 +00005109
5110 // @required
James Dennett596e4752012-06-14 03:11:41 +00005111 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"required")));
Douglas Gregorf1934162010-01-13 21:24:21 +00005112
5113 // @optional
James Dennett596e4752012-06-14 03:11:41 +00005114 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"optional")));
Douglas Gregorf1934162010-01-13 21:24:21 +00005115 }
5116}
5117
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005118static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005119 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005120 CodeCompletionBuilder Builder(Results.getAllocator(),
5121 Results.getCodeCompletionTUInfo());
Douglas Gregorf1934162010-01-13 21:24:21 +00005122
5123 // @class name ;
James Dennett596e4752012-06-14 03:11:41 +00005124 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"class"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005125 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5126 Builder.AddPlaceholderChunk("name");
5127 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf1934162010-01-13 21:24:21 +00005128
Douglas Gregorf4c33342010-05-28 00:22:41 +00005129 if (Results.includeCodePatterns()) {
5130 // @interface name
5131 // FIXME: Could introduce the whole pattern, including superclasses and
5132 // such.
James Dennett596e4752012-06-14 03:11:41 +00005133 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"interface"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005134 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5135 Builder.AddPlaceholderChunk("class");
5136 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf1934162010-01-13 21:24:21 +00005137
Douglas Gregorf4c33342010-05-28 00:22:41 +00005138 // @protocol name
James Dennett596e4752012-06-14 03:11:41 +00005139 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"protocol"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005140 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5141 Builder.AddPlaceholderChunk("protocol");
5142 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00005143
5144 // @implementation name
James Dennett596e4752012-06-14 03:11:41 +00005145 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"implementation"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005146 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5147 Builder.AddPlaceholderChunk("class");
5148 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00005149 }
Douglas Gregorf1934162010-01-13 21:24:21 +00005150
5151 // @compatibility_alias name
James Dennett596e4752012-06-14 03:11:41 +00005152 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"compatibility_alias"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005153 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5154 Builder.AddPlaceholderChunk("alias");
5155 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5156 Builder.AddPlaceholderChunk("class");
5157 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor61e36812013-03-07 23:26:24 +00005158
5159 if (Results.getSema().getLangOpts().Modules) {
5160 // @import name
5161 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "import"));
5162 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5163 Builder.AddPlaceholderChunk("module");
5164 Results.AddResult(Result(Builder.TakeString()));
5165 }
Douglas Gregorf1934162010-01-13 21:24:21 +00005166}
5167
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005168void Sema::CodeCompleteObjCAtDirective(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005169 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005170 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005171 CodeCompletionContext::CCC_Other);
Douglas Gregorf48706c2009-12-07 09:27:33 +00005172 Results.EnterNewScope();
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005173 if (isa<ObjCImplDecl>(CurContext))
David Blaikiebbafb8a2012-03-11 07:00:24 +00005174 AddObjCImplementationResults(getLangOpts(), Results, false);
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005175 else if (CurContext->isObjCContainer())
David Blaikiebbafb8a2012-03-11 07:00:24 +00005176 AddObjCInterfaceResults(getLangOpts(), Results, false);
Douglas Gregorf1934162010-01-13 21:24:21 +00005177 else
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005178 AddObjCTopLevelResults(Results, false);
Douglas Gregorf48706c2009-12-07 09:27:33 +00005179 Results.ExitScope();
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005180 HandleCodeCompleteResults(this, CodeCompleter,
5181 CodeCompletionContext::CCC_Other,
5182 Results.data(),Results.size());
Douglas Gregorf48706c2009-12-07 09:27:33 +00005183}
5184
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005185static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005186 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005187 CodeCompletionBuilder Builder(Results.getAllocator(),
5188 Results.getCodeCompletionTUInfo());
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005189
5190 // @encode ( type-name )
Douglas Gregore5c79d52011-10-18 21:20:17 +00005191 const char *EncodeType = "char[]";
David Blaikiebbafb8a2012-03-11 07:00:24 +00005192 if (Results.getSema().getLangOpts().CPlusPlus ||
5193 Results.getSema().getLangOpts().ConstStrings)
Jordan Rose9da05852012-06-15 18:19:56 +00005194 EncodeType = "const char[]";
Douglas Gregore5c79d52011-10-18 21:20:17 +00005195 Builder.AddResultTypeChunk(EncodeType);
James Dennett596e4752012-06-14 03:11:41 +00005196 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"encode"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005197 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5198 Builder.AddPlaceholderChunk("type-name");
5199 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5200 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005201
5202 // @protocol ( protocol-name )
Douglas Gregore5c79d52011-10-18 21:20:17 +00005203 Builder.AddResultTypeChunk("Protocol *");
James Dennett596e4752012-06-14 03:11:41 +00005204 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"protocol"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005205 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5206 Builder.AddPlaceholderChunk("protocol-name");
5207 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5208 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005209
5210 // @selector ( selector )
Douglas Gregore5c79d52011-10-18 21:20:17 +00005211 Builder.AddResultTypeChunk("SEL");
James Dennett596e4752012-06-14 03:11:41 +00005212 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"selector"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005213 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5214 Builder.AddPlaceholderChunk("selector");
5215 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5216 Results.AddResult(Result(Builder.TakeString()));
Jordan Rose9da05852012-06-15 18:19:56 +00005217
5218 // @"string"
5219 Builder.AddResultTypeChunk("NSString *");
5220 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"\""));
5221 Builder.AddPlaceholderChunk("string");
5222 Builder.AddTextChunk("\"");
5223 Results.AddResult(Result(Builder.TakeString()));
5224
Douglas Gregor951de302012-07-17 23:24:47 +00005225 // @[objects, ...]
Jordan Rose9da05852012-06-15 18:19:56 +00005226 Builder.AddResultTypeChunk("NSArray *");
James Dennett596e4752012-06-14 03:11:41 +00005227 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"["));
Ted Kremeneke65b0862012-03-06 20:05:56 +00005228 Builder.AddPlaceholderChunk("objects, ...");
Ted Kremeneke65b0862012-03-06 20:05:56 +00005229 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
5230 Results.AddResult(Result(Builder.TakeString()));
5231
Douglas Gregor951de302012-07-17 23:24:47 +00005232 // @{key : object, ...}
Jordan Rose9da05852012-06-15 18:19:56 +00005233 Builder.AddResultTypeChunk("NSDictionary *");
James Dennett596e4752012-06-14 03:11:41 +00005234 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"{"));
Ted Kremeneke65b0862012-03-06 20:05:56 +00005235 Builder.AddPlaceholderChunk("key");
Ted Kremeneke65b0862012-03-06 20:05:56 +00005236 Builder.AddChunk(CodeCompletionString::CK_Colon);
5237 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5238 Builder.AddPlaceholderChunk("object, ...");
Ted Kremeneke65b0862012-03-06 20:05:56 +00005239 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5240 Results.AddResult(Result(Builder.TakeString()));
Jordan Rose9da05852012-06-15 18:19:56 +00005241
Douglas Gregor951de302012-07-17 23:24:47 +00005242 // @(expression)
Jordan Rose9da05852012-06-15 18:19:56 +00005243 Builder.AddResultTypeChunk("id");
5244 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "("));
Jordan Rose9da05852012-06-15 18:19:56 +00005245 Builder.AddPlaceholderChunk("expression");
Jordan Rose9da05852012-06-15 18:19:56 +00005246 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5247 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005248}
5249
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005250static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005251 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005252 CodeCompletionBuilder Builder(Results.getAllocator(),
5253 Results.getCodeCompletionTUInfo());
Douglas Gregorf1934162010-01-13 21:24:21 +00005254
Douglas Gregorf4c33342010-05-28 00:22:41 +00005255 if (Results.includeCodePatterns()) {
5256 // @try { statements } @catch ( declaration ) { statements } @finally
5257 // { statements }
James Dennett596e4752012-06-14 03:11:41 +00005258 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"try"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005259 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5260 Builder.AddPlaceholderChunk("statements");
5261 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5262 Builder.AddTextChunk("@catch");
5263 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5264 Builder.AddPlaceholderChunk("parameter");
5265 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5266 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5267 Builder.AddPlaceholderChunk("statements");
5268 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5269 Builder.AddTextChunk("@finally");
5270 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5271 Builder.AddPlaceholderChunk("statements");
5272 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5273 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00005274 }
Douglas Gregorf1934162010-01-13 21:24:21 +00005275
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005276 // @throw
James Dennett596e4752012-06-14 03:11:41 +00005277 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"throw"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005278 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5279 Builder.AddPlaceholderChunk("expression");
5280 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf1934162010-01-13 21:24:21 +00005281
Douglas Gregorf4c33342010-05-28 00:22:41 +00005282 if (Results.includeCodePatterns()) {
5283 // @synchronized ( expression ) { statements }
James Dennett596e4752012-06-14 03:11:41 +00005284 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"synchronized"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005285 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5286 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5287 Builder.AddPlaceholderChunk("expression");
5288 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5289 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5290 Builder.AddPlaceholderChunk("statements");
5291 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5292 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00005293 }
Douglas Gregorf1934162010-01-13 21:24:21 +00005294}
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005295
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005296static void AddObjCVisibilityResults(const LangOptions &LangOpts,
Douglas Gregor48d46252010-01-13 21:54:15 +00005297 ResultBuilder &Results,
5298 bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005299 typedef CodeCompletionResult Result;
James Dennett596e4752012-06-14 03:11:41 +00005300 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"private")));
5301 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"protected")));
5302 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"public")));
Douglas Gregor48d46252010-01-13 21:54:15 +00005303 if (LangOpts.ObjC2)
James Dennett596e4752012-06-14 03:11:41 +00005304 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"package")));
Douglas Gregor48d46252010-01-13 21:54:15 +00005305}
5306
5307void Sema::CodeCompleteObjCAtVisibility(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005308 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005309 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005310 CodeCompletionContext::CCC_Other);
Douglas Gregor48d46252010-01-13 21:54:15 +00005311 Results.EnterNewScope();
David Blaikiebbafb8a2012-03-11 07:00:24 +00005312 AddObjCVisibilityResults(getLangOpts(), Results, false);
Douglas Gregor48d46252010-01-13 21:54:15 +00005313 Results.ExitScope();
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005314 HandleCodeCompleteResults(this, CodeCompleter,
5315 CodeCompletionContext::CCC_Other,
5316 Results.data(),Results.size());
Douglas Gregor48d46252010-01-13 21:54:15 +00005317}
5318
5319void Sema::CodeCompleteObjCAtStatement(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005320 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005321 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005322 CodeCompletionContext::CCC_Other);
Douglas Gregorf1934162010-01-13 21:24:21 +00005323 Results.EnterNewScope();
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005324 AddObjCStatementResults(Results, false);
5325 AddObjCExpressionResults(Results, false);
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005326 Results.ExitScope();
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005327 HandleCodeCompleteResults(this, CodeCompleter,
5328 CodeCompletionContext::CCC_Other,
5329 Results.data(),Results.size());
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005330}
5331
5332void Sema::CodeCompleteObjCAtExpression(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005333 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005334 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005335 CodeCompletionContext::CCC_Other);
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005336 Results.EnterNewScope();
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005337 AddObjCExpressionResults(Results, false);
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005338 Results.ExitScope();
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005339 HandleCodeCompleteResults(this, CodeCompleter,
5340 CodeCompletionContext::CCC_Other,
5341 Results.data(),Results.size());
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005342}
5343
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00005344/// Determine whether the addition of the given flag to an Objective-C
Douglas Gregore6078da2009-11-19 00:14:45 +00005345/// property's attributes will cause a conflict.
Bill Wendling44426052012-12-20 19:22:21 +00005346static bool ObjCPropertyFlagConflicts(unsigned Attributes, unsigned NewFlag) {
Douglas Gregore6078da2009-11-19 00:14:45 +00005347 // Check if we've already added this flag.
Bill Wendling44426052012-12-20 19:22:21 +00005348 if (Attributes & NewFlag)
Douglas Gregore6078da2009-11-19 00:14:45 +00005349 return true;
5350
Bill Wendling44426052012-12-20 19:22:21 +00005351 Attributes |= NewFlag;
Douglas Gregore6078da2009-11-19 00:14:45 +00005352
5353 // Check for collisions with "readonly".
Bill Wendling44426052012-12-20 19:22:21 +00005354 if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) &&
5355 (Attributes & ObjCDeclSpec::DQ_PR_readwrite))
Douglas Gregore6078da2009-11-19 00:14:45 +00005356 return true;
5357
Jordan Rose53cb2f32012-08-20 20:01:13 +00005358 // Check for more than one of { assign, copy, retain, strong, weak }.
Bill Wendling44426052012-12-20 19:22:21 +00005359 unsigned AssignCopyRetMask = Attributes & (ObjCDeclSpec::DQ_PR_assign |
John McCall31168b02011-06-15 23:02:42 +00005360 ObjCDeclSpec::DQ_PR_unsafe_unretained |
Douglas Gregore6078da2009-11-19 00:14:45 +00005361 ObjCDeclSpec::DQ_PR_copy |
Jordan Rose53cb2f32012-08-20 20:01:13 +00005362 ObjCDeclSpec::DQ_PR_retain |
5363 ObjCDeclSpec::DQ_PR_strong |
5364 ObjCDeclSpec::DQ_PR_weak);
Douglas Gregore6078da2009-11-19 00:14:45 +00005365 if (AssignCopyRetMask &&
5366 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_assign &&
John McCall31168b02011-06-15 23:02:42 +00005367 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_unsafe_unretained &&
Douglas Gregore6078da2009-11-19 00:14:45 +00005368 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_copy &&
John McCall31168b02011-06-15 23:02:42 +00005369 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_retain &&
Jordan Rose53cb2f32012-08-20 20:01:13 +00005370 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_strong &&
5371 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_weak)
Douglas Gregore6078da2009-11-19 00:14:45 +00005372 return true;
5373
5374 return false;
5375}
5376
Douglas Gregor36029f42009-11-18 23:08:07 +00005377void Sema::CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS) {
Steve Naroff936354c2009-10-08 21:55:05 +00005378 if (!CodeCompleter)
5379 return;
Douglas Gregor1b605f72009-11-19 01:08:35 +00005380
Bill Wendling44426052012-12-20 19:22:21 +00005381 unsigned Attributes = ODS.getPropertyAttributes();
Steve Naroff936354c2009-10-08 21:55:05 +00005382
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005383 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005384 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005385 CodeCompletionContext::CCC_Other);
Steve Naroff936354c2009-10-08 21:55:05 +00005386 Results.EnterNewScope();
Bill Wendling44426052012-12-20 19:22:21 +00005387 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readonly))
John McCall276321a2010-08-25 06:19:51 +00005388 Results.AddResult(CodeCompletionResult("readonly"));
Bill Wendling44426052012-12-20 19:22:21 +00005389 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_assign))
John McCall276321a2010-08-25 06:19:51 +00005390 Results.AddResult(CodeCompletionResult("assign"));
Bill Wendling44426052012-12-20 19:22:21 +00005391 if (!ObjCPropertyFlagConflicts(Attributes,
John McCall31168b02011-06-15 23:02:42 +00005392 ObjCDeclSpec::DQ_PR_unsafe_unretained))
5393 Results.AddResult(CodeCompletionResult("unsafe_unretained"));
Bill Wendling44426052012-12-20 19:22:21 +00005394 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readwrite))
John McCall276321a2010-08-25 06:19:51 +00005395 Results.AddResult(CodeCompletionResult("readwrite"));
Bill Wendling44426052012-12-20 19:22:21 +00005396 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_retain))
John McCall276321a2010-08-25 06:19:51 +00005397 Results.AddResult(CodeCompletionResult("retain"));
Bill Wendling44426052012-12-20 19:22:21 +00005398 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_strong))
John McCall31168b02011-06-15 23:02:42 +00005399 Results.AddResult(CodeCompletionResult("strong"));
Bill Wendling44426052012-12-20 19:22:21 +00005400 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_copy))
John McCall276321a2010-08-25 06:19:51 +00005401 Results.AddResult(CodeCompletionResult("copy"));
Bill Wendling44426052012-12-20 19:22:21 +00005402 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_nonatomic))
John McCall276321a2010-08-25 06:19:51 +00005403 Results.AddResult(CodeCompletionResult("nonatomic"));
Bill Wendling44426052012-12-20 19:22:21 +00005404 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_atomic))
Fariborz Jahanian1c2d29e2011-06-11 17:14:27 +00005405 Results.AddResult(CodeCompletionResult("atomic"));
Jordan Rose53cb2f32012-08-20 20:01:13 +00005406
5407 // Only suggest "weak" if we're compiling for ARC-with-weak-references or GC.
John McCall460ce582015-10-22 18:38:17 +00005408 if (getLangOpts().ObjCWeak || getLangOpts().getGC() != LangOptions::NonGC)
Bill Wendling44426052012-12-20 19:22:21 +00005409 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_weak))
Jordan Rose53cb2f32012-08-20 20:01:13 +00005410 Results.AddResult(CodeCompletionResult("weak"));
5411
Bill Wendling44426052012-12-20 19:22:21 +00005412 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_setter)) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005413 CodeCompletionBuilder Setter(Results.getAllocator(),
5414 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005415 Setter.AddTypedTextChunk("setter");
Argyrios Kyrtzidis7bbb8812014-02-20 07:55:15 +00005416 Setter.AddTextChunk("=");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005417 Setter.AddPlaceholderChunk("method");
5418 Results.AddResult(CodeCompletionResult(Setter.TakeString()));
Douglas Gregor45f83ee2009-11-19 00:01:57 +00005419 }
Bill Wendling44426052012-12-20 19:22:21 +00005420 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_getter)) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005421 CodeCompletionBuilder Getter(Results.getAllocator(),
5422 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005423 Getter.AddTypedTextChunk("getter");
Argyrios Kyrtzidis7bbb8812014-02-20 07:55:15 +00005424 Getter.AddTextChunk("=");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005425 Getter.AddPlaceholderChunk("method");
5426 Results.AddResult(CodeCompletionResult(Getter.TakeString()));
Douglas Gregor45f83ee2009-11-19 00:01:57 +00005427 }
Douglas Gregor86b42682015-06-19 18:27:52 +00005428 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_nullability)) {
5429 Results.AddResult(CodeCompletionResult("nonnull"));
5430 Results.AddResult(CodeCompletionResult("nullable"));
5431 Results.AddResult(CodeCompletionResult("null_unspecified"));
5432 Results.AddResult(CodeCompletionResult("null_resettable"));
5433 }
Steve Naroff936354c2009-10-08 21:55:05 +00005434 Results.ExitScope();
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005435 HandleCodeCompleteResults(this, CodeCompleter,
5436 CodeCompletionContext::CCC_Other,
5437 Results.data(),Results.size());
Steve Naroff936354c2009-10-08 21:55:05 +00005438}
Steve Naroffeae65032009-11-07 02:08:14 +00005439
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00005440/// Describes the kind of Objective-C method that we want to find
Douglas Gregorc8537c52009-11-19 07:41:15 +00005441/// via code completion.
5442enum ObjCMethodKind {
Dmitri Gribenko4280e5c2012-06-08 23:13:42 +00005443 MK_Any, ///< Any kind of method, provided it means other specified criteria.
5444 MK_ZeroArgSelector, ///< Zero-argument (unary) selector.
5445 MK_OneArgSelector ///< One-argument selector.
Douglas Gregorc8537c52009-11-19 07:41:15 +00005446};
5447
Douglas Gregor67c692c2010-08-26 15:07:07 +00005448static bool isAcceptableObjCSelector(Selector Sel,
5449 ObjCMethodKind WantKind,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005450 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005451 bool AllowSameLength = true) {
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005452 unsigned NumSelIdents = SelIdents.size();
Douglas Gregor67c692c2010-08-26 15:07:07 +00005453 if (NumSelIdents > Sel.getNumArgs())
5454 return false;
5455
5456 switch (WantKind) {
5457 case MK_Any: break;
5458 case MK_ZeroArgSelector: return Sel.isUnarySelector();
5459 case MK_OneArgSelector: return Sel.getNumArgs() == 1;
5460 }
5461
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005462 if (!AllowSameLength && NumSelIdents && NumSelIdents == Sel.getNumArgs())
5463 return false;
5464
Douglas Gregor67c692c2010-08-26 15:07:07 +00005465 for (unsigned I = 0; I != NumSelIdents; ++I)
5466 if (SelIdents[I] != Sel.getIdentifierInfoForSlot(I))
5467 return false;
5468
5469 return true;
5470}
5471
Douglas Gregorc8537c52009-11-19 07:41:15 +00005472static bool isAcceptableObjCMethod(ObjCMethodDecl *Method,
5473 ObjCMethodKind WantKind,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005474 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005475 bool AllowSameLength = true) {
Douglas Gregor67c692c2010-08-26 15:07:07 +00005476 return isAcceptableObjCSelector(Method->getSelector(), WantKind, SelIdents,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005477 AllowSameLength);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005478}
Douglas Gregor1154e272010-09-16 16:06:31 +00005479
5480namespace {
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00005481 /// A set of selectors, which is used to avoid introducing multiple
Douglas Gregor1154e272010-09-16 16:06:31 +00005482 /// completions with the same selector into the result set.
5483 typedef llvm::SmallPtrSet<Selector, 16> VisitedSelectorSet;
5484}
5485
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00005486/// Add all of the Objective-C methods in the given Objective-C
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005487/// container to the set of results.
5488///
5489/// The container will be a class, protocol, category, or implementation of
5490/// any of the above. This mether will recurse to include methods from
5491/// the superclasses of classes along with their categories, protocols, and
5492/// implementations.
5493///
5494/// \param Container the container in which we'll look to find methods.
5495///
James Dennett596e4752012-06-14 03:11:41 +00005496/// \param WantInstanceMethods Whether to add instance methods (only); if
5497/// false, this routine will add factory methods (only).
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005498///
5499/// \param CurContext the context in which we're performing the lookup that
5500/// finds methods.
5501///
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005502/// \param AllowSameLength Whether we allow a method to be added to the list
5503/// when it has the same number of parameters as we have selector identifiers.
5504///
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005505/// \param Results the structure into which we'll add results.
Alex Lorenz638dbc32017-01-24 14:15:08 +00005506static void AddObjCMethods(ObjCContainerDecl *Container,
5507 bool WantInstanceMethods, ObjCMethodKind WantKind,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005508 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005509 DeclContext *CurContext,
Alex Lorenz638dbc32017-01-24 14:15:08 +00005510 VisitedSelectorSet &Selectors, bool AllowSameLength,
5511 ResultBuilder &Results, bool InOriginalClass = true,
5512 bool IsRootClass = false) {
John McCall276321a2010-08-25 06:19:51 +00005513 typedef CodeCompletionResult Result;
Douglas Gregor9b4f3702012-06-12 13:44:08 +00005514 Container = getContainerDef(Container);
Douglas Gregor41778c32013-01-30 06:58:39 +00005515 ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container);
Alex Lorenz638dbc32017-01-24 14:15:08 +00005516 IsRootClass = IsRootClass || (IFace && !IFace->getSuperClass());
Aaron Ballmanaff18c02014-03-13 19:03:34 +00005517 for (auto *M : Container->methods()) {
Douglas Gregor41778c32013-01-30 06:58:39 +00005518 // The instance methods on the root class can be messaged via the
5519 // metaclass.
5520 if (M->isInstanceMethod() == WantInstanceMethods ||
Alex Lorenz638dbc32017-01-24 14:15:08 +00005521 (IsRootClass && !WantInstanceMethods)) {
Douglas Gregor1b605f72009-11-19 01:08:35 +00005522 // Check whether the selector identifiers we've been given are a
5523 // subset of the identifiers for this particular method.
Aaron Ballmanaff18c02014-03-13 19:03:34 +00005524 if (!isAcceptableObjCMethod(M, WantKind, SelIdents, AllowSameLength))
Douglas Gregor1b605f72009-11-19 01:08:35 +00005525 continue;
Douglas Gregorc8537c52009-11-19 07:41:15 +00005526
David Blaikie82e95a32014-11-19 07:49:47 +00005527 if (!Selectors.insert(M->getSelector()).second)
Douglas Gregor1154e272010-09-16 16:06:31 +00005528 continue;
Craig Topperc3ec1492014-05-26 06:22:03 +00005529
5530 Result R = Result(M, Results.getBasePriority(M), nullptr);
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005531 R.StartParameter = SelIdents.size();
Douglas Gregorc8537c52009-11-19 07:41:15 +00005532 R.AllParametersAreInformative = (WantKind != MK_Any);
Douglas Gregor416b5752010-08-25 01:08:01 +00005533 if (!InOriginalClass)
5534 R.Priority += CCD_InBaseClass;
Douglas Gregor1b605f72009-11-19 01:08:35 +00005535 Results.MaybeAddResult(R, CurContext);
5536 }
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005537 }
5538
Douglas Gregorf37c9492010-09-16 15:34:59 +00005539 // Visit the protocols of protocols.
5540 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Douglas Gregore6e48b12012-01-01 19:29:29 +00005541 if (Protocol->hasDefinition()) {
5542 const ObjCList<ObjCProtocolDecl> &Protocols
5543 = Protocol->getReferencedProtocols();
5544 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
5545 E = Protocols.end();
5546 I != E; ++I)
Alex Lorenz638dbc32017-01-24 14:15:08 +00005547 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, CurContext,
5548 Selectors, AllowSameLength, Results, false, IsRootClass);
Douglas Gregore6e48b12012-01-01 19:29:29 +00005549 }
Douglas Gregorf37c9492010-09-16 15:34:59 +00005550 }
5551
Douglas Gregorc0ac7d62011-12-15 05:27:12 +00005552 if (!IFace || !IFace->hasDefinition())
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005553 return;
5554
5555 // Add methods in protocols.
Aaron Ballmana49c5062014-03-13 20:29:09 +00005556 for (auto *I : IFace->protocols())
Alex Lorenz638dbc32017-01-24 14:15:08 +00005557 AddObjCMethods(I, WantInstanceMethods, WantKind, SelIdents, CurContext,
5558 Selectors, AllowSameLength, Results, false, IsRootClass);
5559
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005560 // Add methods in categories.
Aaron Ballman15063e12014-03-13 21:35:02 +00005561 for (auto *CatDecl : IFace->known_categories()) {
Douglas Gregor048fbfa2013-01-16 23:00:23 +00005562 AddObjCMethods(CatDecl, WantInstanceMethods, WantKind, SelIdents,
Alex Lorenz638dbc32017-01-24 14:15:08 +00005563 CurContext, Selectors, AllowSameLength, Results,
5564 InOriginalClass, IsRootClass);
5565
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005566 // Add a categories protocol methods.
5567 const ObjCList<ObjCProtocolDecl> &Protocols
5568 = CatDecl->getReferencedProtocols();
5569 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
5570 E = Protocols.end();
5571 I != E; ++I)
Alex Lorenz638dbc32017-01-24 14:15:08 +00005572 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, CurContext,
5573 Selectors, AllowSameLength, Results, false, IsRootClass);
5574
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005575 // Add methods in category implementations.
5576 if (ObjCCategoryImplDecl *Impl = CatDecl->getImplementation())
Alex Lorenz638dbc32017-01-24 14:15:08 +00005577 AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents, CurContext,
5578 Selectors, AllowSameLength, Results, InOriginalClass,
5579 IsRootClass);
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005580 }
5581
5582 // Add methods in superclass.
Alex Lorenz638dbc32017-01-24 14:15:08 +00005583 // Avoid passing in IsRootClass since root classes won't have super classes.
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005584 if (IFace->getSuperClass())
Alex Lorenz638dbc32017-01-24 14:15:08 +00005585 AddObjCMethods(IFace->getSuperClass(), WantInstanceMethods, WantKind,
5586 SelIdents, CurContext, Selectors, AllowSameLength, Results,
5587 /*IsRootClass=*/false);
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005588
5589 // Add methods in our implementation, if any.
5590 if (ObjCImplementationDecl *Impl = IFace->getImplementation())
Alex Lorenz638dbc32017-01-24 14:15:08 +00005591 AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents, CurContext,
5592 Selectors, AllowSameLength, Results, InOriginalClass,
5593 IsRootClass);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005594}
5595
5596
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005597void Sema::CodeCompleteObjCPropertyGetter(Scope *S) {
Douglas Gregorc8537c52009-11-19 07:41:15 +00005598 // Try to find the interface where getters might live.
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005599 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005600 if (!Class) {
5601 if (ObjCCategoryDecl *Category
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005602 = dyn_cast_or_null<ObjCCategoryDecl>(CurContext))
Douglas Gregorc8537c52009-11-19 07:41:15 +00005603 Class = Category->getClassInterface();
5604
5605 if (!Class)
5606 return;
5607 }
5608
5609 // Find all of the potential getters.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005610 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005611 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005612 CodeCompletionContext::CCC_Other);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005613 Results.EnterNewScope();
5614
Douglas Gregor1154e272010-09-16 16:06:31 +00005615 VisitedSelectorSet Selectors;
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005616 AddObjCMethods(Class, true, MK_ZeroArgSelector, None, CurContext, Selectors,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005617 /*AllowSameLength=*/true, Results);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005618 Results.ExitScope();
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005619 HandleCodeCompleteResults(this, CodeCompleter,
5620 CodeCompletionContext::CCC_Other,
5621 Results.data(),Results.size());
Douglas Gregorc8537c52009-11-19 07:41:15 +00005622}
5623
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005624void Sema::CodeCompleteObjCPropertySetter(Scope *S) {
Douglas Gregorc8537c52009-11-19 07:41:15 +00005625 // Try to find the interface where setters might live.
5626 ObjCInterfaceDecl *Class
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005627 = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005628 if (!Class) {
5629 if (ObjCCategoryDecl *Category
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005630 = dyn_cast_or_null<ObjCCategoryDecl>(CurContext))
Douglas Gregorc8537c52009-11-19 07:41:15 +00005631 Class = Category->getClassInterface();
5632
5633 if (!Class)
5634 return;
5635 }
5636
5637 // Find all of the potential getters.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005638 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005639 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005640 CodeCompletionContext::CCC_Other);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005641 Results.EnterNewScope();
5642
Douglas Gregor1154e272010-09-16 16:06:31 +00005643 VisitedSelectorSet Selectors;
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005644 AddObjCMethods(Class, true, MK_OneArgSelector, None, CurContext,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005645 Selectors, /*AllowSameLength=*/true, Results);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005646
5647 Results.ExitScope();
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005648 HandleCodeCompleteResults(this, CodeCompleter,
5649 CodeCompletionContext::CCC_Other,
5650 Results.data(),Results.size());
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005651}
5652
Douglas Gregorf34a6f02011-02-15 22:19:42 +00005653void Sema::CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS,
5654 bool IsParameter) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005655 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005656 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005657 CodeCompletionContext::CCC_Type);
Douglas Gregor99fa2642010-08-24 01:06:58 +00005658 Results.EnterNewScope();
5659
5660 // Add context-sensitive, Objective-C parameter-passing keywords.
5661 bool AddedInOut = false;
5662 if ((DS.getObjCDeclQualifier() &
5663 (ObjCDeclSpec::DQ_In | ObjCDeclSpec::DQ_Inout)) == 0) {
5664 Results.AddResult("in");
5665 Results.AddResult("inout");
5666 AddedInOut = true;
5667 }
5668 if ((DS.getObjCDeclQualifier() &
5669 (ObjCDeclSpec::DQ_Out | ObjCDeclSpec::DQ_Inout)) == 0) {
5670 Results.AddResult("out");
5671 if (!AddedInOut)
5672 Results.AddResult("inout");
5673 }
5674 if ((DS.getObjCDeclQualifier() &
5675 (ObjCDeclSpec::DQ_Bycopy | ObjCDeclSpec::DQ_Byref |
5676 ObjCDeclSpec::DQ_Oneway)) == 0) {
5677 Results.AddResult("bycopy");
5678 Results.AddResult("byref");
5679 Results.AddResult("oneway");
5680 }
Douglas Gregor86b42682015-06-19 18:27:52 +00005681 if ((DS.getObjCDeclQualifier() & ObjCDeclSpec::DQ_CSNullability) == 0) {
5682 Results.AddResult("nonnull");
5683 Results.AddResult("nullable");
5684 Results.AddResult("null_unspecified");
5685 }
Douglas Gregor99fa2642010-08-24 01:06:58 +00005686
Douglas Gregorf34a6f02011-02-15 22:19:42 +00005687 // If we're completing the return type of an Objective-C method and the
5688 // identifier IBAction refers to a macro, provide a completion item for
5689 // an action, e.g.,
5690 // IBAction)<#selector#>:(id)sender
5691 if (DS.getObjCDeclQualifier() == 0 && !IsParameter &&
Richard Smith20e883e2015-04-29 23:20:19 +00005692 PP.isMacroDefined("IBAction")) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005693 CodeCompletionBuilder Builder(Results.getAllocator(),
5694 Results.getCodeCompletionTUInfo(),
5695 CCP_CodePattern, CXAvailability_Available);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00005696 Builder.AddTypedTextChunk("IBAction");
Benjamin Kramerdb534a42012-03-26 16:57:36 +00005697 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00005698 Builder.AddPlaceholderChunk("selector");
Benjamin Kramerdb534a42012-03-26 16:57:36 +00005699 Builder.AddChunk(CodeCompletionString::CK_Colon);
5700 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00005701 Builder.AddTextChunk("id");
Benjamin Kramerdb534a42012-03-26 16:57:36 +00005702 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00005703 Builder.AddTextChunk("sender");
5704 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
5705 }
Douglas Gregored1f5972013-01-30 07:11:43 +00005706
5707 // If we're completing the return type, provide 'instancetype'.
5708 if (!IsParameter) {
5709 Results.AddResult(CodeCompletionResult("instancetype"));
5710 }
Douglas Gregorf34a6f02011-02-15 22:19:42 +00005711
Douglas Gregor99fa2642010-08-24 01:06:58 +00005712 // Add various builtin type names and specifiers.
5713 AddOrdinaryNameResults(PCC_Type, S, *this, Results);
5714 Results.ExitScope();
5715
5716 // Add the various type names
5717 Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
5718 CodeCompletionDeclConsumer Consumer(Results, CurContext);
5719 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00005720 CodeCompleter->includeGlobals(),
5721 CodeCompleter->loadExternal());
5722
Douglas Gregor99fa2642010-08-24 01:06:58 +00005723 if (CodeCompleter->includeMacros())
Douglas Gregor8cb17462012-10-09 16:01:50 +00005724 AddMacroResults(PP, Results, false);
Douglas Gregor99fa2642010-08-24 01:06:58 +00005725
5726 HandleCodeCompleteResults(this, CodeCompleter,
5727 CodeCompletionContext::CCC_Type,
5728 Results.data(), Results.size());
5729}
5730
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00005731/// When we have an expression with type "id", we may assume
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005732/// that it has some more-specific class type based on knowledge of
5733/// common uses of Objective-C. This routine returns that class type,
5734/// or NULL if no better result could be determined.
5735static ObjCInterfaceDecl *GetAssumedMessageSendExprType(Expr *E) {
Douglas Gregored0b69d2010-09-15 16:23:04 +00005736 ObjCMessageExpr *Msg = dyn_cast_or_null<ObjCMessageExpr>(E);
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005737 if (!Msg)
Craig Topperc3ec1492014-05-26 06:22:03 +00005738 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005739
5740 Selector Sel = Msg->getSelector();
5741 if (Sel.isNull())
Craig Topperc3ec1492014-05-26 06:22:03 +00005742 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005743
5744 IdentifierInfo *Id = Sel.getIdentifierInfoForSlot(0);
5745 if (!Id)
Craig Topperc3ec1492014-05-26 06:22:03 +00005746 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005747
5748 ObjCMethodDecl *Method = Msg->getMethodDecl();
5749 if (!Method)
Craig Topperc3ec1492014-05-26 06:22:03 +00005750 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005751
5752 // Determine the class that we're sending the message to.
Craig Topperc3ec1492014-05-26 06:22:03 +00005753 ObjCInterfaceDecl *IFace = nullptr;
Douglas Gregor9a129192010-04-21 00:45:42 +00005754 switch (Msg->getReceiverKind()) {
5755 case ObjCMessageExpr::Class:
John McCall8b07ec22010-05-15 11:32:37 +00005756 if (const ObjCObjectType *ObjType
5757 = Msg->getClassReceiver()->getAs<ObjCObjectType>())
5758 IFace = ObjType->getInterface();
Douglas Gregor9a129192010-04-21 00:45:42 +00005759 break;
5760
5761 case ObjCMessageExpr::Instance: {
5762 QualType T = Msg->getInstanceReceiver()->getType();
5763 if (const ObjCObjectPointerType *Ptr = T->getAs<ObjCObjectPointerType>())
5764 IFace = Ptr->getInterfaceDecl();
5765 break;
5766 }
5767
5768 case ObjCMessageExpr::SuperInstance:
5769 case ObjCMessageExpr::SuperClass:
5770 break;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005771 }
5772
5773 if (!IFace)
Craig Topperc3ec1492014-05-26 06:22:03 +00005774 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005775
5776 ObjCInterfaceDecl *Super = IFace->getSuperClass();
5777 if (Method->isInstanceMethod())
5778 return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
5779 .Case("retain", IFace)
John McCall31168b02011-06-15 23:02:42 +00005780 .Case("strong", IFace)
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005781 .Case("autorelease", IFace)
5782 .Case("copy", IFace)
5783 .Case("copyWithZone", IFace)
5784 .Case("mutableCopy", IFace)
5785 .Case("mutableCopyWithZone", IFace)
5786 .Case("awakeFromCoder", IFace)
5787 .Case("replacementObjectFromCoder", IFace)
5788 .Case("class", IFace)
5789 .Case("classForCoder", IFace)
5790 .Case("superclass", Super)
Craig Topperc3ec1492014-05-26 06:22:03 +00005791 .Default(nullptr);
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005792
5793 return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
5794 .Case("new", IFace)
5795 .Case("alloc", IFace)
5796 .Case("allocWithZone", IFace)
5797 .Case("class", IFace)
5798 .Case("superclass", Super)
Craig Topperc3ec1492014-05-26 06:22:03 +00005799 .Default(nullptr);
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005800}
5801
Douglas Gregor6fc04132010-08-27 15:10:57 +00005802// Add a special completion for a message send to "super", which fills in the
5803// most likely case of forwarding all of our arguments to the superclass
5804// function.
5805///
5806/// \param S The semantic analysis object.
5807///
Dmitri Gribenkoadba9be2012-08-23 17:58:28 +00005808/// \param NeedSuperKeyword Whether we need to prefix this completion with
Douglas Gregor6fc04132010-08-27 15:10:57 +00005809/// the "super" keyword. Otherwise, we just need to provide the arguments.
5810///
5811/// \param SelIdents The identifiers in the selector that have already been
5812/// provided as arguments for a send to "super".
5813///
Douglas Gregor6fc04132010-08-27 15:10:57 +00005814/// \param Results The set of results to augment.
5815///
5816/// \returns the Objective-C method declaration that would be invoked by
5817/// this "super" completion. If NULL, no completion was added.
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005818static ObjCMethodDecl *AddSuperSendCompletion(
5819 Sema &S, bool NeedSuperKeyword,
5820 ArrayRef<IdentifierInfo *> SelIdents,
5821 ResultBuilder &Results) {
Douglas Gregor6fc04132010-08-27 15:10:57 +00005822 ObjCMethodDecl *CurMethod = S.getCurMethodDecl();
5823 if (!CurMethod)
Craig Topperc3ec1492014-05-26 06:22:03 +00005824 return nullptr;
5825
Douglas Gregor6fc04132010-08-27 15:10:57 +00005826 ObjCInterfaceDecl *Class = CurMethod->getClassInterface();
5827 if (!Class)
Craig Topperc3ec1492014-05-26 06:22:03 +00005828 return nullptr;
5829
Douglas Gregor6fc04132010-08-27 15:10:57 +00005830 // Try to find a superclass method with the same selector.
Craig Topperc3ec1492014-05-26 06:22:03 +00005831 ObjCMethodDecl *SuperMethod = nullptr;
Douglas Gregorb5f1e462011-02-16 00:51:18 +00005832 while ((Class = Class->getSuperClass()) && !SuperMethod) {
5833 // Check in the class
Douglas Gregor6fc04132010-08-27 15:10:57 +00005834 SuperMethod = Class->getMethod(CurMethod->getSelector(),
5835 CurMethod->isInstanceMethod());
5836
Douglas Gregorb5f1e462011-02-16 00:51:18 +00005837 // Check in categories or class extensions.
5838 if (!SuperMethod) {
Aaron Ballman15063e12014-03-13 21:35:02 +00005839 for (const auto *Cat : Class->known_categories()) {
Douglas Gregor048fbfa2013-01-16 23:00:23 +00005840 if ((SuperMethod = Cat->getMethod(CurMethod->getSelector(),
Douglas Gregorb5f1e462011-02-16 00:51:18 +00005841 CurMethod->isInstanceMethod())))
5842 break;
Douglas Gregor048fbfa2013-01-16 23:00:23 +00005843 }
Douglas Gregorb5f1e462011-02-16 00:51:18 +00005844 }
5845 }
5846
Douglas Gregor6fc04132010-08-27 15:10:57 +00005847 if (!SuperMethod)
Craig Topperc3ec1492014-05-26 06:22:03 +00005848 return nullptr;
5849
Douglas Gregor6fc04132010-08-27 15:10:57 +00005850 // Check whether the superclass method has the same signature.
5851 if (CurMethod->param_size() != SuperMethod->param_size() ||
5852 CurMethod->isVariadic() != SuperMethod->isVariadic())
Craig Topperc3ec1492014-05-26 06:22:03 +00005853 return nullptr;
5854
Douglas Gregor6fc04132010-08-27 15:10:57 +00005855 for (ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin(),
5856 CurPEnd = CurMethod->param_end(),
5857 SuperP = SuperMethod->param_begin();
5858 CurP != CurPEnd; ++CurP, ++SuperP) {
5859 // Make sure the parameter types are compatible.
5860 if (!S.Context.hasSameUnqualifiedType((*CurP)->getType(),
5861 (*SuperP)->getType()))
Craig Topperc3ec1492014-05-26 06:22:03 +00005862 return nullptr;
5863
Douglas Gregor6fc04132010-08-27 15:10:57 +00005864 // Make sure we have a parameter name to forward!
5865 if (!(*CurP)->getIdentifier())
Craig Topperc3ec1492014-05-26 06:22:03 +00005866 return nullptr;
Douglas Gregor6fc04132010-08-27 15:10:57 +00005867 }
5868
5869 // We have a superclass method. Now, form the send-to-super completion.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005870 CodeCompletionBuilder Builder(Results.getAllocator(),
5871 Results.getCodeCompletionTUInfo());
Douglas Gregor6fc04132010-08-27 15:10:57 +00005872
5873 // Give this completion a return type.
Douglas Gregorc3425b12015-07-07 06:20:19 +00005874 AddResultTypeChunk(S.Context, getCompletionPrintingPolicy(S), SuperMethod,
5875 Results.getCompletionContext().getBaseType(),
Douglas Gregor75acd922011-09-27 23:30:47 +00005876 Builder);
Douglas Gregor6fc04132010-08-27 15:10:57 +00005877
5878 // If we need the "super" keyword, add it (plus some spacing).
5879 if (NeedSuperKeyword) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005880 Builder.AddTypedTextChunk("super");
5881 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregor6fc04132010-08-27 15:10:57 +00005882 }
5883
5884 Selector Sel = CurMethod->getSelector();
5885 if (Sel.isUnarySelector()) {
5886 if (NeedSuperKeyword)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005887 Builder.AddTextChunk(Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00005888 Sel.getNameForSlot(0)));
Douglas Gregor6fc04132010-08-27 15:10:57 +00005889 else
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005890 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00005891 Sel.getNameForSlot(0)));
Douglas Gregor6fc04132010-08-27 15:10:57 +00005892 } else {
5893 ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin();
5894 for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I, ++CurP) {
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005895 if (I > SelIdents.size())
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005896 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregor6fc04132010-08-27 15:10:57 +00005897
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005898 if (I < SelIdents.size())
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005899 Builder.AddInformativeChunk(
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005900 Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00005901 Sel.getNameForSlot(I) + ":"));
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005902 else if (NeedSuperKeyword || I > SelIdents.size()) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005903 Builder.AddTextChunk(
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005904 Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00005905 Sel.getNameForSlot(I) + ":"));
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005906 Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005907 (*CurP)->getIdentifier()->getName()));
Douglas Gregor6fc04132010-08-27 15:10:57 +00005908 } else {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005909 Builder.AddTypedTextChunk(
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005910 Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00005911 Sel.getNameForSlot(I) + ":"));
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005912 Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005913 (*CurP)->getIdentifier()->getName()));
Douglas Gregor6fc04132010-08-27 15:10:57 +00005914 }
5915 }
5916 }
5917
Douglas Gregor78254c82012-03-27 23:34:16 +00005918 Results.AddResult(CodeCompletionResult(Builder.TakeString(), SuperMethod,
5919 CCP_SuperCompletion));
Douglas Gregor6fc04132010-08-27 15:10:57 +00005920 return SuperMethod;
5921}
5922
Douglas Gregora817a192010-05-27 23:06:34 +00005923void Sema::CodeCompleteObjCMessageReceiver(Scope *S) {
John McCall276321a2010-08-25 06:19:51 +00005924 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005925 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005926 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005927 CodeCompletionContext::CCC_ObjCMessageReceiver,
Richard Smith2bf7fdb2013-01-02 11:42:31 +00005928 getLangOpts().CPlusPlus11
Douglas Gregord8c61782012-02-15 15:34:24 +00005929 ? &ResultBuilder::IsObjCMessageReceiverOrLambdaCapture
5930 : &ResultBuilder::IsObjCMessageReceiver);
Douglas Gregora817a192010-05-27 23:06:34 +00005931
Douglas Gregora817a192010-05-27 23:06:34 +00005932 CodeCompletionDeclConsumer Consumer(Results, CurContext);
5933 Results.EnterNewScope();
Douglas Gregor39982192010-08-15 06:18:01 +00005934 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00005935 CodeCompleter->includeGlobals(),
5936 CodeCompleter->loadExternal());
5937
Douglas Gregora817a192010-05-27 23:06:34 +00005938 // If we are in an Objective-C method inside a class that has a superclass,
5939 // add "super" as an option.
5940 if (ObjCMethodDecl *Method = getCurMethodDecl())
5941 if (ObjCInterfaceDecl *Iface = Method->getClassInterface())
Douglas Gregor6fc04132010-08-27 15:10:57 +00005942 if (Iface->getSuperClass()) {
Douglas Gregora817a192010-05-27 23:06:34 +00005943 Results.AddResult(Result("super"));
Douglas Gregor6fc04132010-08-27 15:10:57 +00005944
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005945 AddSuperSendCompletion(*this, /*NeedSuperKeyword=*/true, None, Results);
Douglas Gregor6fc04132010-08-27 15:10:57 +00005946 }
Douglas Gregora817a192010-05-27 23:06:34 +00005947
Richard Smith2bf7fdb2013-01-02 11:42:31 +00005948 if (getLangOpts().CPlusPlus11)
Douglas Gregord8c61782012-02-15 15:34:24 +00005949 addThisCompletion(*this, Results);
5950
Douglas Gregora817a192010-05-27 23:06:34 +00005951 Results.ExitScope();
5952
5953 if (CodeCompleter->includeMacros())
Douglas Gregor8cb17462012-10-09 16:01:50 +00005954 AddMacroResults(PP, Results, false);
Douglas Gregor50832e02010-09-20 22:39:41 +00005955 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005956 Results.data(), Results.size());
Douglas Gregora817a192010-05-27 23:06:34 +00005957
5958}
5959
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005960void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005961 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00005962 bool AtArgumentExpression) {
Craig Topperc3ec1492014-05-26 06:22:03 +00005963 ObjCInterfaceDecl *CDecl = nullptr;
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005964 if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
5965 // Figure out which interface we're in.
5966 CDecl = CurMethod->getClassInterface();
5967 if (!CDecl)
5968 return;
5969
5970 // Find the superclass of this class.
5971 CDecl = CDecl->getSuperClass();
5972 if (!CDecl)
5973 return;
5974
5975 if (CurMethod->isInstanceMethod()) {
5976 // We are inside an instance method, which means that the message
5977 // send [super ...] is actually calling an instance method on the
Douglas Gregor392a84b2010-10-13 21:24:53 +00005978 // current object.
Craig Topperc3ec1492014-05-26 06:22:03 +00005979 return CodeCompleteObjCInstanceMessage(S, nullptr, SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00005980 AtArgumentExpression,
Douglas Gregor392a84b2010-10-13 21:24:53 +00005981 CDecl);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005982 }
5983
5984 // Fall through to send to the superclass in CDecl.
5985 } else {
5986 // "super" may be the name of a type or variable. Figure out which
5987 // it is.
Argyrios Kyrtzidis3e56dd42013-03-14 22:56:43 +00005988 IdentifierInfo *Super = getSuperIdentifier();
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005989 NamedDecl *ND = LookupSingleName(S, Super, SuperLoc,
5990 LookupOrdinaryName);
5991 if ((CDecl = dyn_cast_or_null<ObjCInterfaceDecl>(ND))) {
5992 // "super" names an interface. Use it.
5993 } else if (TypeDecl *TD = dyn_cast_or_null<TypeDecl>(ND)) {
John McCall8b07ec22010-05-15 11:32:37 +00005994 if (const ObjCObjectType *Iface
5995 = Context.getTypeDeclType(TD)->getAs<ObjCObjectType>())
5996 CDecl = Iface->getInterface();
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005997 } else if (ND && isa<UnresolvedUsingTypenameDecl>(ND)) {
5998 // "super" names an unresolved type; we can't be more specific.
5999 } else {
6000 // Assume that "super" names some kind of value and parse that way.
6001 CXXScopeSpec SS;
Abramo Bagnara7945c982012-01-27 09:46:47 +00006002 SourceLocation TemplateKWLoc;
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006003 UnqualifiedId id;
6004 id.setIdentifier(Super, SuperLoc);
Abramo Bagnara7945c982012-01-27 09:46:47 +00006005 ExprResult SuperExpr = ActOnIdExpression(S, SS, TemplateKWLoc, id,
6006 false, false);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006007 return CodeCompleteObjCInstanceMessage(S, (Expr *)SuperExpr.get(),
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006008 SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006009 AtArgumentExpression);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006010 }
6011
6012 // Fall through
6013 }
6014
John McCallba7bf592010-08-24 05:47:05 +00006015 ParsedType Receiver;
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006016 if (CDecl)
John McCallba7bf592010-08-24 05:47:05 +00006017 Receiver = ParsedType::make(Context.getObjCInterfaceType(CDecl));
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006018 return CodeCompleteObjCClassMessage(S, Receiver, SelIdents,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006019 AtArgumentExpression,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006020 /*IsSuper=*/true);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006021}
6022
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006023/// Given a set of code-completion results for the argument of a message
Douglas Gregor74661272010-09-21 00:03:25 +00006024/// send, determine the preferred type (if any) for that argument expression.
6025static QualType getPreferredArgumentTypeForMessageSend(ResultBuilder &Results,
6026 unsigned NumSelIdents) {
6027 typedef CodeCompletionResult Result;
6028 ASTContext &Context = Results.getSema().Context;
6029
6030 QualType PreferredType;
6031 unsigned BestPriority = CCP_Unlikely * 2;
6032 Result *ResultsData = Results.data();
6033 for (unsigned I = 0, N = Results.size(); I != N; ++I) {
6034 Result &R = ResultsData[I];
6035 if (R.Kind == Result::RK_Declaration &&
6036 isa<ObjCMethodDecl>(R.Declaration)) {
6037 if (R.Priority <= BestPriority) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00006038 const ObjCMethodDecl *Method = cast<ObjCMethodDecl>(R.Declaration);
Douglas Gregor74661272010-09-21 00:03:25 +00006039 if (NumSelIdents <= Method->param_size()) {
Alp Toker03376dc2014-07-07 09:02:20 +00006040 QualType MyPreferredType = Method->parameters()[NumSelIdents - 1]
Douglas Gregor74661272010-09-21 00:03:25 +00006041 ->getType();
6042 if (R.Priority < BestPriority || PreferredType.isNull()) {
6043 BestPriority = R.Priority;
6044 PreferredType = MyPreferredType;
6045 } else if (!Context.hasSameUnqualifiedType(PreferredType,
6046 MyPreferredType)) {
6047 PreferredType = QualType();
6048 }
6049 }
6050 }
6051 }
6052 }
6053
6054 return PreferredType;
6055}
6056
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006057static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
6058 ParsedType Receiver,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006059 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006060 bool AtArgumentExpression,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006061 bool IsSuper,
6062 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00006063 typedef CodeCompletionResult Result;
Craig Topperc3ec1492014-05-26 06:22:03 +00006064 ObjCInterfaceDecl *CDecl = nullptr;
6065
Douglas Gregor8ce33212009-11-17 17:59:40 +00006066 // If the given name refers to an interface type, retrieve the
6067 // corresponding declaration.
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006068 if (Receiver) {
Craig Topperc3ec1492014-05-26 06:22:03 +00006069 QualType T = SemaRef.GetTypeFromParser(Receiver, nullptr);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006070 if (!T.isNull())
John McCall8b07ec22010-05-15 11:32:37 +00006071 if (const ObjCObjectType *Interface = T->getAs<ObjCObjectType>())
6072 CDecl = Interface->getInterface();
Douglas Gregor8ce33212009-11-17 17:59:40 +00006073 }
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006074
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006075 // Add all of the factory methods in this Objective-C class, its protocols,
6076 // superclasses, categories, implementation, etc.
Steve Naroffeae65032009-11-07 02:08:14 +00006077 Results.EnterNewScope();
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006078
Douglas Gregor6fc04132010-08-27 15:10:57 +00006079 // If this is a send-to-super, try to add the special "super" send
6080 // completion.
6081 if (IsSuper) {
6082 if (ObjCMethodDecl *SuperMethod
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006083 = AddSuperSendCompletion(SemaRef, false, SelIdents, Results))
Douglas Gregor6fc04132010-08-27 15:10:57 +00006084 Results.Ignore(SuperMethod);
6085 }
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006086
Douglas Gregorc2cb2e22010-08-27 15:29:55 +00006087 // If we're inside an Objective-C method definition, prefer its selector to
6088 // others.
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006089 if (ObjCMethodDecl *CurMethod = SemaRef.getCurMethodDecl())
Douglas Gregorc2cb2e22010-08-27 15:29:55 +00006090 Results.setPreferredSelector(CurMethod->getSelector());
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006091
Douglas Gregor1154e272010-09-16 16:06:31 +00006092 VisitedSelectorSet Selectors;
Douglas Gregor6285f752010-04-06 16:40:00 +00006093 if (CDecl)
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006094 AddObjCMethods(CDecl, false, MK_Any, SelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00006095 SemaRef.CurContext, Selectors, AtArgumentExpression,
6096 Results);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006097 else {
Douglas Gregor6285f752010-04-06 16:40:00 +00006098 // We're messaging "id" as a type; provide all class/factory methods.
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006099
Douglas Gregord720daf2010-04-06 17:30:22 +00006100 // If we have an external source, load the entire class method
Sebastian Redld44cd6a2010-08-18 23:57:06 +00006101 // pool from the AST file.
Axel Naumanndd433f02012-10-18 19:05:02 +00006102 if (SemaRef.getExternalSource()) {
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006103 for (uint32_t I = 0,
Axel Naumanndd433f02012-10-18 19:05:02 +00006104 N = SemaRef.getExternalSource()->GetNumExternalSelectors();
John McCall75b960e2010-06-01 09:23:16 +00006105 I != N; ++I) {
Axel Naumanndd433f02012-10-18 19:05:02 +00006106 Selector Sel = SemaRef.getExternalSource()->GetExternalSelector(I);
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006107 if (Sel.isNull() || SemaRef.MethodPool.count(Sel))
Douglas Gregord720daf2010-04-06 17:30:22 +00006108 continue;
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006109
6110 SemaRef.ReadMethodPool(Sel);
Douglas Gregord720daf2010-04-06 17:30:22 +00006111 }
6112 }
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006113
6114 for (Sema::GlobalMethodPool::iterator M = SemaRef.MethodPool.begin(),
6115 MEnd = SemaRef.MethodPool.end();
Sebastian Redl75d8a322010-08-02 23:18:59 +00006116 M != MEnd; ++M) {
6117 for (ObjCMethodList *MethList = &M->second.second;
Nico Weber2e0c8f72014-12-27 03:58:08 +00006118 MethList && MethList->getMethod();
Argyrios Kyrtzidisd3da6e02013-04-17 00:08:58 +00006119 MethList = MethList->getNext()) {
Nico Weber2e0c8f72014-12-27 03:58:08 +00006120 if (!isAcceptableObjCMethod(MethList->getMethod(), MK_Any, SelIdents))
Douglas Gregor6285f752010-04-06 16:40:00 +00006121 continue;
Craig Topperc3ec1492014-05-26 06:22:03 +00006122
Nico Weber2e0c8f72014-12-27 03:58:08 +00006123 Result R(MethList->getMethod(),
6124 Results.getBasePriority(MethList->getMethod()), nullptr);
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006125 R.StartParameter = SelIdents.size();
Douglas Gregor6285f752010-04-06 16:40:00 +00006126 R.AllParametersAreInformative = false;
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006127 Results.MaybeAddResult(R, SemaRef.CurContext);
Douglas Gregor6285f752010-04-06 16:40:00 +00006128 }
6129 }
6130 }
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006131
6132 Results.ExitScope();
6133}
Douglas Gregor6285f752010-04-06 16:40:00 +00006134
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006135void Sema::CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006136 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006137 bool AtArgumentExpression,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006138 bool IsSuper) {
Douglas Gregor63745d52011-07-21 01:05:26 +00006139
6140 QualType T = this->GetTypeFromParser(Receiver);
6141
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006142 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006143 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor63745d52011-07-21 01:05:26 +00006144 CodeCompletionContext(CodeCompletionContext::CCC_ObjCClassMessage,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006145 T, SelIdents));
Douglas Gregor63745d52011-07-21 01:05:26 +00006146
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006147 AddClassMessageCompletions(*this, S, Receiver, SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006148 AtArgumentExpression, IsSuper, Results);
Douglas Gregor74661272010-09-21 00:03:25 +00006149
6150 // If we're actually at the argument expression (rather than prior to the
6151 // selector), we're actually performing code completion for an expression.
6152 // Determine whether we have a single, best method. If so, we can
6153 // code-complete the expression using the corresponding parameter type as
6154 // our preferred type, improving completion results.
6155 if (AtArgumentExpression) {
6156 QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006157 SelIdents.size());
Douglas Gregor74661272010-09-21 00:03:25 +00006158 if (PreferredType.isNull())
6159 CodeCompleteOrdinaryName(S, PCC_Expression);
6160 else
6161 CodeCompleteExpression(S, PreferredType);
6162 return;
6163 }
6164
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006165 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor63745d52011-07-21 01:05:26 +00006166 Results.getCompletionContext(),
Douglas Gregor6fc04132010-08-27 15:10:57 +00006167 Results.data(), Results.size());
Steve Naroffeae65032009-11-07 02:08:14 +00006168}
6169
Richard Trieu2bd04012011-09-09 02:00:50 +00006170void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006171 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006172 bool AtArgumentExpression,
Douglas Gregor392a84b2010-10-13 21:24:53 +00006173 ObjCInterfaceDecl *Super) {
John McCall276321a2010-08-25 06:19:51 +00006174 typedef CodeCompletionResult Result;
Steve Naroffeae65032009-11-07 02:08:14 +00006175
6176 Expr *RecExpr = static_cast<Expr *>(Receiver);
Steve Naroffeae65032009-11-07 02:08:14 +00006177
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006178 // If necessary, apply function/array conversion to the receiver.
6179 // C99 6.7.5.3p[7,8].
John Wiegley01296292011-04-08 18:41:53 +00006180 if (RecExpr) {
6181 ExprResult Conv = DefaultFunctionArrayLvalueConversion(RecExpr);
6182 if (Conv.isInvalid()) // conversion failed. bail.
6183 return;
Nikola Smiljanic01a75982014-05-29 10:55:11 +00006184 RecExpr = Conv.get();
John Wiegley01296292011-04-08 18:41:53 +00006185 }
Douglas Gregor392a84b2010-10-13 21:24:53 +00006186 QualType ReceiverType = RecExpr? RecExpr->getType()
6187 : Super? Context.getObjCObjectPointerType(
6188 Context.getObjCInterfaceType(Super))
6189 : Context.getObjCIdType();
Steve Naroffeae65032009-11-07 02:08:14 +00006190
Douglas Gregordc520b02010-11-08 21:12:30 +00006191 // If we're messaging an expression with type "id" or "Class", check
6192 // whether we know something special about the receiver that allows
6193 // us to assume a more-specific receiver type.
Anders Carlsson382ba412014-02-28 19:07:22 +00006194 if (ReceiverType->isObjCIdType() || ReceiverType->isObjCClassType()) {
Douglas Gregordc520b02010-11-08 21:12:30 +00006195 if (ObjCInterfaceDecl *IFace = GetAssumedMessageSendExprType(RecExpr)) {
6196 if (ReceiverType->isObjCClassType())
6197 return CodeCompleteObjCClassMessage(S,
6198 ParsedType::make(Context.getObjCInterfaceType(IFace)),
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006199 SelIdents,
Douglas Gregordc520b02010-11-08 21:12:30 +00006200 AtArgumentExpression, Super);
6201
6202 ReceiverType = Context.getObjCObjectPointerType(
6203 Context.getObjCInterfaceType(IFace));
6204 }
Anders Carlsson382ba412014-02-28 19:07:22 +00006205 } else if (RecExpr && getLangOpts().CPlusPlus) {
6206 ExprResult Conv = PerformContextuallyConvertToObjCPointer(RecExpr);
6207 if (Conv.isUsable()) {
Nikola Smiljanic01a75982014-05-29 10:55:11 +00006208 RecExpr = Conv.get();
Anders Carlsson382ba412014-02-28 19:07:22 +00006209 ReceiverType = RecExpr->getType();
6210 }
6211 }
Douglas Gregordc520b02010-11-08 21:12:30 +00006212
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006213 // Build the set of methods we can see.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006214 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006215 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor63745d52011-07-21 01:05:26 +00006216 CodeCompletionContext(CodeCompletionContext::CCC_ObjCInstanceMessage,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006217 ReceiverType, SelIdents));
Douglas Gregor63745d52011-07-21 01:05:26 +00006218
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006219 Results.EnterNewScope();
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006220
Douglas Gregor6fc04132010-08-27 15:10:57 +00006221 // If this is a send-to-super, try to add the special "super" send
6222 // completion.
Douglas Gregor392a84b2010-10-13 21:24:53 +00006223 if (Super) {
Douglas Gregor6fc04132010-08-27 15:10:57 +00006224 if (ObjCMethodDecl *SuperMethod
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006225 = AddSuperSendCompletion(*this, false, SelIdents, Results))
Douglas Gregor6fc04132010-08-27 15:10:57 +00006226 Results.Ignore(SuperMethod);
6227 }
6228
Douglas Gregorc2cb2e22010-08-27 15:29:55 +00006229 // If we're inside an Objective-C method definition, prefer its selector to
6230 // others.
6231 if (ObjCMethodDecl *CurMethod = getCurMethodDecl())
6232 Results.setPreferredSelector(CurMethod->getSelector());
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006233
Douglas Gregor1154e272010-09-16 16:06:31 +00006234 // Keep track of the selectors we've already added.
6235 VisitedSelectorSet Selectors;
6236
Douglas Gregora3329fa2009-11-18 00:06:18 +00006237 // Handle messages to Class. This really isn't a message to an instance
6238 // method, so we treat it the same way we would treat a message send to a
6239 // class method.
6240 if (ReceiverType->isObjCClassType() ||
6241 ReceiverType->isObjCQualifiedClassType()) {
6242 if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
6243 if (ObjCInterfaceDecl *ClassDecl = CurMethod->getClassInterface())
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006244 AddObjCMethods(ClassDecl, false, MK_Any, SelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00006245 CurContext, Selectors, AtArgumentExpression, Results);
Douglas Gregora3329fa2009-11-18 00:06:18 +00006246 }
6247 }
6248 // Handle messages to a qualified ID ("id<foo>").
6249 else if (const ObjCObjectPointerType *QualID
6250 = ReceiverType->getAsObjCQualifiedIdType()) {
6251 // Search protocols for instance methods.
Aaron Ballman83731462014-03-17 16:14:00 +00006252 for (auto *I : QualID->quals())
6253 AddObjCMethods(I, true, MK_Any, SelIdents, CurContext,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00006254 Selectors, AtArgumentExpression, Results);
Douglas Gregora3329fa2009-11-18 00:06:18 +00006255 }
6256 // Handle messages to a pointer to interface type.
6257 else if (const ObjCObjectPointerType *IFacePtr
6258 = ReceiverType->getAsObjCInterfacePointerType()) {
6259 // Search the class, its superclasses, etc., for instance methods.
Douglas Gregorc8537c52009-11-19 07:41:15 +00006260 AddObjCMethods(IFacePtr->getInterfaceDecl(), true, MK_Any, SelIdents,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006261 CurContext, Selectors, AtArgumentExpression,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00006262 Results);
Douglas Gregora3329fa2009-11-18 00:06:18 +00006263
6264 // Search protocols for instance methods.
Aaron Ballman83731462014-03-17 16:14:00 +00006265 for (auto *I : IFacePtr->quals())
6266 AddObjCMethods(I, true, MK_Any, SelIdents, CurContext,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00006267 Selectors, AtArgumentExpression, Results);
Douglas Gregora3329fa2009-11-18 00:06:18 +00006268 }
Douglas Gregor6285f752010-04-06 16:40:00 +00006269 // Handle messages to "id".
6270 else if (ReceiverType->isObjCIdType()) {
Douglas Gregord720daf2010-04-06 17:30:22 +00006271 // We're messaging "id", so provide all instance methods we know
6272 // about as code-completion results.
6273
6274 // If we have an external source, load the entire class method
Sebastian Redld44cd6a2010-08-18 23:57:06 +00006275 // pool from the AST file.
Douglas Gregord720daf2010-04-06 17:30:22 +00006276 if (ExternalSource) {
John McCall75b960e2010-06-01 09:23:16 +00006277 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
6278 I != N; ++I) {
6279 Selector Sel = ExternalSource->GetExternalSelector(I);
Sebastian Redl75d8a322010-08-02 23:18:59 +00006280 if (Sel.isNull() || MethodPool.count(Sel))
Douglas Gregord720daf2010-04-06 17:30:22 +00006281 continue;
6282
Sebastian Redl75d8a322010-08-02 23:18:59 +00006283 ReadMethodPool(Sel);
Douglas Gregord720daf2010-04-06 17:30:22 +00006284 }
6285 }
6286
Sebastian Redl75d8a322010-08-02 23:18:59 +00006287 for (GlobalMethodPool::iterator M = MethodPool.begin(),
6288 MEnd = MethodPool.end();
6289 M != MEnd; ++M) {
6290 for (ObjCMethodList *MethList = &M->second.first;
Nico Weber2e0c8f72014-12-27 03:58:08 +00006291 MethList && MethList->getMethod();
Argyrios Kyrtzidisd3da6e02013-04-17 00:08:58 +00006292 MethList = MethList->getNext()) {
Nico Weber2e0c8f72014-12-27 03:58:08 +00006293 if (!isAcceptableObjCMethod(MethList->getMethod(), MK_Any, SelIdents))
Douglas Gregor6285f752010-04-06 16:40:00 +00006294 continue;
Douglas Gregor1154e272010-09-16 16:06:31 +00006295
Nico Weber2e0c8f72014-12-27 03:58:08 +00006296 if (!Selectors.insert(MethList->getMethod()->getSelector()).second)
Douglas Gregor1154e272010-09-16 16:06:31 +00006297 continue;
Craig Topperc3ec1492014-05-26 06:22:03 +00006298
Nico Weber2e0c8f72014-12-27 03:58:08 +00006299 Result R(MethList->getMethod(),
6300 Results.getBasePriority(MethList->getMethod()), nullptr);
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006301 R.StartParameter = SelIdents.size();
Douglas Gregor6285f752010-04-06 16:40:00 +00006302 R.AllParametersAreInformative = false;
6303 Results.MaybeAddResult(R, CurContext);
6304 }
6305 }
6306 }
Steve Naroffeae65032009-11-07 02:08:14 +00006307 Results.ExitScope();
Douglas Gregor74661272010-09-21 00:03:25 +00006308
6309
6310 // If we're actually at the argument expression (rather than prior to the
6311 // selector), we're actually performing code completion for an expression.
6312 // Determine whether we have a single, best method. If so, we can
6313 // code-complete the expression using the corresponding parameter type as
6314 // our preferred type, improving completion results.
6315 if (AtArgumentExpression) {
6316 QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006317 SelIdents.size());
Douglas Gregor74661272010-09-21 00:03:25 +00006318 if (PreferredType.isNull())
6319 CodeCompleteOrdinaryName(S, PCC_Expression);
6320 else
6321 CodeCompleteExpression(S, PreferredType);
6322 return;
6323 }
6324
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006325 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor63745d52011-07-21 01:05:26 +00006326 Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006327 Results.data(),Results.size());
Steve Naroffeae65032009-11-07 02:08:14 +00006328}
Douglas Gregorbaf69612009-11-18 04:19:12 +00006329
Douglas Gregor68762e72010-08-23 21:17:50 +00006330void Sema::CodeCompleteObjCForCollection(Scope *S,
6331 DeclGroupPtrTy IterationVar) {
6332 CodeCompleteExpressionData Data;
6333 Data.ObjCCollection = true;
6334
6335 if (IterationVar.getAsOpaquePtr()) {
Serge Pavlov9ddb76e2013-08-27 13:15:56 +00006336 DeclGroupRef DG = IterationVar.get();
Douglas Gregor68762e72010-08-23 21:17:50 +00006337 for (DeclGroupRef::iterator I = DG.begin(), End = DG.end(); I != End; ++I) {
6338 if (*I)
6339 Data.IgnoreDecls.push_back(*I);
6340 }
6341 }
6342
6343 CodeCompleteExpression(S, Data);
6344}
6345
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006346void Sema::CodeCompleteObjCSelector(Scope *S,
6347 ArrayRef<IdentifierInfo *> SelIdents) {
Douglas Gregor67c692c2010-08-26 15:07:07 +00006348 // If we have an external source, load the entire class method
6349 // pool from the AST file.
6350 if (ExternalSource) {
6351 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
6352 I != N; ++I) {
6353 Selector Sel = ExternalSource->GetExternalSelector(I);
6354 if (Sel.isNull() || MethodPool.count(Sel))
6355 continue;
6356
6357 ReadMethodPool(Sel);
6358 }
6359 }
6360
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006361 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006362 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006363 CodeCompletionContext::CCC_SelectorName);
Douglas Gregor67c692c2010-08-26 15:07:07 +00006364 Results.EnterNewScope();
6365 for (GlobalMethodPool::iterator M = MethodPool.begin(),
6366 MEnd = MethodPool.end();
6367 M != MEnd; ++M) {
6368
6369 Selector Sel = M->first;
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006370 if (!isAcceptableObjCSelector(Sel, MK_Any, SelIdents))
Douglas Gregor67c692c2010-08-26 15:07:07 +00006371 continue;
6372
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006373 CodeCompletionBuilder Builder(Results.getAllocator(),
6374 Results.getCodeCompletionTUInfo());
Douglas Gregor67c692c2010-08-26 15:07:07 +00006375 if (Sel.isUnarySelector()) {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00006376 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00006377 Sel.getNameForSlot(0)));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006378 Results.AddResult(Builder.TakeString());
Douglas Gregor67c692c2010-08-26 15:07:07 +00006379 continue;
6380 }
6381
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00006382 std::string Accumulator;
Douglas Gregor67c692c2010-08-26 15:07:07 +00006383 for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I) {
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006384 if (I == SelIdents.size()) {
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00006385 if (!Accumulator.empty()) {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00006386 Builder.AddInformativeChunk(Builder.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006387 Accumulator));
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00006388 Accumulator.clear();
6389 }
6390 }
6391
Benjamin Kramer632500c2011-07-26 16:59:25 +00006392 Accumulator += Sel.getNameForSlot(I);
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00006393 Accumulator += ':';
Douglas Gregor67c692c2010-08-26 15:07:07 +00006394 }
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00006395 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString( Accumulator));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006396 Results.AddResult(Builder.TakeString());
Douglas Gregor67c692c2010-08-26 15:07:07 +00006397 }
6398 Results.ExitScope();
6399
6400 HandleCodeCompleteResults(this, CodeCompleter,
6401 CodeCompletionContext::CCC_SelectorName,
6402 Results.data(), Results.size());
6403}
6404
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006405/// Add all of the protocol declarations that we find in the given
Douglas Gregorbaf69612009-11-18 04:19:12 +00006406/// (translation unit) context.
6407static void AddProtocolResults(DeclContext *Ctx, DeclContext *CurContext,
Douglas Gregor5b4671c2009-11-18 04:49:41 +00006408 bool OnlyForwardDeclarations,
Douglas Gregorbaf69612009-11-18 04:19:12 +00006409 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00006410 typedef CodeCompletionResult Result;
Douglas Gregorbaf69612009-11-18 04:19:12 +00006411
Aaron Ballman629afae2014-03-07 19:56:05 +00006412 for (const auto *D : Ctx->decls()) {
Douglas Gregorbaf69612009-11-18 04:19:12 +00006413 // Record any protocols we find.
Aaron Ballman629afae2014-03-07 19:56:05 +00006414 if (const auto *Proto = dyn_cast<ObjCProtocolDecl>(D))
Douglas Gregore6e48b12012-01-01 19:29:29 +00006415 if (!OnlyForwardDeclarations || !Proto->hasDefinition())
Craig Topperc3ec1492014-05-26 06:22:03 +00006416 Results.AddResult(Result(Proto, Results.getBasePriority(Proto),nullptr),
6417 CurContext, nullptr, false);
Douglas Gregorbaf69612009-11-18 04:19:12 +00006418 }
6419}
6420
Craig Topper883dd332015-12-24 23:58:11 +00006421void Sema::CodeCompleteObjCProtocolReferences(
6422 ArrayRef<IdentifierLocPair> Protocols) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006423 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006424 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006425 CodeCompletionContext::CCC_ObjCProtocolName);
Douglas Gregorbaf69612009-11-18 04:19:12 +00006426
Chandler Carruthede11632016-11-04 06:06:50 +00006427 if (CodeCompleter->includeGlobals()) {
Douglas Gregora3b23b02010-12-09 21:44:02 +00006428 Results.EnterNewScope();
6429
6430 // Tell the result set to ignore all of the protocols we have
6431 // already seen.
6432 // FIXME: This doesn't work when caching code-completion results.
Craig Topper883dd332015-12-24 23:58:11 +00006433 for (const IdentifierLocPair &Pair : Protocols)
6434 if (ObjCProtocolDecl *Protocol = LookupProtocol(Pair.first,
6435 Pair.second))
Douglas Gregora3b23b02010-12-09 21:44:02 +00006436 Results.Ignore(Protocol);
Douglas Gregorbaf69612009-11-18 04:19:12 +00006437
Douglas Gregora3b23b02010-12-09 21:44:02 +00006438 // Add all protocols.
6439 AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, false,
6440 Results);
Douglas Gregor5b4671c2009-11-18 04:49:41 +00006441
Douglas Gregora3b23b02010-12-09 21:44:02 +00006442 Results.ExitScope();
6443 }
6444
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006445 HandleCodeCompleteResults(this, CodeCompleter,
6446 CodeCompletionContext::CCC_ObjCProtocolName,
6447 Results.data(),Results.size());
Douglas Gregor5b4671c2009-11-18 04:49:41 +00006448}
6449
6450void Sema::CodeCompleteObjCProtocolDecl(Scope *) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006451 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006452 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006453 CodeCompletionContext::CCC_ObjCProtocolName);
Douglas Gregor5b4671c2009-11-18 04:49:41 +00006454
Chandler Carruthede11632016-11-04 06:06:50 +00006455 if (CodeCompleter->includeGlobals()) {
Douglas Gregora3b23b02010-12-09 21:44:02 +00006456 Results.EnterNewScope();
6457
6458 // Add all protocols.
6459 AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, true,
6460 Results);
Douglas Gregorbaf69612009-11-18 04:19:12 +00006461
Douglas Gregora3b23b02010-12-09 21:44:02 +00006462 Results.ExitScope();
6463 }
6464
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006465 HandleCodeCompleteResults(this, CodeCompleter,
6466 CodeCompletionContext::CCC_ObjCProtocolName,
6467 Results.data(),Results.size());
Douglas Gregorbaf69612009-11-18 04:19:12 +00006468}
Douglas Gregor49c22a72009-11-18 16:26:39 +00006469
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006470/// Add all of the Objective-C interface declarations that we find in
Douglas Gregor49c22a72009-11-18 16:26:39 +00006471/// the given (translation unit) context.
6472static void AddInterfaceResults(DeclContext *Ctx, DeclContext *CurContext,
6473 bool OnlyForwardDeclarations,
6474 bool OnlyUnimplemented,
6475 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00006476 typedef CodeCompletionResult Result;
Douglas Gregor49c22a72009-11-18 16:26:39 +00006477
Aaron Ballman629afae2014-03-07 19:56:05 +00006478 for (const auto *D : Ctx->decls()) {
Douglas Gregor1c283312010-08-11 12:19:30 +00006479 // Record any interfaces we find.
Aaron Ballman629afae2014-03-07 19:56:05 +00006480 if (const auto *Class = dyn_cast<ObjCInterfaceDecl>(D))
Douglas Gregordc9166c2011-12-15 20:29:51 +00006481 if ((!OnlyForwardDeclarations || !Class->hasDefinition()) &&
Douglas Gregor1c283312010-08-11 12:19:30 +00006482 (!OnlyUnimplemented || !Class->getImplementation()))
Craig Topperc3ec1492014-05-26 06:22:03 +00006483 Results.AddResult(Result(Class, Results.getBasePriority(Class),nullptr),
6484 CurContext, nullptr, false);
Douglas Gregor49c22a72009-11-18 16:26:39 +00006485 }
6486}
6487
6488void Sema::CodeCompleteObjCInterfaceDecl(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006489 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006490 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006491 CodeCompletionContext::CCC_Other);
Douglas Gregor49c22a72009-11-18 16:26:39 +00006492 Results.EnterNewScope();
6493
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006494 if (CodeCompleter->includeGlobals()) {
6495 // Add all classes.
6496 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
6497 false, Results);
6498 }
6499
Douglas Gregor49c22a72009-11-18 16:26:39 +00006500 Results.ExitScope();
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006501
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006502 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006503 CodeCompletionContext::CCC_ObjCInterfaceName,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006504 Results.data(),Results.size());
Douglas Gregor49c22a72009-11-18 16:26:39 +00006505}
6506
Douglas Gregorb2ccf012010-04-15 22:33:43 +00006507void Sema::CodeCompleteObjCSuperclass(Scope *S, IdentifierInfo *ClassName,
6508 SourceLocation ClassNameLoc) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006509 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006510 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006511 CodeCompletionContext::CCC_ObjCInterfaceName);
Douglas Gregor49c22a72009-11-18 16:26:39 +00006512 Results.EnterNewScope();
6513
6514 // Make sure that we ignore the class we're currently defining.
6515 NamedDecl *CurClass
Douglas Gregorb2ccf012010-04-15 22:33:43 +00006516 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006517 if (CurClass && isa<ObjCInterfaceDecl>(CurClass))
Douglas Gregor49c22a72009-11-18 16:26:39 +00006518 Results.Ignore(CurClass);
6519
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006520 if (CodeCompleter->includeGlobals()) {
6521 // Add all classes.
6522 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
6523 false, Results);
6524 }
6525
Douglas Gregor49c22a72009-11-18 16:26:39 +00006526 Results.ExitScope();
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006527
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006528 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006529 CodeCompletionContext::CCC_ObjCInterfaceName,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006530 Results.data(),Results.size());
Douglas Gregor49c22a72009-11-18 16:26:39 +00006531}
6532
6533void Sema::CodeCompleteObjCImplementationDecl(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006534 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006535 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006536 CodeCompletionContext::CCC_Other);
Douglas Gregor49c22a72009-11-18 16:26:39 +00006537 Results.EnterNewScope();
6538
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006539 if (CodeCompleter->includeGlobals()) {
6540 // Add all unimplemented classes.
6541 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
6542 true, Results);
6543 }
6544
Douglas Gregor49c22a72009-11-18 16:26:39 +00006545 Results.ExitScope();
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006546
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006547 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006548 CodeCompletionContext::CCC_ObjCInterfaceName,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006549 Results.data(),Results.size());
Douglas Gregor49c22a72009-11-18 16:26:39 +00006550}
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006551
6552void Sema::CodeCompleteObjCInterfaceCategory(Scope *S,
Douglas Gregorb2ccf012010-04-15 22:33:43 +00006553 IdentifierInfo *ClassName,
6554 SourceLocation ClassNameLoc) {
John McCall276321a2010-08-25 06:19:51 +00006555 typedef CodeCompletionResult Result;
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006556
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006557 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006558 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor21325842011-07-07 16:03:39 +00006559 CodeCompletionContext::CCC_ObjCCategoryName);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006560
6561 // Ignore any categories we find that have already been implemented by this
6562 // interface.
6563 llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
6564 NamedDecl *CurClass
Douglas Gregorb2ccf012010-04-15 22:33:43 +00006565 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006566 if (ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass)){
Aaron Ballman3fe486a2014-03-13 21:23:55 +00006567 for (const auto *Cat : Class->visible_categories())
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006568 CategoryNames.insert(Cat->getIdentifier());
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006569 }
6570
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006571 // Add all of the categories we know about.
6572 Results.EnterNewScope();
6573 TranslationUnitDecl *TU = Context.getTranslationUnitDecl();
Aaron Ballman629afae2014-03-07 19:56:05 +00006574 for (const auto *D : TU->decls())
6575 if (const auto *Category = dyn_cast<ObjCCategoryDecl>(D))
David Blaikie82e95a32014-11-19 07:49:47 +00006576 if (CategoryNames.insert(Category->getIdentifier()).second)
Craig Topperc3ec1492014-05-26 06:22:03 +00006577 Results.AddResult(Result(Category, Results.getBasePriority(Category),
6578 nullptr),
6579 CurContext, nullptr, false);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006580 Results.ExitScope();
6581
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006582 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor21325842011-07-07 16:03:39 +00006583 CodeCompletionContext::CCC_ObjCCategoryName,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006584 Results.data(),Results.size());
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006585}
6586
6587void Sema::CodeCompleteObjCImplementationCategory(Scope *S,
Douglas Gregorb2ccf012010-04-15 22:33:43 +00006588 IdentifierInfo *ClassName,
6589 SourceLocation ClassNameLoc) {
John McCall276321a2010-08-25 06:19:51 +00006590 typedef CodeCompletionResult Result;
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006591
6592 // Find the corresponding interface. If we couldn't find the interface, the
6593 // program itself is ill-formed. However, we'll try to be helpful still by
6594 // providing the list of all of the categories we know about.
6595 NamedDecl *CurClass
Douglas Gregorb2ccf012010-04-15 22:33:43 +00006596 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006597 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass);
6598 if (!Class)
Douglas Gregorb2ccf012010-04-15 22:33:43 +00006599 return CodeCompleteObjCInterfaceCategory(S, ClassName, ClassNameLoc);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006600
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006601 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006602 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor21325842011-07-07 16:03:39 +00006603 CodeCompletionContext::CCC_ObjCCategoryName);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006604
6605 // Add all of the categories that have have corresponding interface
6606 // declarations in this class and any of its superclasses, except for
6607 // already-implemented categories in the class itself.
6608 llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
6609 Results.EnterNewScope();
6610 bool IgnoreImplemented = true;
6611 while (Class) {
Aaron Ballman3fe486a2014-03-13 21:23:55 +00006612 for (const auto *Cat : Class->visible_categories()) {
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006613 if ((!IgnoreImplemented || !Cat->getImplementation()) &&
David Blaikie82e95a32014-11-19 07:49:47 +00006614 CategoryNames.insert(Cat->getIdentifier()).second)
Craig Topperc3ec1492014-05-26 06:22:03 +00006615 Results.AddResult(Result(Cat, Results.getBasePriority(Cat), nullptr),
6616 CurContext, nullptr, false);
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006617 }
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006618
6619 Class = Class->getSuperClass();
6620 IgnoreImplemented = false;
6621 }
6622 Results.ExitScope();
6623
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006624 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor21325842011-07-07 16:03:39 +00006625 CodeCompletionContext::CCC_ObjCCategoryName,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006626 Results.data(),Results.size());
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006627}
Douglas Gregor5d649882009-11-18 22:32:06 +00006628
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00006629void Sema::CodeCompleteObjCPropertyDefinition(Scope *S) {
Douglas Gregorc3425b12015-07-07 06:20:19 +00006630 CodeCompletionContext CCContext(CodeCompletionContext::CCC_Other);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006631 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006632 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorc3425b12015-07-07 06:20:19 +00006633 CCContext);
Douglas Gregor5d649882009-11-18 22:32:06 +00006634
6635 // Figure out where this @synthesize lives.
6636 ObjCContainerDecl *Container
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00006637 = dyn_cast_or_null<ObjCContainerDecl>(CurContext);
Douglas Gregor5d649882009-11-18 22:32:06 +00006638 if (!Container ||
6639 (!isa<ObjCImplementationDecl>(Container) &&
6640 !isa<ObjCCategoryImplDecl>(Container)))
6641 return;
6642
6643 // Ignore any properties that have already been implemented.
Douglas Gregor9b4f3702012-06-12 13:44:08 +00006644 Container = getContainerDef(Container);
Aaron Ballman629afae2014-03-07 19:56:05 +00006645 for (const auto *D : Container->decls())
6646 if (const auto *PropertyImpl = dyn_cast<ObjCPropertyImplDecl>(D))
Douglas Gregor5d649882009-11-18 22:32:06 +00006647 Results.Ignore(PropertyImpl->getPropertyDecl());
6648
6649 // Add any properties that we find.
Douglas Gregorb888acf2010-12-09 23:01:55 +00006650 AddedPropertiesSet AddedProperties;
Douglas Gregor5d649882009-11-18 22:32:06 +00006651 Results.EnterNewScope();
6652 if (ObjCImplementationDecl *ClassImpl
6653 = dyn_cast<ObjCImplementationDecl>(Container))
Douglas Gregorc3425b12015-07-07 06:20:19 +00006654 AddObjCProperties(CCContext, ClassImpl->getClassInterface(), false,
Douglas Gregor95147142011-05-05 15:50:42 +00006655 /*AllowNullaryMethods=*/false, CurContext,
Douglas Gregorb888acf2010-12-09 23:01:55 +00006656 AddedProperties, Results);
Douglas Gregor5d649882009-11-18 22:32:06 +00006657 else
Douglas Gregorc3425b12015-07-07 06:20:19 +00006658 AddObjCProperties(CCContext,
6659 cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl(),
Douglas Gregor95147142011-05-05 15:50:42 +00006660 false, /*AllowNullaryMethods=*/false, CurContext,
6661 AddedProperties, Results);
Douglas Gregor5d649882009-11-18 22:32:06 +00006662 Results.ExitScope();
6663
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006664 HandleCodeCompleteResults(this, CodeCompleter,
6665 CodeCompletionContext::CCC_Other,
6666 Results.data(),Results.size());
Douglas Gregor5d649882009-11-18 22:32:06 +00006667}
6668
6669void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S,
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00006670 IdentifierInfo *PropertyName) {
John McCall276321a2010-08-25 06:19:51 +00006671 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006672 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006673 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006674 CodeCompletionContext::CCC_Other);
Douglas Gregor5d649882009-11-18 22:32:06 +00006675
6676 // Figure out where this @synthesize lives.
6677 ObjCContainerDecl *Container
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00006678 = dyn_cast_or_null<ObjCContainerDecl>(CurContext);
Douglas Gregor5d649882009-11-18 22:32:06 +00006679 if (!Container ||
6680 (!isa<ObjCImplementationDecl>(Container) &&
6681 !isa<ObjCCategoryImplDecl>(Container)))
6682 return;
6683
6684 // Figure out which interface we're looking into.
Craig Topperc3ec1492014-05-26 06:22:03 +00006685 ObjCInterfaceDecl *Class = nullptr;
Douglas Gregor5d649882009-11-18 22:32:06 +00006686 if (ObjCImplementationDecl *ClassImpl
Manman Ren5b786402016-01-28 18:49:28 +00006687 = dyn_cast<ObjCImplementationDecl>(Container))
Douglas Gregor5d649882009-11-18 22:32:06 +00006688 Class = ClassImpl->getClassInterface();
6689 else
6690 Class = cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl()
6691 ->getClassInterface();
6692
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006693 // Determine the type of the property we're synthesizing.
6694 QualType PropertyType = Context.getObjCIdType();
6695 if (Class) {
Manman Ren5b786402016-01-28 18:49:28 +00006696 if (ObjCPropertyDecl *Property = Class->FindPropertyDeclaration(
6697 PropertyName, ObjCPropertyQueryKind::OBJC_PR_query_instance)) {
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006698 PropertyType
6699 = Property->getType().getNonReferenceType().getUnqualifiedType();
6700
6701 // Give preference to ivars
6702 Results.setPreferredType(PropertyType);
6703 }
6704 }
6705
Douglas Gregor5d649882009-11-18 22:32:06 +00006706 // Add all of the instance variables in this class and its superclasses.
6707 Results.EnterNewScope();
Douglas Gregor331faa02011-04-18 14:13:53 +00006708 bool SawSimilarlyNamedIvar = false;
6709 std::string NameWithPrefix;
6710 NameWithPrefix += '_';
Benjamin Kramer632500c2011-07-26 16:59:25 +00006711 NameWithPrefix += PropertyName->getName();
Douglas Gregor331faa02011-04-18 14:13:53 +00006712 std::string NameWithSuffix = PropertyName->getName().str();
6713 NameWithSuffix += '_';
Douglas Gregor5d649882009-11-18 22:32:06 +00006714 for(; Class; Class = Class->getSuperClass()) {
Douglas Gregor331faa02011-04-18 14:13:53 +00006715 for (ObjCIvarDecl *Ivar = Class->all_declared_ivar_begin(); Ivar;
6716 Ivar = Ivar->getNextIvar()) {
Craig Topperc3ec1492014-05-26 06:22:03 +00006717 Results.AddResult(Result(Ivar, Results.getBasePriority(Ivar), nullptr),
6718 CurContext, nullptr, false);
6719
Douglas Gregor331faa02011-04-18 14:13:53 +00006720 // Determine whether we've seen an ivar with a name similar to the
6721 // property.
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006722 if ((PropertyName == Ivar->getIdentifier() ||
Douglas Gregor331faa02011-04-18 14:13:53 +00006723 NameWithPrefix == Ivar->getName() ||
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006724 NameWithSuffix == Ivar->getName())) {
Douglas Gregor331faa02011-04-18 14:13:53 +00006725 SawSimilarlyNamedIvar = true;
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006726
6727 // Reduce the priority of this result by one, to give it a slight
6728 // advantage over other results whose names don't match so closely.
6729 if (Results.size() &&
6730 Results.data()[Results.size() - 1].Kind
6731 == CodeCompletionResult::RK_Declaration &&
6732 Results.data()[Results.size() - 1].Declaration == Ivar)
6733 Results.data()[Results.size() - 1].Priority--;
6734 }
Douglas Gregor331faa02011-04-18 14:13:53 +00006735 }
Douglas Gregor5d649882009-11-18 22:32:06 +00006736 }
Douglas Gregor331faa02011-04-18 14:13:53 +00006737
6738 if (!SawSimilarlyNamedIvar) {
6739 // Create ivar result _propName, that the user can use to synthesize
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006740 // an ivar of the appropriate type.
6741 unsigned Priority = CCP_MemberDeclaration + 1;
Douglas Gregor331faa02011-04-18 14:13:53 +00006742 typedef CodeCompletionResult Result;
6743 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006744 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo(),
6745 Priority,CXAvailability_Available);
Douglas Gregor331faa02011-04-18 14:13:53 +00006746
Douglas Gregor75acd922011-09-27 23:30:47 +00006747 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006748 Builder.AddResultTypeChunk(GetCompletionTypeString(PropertyType, Context,
Douglas Gregor75acd922011-09-27 23:30:47 +00006749 Policy, Allocator));
Douglas Gregor331faa02011-04-18 14:13:53 +00006750 Builder.AddTypedTextChunk(Allocator.CopyString(NameWithPrefix));
6751 Results.AddResult(Result(Builder.TakeString(), Priority,
6752 CXCursor_ObjCIvarDecl));
6753 }
6754
Douglas Gregor5d649882009-11-18 22:32:06 +00006755 Results.ExitScope();
6756
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006757 HandleCodeCompleteResults(this, CodeCompleter,
6758 CodeCompletionContext::CCC_Other,
6759 Results.data(),Results.size());
Douglas Gregor5d649882009-11-18 22:32:06 +00006760}
Douglas Gregor636a61e2010-04-07 00:21:17 +00006761
Douglas Gregor416b5752010-08-25 01:08:01 +00006762// Mapping from selectors to the methods that implement that selector, along
6763// with the "in original class" flag.
Benjamin Kramereb8c4462013-06-29 17:52:13 +00006764typedef llvm::DenseMap<
6765 Selector, llvm::PointerIntPair<ObjCMethodDecl *, 1, bool> > KnownMethodsMap;
Douglas Gregor636a61e2010-04-07 00:21:17 +00006766
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006767/// Find all of the methods that reside in the given container
Douglas Gregor636a61e2010-04-07 00:21:17 +00006768/// (and its superclasses, protocols, etc.) that meet the given
6769/// criteria. Insert those methods into the map of known methods,
6770/// indexed by selector so they can be easily found.
6771static void FindImplementableMethods(ASTContext &Context,
6772 ObjCContainerDecl *Container,
Alex Lorenzb8740422017-10-24 16:39:37 +00006773 Optional<bool> WantInstanceMethods,
Douglas Gregor636a61e2010-04-07 00:21:17 +00006774 QualType ReturnType,
Douglas Gregor416b5752010-08-25 01:08:01 +00006775 KnownMethodsMap &KnownMethods,
6776 bool InOriginalClass = true) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00006777 if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)) {
Douglas Gregor9b4f3702012-06-12 13:44:08 +00006778 // Make sure we have a definition; that's what we'll walk.
Douglas Gregorc0ac7d62011-12-15 05:27:12 +00006779 if (!IFace->hasDefinition())
6780 return;
Douglas Gregor9b4f3702012-06-12 13:44:08 +00006781
6782 IFace = IFace->getDefinition();
6783 Container = IFace;
Douglas Gregorc0ac7d62011-12-15 05:27:12 +00006784
Douglas Gregor636a61e2010-04-07 00:21:17 +00006785 const ObjCList<ObjCProtocolDecl> &Protocols
6786 = IFace->getReferencedProtocols();
6787 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006788 E = Protocols.end();
Douglas Gregor636a61e2010-04-07 00:21:17 +00006789 I != E; ++I)
6790 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006791 KnownMethods, InOriginalClass);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006792
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006793 // Add methods from any class extensions and categories.
Aaron Ballman3fe486a2014-03-13 21:23:55 +00006794 for (auto *Cat : IFace->visible_categories()) {
6795 FindImplementableMethods(Context, Cat, WantInstanceMethods, ReturnType,
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006796 KnownMethods, false);
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006797 }
6798
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006799 // Visit the superclass.
6800 if (IFace->getSuperClass())
6801 FindImplementableMethods(Context, IFace->getSuperClass(),
6802 WantInstanceMethods, ReturnType,
6803 KnownMethods, false);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006804 }
6805
6806 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(Container)) {
6807 // Recurse into protocols.
6808 const ObjCList<ObjCProtocolDecl> &Protocols
6809 = Category->getReferencedProtocols();
6810 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006811 E = Protocols.end();
Douglas Gregor636a61e2010-04-07 00:21:17 +00006812 I != E; ++I)
6813 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006814 KnownMethods, InOriginalClass);
6815
6816 // If this category is the original class, jump to the interface.
6817 if (InOriginalClass && Category->getClassInterface())
6818 FindImplementableMethods(Context, Category->getClassInterface(),
6819 WantInstanceMethods, ReturnType, KnownMethods,
6820 false);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006821 }
6822
6823 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Douglas Gregor9b4f3702012-06-12 13:44:08 +00006824 // Make sure we have a definition; that's what we'll walk.
6825 if (!Protocol->hasDefinition())
6826 return;
6827 Protocol = Protocol->getDefinition();
6828 Container = Protocol;
6829
6830 // Recurse into protocols.
6831 const ObjCList<ObjCProtocolDecl> &Protocols
6832 = Protocol->getReferencedProtocols();
6833 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
6834 E = Protocols.end();
6835 I != E; ++I)
6836 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
6837 KnownMethods, false);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006838 }
6839
6840 // Add methods in this container. This operation occurs last because
6841 // we want the methods from this container to override any methods
6842 // we've previously seen with the same selector.
Aaron Ballmanaff18c02014-03-13 19:03:34 +00006843 for (auto *M : Container->methods()) {
Alex Lorenzb8740422017-10-24 16:39:37 +00006844 if (!WantInstanceMethods || M->isInstanceMethod() == *WantInstanceMethods) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00006845 if (!ReturnType.isNull() &&
Alp Toker314cc812014-01-25 16:55:45 +00006846 !Context.hasSameUnqualifiedType(ReturnType, M->getReturnType()))
Douglas Gregor636a61e2010-04-07 00:21:17 +00006847 continue;
6848
Benjamin Kramereb8c4462013-06-29 17:52:13 +00006849 KnownMethods[M->getSelector()] =
Aaron Ballmanaff18c02014-03-13 19:03:34 +00006850 KnownMethodsMap::mapped_type(M, InOriginalClass);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006851 }
6852 }
6853}
6854
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006855/// Add the parenthesized return or parameter type chunk to a code
Douglas Gregor669a25a2011-02-17 00:22:45 +00006856/// completion string.
6857static void AddObjCPassingTypeChunk(QualType Type,
Douglas Gregor29979142012-04-10 18:35:07 +00006858 unsigned ObjCDeclQuals,
Douglas Gregor669a25a2011-02-17 00:22:45 +00006859 ASTContext &Context,
Douglas Gregor75acd922011-09-27 23:30:47 +00006860 const PrintingPolicy &Policy,
Douglas Gregor669a25a2011-02-17 00:22:45 +00006861 CodeCompletionBuilder &Builder) {
6862 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregor86b42682015-06-19 18:27:52 +00006863 std::string Quals = formatObjCParamQualifiers(ObjCDeclQuals, Type);
Douglas Gregor29979142012-04-10 18:35:07 +00006864 if (!Quals.empty())
6865 Builder.AddTextChunk(Builder.getAllocator().CopyString(Quals));
Douglas Gregor75acd922011-09-27 23:30:47 +00006866 Builder.AddTextChunk(GetCompletionTypeString(Type, Context, Policy,
Douglas Gregor669a25a2011-02-17 00:22:45 +00006867 Builder.getAllocator()));
6868 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6869}
6870
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006871/// Determine whether the given class is or inherits from a class by
Douglas Gregor669a25a2011-02-17 00:22:45 +00006872/// the given name.
6873static bool InheritsFromClassNamed(ObjCInterfaceDecl *Class,
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006874 StringRef Name) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006875 if (!Class)
6876 return false;
6877
6878 if (Class->getIdentifier() && Class->getIdentifier()->getName() == Name)
6879 return true;
6880
6881 return InheritsFromClassNamed(Class->getSuperClass(), Name);
6882}
6883
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006884/// Add code completions for Objective-C Key-Value Coding (KVC) and
Douglas Gregor669a25a2011-02-17 00:22:45 +00006885/// Key-Value Observing (KVO).
6886static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
6887 bool IsInstanceMethod,
6888 QualType ReturnType,
6889 ASTContext &Context,
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006890 VisitedSelectorSet &KnownSelectors,
Douglas Gregor669a25a2011-02-17 00:22:45 +00006891 ResultBuilder &Results) {
6892 IdentifierInfo *PropName = Property->getIdentifier();
6893 if (!PropName || PropName->getLength() == 0)
6894 return;
6895
Douglas Gregor75acd922011-09-27 23:30:47 +00006896 PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema());
6897
Douglas Gregor669a25a2011-02-17 00:22:45 +00006898 // Builder that will create each code completion.
6899 typedef CodeCompletionResult Result;
6900 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006901 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Douglas Gregor669a25a2011-02-17 00:22:45 +00006902
6903 // The selector table.
6904 SelectorTable &Selectors = Context.Selectors;
6905
6906 // The property name, copied into the code completion allocation region
6907 // on demand.
6908 struct KeyHolder {
6909 CodeCompletionAllocator &Allocator;
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006910 StringRef Key;
Douglas Gregor669a25a2011-02-17 00:22:45 +00006911 const char *CopiedKey;
Craig Topperc3ec1492014-05-26 06:22:03 +00006912
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006913 KeyHolder(CodeCompletionAllocator &Allocator, StringRef Key)
Craig Topperc3ec1492014-05-26 06:22:03 +00006914 : Allocator(Allocator), Key(Key), CopiedKey(nullptr) {}
6915
Douglas Gregor669a25a2011-02-17 00:22:45 +00006916 operator const char *() {
6917 if (CopiedKey)
6918 return CopiedKey;
6919
6920 return CopiedKey = Allocator.CopyString(Key);
6921 }
6922 } Key(Allocator, PropName->getName());
6923
6924 // The uppercased name of the property name.
6925 std::string UpperKey = PropName->getName();
6926 if (!UpperKey.empty())
Jordan Rose4938f272013-02-09 10:09:43 +00006927 UpperKey[0] = toUppercase(UpperKey[0]);
Douglas Gregor669a25a2011-02-17 00:22:45 +00006928
6929 bool ReturnTypeMatchesProperty = ReturnType.isNull() ||
6930 Context.hasSameUnqualifiedType(ReturnType.getNonReferenceType(),
6931 Property->getType());
6932 bool ReturnTypeMatchesVoid
6933 = ReturnType.isNull() || ReturnType->isVoidType();
6934
6935 // Add the normal accessor -(type)key.
6936 if (IsInstanceMethod &&
David Blaikie82e95a32014-11-19 07:49:47 +00006937 KnownSelectors.insert(Selectors.getNullarySelector(PropName)).second &&
Douglas Gregor669a25a2011-02-17 00:22:45 +00006938 ReturnTypeMatchesProperty && !Property->getGetterMethodDecl()) {
6939 if (ReturnType.isNull())
Douglas Gregor29979142012-04-10 18:35:07 +00006940 AddObjCPassingTypeChunk(Property->getType(), /*Quals=*/0,
6941 Context, Policy, Builder);
Douglas Gregor669a25a2011-02-17 00:22:45 +00006942
6943 Builder.AddTypedTextChunk(Key);
6944 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
6945 CXCursor_ObjCInstanceMethodDecl));
6946 }
6947
6948 // If we have an integral or boolean property (or the user has provided
6949 // an integral or boolean return type), add the accessor -(type)isKey.
6950 if (IsInstanceMethod &&
6951 ((!ReturnType.isNull() &&
6952 (ReturnType->isIntegerType() || ReturnType->isBooleanType())) ||
6953 (ReturnType.isNull() &&
6954 (Property->getType()->isIntegerType() ||
6955 Property->getType()->isBooleanType())))) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006956 std::string SelectorName = (Twine("is") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006957 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00006958 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
6959 .second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006960 if (ReturnType.isNull()) {
6961 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6962 Builder.AddTextChunk("BOOL");
6963 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6964 }
6965
6966 Builder.AddTypedTextChunk(
6967 Allocator.CopyString(SelectorId->getName()));
6968 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
6969 CXCursor_ObjCInstanceMethodDecl));
6970 }
6971 }
6972
6973 // Add the normal mutator.
6974 if (IsInstanceMethod && ReturnTypeMatchesVoid &&
6975 !Property->getSetterMethodDecl()) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006976 std::string SelectorName = (Twine("set") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006977 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00006978 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006979 if (ReturnType.isNull()) {
6980 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6981 Builder.AddTextChunk("void");
6982 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6983 }
6984
6985 Builder.AddTypedTextChunk(
6986 Allocator.CopyString(SelectorId->getName()));
6987 Builder.AddTypedTextChunk(":");
Douglas Gregor29979142012-04-10 18:35:07 +00006988 AddObjCPassingTypeChunk(Property->getType(), /*Quals=*/0,
6989 Context, Policy, Builder);
Douglas Gregor669a25a2011-02-17 00:22:45 +00006990 Builder.AddTextChunk(Key);
6991 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
6992 CXCursor_ObjCInstanceMethodDecl));
6993 }
6994 }
6995
6996 // Indexed and unordered accessors
6997 unsigned IndexedGetterPriority = CCP_CodePattern;
6998 unsigned IndexedSetterPriority = CCP_CodePattern;
6999 unsigned UnorderedGetterPriority = CCP_CodePattern;
7000 unsigned UnorderedSetterPriority = CCP_CodePattern;
7001 if (const ObjCObjectPointerType *ObjCPointer
7002 = Property->getType()->getAs<ObjCObjectPointerType>()) {
7003 if (ObjCInterfaceDecl *IFace = ObjCPointer->getInterfaceDecl()) {
7004 // If this interface type is not provably derived from a known
7005 // collection, penalize the corresponding completions.
7006 if (!InheritsFromClassNamed(IFace, "NSMutableArray")) {
7007 IndexedSetterPriority += CCD_ProbablyNotObjCCollection;
7008 if (!InheritsFromClassNamed(IFace, "NSArray"))
7009 IndexedGetterPriority += CCD_ProbablyNotObjCCollection;
7010 }
7011
7012 if (!InheritsFromClassNamed(IFace, "NSMutableSet")) {
7013 UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;
7014 if (!InheritsFromClassNamed(IFace, "NSSet"))
7015 UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;
7016 }
7017 }
7018 } else {
7019 IndexedGetterPriority += CCD_ProbablyNotObjCCollection;
7020 IndexedSetterPriority += CCD_ProbablyNotObjCCollection;
7021 UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;
7022 UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;
7023 }
7024
7025 // Add -(NSUInteger)countOf<key>
7026 if (IsInstanceMethod &&
7027 (ReturnType.isNull() || ReturnType->isIntegerType())) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007028 std::string SelectorName = (Twine("countOf") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007029 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007030 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
7031 .second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007032 if (ReturnType.isNull()) {
7033 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7034 Builder.AddTextChunk("NSUInteger");
7035 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7036 }
7037
7038 Builder.AddTypedTextChunk(
7039 Allocator.CopyString(SelectorId->getName()));
7040 Results.AddResult(Result(Builder.TakeString(),
7041 std::min(IndexedGetterPriority,
7042 UnorderedGetterPriority),
7043 CXCursor_ObjCInstanceMethodDecl));
7044 }
7045 }
7046
7047 // Indexed getters
7048 // Add -(id)objectInKeyAtIndex:(NSUInteger)index
7049 if (IsInstanceMethod &&
7050 (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007051 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007052 = (Twine("objectIn") + UpperKey + "AtIndex").str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007053 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007054 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007055 if (ReturnType.isNull()) {
7056 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7057 Builder.AddTextChunk("id");
7058 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7059 }
7060
7061 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7062 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7063 Builder.AddTextChunk("NSUInteger");
7064 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7065 Builder.AddTextChunk("index");
7066 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
7067 CXCursor_ObjCInstanceMethodDecl));
7068 }
7069 }
7070
7071 // Add -(NSArray *)keyAtIndexes:(NSIndexSet *)indexes
7072 if (IsInstanceMethod &&
7073 (ReturnType.isNull() ||
7074 (ReturnType->isObjCObjectPointerType() &&
7075 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
7076 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
7077 ->getName() == "NSArray"))) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007078 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007079 = (Twine(Property->getName()) + "AtIndexes").str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007080 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007081 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007082 if (ReturnType.isNull()) {
7083 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7084 Builder.AddTextChunk("NSArray *");
7085 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7086 }
7087
7088 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7089 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7090 Builder.AddTextChunk("NSIndexSet *");
7091 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7092 Builder.AddTextChunk("indexes");
7093 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
7094 CXCursor_ObjCInstanceMethodDecl));
7095 }
7096 }
7097
7098 // Add -(void)getKey:(type **)buffer range:(NSRange)inRange
7099 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007100 std::string SelectorName = (Twine("get") + UpperKey).str();
Douglas Gregor669a25a2011-02-17 00:22:45 +00007101 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007102 &Context.Idents.get(SelectorName),
Douglas Gregor669a25a2011-02-17 00:22:45 +00007103 &Context.Idents.get("range")
7104 };
7105
David Blaikie82e95a32014-11-19 07:49:47 +00007106 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007107 if (ReturnType.isNull()) {
7108 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7109 Builder.AddTextChunk("void");
7110 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7111 }
7112
7113 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7114 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7115 Builder.AddPlaceholderChunk("object-type");
7116 Builder.AddTextChunk(" **");
7117 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7118 Builder.AddTextChunk("buffer");
7119 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7120 Builder.AddTypedTextChunk("range:");
7121 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7122 Builder.AddTextChunk("NSRange");
7123 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7124 Builder.AddTextChunk("inRange");
7125 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
7126 CXCursor_ObjCInstanceMethodDecl));
7127 }
7128 }
7129
7130 // Mutable indexed accessors
7131
7132 // - (void)insertObject:(type *)object inKeyAtIndex:(NSUInteger)index
7133 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007134 std::string SelectorName = (Twine("in") + UpperKey + "AtIndex").str();
Douglas Gregor669a25a2011-02-17 00:22:45 +00007135 IdentifierInfo *SelectorIds[2] = {
7136 &Context.Idents.get("insertObject"),
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007137 &Context.Idents.get(SelectorName)
Douglas Gregor669a25a2011-02-17 00:22:45 +00007138 };
7139
David Blaikie82e95a32014-11-19 07:49:47 +00007140 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007141 if (ReturnType.isNull()) {
7142 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7143 Builder.AddTextChunk("void");
7144 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7145 }
7146
7147 Builder.AddTypedTextChunk("insertObject:");
7148 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7149 Builder.AddPlaceholderChunk("object-type");
7150 Builder.AddTextChunk(" *");
7151 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7152 Builder.AddTextChunk("object");
7153 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7154 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7155 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7156 Builder.AddPlaceholderChunk("NSUInteger");
7157 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7158 Builder.AddTextChunk("index");
7159 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
7160 CXCursor_ObjCInstanceMethodDecl));
7161 }
7162 }
7163
7164 // - (void)insertKey:(NSArray *)array atIndexes:(NSIndexSet *)indexes
7165 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007166 std::string SelectorName = (Twine("insert") + UpperKey).str();
Douglas Gregor669a25a2011-02-17 00:22:45 +00007167 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007168 &Context.Idents.get(SelectorName),
Douglas Gregor669a25a2011-02-17 00:22:45 +00007169 &Context.Idents.get("atIndexes")
7170 };
7171
David Blaikie82e95a32014-11-19 07:49:47 +00007172 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007173 if (ReturnType.isNull()) {
7174 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7175 Builder.AddTextChunk("void");
7176 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7177 }
7178
7179 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7180 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7181 Builder.AddTextChunk("NSArray *");
7182 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7183 Builder.AddTextChunk("array");
7184 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7185 Builder.AddTypedTextChunk("atIndexes:");
7186 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7187 Builder.AddPlaceholderChunk("NSIndexSet *");
7188 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7189 Builder.AddTextChunk("indexes");
7190 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
7191 CXCursor_ObjCInstanceMethodDecl));
7192 }
7193 }
7194
7195 // -(void)removeObjectFromKeyAtIndex:(NSUInteger)index
7196 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007197 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007198 = (Twine("removeObjectFrom") + UpperKey + "AtIndex").str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007199 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007200 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007201 if (ReturnType.isNull()) {
7202 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7203 Builder.AddTextChunk("void");
7204 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7205 }
7206
7207 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7208 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7209 Builder.AddTextChunk("NSUInteger");
7210 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7211 Builder.AddTextChunk("index");
7212 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
7213 CXCursor_ObjCInstanceMethodDecl));
7214 }
7215 }
7216
7217 // -(void)removeKeyAtIndexes:(NSIndexSet *)indexes
7218 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007219 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007220 = (Twine("remove") + UpperKey + "AtIndexes").str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007221 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007222 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007223 if (ReturnType.isNull()) {
7224 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7225 Builder.AddTextChunk("void");
7226 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7227 }
7228
7229 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7230 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7231 Builder.AddTextChunk("NSIndexSet *");
7232 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7233 Builder.AddTextChunk("indexes");
7234 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
7235 CXCursor_ObjCInstanceMethodDecl));
7236 }
7237 }
7238
7239 // - (void)replaceObjectInKeyAtIndex:(NSUInteger)index withObject:(id)object
7240 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007241 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007242 = (Twine("replaceObjectIn") + UpperKey + "AtIndex").str();
Douglas Gregor669a25a2011-02-17 00:22:45 +00007243 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007244 &Context.Idents.get(SelectorName),
Douglas Gregor669a25a2011-02-17 00:22:45 +00007245 &Context.Idents.get("withObject")
7246 };
7247
David Blaikie82e95a32014-11-19 07:49:47 +00007248 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007249 if (ReturnType.isNull()) {
7250 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7251 Builder.AddTextChunk("void");
7252 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7253 }
7254
7255 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7256 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7257 Builder.AddPlaceholderChunk("NSUInteger");
7258 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7259 Builder.AddTextChunk("index");
7260 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7261 Builder.AddTypedTextChunk("withObject:");
7262 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7263 Builder.AddTextChunk("id");
7264 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7265 Builder.AddTextChunk("object");
7266 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
7267 CXCursor_ObjCInstanceMethodDecl));
7268 }
7269 }
7270
7271 // - (void)replaceKeyAtIndexes:(NSIndexSet *)indexes withKey:(NSArray *)array
7272 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007273 std::string SelectorName1
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007274 = (Twine("replace") + UpperKey + "AtIndexes").str();
7275 std::string SelectorName2 = (Twine("with") + UpperKey).str();
Douglas Gregor669a25a2011-02-17 00:22:45 +00007276 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007277 &Context.Idents.get(SelectorName1),
7278 &Context.Idents.get(SelectorName2)
Douglas Gregor669a25a2011-02-17 00:22:45 +00007279 };
7280
David Blaikie82e95a32014-11-19 07:49:47 +00007281 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007282 if (ReturnType.isNull()) {
7283 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7284 Builder.AddTextChunk("void");
7285 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7286 }
7287
7288 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName1 + ":"));
7289 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7290 Builder.AddPlaceholderChunk("NSIndexSet *");
7291 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7292 Builder.AddTextChunk("indexes");
7293 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7294 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName2 + ":"));
7295 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7296 Builder.AddTextChunk("NSArray *");
7297 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7298 Builder.AddTextChunk("array");
7299 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
7300 CXCursor_ObjCInstanceMethodDecl));
7301 }
7302 }
7303
7304 // Unordered getters
7305 // - (NSEnumerator *)enumeratorOfKey
7306 if (IsInstanceMethod &&
7307 (ReturnType.isNull() ||
7308 (ReturnType->isObjCObjectPointerType() &&
7309 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
7310 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
7311 ->getName() == "NSEnumerator"))) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007312 std::string SelectorName = (Twine("enumeratorOf") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007313 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007314 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
7315 .second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007316 if (ReturnType.isNull()) {
7317 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7318 Builder.AddTextChunk("NSEnumerator *");
7319 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7320 }
7321
7322 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
7323 Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
7324 CXCursor_ObjCInstanceMethodDecl));
7325 }
7326 }
7327
7328 // - (type *)memberOfKey:(type *)object
7329 if (IsInstanceMethod &&
7330 (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007331 std::string SelectorName = (Twine("memberOf") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007332 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007333 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007334 if (ReturnType.isNull()) {
7335 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7336 Builder.AddPlaceholderChunk("object-type");
7337 Builder.AddTextChunk(" *");
7338 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7339 }
7340
7341 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7342 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7343 if (ReturnType.isNull()) {
7344 Builder.AddPlaceholderChunk("object-type");
7345 Builder.AddTextChunk(" *");
7346 } else {
7347 Builder.AddTextChunk(GetCompletionTypeString(ReturnType, Context,
Douglas Gregor75acd922011-09-27 23:30:47 +00007348 Policy,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007349 Builder.getAllocator()));
7350 }
7351 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7352 Builder.AddTextChunk("object");
7353 Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
7354 CXCursor_ObjCInstanceMethodDecl));
7355 }
7356 }
7357
7358 // Mutable unordered accessors
7359 // - (void)addKeyObject:(type *)object
7360 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007361 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007362 = (Twine("add") + UpperKey + Twine("Object")).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007363 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007364 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007365 if (ReturnType.isNull()) {
7366 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7367 Builder.AddTextChunk("void");
7368 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7369 }
7370
7371 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7372 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7373 Builder.AddPlaceholderChunk("object-type");
7374 Builder.AddTextChunk(" *");
7375 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7376 Builder.AddTextChunk("object");
7377 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
7378 CXCursor_ObjCInstanceMethodDecl));
7379 }
7380 }
7381
7382 // - (void)addKey:(NSSet *)objects
7383 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007384 std::string SelectorName = (Twine("add") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007385 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007386 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007387 if (ReturnType.isNull()) {
7388 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7389 Builder.AddTextChunk("void");
7390 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7391 }
7392
7393 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7394 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7395 Builder.AddTextChunk("NSSet *");
7396 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7397 Builder.AddTextChunk("objects");
7398 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
7399 CXCursor_ObjCInstanceMethodDecl));
7400 }
7401 }
7402
7403 // - (void)removeKeyObject:(type *)object
7404 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007405 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007406 = (Twine("remove") + UpperKey + Twine("Object")).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007407 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007408 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007409 if (ReturnType.isNull()) {
7410 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7411 Builder.AddTextChunk("void");
7412 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7413 }
7414
7415 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7416 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7417 Builder.AddPlaceholderChunk("object-type");
7418 Builder.AddTextChunk(" *");
7419 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7420 Builder.AddTextChunk("object");
7421 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
7422 CXCursor_ObjCInstanceMethodDecl));
7423 }
7424 }
7425
7426 // - (void)removeKey:(NSSet *)objects
7427 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007428 std::string SelectorName = (Twine("remove") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007429 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007430 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007431 if (ReturnType.isNull()) {
7432 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7433 Builder.AddTextChunk("void");
7434 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7435 }
7436
7437 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7438 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7439 Builder.AddTextChunk("NSSet *");
7440 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7441 Builder.AddTextChunk("objects");
7442 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
7443 CXCursor_ObjCInstanceMethodDecl));
7444 }
7445 }
7446
7447 // - (void)intersectKey:(NSSet *)objects
7448 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007449 std::string SelectorName = (Twine("intersect") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007450 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007451 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007452 if (ReturnType.isNull()) {
7453 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7454 Builder.AddTextChunk("void");
7455 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7456 }
7457
7458 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7459 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7460 Builder.AddTextChunk("NSSet *");
7461 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7462 Builder.AddTextChunk("objects");
7463 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
7464 CXCursor_ObjCInstanceMethodDecl));
7465 }
7466 }
7467
7468 // Key-Value Observing
7469 // + (NSSet *)keyPathsForValuesAffectingKey
7470 if (!IsInstanceMethod &&
7471 (ReturnType.isNull() ||
7472 (ReturnType->isObjCObjectPointerType() &&
7473 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
7474 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
7475 ->getName() == "NSSet"))) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007476 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007477 = (Twine("keyPathsForValuesAffecting") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007478 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007479 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
7480 .second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007481 if (ReturnType.isNull()) {
7482 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Alex Lorenz71ecb072016-12-08 16:49:05 +00007483 Builder.AddTextChunk("NSSet<NSString *> *");
Douglas Gregor669a25a2011-02-17 00:22:45 +00007484 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7485 }
7486
7487 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
7488 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Douglas Gregor857bcda2011-06-02 04:02:27 +00007489 CXCursor_ObjCClassMethodDecl));
7490 }
7491 }
7492
7493 // + (BOOL)automaticallyNotifiesObserversForKey
7494 if (!IsInstanceMethod &&
7495 (ReturnType.isNull() ||
7496 ReturnType->isIntegerType() ||
7497 ReturnType->isBooleanType())) {
7498 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007499 = (Twine("automaticallyNotifiesObserversOf") + UpperKey).str();
Douglas Gregor857bcda2011-06-02 04:02:27 +00007500 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007501 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
7502 .second) {
Douglas Gregor857bcda2011-06-02 04:02:27 +00007503 if (ReturnType.isNull()) {
7504 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7505 Builder.AddTextChunk("BOOL");
7506 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7507 }
7508
7509 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
7510 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
7511 CXCursor_ObjCClassMethodDecl));
Douglas Gregor669a25a2011-02-17 00:22:45 +00007512 }
7513 }
7514}
7515
Alex Lorenzb8740422017-10-24 16:39:37 +00007516void Sema::CodeCompleteObjCMethodDecl(Scope *S, Optional<bool> IsInstanceMethod,
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00007517 ParsedType ReturnTy) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00007518 // Determine the return type of the method we're declaring, if
7519 // provided.
7520 QualType ReturnType = GetTypeFromParser(ReturnTy);
Craig Topperc3ec1492014-05-26 06:22:03 +00007521 Decl *IDecl = nullptr;
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00007522 if (CurContext->isObjCContainer()) {
7523 ObjCContainerDecl *OCD = dyn_cast<ObjCContainerDecl>(CurContext);
George Burgess IV00f70bd2018-03-01 05:43:23 +00007524 IDecl = OCD;
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00007525 }
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007526 // Determine where we should start searching for methods.
Craig Topperc3ec1492014-05-26 06:22:03 +00007527 ObjCContainerDecl *SearchDecl = nullptr;
Douglas Gregor636a61e2010-04-07 00:21:17 +00007528 bool IsInImplementation = false;
John McCall48871652010-08-21 09:40:31 +00007529 if (Decl *D = IDecl) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00007530 if (ObjCImplementationDecl *Impl = dyn_cast<ObjCImplementationDecl>(D)) {
7531 SearchDecl = Impl->getClassInterface();
Douglas Gregor636a61e2010-04-07 00:21:17 +00007532 IsInImplementation = true;
7533 } else if (ObjCCategoryImplDecl *CatImpl
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007534 = dyn_cast<ObjCCategoryImplDecl>(D)) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00007535 SearchDecl = CatImpl->getCategoryDecl();
Douglas Gregor636a61e2010-04-07 00:21:17 +00007536 IsInImplementation = true;
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007537 } else
Douglas Gregor636a61e2010-04-07 00:21:17 +00007538 SearchDecl = dyn_cast<ObjCContainerDecl>(D);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007539 }
7540
7541 if (!SearchDecl && S) {
Ted Kremenekc37877d2013-10-08 17:08:03 +00007542 if (DeclContext *DC = S->getEntity())
Douglas Gregor636a61e2010-04-07 00:21:17 +00007543 SearchDecl = dyn_cast<ObjCContainerDecl>(DC);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007544 }
7545
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007546 if (!SearchDecl) {
Douglas Gregor00c37ef2010-08-11 21:23:17 +00007547 HandleCodeCompleteResults(this, CodeCompleter,
7548 CodeCompletionContext::CCC_Other,
Craig Topperc3ec1492014-05-26 06:22:03 +00007549 nullptr, 0);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007550 return;
7551 }
7552
7553 // Find all of the methods that we could declare/implement here.
7554 KnownMethodsMap KnownMethods;
7555 FindImplementableMethods(Context, SearchDecl, IsInstanceMethod,
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007556 ReturnType, KnownMethods);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007557
Douglas Gregor636a61e2010-04-07 00:21:17 +00007558 // Add declarations or definitions for each of the known methods.
John McCall276321a2010-08-25 06:19:51 +00007559 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007560 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007561 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007562 CodeCompletionContext::CCC_Other);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007563 Results.EnterNewScope();
Douglas Gregor75acd922011-09-27 23:30:47 +00007564 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007565 for (KnownMethodsMap::iterator M = KnownMethods.begin(),
7566 MEnd = KnownMethods.end();
7567 M != MEnd; ++M) {
Benjamin Kramereb8c4462013-06-29 17:52:13 +00007568 ObjCMethodDecl *Method = M->second.getPointer();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007569 CodeCompletionBuilder Builder(Results.getAllocator(),
7570 Results.getCodeCompletionTUInfo());
Alex Lorenzb8740422017-10-24 16:39:37 +00007571
7572 // Add the '-'/'+' prefix if it wasn't provided yet.
7573 if (!IsInstanceMethod) {
7574 Builder.AddTextChunk(Method->isInstanceMethod() ? "-" : "+");
7575 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7576 }
7577
Douglas Gregor636a61e2010-04-07 00:21:17 +00007578 // If the result type was not already provided, add it to the
7579 // pattern as (type).
Argyrios Kyrtzidisf0917ab2015-07-24 17:00:19 +00007580 if (ReturnType.isNull()) {
7581 QualType ResTy = Method->getSendResultType().stripObjCKindOfType(Context);
7582 AttributedType::stripOuterNullability(ResTy);
7583 AddObjCPassingTypeChunk(ResTy,
Alp Toker314cc812014-01-25 16:55:45 +00007584 Method->getObjCDeclQualifier(), Context, Policy,
7585 Builder);
Argyrios Kyrtzidisf0917ab2015-07-24 17:00:19 +00007586 }
Douglas Gregor636a61e2010-04-07 00:21:17 +00007587
7588 Selector Sel = Method->getSelector();
7589
7590 // Add the first part of the selector to the pattern.
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00007591 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00007592 Sel.getNameForSlot(0)));
Douglas Gregor636a61e2010-04-07 00:21:17 +00007593
7594 // Add parameters to the pattern.
7595 unsigned I = 0;
7596 for (ObjCMethodDecl::param_iterator P = Method->param_begin(),
7597 PEnd = Method->param_end();
7598 P != PEnd; (void)++P, ++I) {
7599 // Add the part of the selector name.
7600 if (I == 0)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007601 Builder.AddTypedTextChunk(":");
Douglas Gregor636a61e2010-04-07 00:21:17 +00007602 else if (I < Sel.getNumArgs()) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007603 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7604 Builder.AddTypedTextChunk(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00007605 Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":"));
Douglas Gregor636a61e2010-04-07 00:21:17 +00007606 } else
7607 break;
7608
7609 // Add the parameter type.
Douglas Gregor86b42682015-06-19 18:27:52 +00007610 QualType ParamType;
7611 if ((*P)->getObjCDeclQualifier() & Decl::OBJC_TQ_CSNullability)
7612 ParamType = (*P)->getType();
7613 else
7614 ParamType = (*P)->getOriginalType();
Douglas Gregor9b7b3e92015-07-07 06:20:27 +00007615 ParamType = ParamType.substObjCTypeArgs(Context, {},
7616 ObjCSubstitutionContext::Parameter);
Argyrios Kyrtzidisf0917ab2015-07-24 17:00:19 +00007617 AttributedType::stripOuterNullability(ParamType);
Douglas Gregor86b42682015-06-19 18:27:52 +00007618 AddObjCPassingTypeChunk(ParamType,
Douglas Gregor29979142012-04-10 18:35:07 +00007619 (*P)->getObjCDeclQualifier(),
7620 Context, Policy,
Douglas Gregor75acd922011-09-27 23:30:47 +00007621 Builder);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007622
7623 if (IdentifierInfo *Id = (*P)->getIdentifier())
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00007624 Builder.AddTextChunk(Builder.getAllocator().CopyString( Id->getName()));
Douglas Gregor636a61e2010-04-07 00:21:17 +00007625 }
7626
7627 if (Method->isVariadic()) {
7628 if (Method->param_size() > 0)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007629 Builder.AddChunk(CodeCompletionString::CK_Comma);
7630 Builder.AddTextChunk("...");
Douglas Gregor400f5972010-08-31 05:13:43 +00007631 }
Douglas Gregor636a61e2010-04-07 00:21:17 +00007632
Douglas Gregord37c59d2010-05-28 00:57:46 +00007633 if (IsInImplementation && Results.includeCodePatterns()) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00007634 // We will be defining the method here, so add a compound statement.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007635 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7636 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
7637 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
Alp Toker314cc812014-01-25 16:55:45 +00007638 if (!Method->getReturnType()->isVoidType()) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00007639 // If the result type is not void, add a return clause.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007640 Builder.AddTextChunk("return");
7641 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7642 Builder.AddPlaceholderChunk("expression");
7643 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007644 } else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007645 Builder.AddPlaceholderChunk("statements");
Douglas Gregor636a61e2010-04-07 00:21:17 +00007646
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007647 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
7648 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007649 }
7650
Douglas Gregor416b5752010-08-25 01:08:01 +00007651 unsigned Priority = CCP_CodePattern;
Benjamin Kramereb8c4462013-06-29 17:52:13 +00007652 if (!M->second.getInt())
Douglas Gregor416b5752010-08-25 01:08:01 +00007653 Priority += CCD_InBaseClass;
7654
Douglas Gregor78254c82012-03-27 23:34:16 +00007655 Results.AddResult(Result(Builder.TakeString(), Method, Priority));
Douglas Gregor636a61e2010-04-07 00:21:17 +00007656 }
7657
Douglas Gregor669a25a2011-02-17 00:22:45 +00007658 // Add Key-Value-Coding and Key-Value-Observing accessor methods for all of
7659 // the properties in this class and its categories.
David Blaikiebbafb8a2012-03-11 07:00:24 +00007660 if (Context.getLangOpts().ObjC2) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007661 SmallVector<ObjCContainerDecl *, 4> Containers;
Douglas Gregor669a25a2011-02-17 00:22:45 +00007662 Containers.push_back(SearchDecl);
7663
Douglas Gregord4a8ced2011-05-04 23:50:46 +00007664 VisitedSelectorSet KnownSelectors;
7665 for (KnownMethodsMap::iterator M = KnownMethods.begin(),
7666 MEnd = KnownMethods.end();
7667 M != MEnd; ++M)
7668 KnownSelectors.insert(M->first);
7669
7670
Douglas Gregor669a25a2011-02-17 00:22:45 +00007671 ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(SearchDecl);
7672 if (!IFace)
7673 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(SearchDecl))
7674 IFace = Category->getClassInterface();
7675
Aaron Ballman3fe486a2014-03-13 21:23:55 +00007676 if (IFace)
7677 for (auto *Cat : IFace->visible_categories())
7678 Containers.push_back(Cat);
Alex Lorenzb8740422017-10-24 16:39:37 +00007679
7680 if (IsInstanceMethod) {
7681 for (unsigned I = 0, N = Containers.size(); I != N; ++I)
7682 for (auto *P : Containers[I]->instance_properties())
7683 AddObjCKeyValueCompletions(P, *IsInstanceMethod, ReturnType, Context,
7684 KnownSelectors, Results);
7685 }
Douglas Gregor669a25a2011-02-17 00:22:45 +00007686 }
7687
Douglas Gregor636a61e2010-04-07 00:21:17 +00007688 Results.ExitScope();
7689
Douglas Gregor00c37ef2010-08-11 21:23:17 +00007690 HandleCodeCompleteResults(this, CodeCompleter,
7691 CodeCompletionContext::CCC_Other,
7692 Results.data(),Results.size());
Douglas Gregor636a61e2010-04-07 00:21:17 +00007693}
Douglas Gregor95887f92010-07-08 23:20:03 +00007694
7695void Sema::CodeCompleteObjCMethodDeclSelector(Scope *S,
7696 bool IsInstanceMethod,
Douglas Gregor45879692010-07-08 23:37:41 +00007697 bool AtParameterName,
John McCallba7bf592010-08-24 05:47:05 +00007698 ParsedType ReturnTy,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00007699 ArrayRef<IdentifierInfo *> SelIdents) {
Douglas Gregor95887f92010-07-08 23:20:03 +00007700 // If we have an external source, load the entire class method
Sebastian Redld44cd6a2010-08-18 23:57:06 +00007701 // pool from the AST file.
Douglas Gregor95887f92010-07-08 23:20:03 +00007702 if (ExternalSource) {
7703 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
7704 I != N; ++I) {
7705 Selector Sel = ExternalSource->GetExternalSelector(I);
Sebastian Redl75d8a322010-08-02 23:18:59 +00007706 if (Sel.isNull() || MethodPool.count(Sel))
Douglas Gregor95887f92010-07-08 23:20:03 +00007707 continue;
Sebastian Redl75d8a322010-08-02 23:18:59 +00007708
7709 ReadMethodPool(Sel);
Douglas Gregor95887f92010-07-08 23:20:03 +00007710 }
7711 }
7712
7713 // Build the set of methods we can see.
John McCall276321a2010-08-25 06:19:51 +00007714 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007715 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007716 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007717 CodeCompletionContext::CCC_Other);
Douglas Gregor95887f92010-07-08 23:20:03 +00007718
7719 if (ReturnTy)
7720 Results.setPreferredType(GetTypeFromParser(ReturnTy).getNonReferenceType());
Sebastian Redl75d8a322010-08-02 23:18:59 +00007721
Douglas Gregor95887f92010-07-08 23:20:03 +00007722 Results.EnterNewScope();
Sebastian Redl75d8a322010-08-02 23:18:59 +00007723 for (GlobalMethodPool::iterator M = MethodPool.begin(),
7724 MEnd = MethodPool.end();
7725 M != MEnd; ++M) {
7726 for (ObjCMethodList *MethList = IsInstanceMethod ? &M->second.first :
7727 &M->second.second;
Nico Weber2e0c8f72014-12-27 03:58:08 +00007728 MethList && MethList->getMethod();
Argyrios Kyrtzidisd3da6e02013-04-17 00:08:58 +00007729 MethList = MethList->getNext()) {
Nico Weber2e0c8f72014-12-27 03:58:08 +00007730 if (!isAcceptableObjCMethod(MethList->getMethod(), MK_Any, SelIdents))
Douglas Gregor95887f92010-07-08 23:20:03 +00007731 continue;
7732
Douglas Gregor45879692010-07-08 23:37:41 +00007733 if (AtParameterName) {
7734 // Suggest parameter names we've seen before.
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00007735 unsigned NumSelIdents = SelIdents.size();
Nico Weber2e0c8f72014-12-27 03:58:08 +00007736 if (NumSelIdents &&
7737 NumSelIdents <= MethList->getMethod()->param_size()) {
7738 ParmVarDecl *Param =
7739 MethList->getMethod()->parameters()[NumSelIdents - 1];
Douglas Gregor45879692010-07-08 23:37:41 +00007740 if (Param->getIdentifier()) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007741 CodeCompletionBuilder Builder(Results.getAllocator(),
7742 Results.getCodeCompletionTUInfo());
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00007743 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007744 Param->getIdentifier()->getName()));
7745 Results.AddResult(Builder.TakeString());
Douglas Gregor45879692010-07-08 23:37:41 +00007746 }
7747 }
7748
7749 continue;
7750 }
Craig Topperc3ec1492014-05-26 06:22:03 +00007751
Nico Weber2e0c8f72014-12-27 03:58:08 +00007752 Result R(MethList->getMethod(),
7753 Results.getBasePriority(MethList->getMethod()), nullptr);
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00007754 R.StartParameter = SelIdents.size();
Douglas Gregor95887f92010-07-08 23:20:03 +00007755 R.AllParametersAreInformative = false;
7756 R.DeclaringEntity = true;
7757 Results.MaybeAddResult(R, CurContext);
7758 }
7759 }
7760
7761 Results.ExitScope();
Alex Lorenz847fda12017-01-03 11:56:40 +00007762
7763 if (!AtParameterName && !SelIdents.empty() &&
7764 SelIdents.front()->getName().startswith("init")) {
7765 for (const auto &M : PP.macros()) {
7766 if (M.first->getName() != "NS_DESIGNATED_INITIALIZER")
7767 continue;
7768 Results.EnterNewScope();
7769 CodeCompletionBuilder Builder(Results.getAllocator(),
7770 Results.getCodeCompletionTUInfo());
7771 Builder.AddTypedTextChunk(
7772 Builder.getAllocator().CopyString(M.first->getName()));
7773 Results.AddResult(CodeCompletionResult(Builder.TakeString(), CCP_Macro,
7774 CXCursor_MacroDefinition));
7775 Results.ExitScope();
7776 }
7777 }
7778
Douglas Gregor00c37ef2010-08-11 21:23:17 +00007779 HandleCodeCompleteResults(this, CodeCompleter,
7780 CodeCompletionContext::CCC_Other,
7781 Results.data(),Results.size());
Douglas Gregor95887f92010-07-08 23:20:03 +00007782}
Douglas Gregorb14904c2010-08-13 22:48:40 +00007783
Douglas Gregorec00a262010-08-24 22:20:20 +00007784void Sema::CodeCompletePreprocessorDirective(bool InConditional) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007785 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007786 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00007787 CodeCompletionContext::CCC_PreprocessorDirective);
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007788 Results.EnterNewScope();
7789
7790 // #if <condition>
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007791 CodeCompletionBuilder Builder(Results.getAllocator(),
7792 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007793 Builder.AddTypedTextChunk("if");
7794 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7795 Builder.AddPlaceholderChunk("condition");
7796 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007797
7798 // #ifdef <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007799 Builder.AddTypedTextChunk("ifdef");
7800 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7801 Builder.AddPlaceholderChunk("macro");
7802 Results.AddResult(Builder.TakeString());
7803
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007804 // #ifndef <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007805 Builder.AddTypedTextChunk("ifndef");
7806 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7807 Builder.AddPlaceholderChunk("macro");
7808 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007809
7810 if (InConditional) {
7811 // #elif <condition>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007812 Builder.AddTypedTextChunk("elif");
7813 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7814 Builder.AddPlaceholderChunk("condition");
7815 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007816
7817 // #else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007818 Builder.AddTypedTextChunk("else");
7819 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007820
7821 // #endif
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007822 Builder.AddTypedTextChunk("endif");
7823 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007824 }
7825
7826 // #include "header"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007827 Builder.AddTypedTextChunk("include");
7828 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7829 Builder.AddTextChunk("\"");
7830 Builder.AddPlaceholderChunk("header");
7831 Builder.AddTextChunk("\"");
7832 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007833
7834 // #include <header>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007835 Builder.AddTypedTextChunk("include");
7836 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7837 Builder.AddTextChunk("<");
7838 Builder.AddPlaceholderChunk("header");
7839 Builder.AddTextChunk(">");
7840 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007841
7842 // #define <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007843 Builder.AddTypedTextChunk("define");
7844 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7845 Builder.AddPlaceholderChunk("macro");
7846 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007847
7848 // #define <macro>(<args>)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007849 Builder.AddTypedTextChunk("define");
7850 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7851 Builder.AddPlaceholderChunk("macro");
7852 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7853 Builder.AddPlaceholderChunk("args");
7854 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7855 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007856
7857 // #undef <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007858 Builder.AddTypedTextChunk("undef");
7859 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7860 Builder.AddPlaceholderChunk("macro");
7861 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007862
7863 // #line <number>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007864 Builder.AddTypedTextChunk("line");
7865 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7866 Builder.AddPlaceholderChunk("number");
7867 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007868
7869 // #line <number> "filename"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007870 Builder.AddTypedTextChunk("line");
7871 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7872 Builder.AddPlaceholderChunk("number");
7873 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7874 Builder.AddTextChunk("\"");
7875 Builder.AddPlaceholderChunk("filename");
7876 Builder.AddTextChunk("\"");
7877 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007878
7879 // #error <message>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007880 Builder.AddTypedTextChunk("error");
7881 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7882 Builder.AddPlaceholderChunk("message");
7883 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007884
7885 // #pragma <arguments>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007886 Builder.AddTypedTextChunk("pragma");
7887 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7888 Builder.AddPlaceholderChunk("arguments");
7889 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007890
David Blaikiebbafb8a2012-03-11 07:00:24 +00007891 if (getLangOpts().ObjC1) {
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007892 // #import "header"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007893 Builder.AddTypedTextChunk("import");
7894 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7895 Builder.AddTextChunk("\"");
7896 Builder.AddPlaceholderChunk("header");
7897 Builder.AddTextChunk("\"");
7898 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007899
7900 // #import <header>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007901 Builder.AddTypedTextChunk("import");
7902 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7903 Builder.AddTextChunk("<");
7904 Builder.AddPlaceholderChunk("header");
7905 Builder.AddTextChunk(">");
7906 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007907 }
7908
7909 // #include_next "header"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007910 Builder.AddTypedTextChunk("include_next");
7911 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7912 Builder.AddTextChunk("\"");
7913 Builder.AddPlaceholderChunk("header");
7914 Builder.AddTextChunk("\"");
7915 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007916
7917 // #include_next <header>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007918 Builder.AddTypedTextChunk("include_next");
7919 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7920 Builder.AddTextChunk("<");
7921 Builder.AddPlaceholderChunk("header");
7922 Builder.AddTextChunk(">");
7923 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007924
7925 // #warning <message>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007926 Builder.AddTypedTextChunk("warning");
7927 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7928 Builder.AddPlaceholderChunk("message");
7929 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007930
7931 // Note: #ident and #sccs are such crazy anachronisms that we don't provide
7932 // completions for them. And __include_macros is a Clang-internal extension
7933 // that we don't want to encourage anyone to use.
7934
7935 // FIXME: we don't support #assert or #unassert, so don't suggest them.
7936 Results.ExitScope();
7937
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007938 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0de55ce2010-08-25 18:41:16 +00007939 CodeCompletionContext::CCC_PreprocessorDirective,
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007940 Results.data(), Results.size());
7941}
7942
7943void Sema::CodeCompleteInPreprocessorConditionalExclusion(Scope *S) {
Douglas Gregorec00a262010-08-24 22:20:20 +00007944 CodeCompleteOrdinaryName(S,
John McCallfaf5fb42010-08-26 23:41:50 +00007945 S->getFnParent()? Sema::PCC_RecoveryInFunction
7946 : Sema::PCC_Namespace);
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007947}
7948
Douglas Gregorec00a262010-08-24 22:20:20 +00007949void Sema::CodeCompletePreprocessorMacroName(bool IsDefinition) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007950 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007951 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00007952 IsDefinition? CodeCompletionContext::CCC_MacroName
7953 : CodeCompletionContext::CCC_MacroNameUse);
Douglas Gregor12785102010-08-24 20:21:13 +00007954 if (!IsDefinition && (!CodeCompleter || CodeCompleter->includeMacros())) {
7955 // Add just the names of macros, not their arguments.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007956 CodeCompletionBuilder Builder(Results.getAllocator(),
7957 Results.getCodeCompletionTUInfo());
Douglas Gregor12785102010-08-24 20:21:13 +00007958 Results.EnterNewScope();
7959 for (Preprocessor::macro_iterator M = PP.macro_begin(),
7960 MEnd = PP.macro_end();
7961 M != MEnd; ++M) {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00007962 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007963 M->first->getName()));
Argyrios Kyrtzidis5c8b1cd2012-09-27 00:24:09 +00007964 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
7965 CCP_CodePattern,
7966 CXCursor_MacroDefinition));
Douglas Gregor12785102010-08-24 20:21:13 +00007967 }
7968 Results.ExitScope();
7969 } else if (IsDefinition) {
7970 // FIXME: Can we detect when the user just wrote an include guard above?
7971 }
7972
Douglas Gregor0ac41382010-09-23 23:01:17 +00007973 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor12785102010-08-24 20:21:13 +00007974 Results.data(), Results.size());
7975}
7976
Douglas Gregorec00a262010-08-24 22:20:20 +00007977void Sema::CodeCompletePreprocessorExpression() {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007978 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007979 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00007980 CodeCompletionContext::CCC_PreprocessorExpression);
Douglas Gregorec00a262010-08-24 22:20:20 +00007981
7982 if (!CodeCompleter || CodeCompleter->includeMacros())
Douglas Gregor8cb17462012-10-09 16:01:50 +00007983 AddMacroResults(PP, Results, true);
Douglas Gregorec00a262010-08-24 22:20:20 +00007984
7985 // defined (<macro>)
7986 Results.EnterNewScope();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007987 CodeCompletionBuilder Builder(Results.getAllocator(),
7988 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007989 Builder.AddTypedTextChunk("defined");
7990 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7991 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7992 Builder.AddPlaceholderChunk("macro");
7993 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7994 Results.AddResult(Builder.TakeString());
Douglas Gregorec00a262010-08-24 22:20:20 +00007995 Results.ExitScope();
7996
7997 HandleCodeCompleteResults(this, CodeCompleter,
7998 CodeCompletionContext::CCC_PreprocessorExpression,
7999 Results.data(), Results.size());
8000}
8001
8002void Sema::CodeCompletePreprocessorMacroArgument(Scope *S,
8003 IdentifierInfo *Macro,
8004 MacroInfo *MacroInfo,
8005 unsigned Argument) {
8006 // FIXME: In the future, we could provide "overload" results, much like we
8007 // do for function calls.
8008
Argyrios Kyrtzidis75f6cd22011-08-18 19:41:28 +00008009 // Now just ignore this. There will be another code-completion callback
8010 // for the expanded tokens.
Douglas Gregorec00a262010-08-24 22:20:20 +00008011}
8012
Douglas Gregor11583702010-08-25 17:04:25 +00008013void Sema::CodeCompleteNaturalLanguage() {
Douglas Gregor11583702010-08-25 17:04:25 +00008014 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregorea736372010-08-25 17:10:00 +00008015 CodeCompletionContext::CCC_NaturalLanguage,
Craig Topperc3ec1492014-05-26 06:22:03 +00008016 nullptr, 0);
Douglas Gregor11583702010-08-25 17:04:25 +00008017}
8018
Alex Lorenzf7f6f822017-05-09 16:05:04 +00008019void Sema::CodeCompleteAvailabilityPlatformName() {
8020 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
8021 CodeCompleter->getCodeCompletionTUInfo(),
8022 CodeCompletionContext::CCC_Other);
8023 Results.EnterNewScope();
8024 static const char *Platforms[] = {"macOS", "iOS", "watchOS", "tvOS"};
8025 for (const char *Platform : llvm::makeArrayRef(Platforms)) {
8026 Results.AddResult(CodeCompletionResult(Platform));
8027 Results.AddResult(CodeCompletionResult(Results.getAllocator().CopyString(
8028 Twine(Platform) + "ApplicationExtension")));
8029 }
8030 Results.ExitScope();
8031 HandleCodeCompleteResults(this, CodeCompleter,
8032 CodeCompletionContext::CCC_Other, Results.data(),
8033 Results.size());
8034}
8035
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00008036void Sema::GatherGlobalCodeCompletions(CodeCompletionAllocator &Allocator,
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008037 CodeCompletionTUInfo &CCTUInfo,
Chris Lattner0e62c1c2011-07-23 10:55:15 +00008038 SmallVectorImpl<CodeCompletionResult> &Results) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008039 ResultBuilder Builder(*this, Allocator, CCTUInfo,
8040 CodeCompletionContext::CCC_Recovery);
Douglas Gregor39982192010-08-15 06:18:01 +00008041 if (!CodeCompleter || CodeCompleter->includeGlobals()) {
8042 CodeCompletionDeclConsumer Consumer(Builder,
8043 Context.getTranslationUnitDecl());
Sam McCallbb2cf632018-01-12 14:51:47 +00008044 LookupVisibleDecls(Context.getTranslationUnitDecl(), LookupAnyName,
8045 Consumer,
8046 !CodeCompleter || CodeCompleter->loadExternal());
Douglas Gregor39982192010-08-15 06:18:01 +00008047 }
Douglas Gregorb14904c2010-08-13 22:48:40 +00008048
8049 if (!CodeCompleter || CodeCompleter->includeMacros())
Douglas Gregor8cb17462012-10-09 16:01:50 +00008050 AddMacroResults(PP, Builder, true);
Douglas Gregorb14904c2010-08-13 22:48:40 +00008051
8052 Results.clear();
8053 Results.insert(Results.end(),
8054 Builder.data(), Builder.data() + Builder.size());
8055}