blob: c56df52eeb41bc765cfe09ddf23a0e16b7684451 [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) {
Eric Liuf5ba09f2018-07-04 10:01:18 +00003703 ResultBuilder Results(
3704 *this, CodeCompleter->getAllocator(),
3705 CodeCompleter->getCodeCompletionTUInfo(),
3706 CodeCompletionContext(CodeCompletionContext::CCC_Expression,
3707 Data.PreferredType));
Douglas Gregor68762e72010-08-23 21:17:50 +00003708 if (Data.ObjCCollection)
3709 Results.setFilter(&ResultBuilder::IsObjCCollection);
3710 else if (Data.IntegralConstantExpression)
Douglas Gregor85b50632010-07-28 21:50:18 +00003711 Results.setFilter(&ResultBuilder::IsIntegralConstantValue);
David Blaikiebbafb8a2012-03-11 07:00:24 +00003712 else if (WantTypesInContext(PCC_Expression, getLangOpts()))
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003713 Results.setFilter(&ResultBuilder::IsOrdinaryName);
3714 else
3715 Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
Douglas Gregor68762e72010-08-23 21:17:50 +00003716
3717 if (!Data.PreferredType.isNull())
3718 Results.setPreferredType(Data.PreferredType.getNonReferenceType());
3719
3720 // Ignore any declarations that we were told that we don't care about.
3721 for (unsigned I = 0, N = Data.IgnoreDecls.size(); I != N; ++I)
3722 Results.Ignore(Data.IgnoreDecls[I]);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003723
3724 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00003725 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00003726 CodeCompleter->includeGlobals(),
3727 CodeCompleter->loadExternal());
3728
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003729 Results.EnterNewScope();
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003730 AddOrdinaryNameResults(PCC_Expression, S, *this, Results);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003731 Results.ExitScope();
3732
Douglas Gregor55b037b2010-07-08 20:55:51 +00003733 bool PreferredTypeIsPointer = false;
Douglas Gregor68762e72010-08-23 21:17:50 +00003734 if (!Data.PreferredType.isNull())
3735 PreferredTypeIsPointer = Data.PreferredType->isAnyPointerType()
3736 || Data.PreferredType->isMemberPointerType()
3737 || Data.PreferredType->isBlockPointerType();
Douglas Gregor55b037b2010-07-08 20:55:51 +00003738
Douglas Gregorce0e8562010-08-23 21:54:33 +00003739 if (S->getFnParent() &&
3740 !Data.ObjCCollection &&
3741 !Data.IntegralConstantExpression)
Craig Topper12126262015-11-15 17:27:57 +00003742 AddPrettyFunctionResults(getLangOpts(), Results);
Douglas Gregorce0e8562010-08-23 21:54:33 +00003743
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003744 if (CodeCompleter->includeMacros())
Douglas Gregor8cb17462012-10-09 16:01:50 +00003745 AddMacroResults(PP, Results, false, PreferredTypeIsPointer);
Eric Liuf5ba09f2018-07-04 10:01:18 +00003746 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
3747 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 if (CodeCompleter->includeMacros()) {
Douglas Gregor8cb17462012-10-09 16:01:50 +00004364 AddMacroResults(PP, Results, false);
Douglas Gregor21325842011-07-07 16:03:39 +00004365 }
Eric Liuf5ba09f2018-07-04 10:01:18 +00004366 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4367 Results.data(), Results.size());
Douglas Gregord328d572009-09-21 18:10:23 +00004368}
4369
Robert Wilhelm16e94b92013-08-09 18:02:13 +00004370static bool anyNullArguments(ArrayRef<Expr *> Args) {
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00004371 if (Args.size() && !Args.data())
Douglas Gregor6ed3eb82010-05-30 06:10:08 +00004372 return true;
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00004373
4374 for (unsigned I = 0; I != Args.size(); ++I)
Douglas Gregor6ed3eb82010-05-30 06:10:08 +00004375 if (!Args[I])
4376 return true;
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00004377
Douglas Gregor6ed3eb82010-05-30 06:10:08 +00004378 return false;
4379}
4380
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004381typedef CodeCompleteConsumer::OverloadCandidate ResultCandidate;
4382
Francisco Lopes da Silva8cafefa2015-01-29 05:54:59 +00004383static void mergeCandidatesWithResults(Sema &SemaRef,
4384 SmallVectorImpl<ResultCandidate> &Results,
4385 OverloadCandidateSet &CandidateSet,
4386 SourceLocation Loc) {
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004387 if (!CandidateSet.empty()) {
4388 // Sort the overload candidate set by placing the best overloads first.
4389 std::stable_sort(
4390 CandidateSet.begin(), CandidateSet.end(),
4391 [&](const OverloadCandidate &X, const OverloadCandidate &Y) {
Richard Smith67ef14f2017-09-26 18:37:55 +00004392 return isBetterOverloadCandidate(SemaRef, X, Y, Loc,
4393 CandidateSet.getKind());
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004394 });
4395
4396 // Add the remaining viable overload candidates as code-completion results.
Erik Verbruggen7ec91072017-09-08 10:23:08 +00004397 for (auto &Candidate : CandidateSet) {
4398 if (Candidate.Function && Candidate.Function->isDeleted())
4399 continue;
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004400 if (Candidate.Viable)
4401 Results.push_back(ResultCandidate(Candidate.Function));
Erik Verbruggen7ec91072017-09-08 10:23:08 +00004402 }
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004403 }
4404}
4405
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00004406/// Get the type of the Nth parameter from a given set of overload
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004407/// candidates.
Francisco Lopes da Silva8cafefa2015-01-29 05:54:59 +00004408static QualType getParamType(Sema &SemaRef,
4409 ArrayRef<ResultCandidate> Candidates,
4410 unsigned N) {
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004411
4412 // Given the overloads 'Candidates' for a function call matching all arguments
4413 // up to N, return the type of the Nth parameter if it is the same for all
4414 // overload candidates.
4415 QualType ParamType;
4416 for (auto &Candidate : Candidates) {
4417 if (auto FType = Candidate.getFunctionType())
4418 if (auto Proto = dyn_cast<FunctionProtoType>(FType))
4419 if (N < Proto->getNumParams()) {
4420 if (ParamType.isNull())
4421 ParamType = Proto->getParamType(N);
4422 else if (!SemaRef.Context.hasSameUnqualifiedType(
4423 ParamType.getNonReferenceType(),
4424 Proto->getParamType(N).getNonReferenceType()))
4425 // Otherwise return a default-constructed QualType.
4426 return QualType();
4427 }
4428 }
4429
4430 return ParamType;
4431}
4432
Francisco Lopes da Silva8cafefa2015-01-29 05:54:59 +00004433static void CodeCompleteOverloadResults(Sema &SemaRef, Scope *S,
4434 MutableArrayRef<ResultCandidate> Candidates,
4435 unsigned CurrentArg,
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004436 bool CompleteExpressionWithCurrentArg = true) {
4437 QualType ParamType;
4438 if (CompleteExpressionWithCurrentArg)
4439 ParamType = getParamType(SemaRef, Candidates, CurrentArg);
4440
4441 if (ParamType.isNull())
4442 SemaRef.CodeCompleteOrdinaryName(S, Sema::PCC_Expression);
4443 else
4444 SemaRef.CodeCompleteExpression(S, ParamType);
4445
4446 if (!Candidates.empty())
4447 SemaRef.CodeCompleter->ProcessOverloadCandidates(SemaRef, CurrentArg,
4448 Candidates.data(),
4449 Candidates.size());
4450}
4451
4452void Sema::CodeCompleteCall(Scope *S, Expr *Fn, ArrayRef<Expr *> Args) {
Douglas Gregorcabea402009-09-22 15:41:20 +00004453 if (!CodeCompleter)
4454 return;
Douglas Gregor3ef59522009-12-11 19:06:04 +00004455
4456 // When we're code-completing for a call, we fall back to ordinary
4457 // name code-completion whenever we can't produce specific
4458 // results. We may want to revisit this strategy in the future,
4459 // e.g., by merging the two kinds of results.
4460
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004461 // FIXME: Provide support for variadic template functions.
Douglas Gregor3ef59522009-12-11 19:06:04 +00004462
Douglas Gregorcabea402009-09-22 15:41:20 +00004463 // Ignore type-dependent call expressions entirely.
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00004464 if (!Fn || Fn->isTypeDependent() || anyNullArguments(Args) ||
4465 Expr::hasAnyTypeDependentArguments(Args)) {
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004466 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregorcabea402009-09-22 15:41:20 +00004467 return;
Douglas Gregor3ef59522009-12-11 19:06:04 +00004468 }
Douglas Gregorcabea402009-09-22 15:41:20 +00004469
John McCall57500772009-12-16 12:17:52 +00004470 // Build an overload candidate set based on the functions we find.
John McCallbc077cf2010-02-08 23:07:23 +00004471 SourceLocation Loc = Fn->getExprLoc();
Richard Smith100b24a2014-04-17 01:52:14 +00004472 OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal);
John McCall57500772009-12-16 12:17:52 +00004473
Chris Lattner0e62c1c2011-07-23 10:55:15 +00004474 SmallVector<ResultCandidate, 8> Results;
Douglas Gregorff59f672010-01-21 15:46:19 +00004475
John McCall57500772009-12-16 12:17:52 +00004476 Expr *NakedFn = Fn->IgnoreParenCasts();
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004477 if (auto ULE = dyn_cast<UnresolvedLookupExpr>(NakedFn))
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00004478 AddOverloadedCallCandidates(ULE, Args, CandidateSet,
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004479 /*PartialOverloading=*/true);
4480 else if (auto UME = dyn_cast<UnresolvedMemberExpr>(NakedFn)) {
4481 TemplateArgumentListInfo TemplateArgsBuffer, *TemplateArgs = nullptr;
4482 if (UME->hasExplicitTemplateArgs()) {
4483 UME->copyTemplateArgumentsInto(TemplateArgsBuffer);
4484 TemplateArgs = &TemplateArgsBuffer;
Douglas Gregorff59f672010-01-21 15:46:19 +00004485 }
Erik Verbruggenf1898cf2017-03-28 07:22:21 +00004486
4487 // Add the base as first argument (use a nullptr if the base is implicit).
4488 SmallVector<Expr *, 12> ArgExprs(
4489 1, UME->isImplicitAccess() ? nullptr : UME->getBase());
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004490 ArgExprs.append(Args.begin(), Args.end());
4491 UnresolvedSet<8> Decls;
4492 Decls.append(UME->decls_begin(), UME->decls_end());
Benjamin Kramere3962ae2017-10-26 08:41:28 +00004493 const bool FirstArgumentIsBase = !UME->isImplicitAccess() && UME->getBase();
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004494 AddFunctionCandidates(Decls, ArgExprs, CandidateSet, TemplateArgs,
4495 /*SuppressUsedConversions=*/false,
Benjamin Kramere3962ae2017-10-26 08:41:28 +00004496 /*PartialOverloading=*/true,
4497 FirstArgumentIsBase);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004498 } else {
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004499 FunctionDecl *FD = nullptr;
4500 if (auto MCE = dyn_cast<MemberExpr>(NakedFn))
4501 FD = dyn_cast<FunctionDecl>(MCE->getMemberDecl());
4502 else if (auto DRE = dyn_cast<DeclRefExpr>(NakedFn))
4503 FD = dyn_cast<FunctionDecl>(DRE->getDecl());
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00004504 if (FD) { // We check whether it's a resolved function declaration.
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00004505 if (!getLangOpts().CPlusPlus ||
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004506 !FD->getType()->getAs<FunctionProtoType>())
4507 Results.push_back(ResultCandidate(FD));
4508 else
4509 AddOverloadCandidate(FD, DeclAccessPair::make(FD, FD->getAccess()),
4510 Args, CandidateSet,
4511 /*SuppressUsedConversions=*/false,
4512 /*PartialOverloading=*/true);
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00004513
4514 } else if (auto DC = NakedFn->getType()->getAsCXXRecordDecl()) {
4515 // If expression's type is CXXRecordDecl, it may overload the function
4516 // call operator, so we check if it does and add them as candidates.
Francisco Lopes da Silvaa349a8a2015-01-25 08:47:59 +00004517 // A complete type is needed to lookup for member function call operators.
Richard Smithdb0ac552015-12-18 22:40:25 +00004518 if (isCompleteType(Loc, NakedFn->getType())) {
Francisco Lopes da Silvaa349a8a2015-01-25 08:47:59 +00004519 DeclarationName OpName = Context.DeclarationNames
4520 .getCXXOperatorName(OO_Call);
4521 LookupResult R(*this, OpName, Loc, LookupOrdinaryName);
4522 LookupQualifiedName(R, DC);
4523 R.suppressDiagnostics();
4524 SmallVector<Expr *, 12> ArgExprs(1, NakedFn);
4525 ArgExprs.append(Args.begin(), Args.end());
4526 AddFunctionCandidates(R.asUnresolvedSet(), ArgExprs, CandidateSet,
4527 /*ExplicitArgs=*/nullptr,
4528 /*SuppressUsedConversions=*/false,
4529 /*PartialOverloading=*/true);
4530 }
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00004531 } else {
4532 // Lastly we check whether expression's type is function pointer or
4533 // function.
4534 QualType T = NakedFn->getType();
4535 if (!T->getPointeeType().isNull())
4536 T = T->getPointeeType();
4537
4538 if (auto FP = T->getAs<FunctionProtoType>()) {
4539 if (!TooManyArguments(FP->getNumParams(), Args.size(),
Francisco Lopes da Silva62a9a4f2015-01-23 13:17:51 +00004540 /*PartialOverloading=*/true) ||
4541 FP->isVariadic())
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00004542 Results.push_back(ResultCandidate(FP));
4543 } else if (auto FT = T->getAs<FunctionType>())
Francisco Lopes da Silva62a9a4f2015-01-23 13:17:51 +00004544 // No prototype and declaration, it may be a K & R style function.
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00004545 Results.push_back(ResultCandidate(FT));
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004546 }
Douglas Gregorcabea402009-09-22 15:41:20 +00004547 }
Douglas Gregor3ef59522009-12-11 19:06:04 +00004548
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004549 mergeCandidatesWithResults(*this, Results, CandidateSet, Loc);
4550 CodeCompleteOverloadResults(*this, S, Results, Args.size(),
4551 !CandidateSet.empty());
4552}
4553
4554void Sema::CodeCompleteConstructor(Scope *S, QualType Type, SourceLocation Loc,
4555 ArrayRef<Expr *> Args) {
4556 if (!CodeCompleter)
4557 return;
4558
4559 // A complete type is needed to lookup for constructors.
Ilya Biryukovfb9dde72018-05-14 13:50:36 +00004560 CXXRecordDecl *RD =
4561 isCompleteType(Loc, Type) ? Type->getAsCXXRecordDecl() : nullptr;
Argyrios Kyrtzidisee1d76f2015-03-13 07:39:30 +00004562 if (!RD) {
4563 CodeCompleteExpression(S, Type);
4564 return;
4565 }
4566
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004567 // FIXME: Provide support for member initializers.
4568 // FIXME: Provide support for variadic template constructors.
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004569
4570 OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal);
4571
Argyrios Kyrtzidisee1d76f2015-03-13 07:39:30 +00004572 for (auto C : LookupConstructors(RD)) {
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004573 if (auto FD = dyn_cast<FunctionDecl>(C)) {
4574 AddOverloadCandidate(FD, DeclAccessPair::make(FD, C->getAccess()),
4575 Args, CandidateSet,
4576 /*SuppressUsedConversions=*/false,
4577 /*PartialOverloading=*/true);
4578 } else if (auto FTD = dyn_cast<FunctionTemplateDecl>(C)) {
4579 AddTemplateOverloadCandidate(FTD,
4580 DeclAccessPair::make(FTD, C->getAccess()),
4581 /*ExplicitTemplateArgs=*/nullptr,
4582 Args, CandidateSet,
4583 /*SuppressUsedConversions=*/false,
4584 /*PartialOverloading=*/true);
4585 }
4586 }
4587
4588 SmallVector<ResultCandidate, 8> Results;
4589 mergeCandidatesWithResults(*this, Results, CandidateSet, Loc);
4590 CodeCompleteOverloadResults(*this, S, Results, Args.size());
Douglas Gregorcabea402009-09-22 15:41:20 +00004591}
4592
John McCall48871652010-08-21 09:40:31 +00004593void Sema::CodeCompleteInitializer(Scope *S, Decl *D) {
4594 ValueDecl *VD = dyn_cast_or_null<ValueDecl>(D);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004595 if (!VD) {
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004596 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004597 return;
4598 }
4599
4600 CodeCompleteExpression(S, VD->getType());
4601}
4602
4603void Sema::CodeCompleteReturn(Scope *S) {
4604 QualType ResultType;
4605 if (isa<BlockDecl>(CurContext)) {
4606 if (BlockScopeInfo *BSI = getCurBlock())
4607 ResultType = BSI->ReturnType;
4608 } else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(CurContext))
Alp Toker314cc812014-01-25 16:55:45 +00004609 ResultType = Function->getReturnType();
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004610 else if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(CurContext))
Alp Toker314cc812014-01-25 16:55:45 +00004611 ResultType = Method->getReturnType();
4612
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004613 if (ResultType.isNull())
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004614 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004615 else
4616 CodeCompleteExpression(S, ResultType);
4617}
4618
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004619void Sema::CodeCompleteAfterIf(Scope *S) {
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004620 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004621 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004622 mapCodeCompletionContext(*this, PCC_Statement));
4623 Results.setFilter(&ResultBuilder::IsOrdinaryName);
4624 Results.EnterNewScope();
4625
4626 CodeCompletionDeclConsumer Consumer(Results, CurContext);
4627 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00004628 CodeCompleter->includeGlobals(),
4629 CodeCompleter->loadExternal());
4630
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004631 AddOrdinaryNameResults(PCC_Statement, S, *this, Results);
4632
4633 // "else" block
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004634 CodeCompletionBuilder Builder(Results.getAllocator(),
4635 Results.getCodeCompletionTUInfo());
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004636 Builder.AddTypedTextChunk("else");
Douglas Gregor3a5d6c22012-02-16 17:49:04 +00004637 if (Results.includeCodePatterns()) {
4638 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4639 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4640 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
4641 Builder.AddPlaceholderChunk("statements");
4642 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
4643 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4644 }
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004645 Results.AddResult(Builder.TakeString());
4646
4647 // "else if" block
4648 Builder.AddTypedTextChunk("else");
4649 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4650 Builder.AddTextChunk("if");
4651 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4652 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00004653 if (getLangOpts().CPlusPlus)
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004654 Builder.AddPlaceholderChunk("condition");
4655 else
4656 Builder.AddPlaceholderChunk("expression");
4657 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor3a5d6c22012-02-16 17:49:04 +00004658 if (Results.includeCodePatterns()) {
4659 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4660 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4661 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
4662 Builder.AddPlaceholderChunk("statements");
4663 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
4664 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4665 }
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004666 Results.AddResult(Builder.TakeString());
4667
4668 Results.ExitScope();
4669
4670 if (S->getFnParent())
Craig Topper12126262015-11-15 17:27:57 +00004671 AddPrettyFunctionResults(getLangOpts(), Results);
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004672
4673 if (CodeCompleter->includeMacros())
Douglas Gregor8cb17462012-10-09 16:01:50 +00004674 AddMacroResults(PP, Results, false);
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004675
4676 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4677 Results.data(),Results.size());
4678}
4679
Richard Trieu2bd04012011-09-09 02:00:50 +00004680void Sema::CodeCompleteAssignmentRHS(Scope *S, Expr *LHS) {
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004681 if (LHS)
4682 CodeCompleteExpression(S, static_cast<Expr *>(LHS)->getType());
4683 else
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004684 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004685}
4686
Jeffrey Yasskinc76498d2010-04-08 16:38:48 +00004687void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS,
Douglas Gregor2436e712009-09-17 21:32:03 +00004688 bool EnteringContext) {
Eric Liu06d34022017-12-12 11:35:46 +00004689 if (SS.isEmpty() || !CodeCompleter)
Douglas Gregor2436e712009-09-17 21:32:03 +00004690 return;
Alex Lorenz8a7a4cf2017-06-15 21:40:54 +00004691
Eric Liu06d34022017-12-12 11:35:46 +00004692 // We want to keep the scope specifier even if it's invalid (e.g. the scope
4693 // "a::b::" is not corresponding to any context/namespace in the AST), since
4694 // it can be useful for global code completion which have information about
4695 // contexts/symbols that are not in the AST.
4696 if (SS.isInvalid()) {
4697 CodeCompletionContext CC(CodeCompletionContext::CCC_Name);
4698 CC.setCXXScopeSpecifier(SS);
4699 HandleCodeCompleteResults(this, CodeCompleter, CC, nullptr, 0);
4700 return;
4701 }
Alex Lorenz8a7a4cf2017-06-15 21:40:54 +00004702 // Always pretend to enter a context to ensure that a dependent type
4703 // resolves to a dependent record.
4704 DeclContext *Ctx = computeDeclContext(SS, /*EnteringContext=*/true);
Douglas Gregor3545ff42009-09-21 16:56:56 +00004705 if (!Ctx)
4706 return;
Douglas Gregor800f2f02009-12-11 18:28:39 +00004707
4708 // Try to instantiate any non-dependent declaration contexts before
4709 // we look in them.
John McCall0b66eb32010-05-01 00:40:08 +00004710 if (!isDependentScopeSpecifier(SS) && RequireCompleteDeclContext(SS, Ctx))
Douglas Gregor800f2f02009-12-11 18:28:39 +00004711 return;
4712
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004713 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004714 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004715 CodeCompletionContext::CCC_Name);
Douglas Gregorac322ec2010-08-27 21:18:54 +00004716 Results.EnterNewScope();
Eric Liu06d34022017-12-12 11:35:46 +00004717
Douglas Gregor3545ff42009-09-21 16:56:56 +00004718 // The "template" keyword can follow "::" in the grammar, but only
4719 // put it into the grammar if the nested-name-specifier is dependent.
Aaron Ballman4a979672014-01-03 13:56:08 +00004720 NestedNameSpecifier *NNS = SS.getScopeRep();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004721 if (!Results.empty() && NNS->isDependent())
Douglas Gregor78a21012010-01-14 16:01:26 +00004722 Results.AddResult("template");
Douglas Gregorac322ec2010-08-27 21:18:54 +00004723
4724 // Add calls to overridden virtual functions, if there are any.
4725 //
4726 // FIXME: This isn't wonderful, because we don't know whether we're actually
4727 // in a context that permits expressions. This is a general issue with
4728 // qualified-id completions.
4729 if (!EnteringContext)
4730 MaybeAddOverrideCalls(*this, Ctx, Results);
Eric Liu06d34022017-12-12 11:35:46 +00004731 Results.ExitScope();
4732
Eric Liufead6ae2017-12-13 10:26:49 +00004733 if (CodeCompleter->includeNamespaceLevelDecls() ||
4734 (!Ctx->isNamespace() && !Ctx->isTranslationUnit())) {
4735 CodeCompletionDeclConsumer Consumer(Results, CurContext);
4736 LookupVisibleDecls(Ctx, LookupOrdinaryName, Consumer,
4737 /*IncludeGlobalScope=*/true,
Sam McCallbb2cf632018-01-12 14:51:47 +00004738 /*IncludeDependentBases=*/true,
4739 CodeCompleter->loadExternal());
Eric Liufead6ae2017-12-13 10:26:49 +00004740 }
Douglas Gregorac322ec2010-08-27 21:18:54 +00004741
Eric Liu06d34022017-12-12 11:35:46 +00004742 auto CC = Results.getCompletionContext();
4743 CC.setCXXScopeSpecifier(SS);
4744
4745 HandleCodeCompleteResults(this, CodeCompleter, CC, Results.data(),
4746 Results.size());
Douglas Gregor2436e712009-09-17 21:32:03 +00004747}
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00004748
4749void Sema::CodeCompleteUsing(Scope *S) {
4750 if (!CodeCompleter)
4751 return;
4752
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004753 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004754 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00004755 CodeCompletionContext::CCC_PotentiallyQualifiedName,
4756 &ResultBuilder::IsNestedNameSpecifier);
Douglas Gregor64b12b52009-09-22 23:31:26 +00004757 Results.EnterNewScope();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004758
4759 // If we aren't in class scope, we could see the "namespace" keyword.
4760 if (!S->isClassScope())
John McCall276321a2010-08-25 06:19:51 +00004761 Results.AddResult(CodeCompletionResult("namespace"));
Douglas Gregor3545ff42009-09-21 16:56:56 +00004762
4763 // After "using", we can see anything that would start a
4764 // nested-name-specifier.
Douglas Gregora6e2edc2010-01-14 03:27:13 +00004765 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00004766 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00004767 CodeCompleter->includeGlobals(),
4768 CodeCompleter->loadExternal());
Douglas Gregor64b12b52009-09-22 23:31:26 +00004769 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00004770
4771 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4772 Results.data(), Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00004773}
4774
4775void Sema::CodeCompleteUsingDirective(Scope *S) {
4776 if (!CodeCompleter)
4777 return;
4778
Douglas Gregor3545ff42009-09-21 16:56:56 +00004779 // After "using namespace", we expect to see a namespace name or namespace
4780 // alias.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004781 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004782 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004783 CodeCompletionContext::CCC_Namespace,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004784 &ResultBuilder::IsNamespaceOrAlias);
Douglas Gregor64b12b52009-09-22 23:31:26 +00004785 Results.EnterNewScope();
Douglas Gregora6e2edc2010-01-14 03:27:13 +00004786 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00004787 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00004788 CodeCompleter->includeGlobals(),
4789 CodeCompleter->loadExternal());
Douglas Gregor64b12b52009-09-22 23:31:26 +00004790 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00004791 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4792 Results.data(), Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00004793}
4794
4795void Sema::CodeCompleteNamespaceDecl(Scope *S) {
4796 if (!CodeCompleter)
4797 return;
4798
Ted Kremenekc37877d2013-10-08 17:08:03 +00004799 DeclContext *Ctx = S->getEntity();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004800 if (!S->getParent())
4801 Ctx = Context.getTranslationUnitDecl();
4802
Douglas Gregor0ac41382010-09-23 23:01:17 +00004803 bool SuppressedGlobalResults
4804 = Ctx && !CodeCompleter->includeGlobals() && isa<TranslationUnitDecl>(Ctx);
4805
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004806 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004807 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00004808 SuppressedGlobalResults
4809 ? CodeCompletionContext::CCC_Namespace
4810 : CodeCompletionContext::CCC_Other,
4811 &ResultBuilder::IsNamespace);
4812
4813 if (Ctx && Ctx->isFileContext() && !SuppressedGlobalResults) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00004814 // We only want to see those namespaces that have already been defined
4815 // within this scope, because its likely that the user is creating an
4816 // extended namespace declaration. Keep track of the most recent
4817 // definition of each namespace.
4818 std::map<NamespaceDecl *, NamespaceDecl *> OrigToLatest;
4819 for (DeclContext::specific_decl_iterator<NamespaceDecl>
4820 NS(Ctx->decls_begin()), NSEnd(Ctx->decls_end());
4821 NS != NSEnd; ++NS)
David Blaikie40ed2972012-06-06 20:45:41 +00004822 OrigToLatest[NS->getOriginalNamespace()] = *NS;
Douglas Gregor3545ff42009-09-21 16:56:56 +00004823
4824 // Add the most recent definition (or extended definition) of each
4825 // namespace to the list of results.
Douglas Gregor64b12b52009-09-22 23:31:26 +00004826 Results.EnterNewScope();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004827 for (std::map<NamespaceDecl *, NamespaceDecl *>::iterator
Douglas Gregor78254c82012-03-27 23:34:16 +00004828 NS = OrigToLatest.begin(),
4829 NSEnd = OrigToLatest.end();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004830 NS != NSEnd; ++NS)
Douglas Gregor0a0e2b32013-01-31 04:52:16 +00004831 Results.AddResult(CodeCompletionResult(
Craig Topperc3ec1492014-05-26 06:22:03 +00004832 NS->second, Results.getBasePriority(NS->second),
4833 nullptr),
4834 CurContext, nullptr, false);
Douglas Gregor64b12b52009-09-22 23:31:26 +00004835 Results.ExitScope();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004836 }
4837
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004838 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004839 Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004840 Results.data(),Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00004841}
4842
4843void Sema::CodeCompleteNamespaceAliasDecl(Scope *S) {
4844 if (!CodeCompleter)
4845 return;
4846
Douglas Gregor3545ff42009-09-21 16:56:56 +00004847 // After "namespace", we expect to see a namespace or alias.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004848 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004849 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004850 CodeCompletionContext::CCC_Namespace,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004851 &ResultBuilder::IsNamespaceOrAlias);
Douglas Gregora6e2edc2010-01-14 03:27:13 +00004852 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00004853 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00004854 CodeCompleter->includeGlobals(),
4855 CodeCompleter->loadExternal());
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004856 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004857 Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004858 Results.data(),Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00004859}
4860
Douglas Gregorc811ede2009-09-18 20:05:18 +00004861void Sema::CodeCompleteOperatorName(Scope *S) {
4862 if (!CodeCompleter)
4863 return;
Douglas Gregor3545ff42009-09-21 16:56:56 +00004864
John McCall276321a2010-08-25 06:19:51 +00004865 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004866 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004867 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004868 CodeCompletionContext::CCC_Type,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004869 &ResultBuilder::IsType);
Douglas Gregor64b12b52009-09-22 23:31:26 +00004870 Results.EnterNewScope();
Douglas Gregorc811ede2009-09-18 20:05:18 +00004871
Douglas Gregor3545ff42009-09-21 16:56:56 +00004872 // Add the names of overloadable operators.
4873#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
4874 if (std::strcmp(Spelling, "?")) \
Douglas Gregor78a21012010-01-14 16:01:26 +00004875 Results.AddResult(Result(Spelling));
Douglas Gregor3545ff42009-09-21 16:56:56 +00004876#include "clang/Basic/OperatorKinds.def"
4877
4878 // Add any type names visible from the current scope
Douglas Gregor6ae4c522010-01-14 03:21:49 +00004879 Results.allowNestedNameSpecifiers();
Douglas Gregora6e2edc2010-01-14 03:27:13 +00004880 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00004881 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00004882 CodeCompleter->includeGlobals(),
4883 CodeCompleter->loadExternal());
4884
Douglas Gregor3545ff42009-09-21 16:56:56 +00004885 // Add any type specifiers
David Blaikiebbafb8a2012-03-11 07:00:24 +00004886 AddTypeSpecifierResults(getLangOpts(), Results);
Douglas Gregor64b12b52009-09-22 23:31:26 +00004887 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00004888
4889 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4890 Results.data(), Results.size());
Douglas Gregorc811ede2009-09-18 20:05:18 +00004891}
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00004892
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00004893void Sema::CodeCompleteConstructorInitializer(
4894 Decl *ConstructorD,
4895 ArrayRef <CXXCtorInitializer *> Initializers) {
Benjamin Kramera4f8df02015-07-09 15:31:10 +00004896 if (!ConstructorD)
4897 return;
4898
4899 AdjustDeclIfTemplate(ConstructorD);
4900
4901 CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(ConstructorD);
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004902 if (!Constructor)
4903 return;
4904
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004905 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004906 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00004907 CodeCompletionContext::CCC_PotentiallyQualifiedName);
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004908 Results.EnterNewScope();
4909
4910 // Fill in any already-initialized fields or base classes.
4911 llvm::SmallPtrSet<FieldDecl *, 4> InitializedFields;
4912 llvm::SmallPtrSet<CanQualType, 4> InitializedBases;
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00004913 for (unsigned I = 0, E = Initializers.size(); I != E; ++I) {
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004914 if (Initializers[I]->isBaseInitializer())
4915 InitializedBases.insert(
4916 Context.getCanonicalType(QualType(Initializers[I]->getBaseClass(), 0)));
4917 else
Francois Pichetd583da02010-12-04 09:14:42 +00004918 InitializedFields.insert(cast<FieldDecl>(
4919 Initializers[I]->getAnyMember()));
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004920 }
4921
4922 // Add completions for base classes.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004923 CodeCompletionBuilder Builder(Results.getAllocator(),
4924 Results.getCodeCompletionTUInfo());
Benjamin Kramera4f8df02015-07-09 15:31:10 +00004925 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00004926 bool SawLastInitializer = Initializers.empty();
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004927 CXXRecordDecl *ClassDecl = Constructor->getParent();
Aaron Ballman574705e2014-03-13 15:41:46 +00004928 for (const auto &Base : ClassDecl->bases()) {
David Blaikie82e95a32014-11-19 07:49:47 +00004929 if (!InitializedBases.insert(Context.getCanonicalType(Base.getType()))
4930 .second) {
Douglas Gregor99129ef2010-08-29 19:27:27 +00004931 SawLastInitializer
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00004932 = !Initializers.empty() &&
4933 Initializers.back()->isBaseInitializer() &&
Aaron Ballman574705e2014-03-13 15:41:46 +00004934 Context.hasSameUnqualifiedType(Base.getType(),
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00004935 QualType(Initializers.back()->getBaseClass(), 0));
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004936 continue;
Douglas Gregor99129ef2010-08-29 19:27:27 +00004937 }
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004938
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004939 Builder.AddTypedTextChunk(
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00004940 Results.getAllocator().CopyString(
Aaron Ballman574705e2014-03-13 15:41:46 +00004941 Base.getType().getAsString(Policy)));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004942 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4943 Builder.AddPlaceholderChunk("args");
4944 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4945 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor99129ef2010-08-29 19:27:27 +00004946 SawLastInitializer? CCP_NextInitializer
4947 : CCP_MemberDeclaration));
4948 SawLastInitializer = false;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004949 }
4950
4951 // Add completions for virtual base classes.
Aaron Ballman445a9392014-03-13 16:15:17 +00004952 for (const auto &Base : ClassDecl->vbases()) {
David Blaikie82e95a32014-11-19 07:49:47 +00004953 if (!InitializedBases.insert(Context.getCanonicalType(Base.getType()))
4954 .second) {
Douglas Gregor99129ef2010-08-29 19:27:27 +00004955 SawLastInitializer
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00004956 = !Initializers.empty() &&
4957 Initializers.back()->isBaseInitializer() &&
Aaron Ballman445a9392014-03-13 16:15:17 +00004958 Context.hasSameUnqualifiedType(Base.getType(),
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00004959 QualType(Initializers.back()->getBaseClass(), 0));
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004960 continue;
Douglas Gregor99129ef2010-08-29 19:27:27 +00004961 }
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004962
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004963 Builder.AddTypedTextChunk(
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00004964 Builder.getAllocator().CopyString(
Aaron Ballman445a9392014-03-13 16:15:17 +00004965 Base.getType().getAsString(Policy)));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004966 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4967 Builder.AddPlaceholderChunk("args");
4968 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4969 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor99129ef2010-08-29 19:27:27 +00004970 SawLastInitializer? CCP_NextInitializer
4971 : CCP_MemberDeclaration));
4972 SawLastInitializer = false;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004973 }
4974
4975 // Add completions for members.
Aaron Ballmane8a8bae2014-03-08 20:12:42 +00004976 for (auto *Field : ClassDecl->fields()) {
David Blaikie82e95a32014-11-19 07:49:47 +00004977 if (!InitializedFields.insert(cast<FieldDecl>(Field->getCanonicalDecl()))
4978 .second) {
Douglas Gregor99129ef2010-08-29 19:27:27 +00004979 SawLastInitializer
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00004980 = !Initializers.empty() &&
4981 Initializers.back()->isAnyMemberInitializer() &&
Aaron Ballmane8a8bae2014-03-08 20:12:42 +00004982 Initializers.back()->getAnyMember() == Field;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004983 continue;
Douglas Gregor99129ef2010-08-29 19:27:27 +00004984 }
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004985
4986 if (!Field->getDeclName())
4987 continue;
4988
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00004989 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004990 Field->getIdentifier()->getName()));
4991 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4992 Builder.AddPlaceholderChunk("args");
4993 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4994 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor99129ef2010-08-29 19:27:27 +00004995 SawLastInitializer? CCP_NextInitializer
Douglas Gregorf3af3112010-09-09 21:42:20 +00004996 : CCP_MemberDeclaration,
Douglas Gregor78254c82012-03-27 23:34:16 +00004997 CXCursor_MemberRef,
4998 CXAvailability_Available,
Aaron Ballmane8a8bae2014-03-08 20:12:42 +00004999 Field));
Douglas Gregor99129ef2010-08-29 19:27:27 +00005000 SawLastInitializer = false;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005001 }
5002 Results.ExitScope();
5003
Douglas Gregor0ac41382010-09-23 23:01:17 +00005004 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005005 Results.data(), Results.size());
5006}
5007
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00005008/// Determine whether this scope denotes a namespace.
Douglas Gregord8c61782012-02-15 15:34:24 +00005009static bool isNamespaceScope(Scope *S) {
Ted Kremenekc37877d2013-10-08 17:08:03 +00005010 DeclContext *DC = S->getEntity();
Douglas Gregord8c61782012-02-15 15:34:24 +00005011 if (!DC)
5012 return false;
5013
5014 return DC->isFileContext();
5015}
5016
5017void Sema::CodeCompleteLambdaIntroducer(Scope *S, LambdaIntroducer &Intro,
5018 bool AfterAmpersand) {
5019 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005020 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregord8c61782012-02-15 15:34:24 +00005021 CodeCompletionContext::CCC_Other);
5022 Results.EnterNewScope();
5023
5024 // Note what has already been captured.
5025 llvm::SmallPtrSet<IdentifierInfo *, 4> Known;
5026 bool IncludedThis = false;
Benjamin Kramerf3ca26982014-05-10 16:31:55 +00005027 for (const auto &C : Intro.Captures) {
5028 if (C.Kind == LCK_This) {
Douglas Gregord8c61782012-02-15 15:34:24 +00005029 IncludedThis = true;
5030 continue;
5031 }
5032
Benjamin Kramerf3ca26982014-05-10 16:31:55 +00005033 Known.insert(C.Id);
Douglas Gregord8c61782012-02-15 15:34:24 +00005034 }
5035
5036 // Look for other capturable variables.
5037 for (; S && !isNamespaceScope(S); S = S->getParent()) {
Aaron Ballman35c54952014-03-17 16:55:25 +00005038 for (const auto *D : S->decls()) {
5039 const auto *Var = dyn_cast<VarDecl>(D);
Douglas Gregord8c61782012-02-15 15:34:24 +00005040 if (!Var ||
5041 !Var->hasLocalStorage() ||
5042 Var->hasAttr<BlocksAttr>())
5043 continue;
5044
David Blaikie82e95a32014-11-19 07:49:47 +00005045 if (Known.insert(Var->getIdentifier()).second)
Douglas Gregor0a0e2b32013-01-31 04:52:16 +00005046 Results.AddResult(CodeCompletionResult(Var, CCP_LocalDeclaration),
Craig Topperc3ec1492014-05-26 06:22:03 +00005047 CurContext, nullptr, false);
Douglas Gregord8c61782012-02-15 15:34:24 +00005048 }
5049 }
5050
5051 // Add 'this', if it would be valid.
5052 if (!IncludedThis && !AfterAmpersand && Intro.Default != LCD_ByCopy)
5053 addThisCompletion(*this, Results);
5054
5055 Results.ExitScope();
5056
5057 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5058 Results.data(), Results.size());
5059}
5060
James Dennett596e4752012-06-14 03:11:41 +00005061/// Macro that optionally prepends an "@" to the string literal passed in via
5062/// Keyword, depending on whether NeedAt is true or false.
5063#define OBJC_AT_KEYWORD_NAME(NeedAt,Keyword) ((NeedAt)? "@" Keyword : Keyword)
5064
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005065static void AddObjCImplementationResults(const LangOptions &LangOpts,
Douglas Gregorf1934162010-01-13 21:24:21 +00005066 ResultBuilder &Results,
5067 bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005068 typedef CodeCompletionResult Result;
Douglas Gregorf1934162010-01-13 21:24:21 +00005069 // Since we have an implementation, we can end it.
James Dennett596e4752012-06-14 03:11:41 +00005070 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"end")));
Douglas Gregorf1934162010-01-13 21:24:21 +00005071
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005072 CodeCompletionBuilder Builder(Results.getAllocator(),
5073 Results.getCodeCompletionTUInfo());
Douglas Gregorf1934162010-01-13 21:24:21 +00005074 if (LangOpts.ObjC2) {
5075 // @dynamic
James Dennett596e4752012-06-14 03:11:41 +00005076 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"dynamic"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005077 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5078 Builder.AddPlaceholderChunk("property");
5079 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf1934162010-01-13 21:24:21 +00005080
5081 // @synthesize
James Dennett596e4752012-06-14 03:11:41 +00005082 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"synthesize"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005083 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5084 Builder.AddPlaceholderChunk("property");
5085 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf1934162010-01-13 21:24:21 +00005086 }
5087}
5088
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005089static void AddObjCInterfaceResults(const LangOptions &LangOpts,
Douglas Gregorf1934162010-01-13 21:24:21 +00005090 ResultBuilder &Results,
5091 bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005092 typedef CodeCompletionResult Result;
Douglas Gregorf1934162010-01-13 21:24:21 +00005093
5094 // Since we have an interface or protocol, we can end it.
James Dennett596e4752012-06-14 03:11:41 +00005095 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"end")));
Douglas Gregorf1934162010-01-13 21:24:21 +00005096
5097 if (LangOpts.ObjC2) {
5098 // @property
James Dennett596e4752012-06-14 03:11:41 +00005099 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"property")));
Douglas Gregorf1934162010-01-13 21:24:21 +00005100
5101 // @required
James Dennett596e4752012-06-14 03:11:41 +00005102 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"required")));
Douglas Gregorf1934162010-01-13 21:24:21 +00005103
5104 // @optional
James Dennett596e4752012-06-14 03:11:41 +00005105 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"optional")));
Douglas Gregorf1934162010-01-13 21:24:21 +00005106 }
5107}
5108
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005109static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005110 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005111 CodeCompletionBuilder Builder(Results.getAllocator(),
5112 Results.getCodeCompletionTUInfo());
Douglas Gregorf1934162010-01-13 21:24:21 +00005113
5114 // @class name ;
James Dennett596e4752012-06-14 03:11:41 +00005115 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"class"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005116 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5117 Builder.AddPlaceholderChunk("name");
5118 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf1934162010-01-13 21:24:21 +00005119
Douglas Gregorf4c33342010-05-28 00:22:41 +00005120 if (Results.includeCodePatterns()) {
5121 // @interface name
5122 // FIXME: Could introduce the whole pattern, including superclasses and
5123 // such.
James Dennett596e4752012-06-14 03:11:41 +00005124 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"interface"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005125 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5126 Builder.AddPlaceholderChunk("class");
5127 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf1934162010-01-13 21:24:21 +00005128
Douglas Gregorf4c33342010-05-28 00:22:41 +00005129 // @protocol name
James Dennett596e4752012-06-14 03:11:41 +00005130 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"protocol"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005131 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5132 Builder.AddPlaceholderChunk("protocol");
5133 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00005134
5135 // @implementation name
James Dennett596e4752012-06-14 03:11:41 +00005136 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"implementation"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005137 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5138 Builder.AddPlaceholderChunk("class");
5139 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00005140 }
Douglas Gregorf1934162010-01-13 21:24:21 +00005141
5142 // @compatibility_alias name
James Dennett596e4752012-06-14 03:11:41 +00005143 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"compatibility_alias"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005144 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5145 Builder.AddPlaceholderChunk("alias");
5146 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5147 Builder.AddPlaceholderChunk("class");
5148 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor61e36812013-03-07 23:26:24 +00005149
5150 if (Results.getSema().getLangOpts().Modules) {
5151 // @import name
5152 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "import"));
5153 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5154 Builder.AddPlaceholderChunk("module");
5155 Results.AddResult(Result(Builder.TakeString()));
5156 }
Douglas Gregorf1934162010-01-13 21:24:21 +00005157}
5158
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005159void Sema::CodeCompleteObjCAtDirective(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005160 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005161 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005162 CodeCompletionContext::CCC_Other);
Douglas Gregorf48706c2009-12-07 09:27:33 +00005163 Results.EnterNewScope();
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005164 if (isa<ObjCImplDecl>(CurContext))
David Blaikiebbafb8a2012-03-11 07:00:24 +00005165 AddObjCImplementationResults(getLangOpts(), Results, false);
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005166 else if (CurContext->isObjCContainer())
David Blaikiebbafb8a2012-03-11 07:00:24 +00005167 AddObjCInterfaceResults(getLangOpts(), Results, false);
Douglas Gregorf1934162010-01-13 21:24:21 +00005168 else
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005169 AddObjCTopLevelResults(Results, false);
Douglas Gregorf48706c2009-12-07 09:27:33 +00005170 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005171 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5172 Results.data(), Results.size());
Douglas Gregorf48706c2009-12-07 09:27:33 +00005173}
5174
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005175static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005176 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005177 CodeCompletionBuilder Builder(Results.getAllocator(),
5178 Results.getCodeCompletionTUInfo());
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005179
5180 // @encode ( type-name )
Douglas Gregore5c79d52011-10-18 21:20:17 +00005181 const char *EncodeType = "char[]";
David Blaikiebbafb8a2012-03-11 07:00:24 +00005182 if (Results.getSema().getLangOpts().CPlusPlus ||
5183 Results.getSema().getLangOpts().ConstStrings)
Jordan Rose9da05852012-06-15 18:19:56 +00005184 EncodeType = "const char[]";
Douglas Gregore5c79d52011-10-18 21:20:17 +00005185 Builder.AddResultTypeChunk(EncodeType);
James Dennett596e4752012-06-14 03:11:41 +00005186 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"encode"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005187 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5188 Builder.AddPlaceholderChunk("type-name");
5189 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5190 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005191
5192 // @protocol ( protocol-name )
Douglas Gregore5c79d52011-10-18 21:20:17 +00005193 Builder.AddResultTypeChunk("Protocol *");
James Dennett596e4752012-06-14 03:11:41 +00005194 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"protocol"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005195 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5196 Builder.AddPlaceholderChunk("protocol-name");
5197 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5198 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005199
5200 // @selector ( selector )
Douglas Gregore5c79d52011-10-18 21:20:17 +00005201 Builder.AddResultTypeChunk("SEL");
James Dennett596e4752012-06-14 03:11:41 +00005202 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"selector"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005203 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5204 Builder.AddPlaceholderChunk("selector");
5205 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5206 Results.AddResult(Result(Builder.TakeString()));
Jordan Rose9da05852012-06-15 18:19:56 +00005207
5208 // @"string"
5209 Builder.AddResultTypeChunk("NSString *");
5210 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"\""));
5211 Builder.AddPlaceholderChunk("string");
5212 Builder.AddTextChunk("\"");
5213 Results.AddResult(Result(Builder.TakeString()));
5214
Douglas Gregor951de302012-07-17 23:24:47 +00005215 // @[objects, ...]
Jordan Rose9da05852012-06-15 18:19:56 +00005216 Builder.AddResultTypeChunk("NSArray *");
James Dennett596e4752012-06-14 03:11:41 +00005217 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"["));
Ted Kremeneke65b0862012-03-06 20:05:56 +00005218 Builder.AddPlaceholderChunk("objects, ...");
Ted Kremeneke65b0862012-03-06 20:05:56 +00005219 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
5220 Results.AddResult(Result(Builder.TakeString()));
5221
Douglas Gregor951de302012-07-17 23:24:47 +00005222 // @{key : object, ...}
Jordan Rose9da05852012-06-15 18:19:56 +00005223 Builder.AddResultTypeChunk("NSDictionary *");
James Dennett596e4752012-06-14 03:11:41 +00005224 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"{"));
Ted Kremeneke65b0862012-03-06 20:05:56 +00005225 Builder.AddPlaceholderChunk("key");
Ted Kremeneke65b0862012-03-06 20:05:56 +00005226 Builder.AddChunk(CodeCompletionString::CK_Colon);
5227 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5228 Builder.AddPlaceholderChunk("object, ...");
Ted Kremeneke65b0862012-03-06 20:05:56 +00005229 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5230 Results.AddResult(Result(Builder.TakeString()));
Jordan Rose9da05852012-06-15 18:19:56 +00005231
Douglas Gregor951de302012-07-17 23:24:47 +00005232 // @(expression)
Jordan Rose9da05852012-06-15 18:19:56 +00005233 Builder.AddResultTypeChunk("id");
5234 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "("));
Jordan Rose9da05852012-06-15 18:19:56 +00005235 Builder.AddPlaceholderChunk("expression");
Jordan Rose9da05852012-06-15 18:19:56 +00005236 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5237 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005238}
5239
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005240static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005241 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005242 CodeCompletionBuilder Builder(Results.getAllocator(),
5243 Results.getCodeCompletionTUInfo());
Douglas Gregorf1934162010-01-13 21:24:21 +00005244
Douglas Gregorf4c33342010-05-28 00:22:41 +00005245 if (Results.includeCodePatterns()) {
5246 // @try { statements } @catch ( declaration ) { statements } @finally
5247 // { statements }
James Dennett596e4752012-06-14 03:11:41 +00005248 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"try"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005249 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5250 Builder.AddPlaceholderChunk("statements");
5251 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5252 Builder.AddTextChunk("@catch");
5253 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5254 Builder.AddPlaceholderChunk("parameter");
5255 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5256 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5257 Builder.AddPlaceholderChunk("statements");
5258 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5259 Builder.AddTextChunk("@finally");
5260 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5261 Builder.AddPlaceholderChunk("statements");
5262 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5263 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00005264 }
Douglas Gregorf1934162010-01-13 21:24:21 +00005265
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005266 // @throw
James Dennett596e4752012-06-14 03:11:41 +00005267 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"throw"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005268 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5269 Builder.AddPlaceholderChunk("expression");
5270 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf1934162010-01-13 21:24:21 +00005271
Douglas Gregorf4c33342010-05-28 00:22:41 +00005272 if (Results.includeCodePatterns()) {
5273 // @synchronized ( expression ) { statements }
James Dennett596e4752012-06-14 03:11:41 +00005274 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"synchronized"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005275 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5276 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5277 Builder.AddPlaceholderChunk("expression");
5278 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5279 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5280 Builder.AddPlaceholderChunk("statements");
5281 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5282 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00005283 }
Douglas Gregorf1934162010-01-13 21:24:21 +00005284}
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005285
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005286static void AddObjCVisibilityResults(const LangOptions &LangOpts,
Douglas Gregor48d46252010-01-13 21:54:15 +00005287 ResultBuilder &Results,
5288 bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005289 typedef CodeCompletionResult Result;
James Dennett596e4752012-06-14 03:11:41 +00005290 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"private")));
5291 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"protected")));
5292 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"public")));
Douglas Gregor48d46252010-01-13 21:54:15 +00005293 if (LangOpts.ObjC2)
James Dennett596e4752012-06-14 03:11:41 +00005294 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"package")));
Douglas Gregor48d46252010-01-13 21:54:15 +00005295}
5296
5297void Sema::CodeCompleteObjCAtVisibility(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005298 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005299 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005300 CodeCompletionContext::CCC_Other);
Douglas Gregor48d46252010-01-13 21:54:15 +00005301 Results.EnterNewScope();
David Blaikiebbafb8a2012-03-11 07:00:24 +00005302 AddObjCVisibilityResults(getLangOpts(), Results, false);
Douglas Gregor48d46252010-01-13 21:54:15 +00005303 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005304 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5305 Results.data(), Results.size());
Douglas Gregor48d46252010-01-13 21:54:15 +00005306}
5307
5308void Sema::CodeCompleteObjCAtStatement(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005309 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005310 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005311 CodeCompletionContext::CCC_Other);
Douglas Gregorf1934162010-01-13 21:24:21 +00005312 Results.EnterNewScope();
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005313 AddObjCStatementResults(Results, false);
5314 AddObjCExpressionResults(Results, false);
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005315 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005316 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5317 Results.data(), Results.size());
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005318}
5319
5320void Sema::CodeCompleteObjCAtExpression(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005321 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005322 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005323 CodeCompletionContext::CCC_Other);
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005324 Results.EnterNewScope();
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005325 AddObjCExpressionResults(Results, false);
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005326 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005327 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5328 Results.data(), Results.size());
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005329}
5330
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00005331/// Determine whether the addition of the given flag to an Objective-C
Douglas Gregore6078da2009-11-19 00:14:45 +00005332/// property's attributes will cause a conflict.
Bill Wendling44426052012-12-20 19:22:21 +00005333static bool ObjCPropertyFlagConflicts(unsigned Attributes, unsigned NewFlag) {
Douglas Gregore6078da2009-11-19 00:14:45 +00005334 // Check if we've already added this flag.
Bill Wendling44426052012-12-20 19:22:21 +00005335 if (Attributes & NewFlag)
Douglas Gregore6078da2009-11-19 00:14:45 +00005336 return true;
5337
Bill Wendling44426052012-12-20 19:22:21 +00005338 Attributes |= NewFlag;
Douglas Gregore6078da2009-11-19 00:14:45 +00005339
5340 // Check for collisions with "readonly".
Bill Wendling44426052012-12-20 19:22:21 +00005341 if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) &&
5342 (Attributes & ObjCDeclSpec::DQ_PR_readwrite))
Douglas Gregore6078da2009-11-19 00:14:45 +00005343 return true;
5344
Jordan Rose53cb2f32012-08-20 20:01:13 +00005345 // Check for more than one of { assign, copy, retain, strong, weak }.
Bill Wendling44426052012-12-20 19:22:21 +00005346 unsigned AssignCopyRetMask = Attributes & (ObjCDeclSpec::DQ_PR_assign |
John McCall31168b02011-06-15 23:02:42 +00005347 ObjCDeclSpec::DQ_PR_unsafe_unretained |
Douglas Gregore6078da2009-11-19 00:14:45 +00005348 ObjCDeclSpec::DQ_PR_copy |
Jordan Rose53cb2f32012-08-20 20:01:13 +00005349 ObjCDeclSpec::DQ_PR_retain |
5350 ObjCDeclSpec::DQ_PR_strong |
5351 ObjCDeclSpec::DQ_PR_weak);
Douglas Gregore6078da2009-11-19 00:14:45 +00005352 if (AssignCopyRetMask &&
5353 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_assign &&
John McCall31168b02011-06-15 23:02:42 +00005354 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_unsafe_unretained &&
Douglas Gregore6078da2009-11-19 00:14:45 +00005355 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_copy &&
John McCall31168b02011-06-15 23:02:42 +00005356 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_retain &&
Jordan Rose53cb2f32012-08-20 20:01:13 +00005357 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_strong &&
5358 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_weak)
Douglas Gregore6078da2009-11-19 00:14:45 +00005359 return true;
5360
5361 return false;
5362}
5363
Douglas Gregor36029f42009-11-18 23:08:07 +00005364void Sema::CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS) {
Steve Naroff936354c2009-10-08 21:55:05 +00005365 if (!CodeCompleter)
5366 return;
Douglas Gregor1b605f72009-11-19 01:08:35 +00005367
Bill Wendling44426052012-12-20 19:22:21 +00005368 unsigned Attributes = ODS.getPropertyAttributes();
Steve Naroff936354c2009-10-08 21:55:05 +00005369
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005370 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005371 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005372 CodeCompletionContext::CCC_Other);
Steve Naroff936354c2009-10-08 21:55:05 +00005373 Results.EnterNewScope();
Bill Wendling44426052012-12-20 19:22:21 +00005374 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readonly))
John McCall276321a2010-08-25 06:19:51 +00005375 Results.AddResult(CodeCompletionResult("readonly"));
Bill Wendling44426052012-12-20 19:22:21 +00005376 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_assign))
John McCall276321a2010-08-25 06:19:51 +00005377 Results.AddResult(CodeCompletionResult("assign"));
Bill Wendling44426052012-12-20 19:22:21 +00005378 if (!ObjCPropertyFlagConflicts(Attributes,
John McCall31168b02011-06-15 23:02:42 +00005379 ObjCDeclSpec::DQ_PR_unsafe_unretained))
5380 Results.AddResult(CodeCompletionResult("unsafe_unretained"));
Bill Wendling44426052012-12-20 19:22:21 +00005381 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readwrite))
John McCall276321a2010-08-25 06:19:51 +00005382 Results.AddResult(CodeCompletionResult("readwrite"));
Bill Wendling44426052012-12-20 19:22:21 +00005383 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_retain))
John McCall276321a2010-08-25 06:19:51 +00005384 Results.AddResult(CodeCompletionResult("retain"));
Bill Wendling44426052012-12-20 19:22:21 +00005385 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_strong))
John McCall31168b02011-06-15 23:02:42 +00005386 Results.AddResult(CodeCompletionResult("strong"));
Bill Wendling44426052012-12-20 19:22:21 +00005387 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_copy))
John McCall276321a2010-08-25 06:19:51 +00005388 Results.AddResult(CodeCompletionResult("copy"));
Bill Wendling44426052012-12-20 19:22:21 +00005389 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_nonatomic))
John McCall276321a2010-08-25 06:19:51 +00005390 Results.AddResult(CodeCompletionResult("nonatomic"));
Bill Wendling44426052012-12-20 19:22:21 +00005391 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_atomic))
Fariborz Jahanian1c2d29e2011-06-11 17:14:27 +00005392 Results.AddResult(CodeCompletionResult("atomic"));
Jordan Rose53cb2f32012-08-20 20:01:13 +00005393
5394 // Only suggest "weak" if we're compiling for ARC-with-weak-references or GC.
John McCall460ce582015-10-22 18:38:17 +00005395 if (getLangOpts().ObjCWeak || getLangOpts().getGC() != LangOptions::NonGC)
Bill Wendling44426052012-12-20 19:22:21 +00005396 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_weak))
Jordan Rose53cb2f32012-08-20 20:01:13 +00005397 Results.AddResult(CodeCompletionResult("weak"));
5398
Bill Wendling44426052012-12-20 19:22:21 +00005399 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_setter)) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005400 CodeCompletionBuilder Setter(Results.getAllocator(),
5401 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005402 Setter.AddTypedTextChunk("setter");
Argyrios Kyrtzidis7bbb8812014-02-20 07:55:15 +00005403 Setter.AddTextChunk("=");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005404 Setter.AddPlaceholderChunk("method");
5405 Results.AddResult(CodeCompletionResult(Setter.TakeString()));
Douglas Gregor45f83ee2009-11-19 00:01:57 +00005406 }
Bill Wendling44426052012-12-20 19:22:21 +00005407 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_getter)) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005408 CodeCompletionBuilder Getter(Results.getAllocator(),
5409 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005410 Getter.AddTypedTextChunk("getter");
Argyrios Kyrtzidis7bbb8812014-02-20 07:55:15 +00005411 Getter.AddTextChunk("=");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005412 Getter.AddPlaceholderChunk("method");
5413 Results.AddResult(CodeCompletionResult(Getter.TakeString()));
Douglas Gregor45f83ee2009-11-19 00:01:57 +00005414 }
Douglas Gregor86b42682015-06-19 18:27:52 +00005415 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_nullability)) {
5416 Results.AddResult(CodeCompletionResult("nonnull"));
5417 Results.AddResult(CodeCompletionResult("nullable"));
5418 Results.AddResult(CodeCompletionResult("null_unspecified"));
5419 Results.AddResult(CodeCompletionResult("null_resettable"));
5420 }
Steve Naroff936354c2009-10-08 21:55:05 +00005421 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005422 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5423 Results.data(), Results.size());
Steve Naroff936354c2009-10-08 21:55:05 +00005424}
Steve Naroffeae65032009-11-07 02:08:14 +00005425
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00005426/// Describes the kind of Objective-C method that we want to find
Douglas Gregorc8537c52009-11-19 07:41:15 +00005427/// via code completion.
5428enum ObjCMethodKind {
Dmitri Gribenko4280e5c2012-06-08 23:13:42 +00005429 MK_Any, ///< Any kind of method, provided it means other specified criteria.
5430 MK_ZeroArgSelector, ///< Zero-argument (unary) selector.
5431 MK_OneArgSelector ///< One-argument selector.
Douglas Gregorc8537c52009-11-19 07:41:15 +00005432};
5433
Douglas Gregor67c692c2010-08-26 15:07:07 +00005434static bool isAcceptableObjCSelector(Selector Sel,
5435 ObjCMethodKind WantKind,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005436 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005437 bool AllowSameLength = true) {
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005438 unsigned NumSelIdents = SelIdents.size();
Douglas Gregor67c692c2010-08-26 15:07:07 +00005439 if (NumSelIdents > Sel.getNumArgs())
5440 return false;
5441
5442 switch (WantKind) {
5443 case MK_Any: break;
5444 case MK_ZeroArgSelector: return Sel.isUnarySelector();
5445 case MK_OneArgSelector: return Sel.getNumArgs() == 1;
5446 }
5447
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005448 if (!AllowSameLength && NumSelIdents && NumSelIdents == Sel.getNumArgs())
5449 return false;
5450
Douglas Gregor67c692c2010-08-26 15:07:07 +00005451 for (unsigned I = 0; I != NumSelIdents; ++I)
5452 if (SelIdents[I] != Sel.getIdentifierInfoForSlot(I))
5453 return false;
5454
5455 return true;
5456}
5457
Douglas Gregorc8537c52009-11-19 07:41:15 +00005458static bool isAcceptableObjCMethod(ObjCMethodDecl *Method,
5459 ObjCMethodKind WantKind,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005460 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005461 bool AllowSameLength = true) {
Douglas Gregor67c692c2010-08-26 15:07:07 +00005462 return isAcceptableObjCSelector(Method->getSelector(), WantKind, SelIdents,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005463 AllowSameLength);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005464}
Douglas Gregor1154e272010-09-16 16:06:31 +00005465
5466namespace {
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00005467 /// A set of selectors, which is used to avoid introducing multiple
Douglas Gregor1154e272010-09-16 16:06:31 +00005468 /// completions with the same selector into the result set.
5469 typedef llvm::SmallPtrSet<Selector, 16> VisitedSelectorSet;
5470}
5471
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00005472/// Add all of the Objective-C methods in the given Objective-C
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005473/// container to the set of results.
5474///
5475/// The container will be a class, protocol, category, or implementation of
5476/// any of the above. This mether will recurse to include methods from
5477/// the superclasses of classes along with their categories, protocols, and
5478/// implementations.
5479///
5480/// \param Container the container in which we'll look to find methods.
5481///
James Dennett596e4752012-06-14 03:11:41 +00005482/// \param WantInstanceMethods Whether to add instance methods (only); if
5483/// false, this routine will add factory methods (only).
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005484///
5485/// \param CurContext the context in which we're performing the lookup that
5486/// finds methods.
5487///
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005488/// \param AllowSameLength Whether we allow a method to be added to the list
5489/// when it has the same number of parameters as we have selector identifiers.
5490///
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005491/// \param Results the structure into which we'll add results.
Alex Lorenz638dbc32017-01-24 14:15:08 +00005492static void AddObjCMethods(ObjCContainerDecl *Container,
5493 bool WantInstanceMethods, ObjCMethodKind WantKind,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005494 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005495 DeclContext *CurContext,
Alex Lorenz638dbc32017-01-24 14:15:08 +00005496 VisitedSelectorSet &Selectors, bool AllowSameLength,
5497 ResultBuilder &Results, bool InOriginalClass = true,
5498 bool IsRootClass = false) {
John McCall276321a2010-08-25 06:19:51 +00005499 typedef CodeCompletionResult Result;
Douglas Gregor9b4f3702012-06-12 13:44:08 +00005500 Container = getContainerDef(Container);
Douglas Gregor41778c32013-01-30 06:58:39 +00005501 ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container);
Alex Lorenz638dbc32017-01-24 14:15:08 +00005502 IsRootClass = IsRootClass || (IFace && !IFace->getSuperClass());
Aaron Ballmanaff18c02014-03-13 19:03:34 +00005503 for (auto *M : Container->methods()) {
Douglas Gregor41778c32013-01-30 06:58:39 +00005504 // The instance methods on the root class can be messaged via the
5505 // metaclass.
5506 if (M->isInstanceMethod() == WantInstanceMethods ||
Alex Lorenz638dbc32017-01-24 14:15:08 +00005507 (IsRootClass && !WantInstanceMethods)) {
Douglas Gregor1b605f72009-11-19 01:08:35 +00005508 // Check whether the selector identifiers we've been given are a
5509 // subset of the identifiers for this particular method.
Aaron Ballmanaff18c02014-03-13 19:03:34 +00005510 if (!isAcceptableObjCMethod(M, WantKind, SelIdents, AllowSameLength))
Douglas Gregor1b605f72009-11-19 01:08:35 +00005511 continue;
Douglas Gregorc8537c52009-11-19 07:41:15 +00005512
David Blaikie82e95a32014-11-19 07:49:47 +00005513 if (!Selectors.insert(M->getSelector()).second)
Douglas Gregor1154e272010-09-16 16:06:31 +00005514 continue;
Craig Topperc3ec1492014-05-26 06:22:03 +00005515
5516 Result R = Result(M, Results.getBasePriority(M), nullptr);
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005517 R.StartParameter = SelIdents.size();
Douglas Gregorc8537c52009-11-19 07:41:15 +00005518 R.AllParametersAreInformative = (WantKind != MK_Any);
Douglas Gregor416b5752010-08-25 01:08:01 +00005519 if (!InOriginalClass)
5520 R.Priority += CCD_InBaseClass;
Douglas Gregor1b605f72009-11-19 01:08:35 +00005521 Results.MaybeAddResult(R, CurContext);
5522 }
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005523 }
5524
Douglas Gregorf37c9492010-09-16 15:34:59 +00005525 // Visit the protocols of protocols.
5526 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Douglas Gregore6e48b12012-01-01 19:29:29 +00005527 if (Protocol->hasDefinition()) {
5528 const ObjCList<ObjCProtocolDecl> &Protocols
5529 = Protocol->getReferencedProtocols();
5530 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
5531 E = Protocols.end();
5532 I != E; ++I)
Alex Lorenz638dbc32017-01-24 14:15:08 +00005533 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, CurContext,
5534 Selectors, AllowSameLength, Results, false, IsRootClass);
Douglas Gregore6e48b12012-01-01 19:29:29 +00005535 }
Douglas Gregorf37c9492010-09-16 15:34:59 +00005536 }
5537
Douglas Gregorc0ac7d62011-12-15 05:27:12 +00005538 if (!IFace || !IFace->hasDefinition())
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005539 return;
5540
5541 // Add methods in protocols.
Aaron Ballmana49c5062014-03-13 20:29:09 +00005542 for (auto *I : IFace->protocols())
Alex Lorenz638dbc32017-01-24 14:15:08 +00005543 AddObjCMethods(I, WantInstanceMethods, WantKind, SelIdents, CurContext,
5544 Selectors, AllowSameLength, Results, false, IsRootClass);
5545
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005546 // Add methods in categories.
Aaron Ballman15063e12014-03-13 21:35:02 +00005547 for (auto *CatDecl : IFace->known_categories()) {
Douglas Gregor048fbfa2013-01-16 23:00:23 +00005548 AddObjCMethods(CatDecl, WantInstanceMethods, WantKind, SelIdents,
Alex Lorenz638dbc32017-01-24 14:15:08 +00005549 CurContext, Selectors, AllowSameLength, Results,
5550 InOriginalClass, IsRootClass);
5551
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005552 // Add a categories protocol methods.
5553 const ObjCList<ObjCProtocolDecl> &Protocols
5554 = CatDecl->getReferencedProtocols();
5555 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
5556 E = Protocols.end();
5557 I != E; ++I)
Alex Lorenz638dbc32017-01-24 14:15:08 +00005558 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, CurContext,
5559 Selectors, AllowSameLength, Results, false, IsRootClass);
5560
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005561 // Add methods in category implementations.
5562 if (ObjCCategoryImplDecl *Impl = CatDecl->getImplementation())
Alex Lorenz638dbc32017-01-24 14:15:08 +00005563 AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents, CurContext,
5564 Selectors, AllowSameLength, Results, InOriginalClass,
5565 IsRootClass);
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005566 }
5567
5568 // Add methods in superclass.
Alex Lorenz638dbc32017-01-24 14:15:08 +00005569 // Avoid passing in IsRootClass since root classes won't have super classes.
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005570 if (IFace->getSuperClass())
Alex Lorenz638dbc32017-01-24 14:15:08 +00005571 AddObjCMethods(IFace->getSuperClass(), WantInstanceMethods, WantKind,
5572 SelIdents, CurContext, Selectors, AllowSameLength, Results,
5573 /*IsRootClass=*/false);
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005574
5575 // Add methods in our implementation, if any.
5576 if (ObjCImplementationDecl *Impl = IFace->getImplementation())
Alex Lorenz638dbc32017-01-24 14:15:08 +00005577 AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents, CurContext,
5578 Selectors, AllowSameLength, Results, InOriginalClass,
5579 IsRootClass);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005580}
5581
5582
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005583void Sema::CodeCompleteObjCPropertyGetter(Scope *S) {
Douglas Gregorc8537c52009-11-19 07:41:15 +00005584 // Try to find the interface where getters might live.
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005585 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005586 if (!Class) {
5587 if (ObjCCategoryDecl *Category
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005588 = dyn_cast_or_null<ObjCCategoryDecl>(CurContext))
Douglas Gregorc8537c52009-11-19 07:41:15 +00005589 Class = Category->getClassInterface();
5590
5591 if (!Class)
5592 return;
5593 }
5594
5595 // Find all of the potential getters.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005596 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005597 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005598 CodeCompletionContext::CCC_Other);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005599 Results.EnterNewScope();
5600
Douglas Gregor1154e272010-09-16 16:06:31 +00005601 VisitedSelectorSet Selectors;
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005602 AddObjCMethods(Class, true, MK_ZeroArgSelector, None, CurContext, Selectors,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005603 /*AllowSameLength=*/true, Results);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005604 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005605 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5606 Results.data(), Results.size());
Douglas Gregorc8537c52009-11-19 07:41:15 +00005607}
5608
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005609void Sema::CodeCompleteObjCPropertySetter(Scope *S) {
Douglas Gregorc8537c52009-11-19 07:41:15 +00005610 // Try to find the interface where setters might live.
5611 ObjCInterfaceDecl *Class
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005612 = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005613 if (!Class) {
5614 if (ObjCCategoryDecl *Category
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005615 = dyn_cast_or_null<ObjCCategoryDecl>(CurContext))
Douglas Gregorc8537c52009-11-19 07:41:15 +00005616 Class = Category->getClassInterface();
5617
5618 if (!Class)
5619 return;
5620 }
5621
5622 // Find all of the potential getters.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005623 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005624 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005625 CodeCompletionContext::CCC_Other);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005626 Results.EnterNewScope();
5627
Douglas Gregor1154e272010-09-16 16:06:31 +00005628 VisitedSelectorSet Selectors;
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005629 AddObjCMethods(Class, true, MK_OneArgSelector, None, CurContext,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005630 Selectors, /*AllowSameLength=*/true, Results);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005631
5632 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005633 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5634 Results.data(), Results.size());
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005635}
5636
Douglas Gregorf34a6f02011-02-15 22:19:42 +00005637void Sema::CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS,
5638 bool IsParameter) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005639 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005640 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005641 CodeCompletionContext::CCC_Type);
Douglas Gregor99fa2642010-08-24 01:06:58 +00005642 Results.EnterNewScope();
5643
5644 // Add context-sensitive, Objective-C parameter-passing keywords.
5645 bool AddedInOut = false;
5646 if ((DS.getObjCDeclQualifier() &
5647 (ObjCDeclSpec::DQ_In | ObjCDeclSpec::DQ_Inout)) == 0) {
5648 Results.AddResult("in");
5649 Results.AddResult("inout");
5650 AddedInOut = true;
5651 }
5652 if ((DS.getObjCDeclQualifier() &
5653 (ObjCDeclSpec::DQ_Out | ObjCDeclSpec::DQ_Inout)) == 0) {
5654 Results.AddResult("out");
5655 if (!AddedInOut)
5656 Results.AddResult("inout");
5657 }
5658 if ((DS.getObjCDeclQualifier() &
5659 (ObjCDeclSpec::DQ_Bycopy | ObjCDeclSpec::DQ_Byref |
5660 ObjCDeclSpec::DQ_Oneway)) == 0) {
5661 Results.AddResult("bycopy");
5662 Results.AddResult("byref");
5663 Results.AddResult("oneway");
5664 }
Douglas Gregor86b42682015-06-19 18:27:52 +00005665 if ((DS.getObjCDeclQualifier() & ObjCDeclSpec::DQ_CSNullability) == 0) {
5666 Results.AddResult("nonnull");
5667 Results.AddResult("nullable");
5668 Results.AddResult("null_unspecified");
5669 }
Douglas Gregor99fa2642010-08-24 01:06:58 +00005670
Douglas Gregorf34a6f02011-02-15 22:19:42 +00005671 // If we're completing the return type of an Objective-C method and the
5672 // identifier IBAction refers to a macro, provide a completion item for
5673 // an action, e.g.,
5674 // IBAction)<#selector#>:(id)sender
5675 if (DS.getObjCDeclQualifier() == 0 && !IsParameter &&
Richard Smith20e883e2015-04-29 23:20:19 +00005676 PP.isMacroDefined("IBAction")) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005677 CodeCompletionBuilder Builder(Results.getAllocator(),
5678 Results.getCodeCompletionTUInfo(),
5679 CCP_CodePattern, CXAvailability_Available);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00005680 Builder.AddTypedTextChunk("IBAction");
Benjamin Kramerdb534a42012-03-26 16:57:36 +00005681 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00005682 Builder.AddPlaceholderChunk("selector");
Benjamin Kramerdb534a42012-03-26 16:57:36 +00005683 Builder.AddChunk(CodeCompletionString::CK_Colon);
5684 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00005685 Builder.AddTextChunk("id");
Benjamin Kramerdb534a42012-03-26 16:57:36 +00005686 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00005687 Builder.AddTextChunk("sender");
5688 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
5689 }
Douglas Gregored1f5972013-01-30 07:11:43 +00005690
5691 // If we're completing the return type, provide 'instancetype'.
5692 if (!IsParameter) {
5693 Results.AddResult(CodeCompletionResult("instancetype"));
5694 }
Douglas Gregorf34a6f02011-02-15 22:19:42 +00005695
Douglas Gregor99fa2642010-08-24 01:06:58 +00005696 // Add various builtin type names and specifiers.
5697 AddOrdinaryNameResults(PCC_Type, S, *this, Results);
5698 Results.ExitScope();
5699
5700 // Add the various type names
5701 Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
5702 CodeCompletionDeclConsumer Consumer(Results, CurContext);
5703 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00005704 CodeCompleter->includeGlobals(),
5705 CodeCompleter->loadExternal());
5706
Douglas Gregor99fa2642010-08-24 01:06:58 +00005707 if (CodeCompleter->includeMacros())
Douglas Gregor8cb17462012-10-09 16:01:50 +00005708 AddMacroResults(PP, Results, false);
Douglas Gregor99fa2642010-08-24 01:06:58 +00005709
Eric Liuf5ba09f2018-07-04 10:01:18 +00005710 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor99fa2642010-08-24 01:06:58 +00005711 Results.data(), Results.size());
5712}
5713
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00005714/// When we have an expression with type "id", we may assume
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005715/// that it has some more-specific class type based on knowledge of
5716/// common uses of Objective-C. This routine returns that class type,
5717/// or NULL if no better result could be determined.
5718static ObjCInterfaceDecl *GetAssumedMessageSendExprType(Expr *E) {
Douglas Gregored0b69d2010-09-15 16:23:04 +00005719 ObjCMessageExpr *Msg = dyn_cast_or_null<ObjCMessageExpr>(E);
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005720 if (!Msg)
Craig Topperc3ec1492014-05-26 06:22:03 +00005721 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005722
5723 Selector Sel = Msg->getSelector();
5724 if (Sel.isNull())
Craig Topperc3ec1492014-05-26 06:22:03 +00005725 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005726
5727 IdentifierInfo *Id = Sel.getIdentifierInfoForSlot(0);
5728 if (!Id)
Craig Topperc3ec1492014-05-26 06:22:03 +00005729 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005730
5731 ObjCMethodDecl *Method = Msg->getMethodDecl();
5732 if (!Method)
Craig Topperc3ec1492014-05-26 06:22:03 +00005733 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005734
5735 // Determine the class that we're sending the message to.
Craig Topperc3ec1492014-05-26 06:22:03 +00005736 ObjCInterfaceDecl *IFace = nullptr;
Douglas Gregor9a129192010-04-21 00:45:42 +00005737 switch (Msg->getReceiverKind()) {
5738 case ObjCMessageExpr::Class:
John McCall8b07ec22010-05-15 11:32:37 +00005739 if (const ObjCObjectType *ObjType
5740 = Msg->getClassReceiver()->getAs<ObjCObjectType>())
5741 IFace = ObjType->getInterface();
Douglas Gregor9a129192010-04-21 00:45:42 +00005742 break;
5743
5744 case ObjCMessageExpr::Instance: {
5745 QualType T = Msg->getInstanceReceiver()->getType();
5746 if (const ObjCObjectPointerType *Ptr = T->getAs<ObjCObjectPointerType>())
5747 IFace = Ptr->getInterfaceDecl();
5748 break;
5749 }
5750
5751 case ObjCMessageExpr::SuperInstance:
5752 case ObjCMessageExpr::SuperClass:
5753 break;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005754 }
5755
5756 if (!IFace)
Craig Topperc3ec1492014-05-26 06:22:03 +00005757 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005758
5759 ObjCInterfaceDecl *Super = IFace->getSuperClass();
5760 if (Method->isInstanceMethod())
5761 return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
5762 .Case("retain", IFace)
John McCall31168b02011-06-15 23:02:42 +00005763 .Case("strong", IFace)
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005764 .Case("autorelease", IFace)
5765 .Case("copy", IFace)
5766 .Case("copyWithZone", IFace)
5767 .Case("mutableCopy", IFace)
5768 .Case("mutableCopyWithZone", IFace)
5769 .Case("awakeFromCoder", IFace)
5770 .Case("replacementObjectFromCoder", IFace)
5771 .Case("class", IFace)
5772 .Case("classForCoder", IFace)
5773 .Case("superclass", Super)
Craig Topperc3ec1492014-05-26 06:22:03 +00005774 .Default(nullptr);
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005775
5776 return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
5777 .Case("new", IFace)
5778 .Case("alloc", IFace)
5779 .Case("allocWithZone", IFace)
5780 .Case("class", IFace)
5781 .Case("superclass", Super)
Craig Topperc3ec1492014-05-26 06:22:03 +00005782 .Default(nullptr);
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005783}
5784
Douglas Gregor6fc04132010-08-27 15:10:57 +00005785// Add a special completion for a message send to "super", which fills in the
5786// most likely case of forwarding all of our arguments to the superclass
5787// function.
5788///
5789/// \param S The semantic analysis object.
5790///
Dmitri Gribenkoadba9be2012-08-23 17:58:28 +00005791/// \param NeedSuperKeyword Whether we need to prefix this completion with
Douglas Gregor6fc04132010-08-27 15:10:57 +00005792/// the "super" keyword. Otherwise, we just need to provide the arguments.
5793///
5794/// \param SelIdents The identifiers in the selector that have already been
5795/// provided as arguments for a send to "super".
5796///
Douglas Gregor6fc04132010-08-27 15:10:57 +00005797/// \param Results The set of results to augment.
5798///
5799/// \returns the Objective-C method declaration that would be invoked by
5800/// this "super" completion. If NULL, no completion was added.
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005801static ObjCMethodDecl *AddSuperSendCompletion(
5802 Sema &S, bool NeedSuperKeyword,
5803 ArrayRef<IdentifierInfo *> SelIdents,
5804 ResultBuilder &Results) {
Douglas Gregor6fc04132010-08-27 15:10:57 +00005805 ObjCMethodDecl *CurMethod = S.getCurMethodDecl();
5806 if (!CurMethod)
Craig Topperc3ec1492014-05-26 06:22:03 +00005807 return nullptr;
5808
Douglas Gregor6fc04132010-08-27 15:10:57 +00005809 ObjCInterfaceDecl *Class = CurMethod->getClassInterface();
5810 if (!Class)
Craig Topperc3ec1492014-05-26 06:22:03 +00005811 return nullptr;
5812
Douglas Gregor6fc04132010-08-27 15:10:57 +00005813 // Try to find a superclass method with the same selector.
Craig Topperc3ec1492014-05-26 06:22:03 +00005814 ObjCMethodDecl *SuperMethod = nullptr;
Douglas Gregorb5f1e462011-02-16 00:51:18 +00005815 while ((Class = Class->getSuperClass()) && !SuperMethod) {
5816 // Check in the class
Douglas Gregor6fc04132010-08-27 15:10:57 +00005817 SuperMethod = Class->getMethod(CurMethod->getSelector(),
5818 CurMethod->isInstanceMethod());
5819
Douglas Gregorb5f1e462011-02-16 00:51:18 +00005820 // Check in categories or class extensions.
5821 if (!SuperMethod) {
Aaron Ballman15063e12014-03-13 21:35:02 +00005822 for (const auto *Cat : Class->known_categories()) {
Douglas Gregor048fbfa2013-01-16 23:00:23 +00005823 if ((SuperMethod = Cat->getMethod(CurMethod->getSelector(),
Douglas Gregorb5f1e462011-02-16 00:51:18 +00005824 CurMethod->isInstanceMethod())))
5825 break;
Douglas Gregor048fbfa2013-01-16 23:00:23 +00005826 }
Douglas Gregorb5f1e462011-02-16 00:51:18 +00005827 }
5828 }
5829
Douglas Gregor6fc04132010-08-27 15:10:57 +00005830 if (!SuperMethod)
Craig Topperc3ec1492014-05-26 06:22:03 +00005831 return nullptr;
5832
Douglas Gregor6fc04132010-08-27 15:10:57 +00005833 // Check whether the superclass method has the same signature.
5834 if (CurMethod->param_size() != SuperMethod->param_size() ||
5835 CurMethod->isVariadic() != SuperMethod->isVariadic())
Craig Topperc3ec1492014-05-26 06:22:03 +00005836 return nullptr;
5837
Douglas Gregor6fc04132010-08-27 15:10:57 +00005838 for (ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin(),
5839 CurPEnd = CurMethod->param_end(),
5840 SuperP = SuperMethod->param_begin();
5841 CurP != CurPEnd; ++CurP, ++SuperP) {
5842 // Make sure the parameter types are compatible.
5843 if (!S.Context.hasSameUnqualifiedType((*CurP)->getType(),
5844 (*SuperP)->getType()))
Craig Topperc3ec1492014-05-26 06:22:03 +00005845 return nullptr;
5846
Douglas Gregor6fc04132010-08-27 15:10:57 +00005847 // Make sure we have a parameter name to forward!
5848 if (!(*CurP)->getIdentifier())
Craig Topperc3ec1492014-05-26 06:22:03 +00005849 return nullptr;
Douglas Gregor6fc04132010-08-27 15:10:57 +00005850 }
5851
5852 // We have a superclass method. Now, form the send-to-super completion.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005853 CodeCompletionBuilder Builder(Results.getAllocator(),
5854 Results.getCodeCompletionTUInfo());
Douglas Gregor6fc04132010-08-27 15:10:57 +00005855
5856 // Give this completion a return type.
Douglas Gregorc3425b12015-07-07 06:20:19 +00005857 AddResultTypeChunk(S.Context, getCompletionPrintingPolicy(S), SuperMethod,
5858 Results.getCompletionContext().getBaseType(),
Douglas Gregor75acd922011-09-27 23:30:47 +00005859 Builder);
Douglas Gregor6fc04132010-08-27 15:10:57 +00005860
5861 // If we need the "super" keyword, add it (plus some spacing).
5862 if (NeedSuperKeyword) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005863 Builder.AddTypedTextChunk("super");
5864 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregor6fc04132010-08-27 15:10:57 +00005865 }
5866
5867 Selector Sel = CurMethod->getSelector();
5868 if (Sel.isUnarySelector()) {
5869 if (NeedSuperKeyword)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005870 Builder.AddTextChunk(Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00005871 Sel.getNameForSlot(0)));
Douglas Gregor6fc04132010-08-27 15:10:57 +00005872 else
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005873 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00005874 Sel.getNameForSlot(0)));
Douglas Gregor6fc04132010-08-27 15:10:57 +00005875 } else {
5876 ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin();
5877 for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I, ++CurP) {
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005878 if (I > SelIdents.size())
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005879 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregor6fc04132010-08-27 15:10:57 +00005880
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005881 if (I < SelIdents.size())
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005882 Builder.AddInformativeChunk(
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005883 Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00005884 Sel.getNameForSlot(I) + ":"));
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005885 else if (NeedSuperKeyword || I > SelIdents.size()) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005886 Builder.AddTextChunk(
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005887 Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00005888 Sel.getNameForSlot(I) + ":"));
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005889 Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005890 (*CurP)->getIdentifier()->getName()));
Douglas Gregor6fc04132010-08-27 15:10:57 +00005891 } else {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005892 Builder.AddTypedTextChunk(
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005893 Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00005894 Sel.getNameForSlot(I) + ":"));
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005895 Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005896 (*CurP)->getIdentifier()->getName()));
Douglas Gregor6fc04132010-08-27 15:10:57 +00005897 }
5898 }
5899 }
5900
Douglas Gregor78254c82012-03-27 23:34:16 +00005901 Results.AddResult(CodeCompletionResult(Builder.TakeString(), SuperMethod,
5902 CCP_SuperCompletion));
Douglas Gregor6fc04132010-08-27 15:10:57 +00005903 return SuperMethod;
5904}
5905
Douglas Gregora817a192010-05-27 23:06:34 +00005906void Sema::CodeCompleteObjCMessageReceiver(Scope *S) {
John McCall276321a2010-08-25 06:19:51 +00005907 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005908 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005909 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005910 CodeCompletionContext::CCC_ObjCMessageReceiver,
Richard Smith2bf7fdb2013-01-02 11:42:31 +00005911 getLangOpts().CPlusPlus11
Douglas Gregord8c61782012-02-15 15:34:24 +00005912 ? &ResultBuilder::IsObjCMessageReceiverOrLambdaCapture
5913 : &ResultBuilder::IsObjCMessageReceiver);
Douglas Gregora817a192010-05-27 23:06:34 +00005914
Douglas Gregora817a192010-05-27 23:06:34 +00005915 CodeCompletionDeclConsumer Consumer(Results, CurContext);
5916 Results.EnterNewScope();
Douglas Gregor39982192010-08-15 06:18:01 +00005917 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00005918 CodeCompleter->includeGlobals(),
5919 CodeCompleter->loadExternal());
5920
Douglas Gregora817a192010-05-27 23:06:34 +00005921 // If we are in an Objective-C method inside a class that has a superclass,
5922 // add "super" as an option.
5923 if (ObjCMethodDecl *Method = getCurMethodDecl())
5924 if (ObjCInterfaceDecl *Iface = Method->getClassInterface())
Douglas Gregor6fc04132010-08-27 15:10:57 +00005925 if (Iface->getSuperClass()) {
Douglas Gregora817a192010-05-27 23:06:34 +00005926 Results.AddResult(Result("super"));
Douglas Gregor6fc04132010-08-27 15:10:57 +00005927
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005928 AddSuperSendCompletion(*this, /*NeedSuperKeyword=*/true, None, Results);
Douglas Gregor6fc04132010-08-27 15:10:57 +00005929 }
Douglas Gregora817a192010-05-27 23:06:34 +00005930
Richard Smith2bf7fdb2013-01-02 11:42:31 +00005931 if (getLangOpts().CPlusPlus11)
Douglas Gregord8c61782012-02-15 15:34:24 +00005932 addThisCompletion(*this, Results);
5933
Douglas Gregora817a192010-05-27 23:06:34 +00005934 Results.ExitScope();
5935
5936 if (CodeCompleter->includeMacros())
Douglas Gregor8cb17462012-10-09 16:01:50 +00005937 AddMacroResults(PP, Results, false);
Douglas Gregor50832e02010-09-20 22:39:41 +00005938 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005939 Results.data(), Results.size());
Douglas Gregora817a192010-05-27 23:06:34 +00005940
5941}
5942
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005943void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005944 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00005945 bool AtArgumentExpression) {
Craig Topperc3ec1492014-05-26 06:22:03 +00005946 ObjCInterfaceDecl *CDecl = nullptr;
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005947 if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
5948 // Figure out which interface we're in.
5949 CDecl = CurMethod->getClassInterface();
5950 if (!CDecl)
5951 return;
5952
5953 // Find the superclass of this class.
5954 CDecl = CDecl->getSuperClass();
5955 if (!CDecl)
5956 return;
5957
5958 if (CurMethod->isInstanceMethod()) {
5959 // We are inside an instance method, which means that the message
5960 // send [super ...] is actually calling an instance method on the
Douglas Gregor392a84b2010-10-13 21:24:53 +00005961 // current object.
Craig Topperc3ec1492014-05-26 06:22:03 +00005962 return CodeCompleteObjCInstanceMessage(S, nullptr, SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00005963 AtArgumentExpression,
Douglas Gregor392a84b2010-10-13 21:24:53 +00005964 CDecl);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005965 }
5966
5967 // Fall through to send to the superclass in CDecl.
5968 } else {
5969 // "super" may be the name of a type or variable. Figure out which
5970 // it is.
Argyrios Kyrtzidis3e56dd42013-03-14 22:56:43 +00005971 IdentifierInfo *Super = getSuperIdentifier();
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005972 NamedDecl *ND = LookupSingleName(S, Super, SuperLoc,
5973 LookupOrdinaryName);
5974 if ((CDecl = dyn_cast_or_null<ObjCInterfaceDecl>(ND))) {
5975 // "super" names an interface. Use it.
5976 } else if (TypeDecl *TD = dyn_cast_or_null<TypeDecl>(ND)) {
John McCall8b07ec22010-05-15 11:32:37 +00005977 if (const ObjCObjectType *Iface
5978 = Context.getTypeDeclType(TD)->getAs<ObjCObjectType>())
5979 CDecl = Iface->getInterface();
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005980 } else if (ND && isa<UnresolvedUsingTypenameDecl>(ND)) {
5981 // "super" names an unresolved type; we can't be more specific.
5982 } else {
5983 // Assume that "super" names some kind of value and parse that way.
5984 CXXScopeSpec SS;
Abramo Bagnara7945c982012-01-27 09:46:47 +00005985 SourceLocation TemplateKWLoc;
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005986 UnqualifiedId id;
5987 id.setIdentifier(Super, SuperLoc);
Abramo Bagnara7945c982012-01-27 09:46:47 +00005988 ExprResult SuperExpr = ActOnIdExpression(S, SS, TemplateKWLoc, id,
5989 false, false);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005990 return CodeCompleteObjCInstanceMessage(S, (Expr *)SuperExpr.get(),
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005991 SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00005992 AtArgumentExpression);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005993 }
5994
5995 // Fall through
5996 }
5997
John McCallba7bf592010-08-24 05:47:05 +00005998 ParsedType Receiver;
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005999 if (CDecl)
John McCallba7bf592010-08-24 05:47:05 +00006000 Receiver = ParsedType::make(Context.getObjCInterfaceType(CDecl));
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006001 return CodeCompleteObjCClassMessage(S, Receiver, SelIdents,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006002 AtArgumentExpression,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006003 /*IsSuper=*/true);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006004}
6005
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006006/// Given a set of code-completion results for the argument of a message
Douglas Gregor74661272010-09-21 00:03:25 +00006007/// send, determine the preferred type (if any) for that argument expression.
6008static QualType getPreferredArgumentTypeForMessageSend(ResultBuilder &Results,
6009 unsigned NumSelIdents) {
6010 typedef CodeCompletionResult Result;
6011 ASTContext &Context = Results.getSema().Context;
6012
6013 QualType PreferredType;
6014 unsigned BestPriority = CCP_Unlikely * 2;
6015 Result *ResultsData = Results.data();
6016 for (unsigned I = 0, N = Results.size(); I != N; ++I) {
6017 Result &R = ResultsData[I];
6018 if (R.Kind == Result::RK_Declaration &&
6019 isa<ObjCMethodDecl>(R.Declaration)) {
6020 if (R.Priority <= BestPriority) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00006021 const ObjCMethodDecl *Method = cast<ObjCMethodDecl>(R.Declaration);
Douglas Gregor74661272010-09-21 00:03:25 +00006022 if (NumSelIdents <= Method->param_size()) {
Alp Toker03376dc2014-07-07 09:02:20 +00006023 QualType MyPreferredType = Method->parameters()[NumSelIdents - 1]
Douglas Gregor74661272010-09-21 00:03:25 +00006024 ->getType();
6025 if (R.Priority < BestPriority || PreferredType.isNull()) {
6026 BestPriority = R.Priority;
6027 PreferredType = MyPreferredType;
6028 } else if (!Context.hasSameUnqualifiedType(PreferredType,
6029 MyPreferredType)) {
6030 PreferredType = QualType();
6031 }
6032 }
6033 }
6034 }
6035 }
6036
6037 return PreferredType;
6038}
6039
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006040static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
6041 ParsedType Receiver,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006042 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006043 bool AtArgumentExpression,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006044 bool IsSuper,
6045 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00006046 typedef CodeCompletionResult Result;
Craig Topperc3ec1492014-05-26 06:22:03 +00006047 ObjCInterfaceDecl *CDecl = nullptr;
6048
Douglas Gregor8ce33212009-11-17 17:59:40 +00006049 // If the given name refers to an interface type, retrieve the
6050 // corresponding declaration.
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006051 if (Receiver) {
Craig Topperc3ec1492014-05-26 06:22:03 +00006052 QualType T = SemaRef.GetTypeFromParser(Receiver, nullptr);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006053 if (!T.isNull())
John McCall8b07ec22010-05-15 11:32:37 +00006054 if (const ObjCObjectType *Interface = T->getAs<ObjCObjectType>())
6055 CDecl = Interface->getInterface();
Douglas Gregor8ce33212009-11-17 17:59:40 +00006056 }
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006057
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006058 // Add all of the factory methods in this Objective-C class, its protocols,
6059 // superclasses, categories, implementation, etc.
Steve Naroffeae65032009-11-07 02:08:14 +00006060 Results.EnterNewScope();
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006061
Douglas Gregor6fc04132010-08-27 15:10:57 +00006062 // If this is a send-to-super, try to add the special "super" send
6063 // completion.
6064 if (IsSuper) {
6065 if (ObjCMethodDecl *SuperMethod
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006066 = AddSuperSendCompletion(SemaRef, false, SelIdents, Results))
Douglas Gregor6fc04132010-08-27 15:10:57 +00006067 Results.Ignore(SuperMethod);
6068 }
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006069
Douglas Gregorc2cb2e22010-08-27 15:29:55 +00006070 // If we're inside an Objective-C method definition, prefer its selector to
6071 // others.
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006072 if (ObjCMethodDecl *CurMethod = SemaRef.getCurMethodDecl())
Douglas Gregorc2cb2e22010-08-27 15:29:55 +00006073 Results.setPreferredSelector(CurMethod->getSelector());
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006074
Douglas Gregor1154e272010-09-16 16:06:31 +00006075 VisitedSelectorSet Selectors;
Douglas Gregor6285f752010-04-06 16:40:00 +00006076 if (CDecl)
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006077 AddObjCMethods(CDecl, false, MK_Any, SelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00006078 SemaRef.CurContext, Selectors, AtArgumentExpression,
6079 Results);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006080 else {
Douglas Gregor6285f752010-04-06 16:40:00 +00006081 // We're messaging "id" as a type; provide all class/factory methods.
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006082
Douglas Gregord720daf2010-04-06 17:30:22 +00006083 // If we have an external source, load the entire class method
Sebastian Redld44cd6a2010-08-18 23:57:06 +00006084 // pool from the AST file.
Axel Naumanndd433f02012-10-18 19:05:02 +00006085 if (SemaRef.getExternalSource()) {
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006086 for (uint32_t I = 0,
Axel Naumanndd433f02012-10-18 19:05:02 +00006087 N = SemaRef.getExternalSource()->GetNumExternalSelectors();
John McCall75b960e2010-06-01 09:23:16 +00006088 I != N; ++I) {
Axel Naumanndd433f02012-10-18 19:05:02 +00006089 Selector Sel = SemaRef.getExternalSource()->GetExternalSelector(I);
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006090 if (Sel.isNull() || SemaRef.MethodPool.count(Sel))
Douglas Gregord720daf2010-04-06 17:30:22 +00006091 continue;
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006092
6093 SemaRef.ReadMethodPool(Sel);
Douglas Gregord720daf2010-04-06 17:30:22 +00006094 }
6095 }
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006096
6097 for (Sema::GlobalMethodPool::iterator M = SemaRef.MethodPool.begin(),
6098 MEnd = SemaRef.MethodPool.end();
Sebastian Redl75d8a322010-08-02 23:18:59 +00006099 M != MEnd; ++M) {
6100 for (ObjCMethodList *MethList = &M->second.second;
Nico Weber2e0c8f72014-12-27 03:58:08 +00006101 MethList && MethList->getMethod();
Argyrios Kyrtzidisd3da6e02013-04-17 00:08:58 +00006102 MethList = MethList->getNext()) {
Nico Weber2e0c8f72014-12-27 03:58:08 +00006103 if (!isAcceptableObjCMethod(MethList->getMethod(), MK_Any, SelIdents))
Douglas Gregor6285f752010-04-06 16:40:00 +00006104 continue;
Craig Topperc3ec1492014-05-26 06:22:03 +00006105
Nico Weber2e0c8f72014-12-27 03:58:08 +00006106 Result R(MethList->getMethod(),
6107 Results.getBasePriority(MethList->getMethod()), nullptr);
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006108 R.StartParameter = SelIdents.size();
Douglas Gregor6285f752010-04-06 16:40:00 +00006109 R.AllParametersAreInformative = false;
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006110 Results.MaybeAddResult(R, SemaRef.CurContext);
Douglas Gregor6285f752010-04-06 16:40:00 +00006111 }
6112 }
6113 }
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006114
6115 Results.ExitScope();
6116}
Douglas Gregor6285f752010-04-06 16:40:00 +00006117
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006118void Sema::CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006119 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006120 bool AtArgumentExpression,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006121 bool IsSuper) {
Douglas Gregor63745d52011-07-21 01:05:26 +00006122
6123 QualType T = this->GetTypeFromParser(Receiver);
6124
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006125 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006126 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor63745d52011-07-21 01:05:26 +00006127 CodeCompletionContext(CodeCompletionContext::CCC_ObjCClassMessage,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006128 T, SelIdents));
Douglas Gregor63745d52011-07-21 01:05:26 +00006129
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006130 AddClassMessageCompletions(*this, S, Receiver, SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006131 AtArgumentExpression, IsSuper, Results);
Douglas Gregor74661272010-09-21 00:03:25 +00006132
6133 // If we're actually at the argument expression (rather than prior to the
6134 // selector), we're actually performing code completion for an expression.
6135 // Determine whether we have a single, best method. If so, we can
6136 // code-complete the expression using the corresponding parameter type as
6137 // our preferred type, improving completion results.
6138 if (AtArgumentExpression) {
6139 QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006140 SelIdents.size());
Douglas Gregor74661272010-09-21 00:03:25 +00006141 if (PreferredType.isNull())
6142 CodeCompleteOrdinaryName(S, PCC_Expression);
6143 else
6144 CodeCompleteExpression(S, PreferredType);
6145 return;
6146 }
6147
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006148 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor63745d52011-07-21 01:05:26 +00006149 Results.getCompletionContext(),
Douglas Gregor6fc04132010-08-27 15:10:57 +00006150 Results.data(), Results.size());
Steve Naroffeae65032009-11-07 02:08:14 +00006151}
6152
Richard Trieu2bd04012011-09-09 02:00:50 +00006153void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006154 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006155 bool AtArgumentExpression,
Douglas Gregor392a84b2010-10-13 21:24:53 +00006156 ObjCInterfaceDecl *Super) {
John McCall276321a2010-08-25 06:19:51 +00006157 typedef CodeCompletionResult Result;
Steve Naroffeae65032009-11-07 02:08:14 +00006158
6159 Expr *RecExpr = static_cast<Expr *>(Receiver);
Steve Naroffeae65032009-11-07 02:08:14 +00006160
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006161 // If necessary, apply function/array conversion to the receiver.
6162 // C99 6.7.5.3p[7,8].
John Wiegley01296292011-04-08 18:41:53 +00006163 if (RecExpr) {
6164 ExprResult Conv = DefaultFunctionArrayLvalueConversion(RecExpr);
6165 if (Conv.isInvalid()) // conversion failed. bail.
6166 return;
Nikola Smiljanic01a75982014-05-29 10:55:11 +00006167 RecExpr = Conv.get();
John Wiegley01296292011-04-08 18:41:53 +00006168 }
Douglas Gregor392a84b2010-10-13 21:24:53 +00006169 QualType ReceiverType = RecExpr? RecExpr->getType()
6170 : Super? Context.getObjCObjectPointerType(
6171 Context.getObjCInterfaceType(Super))
6172 : Context.getObjCIdType();
Steve Naroffeae65032009-11-07 02:08:14 +00006173
Douglas Gregordc520b02010-11-08 21:12:30 +00006174 // If we're messaging an expression with type "id" or "Class", check
6175 // whether we know something special about the receiver that allows
6176 // us to assume a more-specific receiver type.
Anders Carlsson382ba412014-02-28 19:07:22 +00006177 if (ReceiverType->isObjCIdType() || ReceiverType->isObjCClassType()) {
Douglas Gregordc520b02010-11-08 21:12:30 +00006178 if (ObjCInterfaceDecl *IFace = GetAssumedMessageSendExprType(RecExpr)) {
6179 if (ReceiverType->isObjCClassType())
6180 return CodeCompleteObjCClassMessage(S,
6181 ParsedType::make(Context.getObjCInterfaceType(IFace)),
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006182 SelIdents,
Douglas Gregordc520b02010-11-08 21:12:30 +00006183 AtArgumentExpression, Super);
6184
6185 ReceiverType = Context.getObjCObjectPointerType(
6186 Context.getObjCInterfaceType(IFace));
6187 }
Anders Carlsson382ba412014-02-28 19:07:22 +00006188 } else if (RecExpr && getLangOpts().CPlusPlus) {
6189 ExprResult Conv = PerformContextuallyConvertToObjCPointer(RecExpr);
6190 if (Conv.isUsable()) {
Nikola Smiljanic01a75982014-05-29 10:55:11 +00006191 RecExpr = Conv.get();
Anders Carlsson382ba412014-02-28 19:07:22 +00006192 ReceiverType = RecExpr->getType();
6193 }
6194 }
Douglas Gregordc520b02010-11-08 21:12:30 +00006195
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006196 // Build the set of methods we can see.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006197 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006198 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor63745d52011-07-21 01:05:26 +00006199 CodeCompletionContext(CodeCompletionContext::CCC_ObjCInstanceMessage,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006200 ReceiverType, SelIdents));
Douglas Gregor63745d52011-07-21 01:05:26 +00006201
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006202 Results.EnterNewScope();
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006203
Douglas Gregor6fc04132010-08-27 15:10:57 +00006204 // If this is a send-to-super, try to add the special "super" send
6205 // completion.
Douglas Gregor392a84b2010-10-13 21:24:53 +00006206 if (Super) {
Douglas Gregor6fc04132010-08-27 15:10:57 +00006207 if (ObjCMethodDecl *SuperMethod
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006208 = AddSuperSendCompletion(*this, false, SelIdents, Results))
Douglas Gregor6fc04132010-08-27 15:10:57 +00006209 Results.Ignore(SuperMethod);
6210 }
6211
Douglas Gregorc2cb2e22010-08-27 15:29:55 +00006212 // If we're inside an Objective-C method definition, prefer its selector to
6213 // others.
6214 if (ObjCMethodDecl *CurMethod = getCurMethodDecl())
6215 Results.setPreferredSelector(CurMethod->getSelector());
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006216
Douglas Gregor1154e272010-09-16 16:06:31 +00006217 // Keep track of the selectors we've already added.
6218 VisitedSelectorSet Selectors;
6219
Douglas Gregora3329fa2009-11-18 00:06:18 +00006220 // Handle messages to Class. This really isn't a message to an instance
6221 // method, so we treat it the same way we would treat a message send to a
6222 // class method.
6223 if (ReceiverType->isObjCClassType() ||
6224 ReceiverType->isObjCQualifiedClassType()) {
6225 if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
6226 if (ObjCInterfaceDecl *ClassDecl = CurMethod->getClassInterface())
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006227 AddObjCMethods(ClassDecl, false, MK_Any, SelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00006228 CurContext, Selectors, AtArgumentExpression, Results);
Douglas Gregora3329fa2009-11-18 00:06:18 +00006229 }
6230 }
6231 // Handle messages to a qualified ID ("id<foo>").
6232 else if (const ObjCObjectPointerType *QualID
6233 = ReceiverType->getAsObjCQualifiedIdType()) {
6234 // Search protocols for instance methods.
Aaron Ballman83731462014-03-17 16:14:00 +00006235 for (auto *I : QualID->quals())
6236 AddObjCMethods(I, true, MK_Any, SelIdents, CurContext,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00006237 Selectors, AtArgumentExpression, Results);
Douglas Gregora3329fa2009-11-18 00:06:18 +00006238 }
6239 // Handle messages to a pointer to interface type.
6240 else if (const ObjCObjectPointerType *IFacePtr
6241 = ReceiverType->getAsObjCInterfacePointerType()) {
6242 // Search the class, its superclasses, etc., for instance methods.
Douglas Gregorc8537c52009-11-19 07:41:15 +00006243 AddObjCMethods(IFacePtr->getInterfaceDecl(), true, MK_Any, SelIdents,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006244 CurContext, Selectors, AtArgumentExpression,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00006245 Results);
Douglas Gregora3329fa2009-11-18 00:06:18 +00006246
6247 // Search protocols for instance methods.
Aaron Ballman83731462014-03-17 16:14:00 +00006248 for (auto *I : IFacePtr->quals())
6249 AddObjCMethods(I, true, MK_Any, SelIdents, CurContext,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00006250 Selectors, AtArgumentExpression, Results);
Douglas Gregora3329fa2009-11-18 00:06:18 +00006251 }
Douglas Gregor6285f752010-04-06 16:40:00 +00006252 // Handle messages to "id".
6253 else if (ReceiverType->isObjCIdType()) {
Douglas Gregord720daf2010-04-06 17:30:22 +00006254 // We're messaging "id", so provide all instance methods we know
6255 // about as code-completion results.
6256
6257 // If we have an external source, load the entire class method
Sebastian Redld44cd6a2010-08-18 23:57:06 +00006258 // pool from the AST file.
Douglas Gregord720daf2010-04-06 17:30:22 +00006259 if (ExternalSource) {
John McCall75b960e2010-06-01 09:23:16 +00006260 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
6261 I != N; ++I) {
6262 Selector Sel = ExternalSource->GetExternalSelector(I);
Sebastian Redl75d8a322010-08-02 23:18:59 +00006263 if (Sel.isNull() || MethodPool.count(Sel))
Douglas Gregord720daf2010-04-06 17:30:22 +00006264 continue;
6265
Sebastian Redl75d8a322010-08-02 23:18:59 +00006266 ReadMethodPool(Sel);
Douglas Gregord720daf2010-04-06 17:30:22 +00006267 }
6268 }
6269
Sebastian Redl75d8a322010-08-02 23:18:59 +00006270 for (GlobalMethodPool::iterator M = MethodPool.begin(),
6271 MEnd = MethodPool.end();
6272 M != MEnd; ++M) {
6273 for (ObjCMethodList *MethList = &M->second.first;
Nico Weber2e0c8f72014-12-27 03:58:08 +00006274 MethList && MethList->getMethod();
Argyrios Kyrtzidisd3da6e02013-04-17 00:08:58 +00006275 MethList = MethList->getNext()) {
Nico Weber2e0c8f72014-12-27 03:58:08 +00006276 if (!isAcceptableObjCMethod(MethList->getMethod(), MK_Any, SelIdents))
Douglas Gregor6285f752010-04-06 16:40:00 +00006277 continue;
Douglas Gregor1154e272010-09-16 16:06:31 +00006278
Nico Weber2e0c8f72014-12-27 03:58:08 +00006279 if (!Selectors.insert(MethList->getMethod()->getSelector()).second)
Douglas Gregor1154e272010-09-16 16:06:31 +00006280 continue;
Craig Topperc3ec1492014-05-26 06:22:03 +00006281
Nico Weber2e0c8f72014-12-27 03:58:08 +00006282 Result R(MethList->getMethod(),
6283 Results.getBasePriority(MethList->getMethod()), nullptr);
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006284 R.StartParameter = SelIdents.size();
Douglas Gregor6285f752010-04-06 16:40:00 +00006285 R.AllParametersAreInformative = false;
6286 Results.MaybeAddResult(R, CurContext);
6287 }
6288 }
6289 }
Steve Naroffeae65032009-11-07 02:08:14 +00006290 Results.ExitScope();
Douglas Gregor74661272010-09-21 00:03:25 +00006291
6292
6293 // If we're actually at the argument expression (rather than prior to the
6294 // selector), we're actually performing code completion for an expression.
6295 // Determine whether we have a single, best method. If so, we can
6296 // code-complete the expression using the corresponding parameter type as
6297 // our preferred type, improving completion results.
6298 if (AtArgumentExpression) {
6299 QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006300 SelIdents.size());
Douglas Gregor74661272010-09-21 00:03:25 +00006301 if (PreferredType.isNull())
6302 CodeCompleteOrdinaryName(S, PCC_Expression);
6303 else
6304 CodeCompleteExpression(S, PreferredType);
6305 return;
6306 }
6307
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006308 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor63745d52011-07-21 01:05:26 +00006309 Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006310 Results.data(),Results.size());
Steve Naroffeae65032009-11-07 02:08:14 +00006311}
Douglas Gregorbaf69612009-11-18 04:19:12 +00006312
Douglas Gregor68762e72010-08-23 21:17:50 +00006313void Sema::CodeCompleteObjCForCollection(Scope *S,
6314 DeclGroupPtrTy IterationVar) {
6315 CodeCompleteExpressionData Data;
6316 Data.ObjCCollection = true;
6317
6318 if (IterationVar.getAsOpaquePtr()) {
Serge Pavlov9ddb76e2013-08-27 13:15:56 +00006319 DeclGroupRef DG = IterationVar.get();
Douglas Gregor68762e72010-08-23 21:17:50 +00006320 for (DeclGroupRef::iterator I = DG.begin(), End = DG.end(); I != End; ++I) {
6321 if (*I)
6322 Data.IgnoreDecls.push_back(*I);
6323 }
6324 }
6325
6326 CodeCompleteExpression(S, Data);
6327}
6328
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006329void Sema::CodeCompleteObjCSelector(Scope *S,
6330 ArrayRef<IdentifierInfo *> SelIdents) {
Douglas Gregor67c692c2010-08-26 15:07:07 +00006331 // If we have an external source, load the entire class method
6332 // pool from the AST file.
6333 if (ExternalSource) {
6334 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
6335 I != N; ++I) {
6336 Selector Sel = ExternalSource->GetExternalSelector(I);
6337 if (Sel.isNull() || MethodPool.count(Sel))
6338 continue;
6339
6340 ReadMethodPool(Sel);
6341 }
6342 }
6343
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006344 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006345 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006346 CodeCompletionContext::CCC_SelectorName);
Douglas Gregor67c692c2010-08-26 15:07:07 +00006347 Results.EnterNewScope();
6348 for (GlobalMethodPool::iterator M = MethodPool.begin(),
6349 MEnd = MethodPool.end();
6350 M != MEnd; ++M) {
6351
6352 Selector Sel = M->first;
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006353 if (!isAcceptableObjCSelector(Sel, MK_Any, SelIdents))
Douglas Gregor67c692c2010-08-26 15:07:07 +00006354 continue;
6355
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006356 CodeCompletionBuilder Builder(Results.getAllocator(),
6357 Results.getCodeCompletionTUInfo());
Douglas Gregor67c692c2010-08-26 15:07:07 +00006358 if (Sel.isUnarySelector()) {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00006359 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00006360 Sel.getNameForSlot(0)));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006361 Results.AddResult(Builder.TakeString());
Douglas Gregor67c692c2010-08-26 15:07:07 +00006362 continue;
6363 }
6364
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00006365 std::string Accumulator;
Douglas Gregor67c692c2010-08-26 15:07:07 +00006366 for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I) {
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006367 if (I == SelIdents.size()) {
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00006368 if (!Accumulator.empty()) {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00006369 Builder.AddInformativeChunk(Builder.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006370 Accumulator));
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00006371 Accumulator.clear();
6372 }
6373 }
6374
Benjamin Kramer632500c2011-07-26 16:59:25 +00006375 Accumulator += Sel.getNameForSlot(I);
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00006376 Accumulator += ':';
Douglas Gregor67c692c2010-08-26 15:07:07 +00006377 }
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00006378 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString( Accumulator));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006379 Results.AddResult(Builder.TakeString());
Douglas Gregor67c692c2010-08-26 15:07:07 +00006380 }
6381 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00006382
6383 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor67c692c2010-08-26 15:07:07 +00006384 Results.data(), Results.size());
6385}
6386
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006387/// Add all of the protocol declarations that we find in the given
Douglas Gregorbaf69612009-11-18 04:19:12 +00006388/// (translation unit) context.
6389static void AddProtocolResults(DeclContext *Ctx, DeclContext *CurContext,
Douglas Gregor5b4671c2009-11-18 04:49:41 +00006390 bool OnlyForwardDeclarations,
Douglas Gregorbaf69612009-11-18 04:19:12 +00006391 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00006392 typedef CodeCompletionResult Result;
Douglas Gregorbaf69612009-11-18 04:19:12 +00006393
Aaron Ballman629afae2014-03-07 19:56:05 +00006394 for (const auto *D : Ctx->decls()) {
Douglas Gregorbaf69612009-11-18 04:19:12 +00006395 // Record any protocols we find.
Aaron Ballman629afae2014-03-07 19:56:05 +00006396 if (const auto *Proto = dyn_cast<ObjCProtocolDecl>(D))
Douglas Gregore6e48b12012-01-01 19:29:29 +00006397 if (!OnlyForwardDeclarations || !Proto->hasDefinition())
Craig Topperc3ec1492014-05-26 06:22:03 +00006398 Results.AddResult(Result(Proto, Results.getBasePriority(Proto),nullptr),
6399 CurContext, nullptr, false);
Douglas Gregorbaf69612009-11-18 04:19:12 +00006400 }
6401}
6402
Craig Topper883dd332015-12-24 23:58:11 +00006403void Sema::CodeCompleteObjCProtocolReferences(
6404 ArrayRef<IdentifierLocPair> Protocols) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006405 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006406 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006407 CodeCompletionContext::CCC_ObjCProtocolName);
Douglas Gregorbaf69612009-11-18 04:19:12 +00006408
Chandler Carruthede11632016-11-04 06:06:50 +00006409 if (CodeCompleter->includeGlobals()) {
Douglas Gregora3b23b02010-12-09 21:44:02 +00006410 Results.EnterNewScope();
6411
6412 // Tell the result set to ignore all of the protocols we have
6413 // already seen.
6414 // FIXME: This doesn't work when caching code-completion results.
Craig Topper883dd332015-12-24 23:58:11 +00006415 for (const IdentifierLocPair &Pair : Protocols)
6416 if (ObjCProtocolDecl *Protocol = LookupProtocol(Pair.first,
6417 Pair.second))
Douglas Gregora3b23b02010-12-09 21:44:02 +00006418 Results.Ignore(Protocol);
Douglas Gregorbaf69612009-11-18 04:19:12 +00006419
Douglas Gregora3b23b02010-12-09 21:44:02 +00006420 // Add all protocols.
6421 AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, false,
6422 Results);
Douglas Gregor5b4671c2009-11-18 04:49:41 +00006423
Douglas Gregora3b23b02010-12-09 21:44:02 +00006424 Results.ExitScope();
6425 }
Eric Liuf5ba09f2018-07-04 10:01:18 +00006426
6427 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6428 Results.data(), Results.size());
Douglas Gregor5b4671c2009-11-18 04:49:41 +00006429}
6430
6431void Sema::CodeCompleteObjCProtocolDecl(Scope *) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006432 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006433 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006434 CodeCompletionContext::CCC_ObjCProtocolName);
Douglas Gregor5b4671c2009-11-18 04:49:41 +00006435
Chandler Carruthede11632016-11-04 06:06:50 +00006436 if (CodeCompleter->includeGlobals()) {
Douglas Gregora3b23b02010-12-09 21:44:02 +00006437 Results.EnterNewScope();
6438
6439 // Add all protocols.
6440 AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, true,
6441 Results);
Douglas Gregorbaf69612009-11-18 04:19:12 +00006442
Douglas Gregora3b23b02010-12-09 21:44:02 +00006443 Results.ExitScope();
6444 }
Eric Liuf5ba09f2018-07-04 10:01:18 +00006445
6446 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6447 Results.data(), Results.size());
Douglas Gregorbaf69612009-11-18 04:19:12 +00006448}
Douglas Gregor49c22a72009-11-18 16:26:39 +00006449
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006450/// Add all of the Objective-C interface declarations that we find in
Douglas Gregor49c22a72009-11-18 16:26:39 +00006451/// the given (translation unit) context.
6452static void AddInterfaceResults(DeclContext *Ctx, DeclContext *CurContext,
6453 bool OnlyForwardDeclarations,
6454 bool OnlyUnimplemented,
6455 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00006456 typedef CodeCompletionResult Result;
Douglas Gregor49c22a72009-11-18 16:26:39 +00006457
Aaron Ballman629afae2014-03-07 19:56:05 +00006458 for (const auto *D : Ctx->decls()) {
Douglas Gregor1c283312010-08-11 12:19:30 +00006459 // Record any interfaces we find.
Aaron Ballman629afae2014-03-07 19:56:05 +00006460 if (const auto *Class = dyn_cast<ObjCInterfaceDecl>(D))
Douglas Gregordc9166c2011-12-15 20:29:51 +00006461 if ((!OnlyForwardDeclarations || !Class->hasDefinition()) &&
Douglas Gregor1c283312010-08-11 12:19:30 +00006462 (!OnlyUnimplemented || !Class->getImplementation()))
Craig Topperc3ec1492014-05-26 06:22:03 +00006463 Results.AddResult(Result(Class, Results.getBasePriority(Class),nullptr),
6464 CurContext, nullptr, false);
Douglas Gregor49c22a72009-11-18 16:26:39 +00006465 }
6466}
6467
Eric Liuf5ba09f2018-07-04 10:01:18 +00006468void Sema::CodeCompleteObjCInterfaceDecl(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006469 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006470 CodeCompleter->getCodeCompletionTUInfo(),
Eric Liuf5ba09f2018-07-04 10:01:18 +00006471 CodeCompletionContext::CCC_ObjCInterfaceName);
Douglas Gregor49c22a72009-11-18 16:26:39 +00006472 Results.EnterNewScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00006473
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006474 if (CodeCompleter->includeGlobals()) {
6475 // Add all classes.
6476 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
6477 false, Results);
6478 }
6479
Douglas Gregor49c22a72009-11-18 16:26:39 +00006480 Results.ExitScope();
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006481
Eric Liuf5ba09f2018-07-04 10:01:18 +00006482 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6483 Results.data(), Results.size());
Douglas Gregor49c22a72009-11-18 16:26:39 +00006484}
6485
Douglas Gregorb2ccf012010-04-15 22:33:43 +00006486void Sema::CodeCompleteObjCSuperclass(Scope *S, IdentifierInfo *ClassName,
6487 SourceLocation ClassNameLoc) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006488 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006489 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006490 CodeCompletionContext::CCC_ObjCInterfaceName);
Douglas Gregor49c22a72009-11-18 16:26:39 +00006491 Results.EnterNewScope();
6492
6493 // Make sure that we ignore the class we're currently defining.
6494 NamedDecl *CurClass
Douglas Gregorb2ccf012010-04-15 22:33:43 +00006495 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006496 if (CurClass && isa<ObjCInterfaceDecl>(CurClass))
Douglas Gregor49c22a72009-11-18 16:26:39 +00006497 Results.Ignore(CurClass);
6498
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006499 if (CodeCompleter->includeGlobals()) {
6500 // Add all classes.
6501 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
6502 false, Results);
6503 }
6504
Douglas Gregor49c22a72009-11-18 16:26:39 +00006505 Results.ExitScope();
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006506
Eric Liuf5ba09f2018-07-04 10:01:18 +00006507 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6508 Results.data(), Results.size());
Douglas Gregor49c22a72009-11-18 16:26:39 +00006509}
6510
Eric Liuf5ba09f2018-07-04 10:01:18 +00006511void Sema::CodeCompleteObjCImplementationDecl(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006512 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006513 CodeCompleter->getCodeCompletionTUInfo(),
Eric Liuf5ba09f2018-07-04 10:01:18 +00006514 CodeCompletionContext::CCC_ObjCImplementation);
Douglas Gregor49c22a72009-11-18 16:26:39 +00006515 Results.EnterNewScope();
6516
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006517 if (CodeCompleter->includeGlobals()) {
6518 // Add all unimplemented classes.
6519 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
6520 true, Results);
6521 }
6522
Douglas Gregor49c22a72009-11-18 16:26:39 +00006523 Results.ExitScope();
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006524
Eric Liuf5ba09f2018-07-04 10:01:18 +00006525 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6526 Results.data(), Results.size());
Douglas Gregor49c22a72009-11-18 16:26:39 +00006527}
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006528
6529void Sema::CodeCompleteObjCInterfaceCategory(Scope *S,
Douglas Gregorb2ccf012010-04-15 22:33:43 +00006530 IdentifierInfo *ClassName,
6531 SourceLocation ClassNameLoc) {
John McCall276321a2010-08-25 06:19:51 +00006532 typedef CodeCompletionResult Result;
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006533
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006534 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006535 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor21325842011-07-07 16:03:39 +00006536 CodeCompletionContext::CCC_ObjCCategoryName);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006537
6538 // Ignore any categories we find that have already been implemented by this
6539 // interface.
6540 llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
6541 NamedDecl *CurClass
Douglas Gregorb2ccf012010-04-15 22:33:43 +00006542 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006543 if (ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass)){
Aaron Ballman3fe486a2014-03-13 21:23:55 +00006544 for (const auto *Cat : Class->visible_categories())
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006545 CategoryNames.insert(Cat->getIdentifier());
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006546 }
6547
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006548 // Add all of the categories we know about.
6549 Results.EnterNewScope();
6550 TranslationUnitDecl *TU = Context.getTranslationUnitDecl();
Aaron Ballman629afae2014-03-07 19:56:05 +00006551 for (const auto *D : TU->decls())
6552 if (const auto *Category = dyn_cast<ObjCCategoryDecl>(D))
David Blaikie82e95a32014-11-19 07:49:47 +00006553 if (CategoryNames.insert(Category->getIdentifier()).second)
Craig Topperc3ec1492014-05-26 06:22:03 +00006554 Results.AddResult(Result(Category, Results.getBasePriority(Category),
6555 nullptr),
6556 CurContext, nullptr, false);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006557 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00006558
6559 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6560 Results.data(), Results.size());
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006561}
6562
6563void Sema::CodeCompleteObjCImplementationCategory(Scope *S,
Douglas Gregorb2ccf012010-04-15 22:33:43 +00006564 IdentifierInfo *ClassName,
6565 SourceLocation ClassNameLoc) {
John McCall276321a2010-08-25 06:19:51 +00006566 typedef CodeCompletionResult Result;
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006567
6568 // Find the corresponding interface. If we couldn't find the interface, the
6569 // program itself is ill-formed. However, we'll try to be helpful still by
6570 // providing the list of all of the categories we know about.
6571 NamedDecl *CurClass
Douglas Gregorb2ccf012010-04-15 22:33:43 +00006572 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006573 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass);
6574 if (!Class)
Douglas Gregorb2ccf012010-04-15 22:33:43 +00006575 return CodeCompleteObjCInterfaceCategory(S, ClassName, ClassNameLoc);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006576
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006577 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006578 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor21325842011-07-07 16:03:39 +00006579 CodeCompletionContext::CCC_ObjCCategoryName);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006580
6581 // Add all of the categories that have have corresponding interface
6582 // declarations in this class and any of its superclasses, except for
6583 // already-implemented categories in the class itself.
6584 llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
6585 Results.EnterNewScope();
6586 bool IgnoreImplemented = true;
6587 while (Class) {
Aaron Ballman3fe486a2014-03-13 21:23:55 +00006588 for (const auto *Cat : Class->visible_categories()) {
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006589 if ((!IgnoreImplemented || !Cat->getImplementation()) &&
David Blaikie82e95a32014-11-19 07:49:47 +00006590 CategoryNames.insert(Cat->getIdentifier()).second)
Craig Topperc3ec1492014-05-26 06:22:03 +00006591 Results.AddResult(Result(Cat, Results.getBasePriority(Cat), nullptr),
6592 CurContext, nullptr, false);
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006593 }
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006594
6595 Class = Class->getSuperClass();
6596 IgnoreImplemented = false;
6597 }
6598 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00006599
6600 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6601 Results.data(), Results.size());
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006602}
Douglas Gregor5d649882009-11-18 22:32:06 +00006603
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00006604void Sema::CodeCompleteObjCPropertyDefinition(Scope *S) {
Douglas Gregorc3425b12015-07-07 06:20:19 +00006605 CodeCompletionContext CCContext(CodeCompletionContext::CCC_Other);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006606 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006607 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorc3425b12015-07-07 06:20:19 +00006608 CCContext);
Douglas Gregor5d649882009-11-18 22:32:06 +00006609
6610 // Figure out where this @synthesize lives.
6611 ObjCContainerDecl *Container
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00006612 = dyn_cast_or_null<ObjCContainerDecl>(CurContext);
Douglas Gregor5d649882009-11-18 22:32:06 +00006613 if (!Container ||
6614 (!isa<ObjCImplementationDecl>(Container) &&
6615 !isa<ObjCCategoryImplDecl>(Container)))
6616 return;
6617
6618 // Ignore any properties that have already been implemented.
Douglas Gregor9b4f3702012-06-12 13:44:08 +00006619 Container = getContainerDef(Container);
Aaron Ballman629afae2014-03-07 19:56:05 +00006620 for (const auto *D : Container->decls())
6621 if (const auto *PropertyImpl = dyn_cast<ObjCPropertyImplDecl>(D))
Douglas Gregor5d649882009-11-18 22:32:06 +00006622 Results.Ignore(PropertyImpl->getPropertyDecl());
6623
6624 // Add any properties that we find.
Douglas Gregorb888acf2010-12-09 23:01:55 +00006625 AddedPropertiesSet AddedProperties;
Douglas Gregor5d649882009-11-18 22:32:06 +00006626 Results.EnterNewScope();
6627 if (ObjCImplementationDecl *ClassImpl
6628 = dyn_cast<ObjCImplementationDecl>(Container))
Douglas Gregorc3425b12015-07-07 06:20:19 +00006629 AddObjCProperties(CCContext, ClassImpl->getClassInterface(), false,
Douglas Gregor95147142011-05-05 15:50:42 +00006630 /*AllowNullaryMethods=*/false, CurContext,
Douglas Gregorb888acf2010-12-09 23:01:55 +00006631 AddedProperties, Results);
Douglas Gregor5d649882009-11-18 22:32:06 +00006632 else
Douglas Gregorc3425b12015-07-07 06:20:19 +00006633 AddObjCProperties(CCContext,
6634 cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl(),
Douglas Gregor95147142011-05-05 15:50:42 +00006635 false, /*AllowNullaryMethods=*/false, CurContext,
6636 AddedProperties, Results);
Douglas Gregor5d649882009-11-18 22:32:06 +00006637 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00006638
6639 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6640 Results.data(), Results.size());
Douglas Gregor5d649882009-11-18 22:32:06 +00006641}
6642
6643void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S,
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00006644 IdentifierInfo *PropertyName) {
John McCall276321a2010-08-25 06:19:51 +00006645 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006646 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006647 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006648 CodeCompletionContext::CCC_Other);
Douglas Gregor5d649882009-11-18 22:32:06 +00006649
6650 // Figure out where this @synthesize lives.
6651 ObjCContainerDecl *Container
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00006652 = dyn_cast_or_null<ObjCContainerDecl>(CurContext);
Douglas Gregor5d649882009-11-18 22:32:06 +00006653 if (!Container ||
6654 (!isa<ObjCImplementationDecl>(Container) &&
6655 !isa<ObjCCategoryImplDecl>(Container)))
6656 return;
6657
6658 // Figure out which interface we're looking into.
Craig Topperc3ec1492014-05-26 06:22:03 +00006659 ObjCInterfaceDecl *Class = nullptr;
Douglas Gregor5d649882009-11-18 22:32:06 +00006660 if (ObjCImplementationDecl *ClassImpl
Manman Ren5b786402016-01-28 18:49:28 +00006661 = dyn_cast<ObjCImplementationDecl>(Container))
Douglas Gregor5d649882009-11-18 22:32:06 +00006662 Class = ClassImpl->getClassInterface();
6663 else
6664 Class = cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl()
6665 ->getClassInterface();
6666
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006667 // Determine the type of the property we're synthesizing.
6668 QualType PropertyType = Context.getObjCIdType();
6669 if (Class) {
Manman Ren5b786402016-01-28 18:49:28 +00006670 if (ObjCPropertyDecl *Property = Class->FindPropertyDeclaration(
6671 PropertyName, ObjCPropertyQueryKind::OBJC_PR_query_instance)) {
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006672 PropertyType
6673 = Property->getType().getNonReferenceType().getUnqualifiedType();
6674
6675 // Give preference to ivars
6676 Results.setPreferredType(PropertyType);
6677 }
6678 }
6679
Douglas Gregor5d649882009-11-18 22:32:06 +00006680 // Add all of the instance variables in this class and its superclasses.
6681 Results.EnterNewScope();
Douglas Gregor331faa02011-04-18 14:13:53 +00006682 bool SawSimilarlyNamedIvar = false;
6683 std::string NameWithPrefix;
6684 NameWithPrefix += '_';
Benjamin Kramer632500c2011-07-26 16:59:25 +00006685 NameWithPrefix += PropertyName->getName();
Douglas Gregor331faa02011-04-18 14:13:53 +00006686 std::string NameWithSuffix = PropertyName->getName().str();
6687 NameWithSuffix += '_';
Douglas Gregor5d649882009-11-18 22:32:06 +00006688 for(; Class; Class = Class->getSuperClass()) {
Douglas Gregor331faa02011-04-18 14:13:53 +00006689 for (ObjCIvarDecl *Ivar = Class->all_declared_ivar_begin(); Ivar;
6690 Ivar = Ivar->getNextIvar()) {
Craig Topperc3ec1492014-05-26 06:22:03 +00006691 Results.AddResult(Result(Ivar, Results.getBasePriority(Ivar), nullptr),
6692 CurContext, nullptr, false);
6693
Douglas Gregor331faa02011-04-18 14:13:53 +00006694 // Determine whether we've seen an ivar with a name similar to the
6695 // property.
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006696 if ((PropertyName == Ivar->getIdentifier() ||
Douglas Gregor331faa02011-04-18 14:13:53 +00006697 NameWithPrefix == Ivar->getName() ||
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006698 NameWithSuffix == Ivar->getName())) {
Douglas Gregor331faa02011-04-18 14:13:53 +00006699 SawSimilarlyNamedIvar = true;
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006700
6701 // Reduce the priority of this result by one, to give it a slight
6702 // advantage over other results whose names don't match so closely.
6703 if (Results.size() &&
6704 Results.data()[Results.size() - 1].Kind
6705 == CodeCompletionResult::RK_Declaration &&
6706 Results.data()[Results.size() - 1].Declaration == Ivar)
6707 Results.data()[Results.size() - 1].Priority--;
6708 }
Douglas Gregor331faa02011-04-18 14:13:53 +00006709 }
Douglas Gregor5d649882009-11-18 22:32:06 +00006710 }
Douglas Gregor331faa02011-04-18 14:13:53 +00006711
6712 if (!SawSimilarlyNamedIvar) {
6713 // Create ivar result _propName, that the user can use to synthesize
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006714 // an ivar of the appropriate type.
6715 unsigned Priority = CCP_MemberDeclaration + 1;
Douglas Gregor331faa02011-04-18 14:13:53 +00006716 typedef CodeCompletionResult Result;
6717 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006718 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo(),
6719 Priority,CXAvailability_Available);
Douglas Gregor331faa02011-04-18 14:13:53 +00006720
Douglas Gregor75acd922011-09-27 23:30:47 +00006721 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006722 Builder.AddResultTypeChunk(GetCompletionTypeString(PropertyType, Context,
Douglas Gregor75acd922011-09-27 23:30:47 +00006723 Policy, Allocator));
Douglas Gregor331faa02011-04-18 14:13:53 +00006724 Builder.AddTypedTextChunk(Allocator.CopyString(NameWithPrefix));
6725 Results.AddResult(Result(Builder.TakeString(), Priority,
6726 CXCursor_ObjCIvarDecl));
6727 }
6728
Douglas Gregor5d649882009-11-18 22:32:06 +00006729 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00006730
6731 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6732 Results.data(), Results.size());
Douglas Gregor5d649882009-11-18 22:32:06 +00006733}
Douglas Gregor636a61e2010-04-07 00:21:17 +00006734
Douglas Gregor416b5752010-08-25 01:08:01 +00006735// Mapping from selectors to the methods that implement that selector, along
6736// with the "in original class" flag.
Benjamin Kramereb8c4462013-06-29 17:52:13 +00006737typedef llvm::DenseMap<
6738 Selector, llvm::PointerIntPair<ObjCMethodDecl *, 1, bool> > KnownMethodsMap;
Douglas Gregor636a61e2010-04-07 00:21:17 +00006739
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006740/// Find all of the methods that reside in the given container
Douglas Gregor636a61e2010-04-07 00:21:17 +00006741/// (and its superclasses, protocols, etc.) that meet the given
6742/// criteria. Insert those methods into the map of known methods,
6743/// indexed by selector so they can be easily found.
6744static void FindImplementableMethods(ASTContext &Context,
6745 ObjCContainerDecl *Container,
Alex Lorenzb8740422017-10-24 16:39:37 +00006746 Optional<bool> WantInstanceMethods,
Douglas Gregor636a61e2010-04-07 00:21:17 +00006747 QualType ReturnType,
Douglas Gregor416b5752010-08-25 01:08:01 +00006748 KnownMethodsMap &KnownMethods,
6749 bool InOriginalClass = true) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00006750 if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)) {
Douglas Gregor9b4f3702012-06-12 13:44:08 +00006751 // Make sure we have a definition; that's what we'll walk.
Douglas Gregorc0ac7d62011-12-15 05:27:12 +00006752 if (!IFace->hasDefinition())
6753 return;
Douglas Gregor9b4f3702012-06-12 13:44:08 +00006754
6755 IFace = IFace->getDefinition();
6756 Container = IFace;
Douglas Gregorc0ac7d62011-12-15 05:27:12 +00006757
Douglas Gregor636a61e2010-04-07 00:21:17 +00006758 const ObjCList<ObjCProtocolDecl> &Protocols
6759 = IFace->getReferencedProtocols();
6760 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006761 E = Protocols.end();
Douglas Gregor636a61e2010-04-07 00:21:17 +00006762 I != E; ++I)
6763 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006764 KnownMethods, InOriginalClass);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006765
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006766 // Add methods from any class extensions and categories.
Aaron Ballman3fe486a2014-03-13 21:23:55 +00006767 for (auto *Cat : IFace->visible_categories()) {
6768 FindImplementableMethods(Context, Cat, WantInstanceMethods, ReturnType,
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006769 KnownMethods, false);
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006770 }
6771
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006772 // Visit the superclass.
6773 if (IFace->getSuperClass())
6774 FindImplementableMethods(Context, IFace->getSuperClass(),
6775 WantInstanceMethods, ReturnType,
6776 KnownMethods, false);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006777 }
6778
6779 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(Container)) {
6780 // Recurse into protocols.
6781 const ObjCList<ObjCProtocolDecl> &Protocols
6782 = Category->getReferencedProtocols();
6783 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006784 E = Protocols.end();
Douglas Gregor636a61e2010-04-07 00:21:17 +00006785 I != E; ++I)
6786 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006787 KnownMethods, InOriginalClass);
6788
6789 // If this category is the original class, jump to the interface.
6790 if (InOriginalClass && Category->getClassInterface())
6791 FindImplementableMethods(Context, Category->getClassInterface(),
6792 WantInstanceMethods, ReturnType, KnownMethods,
6793 false);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006794 }
6795
6796 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Douglas Gregor9b4f3702012-06-12 13:44:08 +00006797 // Make sure we have a definition; that's what we'll walk.
6798 if (!Protocol->hasDefinition())
6799 return;
6800 Protocol = Protocol->getDefinition();
6801 Container = Protocol;
6802
6803 // Recurse into protocols.
6804 const ObjCList<ObjCProtocolDecl> &Protocols
6805 = Protocol->getReferencedProtocols();
6806 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
6807 E = Protocols.end();
6808 I != E; ++I)
6809 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
6810 KnownMethods, false);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006811 }
6812
6813 // Add methods in this container. This operation occurs last because
6814 // we want the methods from this container to override any methods
6815 // we've previously seen with the same selector.
Aaron Ballmanaff18c02014-03-13 19:03:34 +00006816 for (auto *M : Container->methods()) {
Alex Lorenzb8740422017-10-24 16:39:37 +00006817 if (!WantInstanceMethods || M->isInstanceMethod() == *WantInstanceMethods) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00006818 if (!ReturnType.isNull() &&
Alp Toker314cc812014-01-25 16:55:45 +00006819 !Context.hasSameUnqualifiedType(ReturnType, M->getReturnType()))
Douglas Gregor636a61e2010-04-07 00:21:17 +00006820 continue;
6821
Benjamin Kramereb8c4462013-06-29 17:52:13 +00006822 KnownMethods[M->getSelector()] =
Aaron Ballmanaff18c02014-03-13 19:03:34 +00006823 KnownMethodsMap::mapped_type(M, InOriginalClass);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006824 }
6825 }
6826}
6827
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006828/// Add the parenthesized return or parameter type chunk to a code
Douglas Gregor669a25a2011-02-17 00:22:45 +00006829/// completion string.
6830static void AddObjCPassingTypeChunk(QualType Type,
Douglas Gregor29979142012-04-10 18:35:07 +00006831 unsigned ObjCDeclQuals,
Douglas Gregor669a25a2011-02-17 00:22:45 +00006832 ASTContext &Context,
Douglas Gregor75acd922011-09-27 23:30:47 +00006833 const PrintingPolicy &Policy,
Douglas Gregor669a25a2011-02-17 00:22:45 +00006834 CodeCompletionBuilder &Builder) {
6835 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregor86b42682015-06-19 18:27:52 +00006836 std::string Quals = formatObjCParamQualifiers(ObjCDeclQuals, Type);
Douglas Gregor29979142012-04-10 18:35:07 +00006837 if (!Quals.empty())
6838 Builder.AddTextChunk(Builder.getAllocator().CopyString(Quals));
Douglas Gregor75acd922011-09-27 23:30:47 +00006839 Builder.AddTextChunk(GetCompletionTypeString(Type, Context, Policy,
Douglas Gregor669a25a2011-02-17 00:22:45 +00006840 Builder.getAllocator()));
6841 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6842}
6843
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006844/// Determine whether the given class is or inherits from a class by
Douglas Gregor669a25a2011-02-17 00:22:45 +00006845/// the given name.
6846static bool InheritsFromClassNamed(ObjCInterfaceDecl *Class,
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006847 StringRef Name) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006848 if (!Class)
6849 return false;
6850
6851 if (Class->getIdentifier() && Class->getIdentifier()->getName() == Name)
6852 return true;
6853
6854 return InheritsFromClassNamed(Class->getSuperClass(), Name);
6855}
6856
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006857/// Add code completions for Objective-C Key-Value Coding (KVC) and
Douglas Gregor669a25a2011-02-17 00:22:45 +00006858/// Key-Value Observing (KVO).
6859static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
6860 bool IsInstanceMethod,
6861 QualType ReturnType,
6862 ASTContext &Context,
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006863 VisitedSelectorSet &KnownSelectors,
Douglas Gregor669a25a2011-02-17 00:22:45 +00006864 ResultBuilder &Results) {
6865 IdentifierInfo *PropName = Property->getIdentifier();
6866 if (!PropName || PropName->getLength() == 0)
6867 return;
6868
Douglas Gregor75acd922011-09-27 23:30:47 +00006869 PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema());
6870
Douglas Gregor669a25a2011-02-17 00:22:45 +00006871 // Builder that will create each code completion.
6872 typedef CodeCompletionResult Result;
6873 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006874 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Douglas Gregor669a25a2011-02-17 00:22:45 +00006875
6876 // The selector table.
6877 SelectorTable &Selectors = Context.Selectors;
6878
6879 // The property name, copied into the code completion allocation region
6880 // on demand.
6881 struct KeyHolder {
6882 CodeCompletionAllocator &Allocator;
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006883 StringRef Key;
Douglas Gregor669a25a2011-02-17 00:22:45 +00006884 const char *CopiedKey;
Craig Topperc3ec1492014-05-26 06:22:03 +00006885
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006886 KeyHolder(CodeCompletionAllocator &Allocator, StringRef Key)
Craig Topperc3ec1492014-05-26 06:22:03 +00006887 : Allocator(Allocator), Key(Key), CopiedKey(nullptr) {}
6888
Douglas Gregor669a25a2011-02-17 00:22:45 +00006889 operator const char *() {
6890 if (CopiedKey)
6891 return CopiedKey;
6892
6893 return CopiedKey = Allocator.CopyString(Key);
6894 }
6895 } Key(Allocator, PropName->getName());
6896
6897 // The uppercased name of the property name.
6898 std::string UpperKey = PropName->getName();
6899 if (!UpperKey.empty())
Jordan Rose4938f272013-02-09 10:09:43 +00006900 UpperKey[0] = toUppercase(UpperKey[0]);
Douglas Gregor669a25a2011-02-17 00:22:45 +00006901
6902 bool ReturnTypeMatchesProperty = ReturnType.isNull() ||
6903 Context.hasSameUnqualifiedType(ReturnType.getNonReferenceType(),
6904 Property->getType());
6905 bool ReturnTypeMatchesVoid
6906 = ReturnType.isNull() || ReturnType->isVoidType();
6907
6908 // Add the normal accessor -(type)key.
6909 if (IsInstanceMethod &&
David Blaikie82e95a32014-11-19 07:49:47 +00006910 KnownSelectors.insert(Selectors.getNullarySelector(PropName)).second &&
Douglas Gregor669a25a2011-02-17 00:22:45 +00006911 ReturnTypeMatchesProperty && !Property->getGetterMethodDecl()) {
6912 if (ReturnType.isNull())
Douglas Gregor29979142012-04-10 18:35:07 +00006913 AddObjCPassingTypeChunk(Property->getType(), /*Quals=*/0,
6914 Context, Policy, Builder);
Douglas Gregor669a25a2011-02-17 00:22:45 +00006915
6916 Builder.AddTypedTextChunk(Key);
6917 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
6918 CXCursor_ObjCInstanceMethodDecl));
6919 }
6920
6921 // If we have an integral or boolean property (or the user has provided
6922 // an integral or boolean return type), add the accessor -(type)isKey.
6923 if (IsInstanceMethod &&
6924 ((!ReturnType.isNull() &&
6925 (ReturnType->isIntegerType() || ReturnType->isBooleanType())) ||
6926 (ReturnType.isNull() &&
6927 (Property->getType()->isIntegerType() ||
6928 Property->getType()->isBooleanType())))) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006929 std::string SelectorName = (Twine("is") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006930 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00006931 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
6932 .second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006933 if (ReturnType.isNull()) {
6934 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6935 Builder.AddTextChunk("BOOL");
6936 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6937 }
6938
6939 Builder.AddTypedTextChunk(
6940 Allocator.CopyString(SelectorId->getName()));
6941 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
6942 CXCursor_ObjCInstanceMethodDecl));
6943 }
6944 }
6945
6946 // Add the normal mutator.
6947 if (IsInstanceMethod && ReturnTypeMatchesVoid &&
6948 !Property->getSetterMethodDecl()) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006949 std::string SelectorName = (Twine("set") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006950 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00006951 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006952 if (ReturnType.isNull()) {
6953 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6954 Builder.AddTextChunk("void");
6955 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6956 }
6957
6958 Builder.AddTypedTextChunk(
6959 Allocator.CopyString(SelectorId->getName()));
6960 Builder.AddTypedTextChunk(":");
Douglas Gregor29979142012-04-10 18:35:07 +00006961 AddObjCPassingTypeChunk(Property->getType(), /*Quals=*/0,
6962 Context, Policy, Builder);
Douglas Gregor669a25a2011-02-17 00:22:45 +00006963 Builder.AddTextChunk(Key);
6964 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
6965 CXCursor_ObjCInstanceMethodDecl));
6966 }
6967 }
6968
6969 // Indexed and unordered accessors
6970 unsigned IndexedGetterPriority = CCP_CodePattern;
6971 unsigned IndexedSetterPriority = CCP_CodePattern;
6972 unsigned UnorderedGetterPriority = CCP_CodePattern;
6973 unsigned UnorderedSetterPriority = CCP_CodePattern;
6974 if (const ObjCObjectPointerType *ObjCPointer
6975 = Property->getType()->getAs<ObjCObjectPointerType>()) {
6976 if (ObjCInterfaceDecl *IFace = ObjCPointer->getInterfaceDecl()) {
6977 // If this interface type is not provably derived from a known
6978 // collection, penalize the corresponding completions.
6979 if (!InheritsFromClassNamed(IFace, "NSMutableArray")) {
6980 IndexedSetterPriority += CCD_ProbablyNotObjCCollection;
6981 if (!InheritsFromClassNamed(IFace, "NSArray"))
6982 IndexedGetterPriority += CCD_ProbablyNotObjCCollection;
6983 }
6984
6985 if (!InheritsFromClassNamed(IFace, "NSMutableSet")) {
6986 UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;
6987 if (!InheritsFromClassNamed(IFace, "NSSet"))
6988 UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;
6989 }
6990 }
6991 } else {
6992 IndexedGetterPriority += CCD_ProbablyNotObjCCollection;
6993 IndexedSetterPriority += CCD_ProbablyNotObjCCollection;
6994 UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;
6995 UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;
6996 }
6997
6998 // Add -(NSUInteger)countOf<key>
6999 if (IsInstanceMethod &&
7000 (ReturnType.isNull() || ReturnType->isIntegerType())) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007001 std::string SelectorName = (Twine("countOf") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007002 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007003 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
7004 .second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007005 if (ReturnType.isNull()) {
7006 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7007 Builder.AddTextChunk("NSUInteger");
7008 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7009 }
7010
7011 Builder.AddTypedTextChunk(
7012 Allocator.CopyString(SelectorId->getName()));
7013 Results.AddResult(Result(Builder.TakeString(),
7014 std::min(IndexedGetterPriority,
7015 UnorderedGetterPriority),
7016 CXCursor_ObjCInstanceMethodDecl));
7017 }
7018 }
7019
7020 // Indexed getters
7021 // Add -(id)objectInKeyAtIndex:(NSUInteger)index
7022 if (IsInstanceMethod &&
7023 (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007024 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007025 = (Twine("objectIn") + UpperKey + "AtIndex").str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007026 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007027 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007028 if (ReturnType.isNull()) {
7029 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7030 Builder.AddTextChunk("id");
7031 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7032 }
7033
7034 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7035 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7036 Builder.AddTextChunk("NSUInteger");
7037 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7038 Builder.AddTextChunk("index");
7039 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
7040 CXCursor_ObjCInstanceMethodDecl));
7041 }
7042 }
7043
7044 // Add -(NSArray *)keyAtIndexes:(NSIndexSet *)indexes
7045 if (IsInstanceMethod &&
7046 (ReturnType.isNull() ||
7047 (ReturnType->isObjCObjectPointerType() &&
7048 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
7049 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
7050 ->getName() == "NSArray"))) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007051 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007052 = (Twine(Property->getName()) + "AtIndexes").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("NSArray *");
7058 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7059 }
7060
7061 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7062 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7063 Builder.AddTextChunk("NSIndexSet *");
7064 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7065 Builder.AddTextChunk("indexes");
7066 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
7067 CXCursor_ObjCInstanceMethodDecl));
7068 }
7069 }
7070
7071 // Add -(void)getKey:(type **)buffer range:(NSRange)inRange
7072 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007073 std::string SelectorName = (Twine("get") + UpperKey).str();
Douglas Gregor669a25a2011-02-17 00:22:45 +00007074 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007075 &Context.Idents.get(SelectorName),
Douglas Gregor669a25a2011-02-17 00:22:45 +00007076 &Context.Idents.get("range")
7077 };
7078
David Blaikie82e95a32014-11-19 07:49:47 +00007079 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007080 if (ReturnType.isNull()) {
7081 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7082 Builder.AddTextChunk("void");
7083 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7084 }
7085
7086 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7087 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7088 Builder.AddPlaceholderChunk("object-type");
7089 Builder.AddTextChunk(" **");
7090 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7091 Builder.AddTextChunk("buffer");
7092 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7093 Builder.AddTypedTextChunk("range:");
7094 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7095 Builder.AddTextChunk("NSRange");
7096 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7097 Builder.AddTextChunk("inRange");
7098 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
7099 CXCursor_ObjCInstanceMethodDecl));
7100 }
7101 }
7102
7103 // Mutable indexed accessors
7104
7105 // - (void)insertObject:(type *)object inKeyAtIndex:(NSUInteger)index
7106 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007107 std::string SelectorName = (Twine("in") + UpperKey + "AtIndex").str();
Douglas Gregor669a25a2011-02-17 00:22:45 +00007108 IdentifierInfo *SelectorIds[2] = {
7109 &Context.Idents.get("insertObject"),
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007110 &Context.Idents.get(SelectorName)
Douglas Gregor669a25a2011-02-17 00:22:45 +00007111 };
7112
David Blaikie82e95a32014-11-19 07:49:47 +00007113 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007114 if (ReturnType.isNull()) {
7115 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7116 Builder.AddTextChunk("void");
7117 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7118 }
7119
7120 Builder.AddTypedTextChunk("insertObject:");
7121 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7122 Builder.AddPlaceholderChunk("object-type");
7123 Builder.AddTextChunk(" *");
7124 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7125 Builder.AddTextChunk("object");
7126 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7127 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7128 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7129 Builder.AddPlaceholderChunk("NSUInteger");
7130 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7131 Builder.AddTextChunk("index");
7132 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
7133 CXCursor_ObjCInstanceMethodDecl));
7134 }
7135 }
7136
7137 // - (void)insertKey:(NSArray *)array atIndexes:(NSIndexSet *)indexes
7138 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007139 std::string SelectorName = (Twine("insert") + UpperKey).str();
Douglas Gregor669a25a2011-02-17 00:22:45 +00007140 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007141 &Context.Idents.get(SelectorName),
Douglas Gregor669a25a2011-02-17 00:22:45 +00007142 &Context.Idents.get("atIndexes")
7143 };
7144
David Blaikie82e95a32014-11-19 07:49:47 +00007145 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007146 if (ReturnType.isNull()) {
7147 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7148 Builder.AddTextChunk("void");
7149 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7150 }
7151
7152 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7153 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7154 Builder.AddTextChunk("NSArray *");
7155 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7156 Builder.AddTextChunk("array");
7157 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7158 Builder.AddTypedTextChunk("atIndexes:");
7159 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7160 Builder.AddPlaceholderChunk("NSIndexSet *");
7161 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7162 Builder.AddTextChunk("indexes");
7163 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
7164 CXCursor_ObjCInstanceMethodDecl));
7165 }
7166 }
7167
7168 // -(void)removeObjectFromKeyAtIndex:(NSUInteger)index
7169 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007170 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007171 = (Twine("removeObjectFrom") + UpperKey + "AtIndex").str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007172 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007173 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007174 if (ReturnType.isNull()) {
7175 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7176 Builder.AddTextChunk("void");
7177 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7178 }
7179
7180 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7181 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7182 Builder.AddTextChunk("NSUInteger");
7183 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7184 Builder.AddTextChunk("index");
7185 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
7186 CXCursor_ObjCInstanceMethodDecl));
7187 }
7188 }
7189
7190 // -(void)removeKeyAtIndexes:(NSIndexSet *)indexes
7191 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007192 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007193 = (Twine("remove") + UpperKey + "AtIndexes").str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007194 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007195 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007196 if (ReturnType.isNull()) {
7197 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7198 Builder.AddTextChunk("void");
7199 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7200 }
7201
7202 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7203 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7204 Builder.AddTextChunk("NSIndexSet *");
7205 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7206 Builder.AddTextChunk("indexes");
7207 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
7208 CXCursor_ObjCInstanceMethodDecl));
7209 }
7210 }
7211
7212 // - (void)replaceObjectInKeyAtIndex:(NSUInteger)index withObject:(id)object
7213 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007214 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007215 = (Twine("replaceObjectIn") + UpperKey + "AtIndex").str();
Douglas Gregor669a25a2011-02-17 00:22:45 +00007216 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007217 &Context.Idents.get(SelectorName),
Douglas Gregor669a25a2011-02-17 00:22:45 +00007218 &Context.Idents.get("withObject")
7219 };
7220
David Blaikie82e95a32014-11-19 07:49:47 +00007221 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007222 if (ReturnType.isNull()) {
7223 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7224 Builder.AddTextChunk("void");
7225 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7226 }
7227
7228 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7229 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7230 Builder.AddPlaceholderChunk("NSUInteger");
7231 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7232 Builder.AddTextChunk("index");
7233 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7234 Builder.AddTypedTextChunk("withObject:");
7235 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7236 Builder.AddTextChunk("id");
7237 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7238 Builder.AddTextChunk("object");
7239 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
7240 CXCursor_ObjCInstanceMethodDecl));
7241 }
7242 }
7243
7244 // - (void)replaceKeyAtIndexes:(NSIndexSet *)indexes withKey:(NSArray *)array
7245 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007246 std::string SelectorName1
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007247 = (Twine("replace") + UpperKey + "AtIndexes").str();
7248 std::string SelectorName2 = (Twine("with") + UpperKey).str();
Douglas Gregor669a25a2011-02-17 00:22:45 +00007249 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007250 &Context.Idents.get(SelectorName1),
7251 &Context.Idents.get(SelectorName2)
Douglas Gregor669a25a2011-02-17 00:22:45 +00007252 };
7253
David Blaikie82e95a32014-11-19 07:49:47 +00007254 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007255 if (ReturnType.isNull()) {
7256 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7257 Builder.AddTextChunk("void");
7258 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7259 }
7260
7261 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName1 + ":"));
7262 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7263 Builder.AddPlaceholderChunk("NSIndexSet *");
7264 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7265 Builder.AddTextChunk("indexes");
7266 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7267 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName2 + ":"));
7268 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7269 Builder.AddTextChunk("NSArray *");
7270 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7271 Builder.AddTextChunk("array");
7272 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
7273 CXCursor_ObjCInstanceMethodDecl));
7274 }
7275 }
7276
7277 // Unordered getters
7278 // - (NSEnumerator *)enumeratorOfKey
7279 if (IsInstanceMethod &&
7280 (ReturnType.isNull() ||
7281 (ReturnType->isObjCObjectPointerType() &&
7282 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
7283 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
7284 ->getName() == "NSEnumerator"))) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007285 std::string SelectorName = (Twine("enumeratorOf") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007286 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007287 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
7288 .second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007289 if (ReturnType.isNull()) {
7290 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7291 Builder.AddTextChunk("NSEnumerator *");
7292 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7293 }
7294
7295 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
7296 Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
7297 CXCursor_ObjCInstanceMethodDecl));
7298 }
7299 }
7300
7301 // - (type *)memberOfKey:(type *)object
7302 if (IsInstanceMethod &&
7303 (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007304 std::string SelectorName = (Twine("memberOf") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007305 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007306 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007307 if (ReturnType.isNull()) {
7308 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7309 Builder.AddPlaceholderChunk("object-type");
7310 Builder.AddTextChunk(" *");
7311 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7312 }
7313
7314 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7315 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7316 if (ReturnType.isNull()) {
7317 Builder.AddPlaceholderChunk("object-type");
7318 Builder.AddTextChunk(" *");
7319 } else {
7320 Builder.AddTextChunk(GetCompletionTypeString(ReturnType, Context,
Douglas Gregor75acd922011-09-27 23:30:47 +00007321 Policy,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007322 Builder.getAllocator()));
7323 }
7324 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7325 Builder.AddTextChunk("object");
7326 Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
7327 CXCursor_ObjCInstanceMethodDecl));
7328 }
7329 }
7330
7331 // Mutable unordered accessors
7332 // - (void)addKeyObject:(type *)object
7333 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007334 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007335 = (Twine("add") + UpperKey + Twine("Object")).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007336 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007337 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007338 if (ReturnType.isNull()) {
7339 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7340 Builder.AddTextChunk("void");
7341 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7342 }
7343
7344 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7345 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7346 Builder.AddPlaceholderChunk("object-type");
7347 Builder.AddTextChunk(" *");
7348 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7349 Builder.AddTextChunk("object");
7350 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
7351 CXCursor_ObjCInstanceMethodDecl));
7352 }
7353 }
7354
7355 // - (void)addKey:(NSSet *)objects
7356 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007357 std::string SelectorName = (Twine("add") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007358 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007359 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007360 if (ReturnType.isNull()) {
7361 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7362 Builder.AddTextChunk("void");
7363 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7364 }
7365
7366 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7367 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7368 Builder.AddTextChunk("NSSet *");
7369 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7370 Builder.AddTextChunk("objects");
7371 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
7372 CXCursor_ObjCInstanceMethodDecl));
7373 }
7374 }
7375
7376 // - (void)removeKeyObject:(type *)object
7377 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007378 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007379 = (Twine("remove") + UpperKey + Twine("Object")).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007380 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007381 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007382 if (ReturnType.isNull()) {
7383 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7384 Builder.AddTextChunk("void");
7385 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7386 }
7387
7388 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7389 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7390 Builder.AddPlaceholderChunk("object-type");
7391 Builder.AddTextChunk(" *");
7392 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7393 Builder.AddTextChunk("object");
7394 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
7395 CXCursor_ObjCInstanceMethodDecl));
7396 }
7397 }
7398
7399 // - (void)removeKey:(NSSet *)objects
7400 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007401 std::string SelectorName = (Twine("remove") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007402 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007403 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007404 if (ReturnType.isNull()) {
7405 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7406 Builder.AddTextChunk("void");
7407 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7408 }
7409
7410 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7411 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7412 Builder.AddTextChunk("NSSet *");
7413 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7414 Builder.AddTextChunk("objects");
7415 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
7416 CXCursor_ObjCInstanceMethodDecl));
7417 }
7418 }
7419
7420 // - (void)intersectKey:(NSSet *)objects
7421 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007422 std::string SelectorName = (Twine("intersect") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007423 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007424 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007425 if (ReturnType.isNull()) {
7426 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7427 Builder.AddTextChunk("void");
7428 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7429 }
7430
7431 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7432 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7433 Builder.AddTextChunk("NSSet *");
7434 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7435 Builder.AddTextChunk("objects");
7436 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
7437 CXCursor_ObjCInstanceMethodDecl));
7438 }
7439 }
7440
7441 // Key-Value Observing
7442 // + (NSSet *)keyPathsForValuesAffectingKey
7443 if (!IsInstanceMethod &&
7444 (ReturnType.isNull() ||
7445 (ReturnType->isObjCObjectPointerType() &&
7446 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
7447 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
7448 ->getName() == "NSSet"))) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007449 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007450 = (Twine("keyPathsForValuesAffecting") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007451 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007452 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
7453 .second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007454 if (ReturnType.isNull()) {
7455 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Alex Lorenz71ecb072016-12-08 16:49:05 +00007456 Builder.AddTextChunk("NSSet<NSString *> *");
Douglas Gregor669a25a2011-02-17 00:22:45 +00007457 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7458 }
7459
7460 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
7461 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Douglas Gregor857bcda2011-06-02 04:02:27 +00007462 CXCursor_ObjCClassMethodDecl));
7463 }
7464 }
7465
7466 // + (BOOL)automaticallyNotifiesObserversForKey
7467 if (!IsInstanceMethod &&
7468 (ReturnType.isNull() ||
7469 ReturnType->isIntegerType() ||
7470 ReturnType->isBooleanType())) {
7471 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007472 = (Twine("automaticallyNotifiesObserversOf") + UpperKey).str();
Douglas Gregor857bcda2011-06-02 04:02:27 +00007473 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007474 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
7475 .second) {
Douglas Gregor857bcda2011-06-02 04:02:27 +00007476 if (ReturnType.isNull()) {
7477 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7478 Builder.AddTextChunk("BOOL");
7479 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7480 }
7481
7482 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
7483 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
7484 CXCursor_ObjCClassMethodDecl));
Douglas Gregor669a25a2011-02-17 00:22:45 +00007485 }
7486 }
7487}
7488
Alex Lorenzb8740422017-10-24 16:39:37 +00007489void Sema::CodeCompleteObjCMethodDecl(Scope *S, Optional<bool> IsInstanceMethod,
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00007490 ParsedType ReturnTy) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00007491 // Determine the return type of the method we're declaring, if
7492 // provided.
7493 QualType ReturnType = GetTypeFromParser(ReturnTy);
Craig Topperc3ec1492014-05-26 06:22:03 +00007494 Decl *IDecl = nullptr;
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00007495 if (CurContext->isObjCContainer()) {
7496 ObjCContainerDecl *OCD = dyn_cast<ObjCContainerDecl>(CurContext);
George Burgess IV00f70bd2018-03-01 05:43:23 +00007497 IDecl = OCD;
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00007498 }
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007499 // Determine where we should start searching for methods.
Craig Topperc3ec1492014-05-26 06:22:03 +00007500 ObjCContainerDecl *SearchDecl = nullptr;
Douglas Gregor636a61e2010-04-07 00:21:17 +00007501 bool IsInImplementation = false;
John McCall48871652010-08-21 09:40:31 +00007502 if (Decl *D = IDecl) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00007503 if (ObjCImplementationDecl *Impl = dyn_cast<ObjCImplementationDecl>(D)) {
7504 SearchDecl = Impl->getClassInterface();
Douglas Gregor636a61e2010-04-07 00:21:17 +00007505 IsInImplementation = true;
7506 } else if (ObjCCategoryImplDecl *CatImpl
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007507 = dyn_cast<ObjCCategoryImplDecl>(D)) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00007508 SearchDecl = CatImpl->getCategoryDecl();
Douglas Gregor636a61e2010-04-07 00:21:17 +00007509 IsInImplementation = true;
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007510 } else
Douglas Gregor636a61e2010-04-07 00:21:17 +00007511 SearchDecl = dyn_cast<ObjCContainerDecl>(D);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007512 }
7513
7514 if (!SearchDecl && S) {
Ted Kremenekc37877d2013-10-08 17:08:03 +00007515 if (DeclContext *DC = S->getEntity())
Douglas Gregor636a61e2010-04-07 00:21:17 +00007516 SearchDecl = dyn_cast<ObjCContainerDecl>(DC);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007517 }
7518
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007519 if (!SearchDecl) {
Douglas Gregor00c37ef2010-08-11 21:23:17 +00007520 HandleCodeCompleteResults(this, CodeCompleter,
7521 CodeCompletionContext::CCC_Other,
Craig Topperc3ec1492014-05-26 06:22:03 +00007522 nullptr, 0);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007523 return;
7524 }
7525
7526 // Find all of the methods that we could declare/implement here.
7527 KnownMethodsMap KnownMethods;
7528 FindImplementableMethods(Context, SearchDecl, IsInstanceMethod,
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007529 ReturnType, KnownMethods);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007530
Douglas Gregor636a61e2010-04-07 00:21:17 +00007531 // Add declarations or definitions for each of the known methods.
John McCall276321a2010-08-25 06:19:51 +00007532 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007533 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007534 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007535 CodeCompletionContext::CCC_Other);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007536 Results.EnterNewScope();
Douglas Gregor75acd922011-09-27 23:30:47 +00007537 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007538 for (KnownMethodsMap::iterator M = KnownMethods.begin(),
7539 MEnd = KnownMethods.end();
7540 M != MEnd; ++M) {
Benjamin Kramereb8c4462013-06-29 17:52:13 +00007541 ObjCMethodDecl *Method = M->second.getPointer();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007542 CodeCompletionBuilder Builder(Results.getAllocator(),
7543 Results.getCodeCompletionTUInfo());
Alex Lorenzb8740422017-10-24 16:39:37 +00007544
7545 // Add the '-'/'+' prefix if it wasn't provided yet.
7546 if (!IsInstanceMethod) {
7547 Builder.AddTextChunk(Method->isInstanceMethod() ? "-" : "+");
7548 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7549 }
7550
Douglas Gregor636a61e2010-04-07 00:21:17 +00007551 // If the result type was not already provided, add it to the
7552 // pattern as (type).
Argyrios Kyrtzidisf0917ab2015-07-24 17:00:19 +00007553 if (ReturnType.isNull()) {
7554 QualType ResTy = Method->getSendResultType().stripObjCKindOfType(Context);
7555 AttributedType::stripOuterNullability(ResTy);
7556 AddObjCPassingTypeChunk(ResTy,
Alp Toker314cc812014-01-25 16:55:45 +00007557 Method->getObjCDeclQualifier(), Context, Policy,
7558 Builder);
Argyrios Kyrtzidisf0917ab2015-07-24 17:00:19 +00007559 }
Douglas Gregor636a61e2010-04-07 00:21:17 +00007560
7561 Selector Sel = Method->getSelector();
7562
7563 // Add the first part of the selector to the pattern.
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00007564 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00007565 Sel.getNameForSlot(0)));
Douglas Gregor636a61e2010-04-07 00:21:17 +00007566
7567 // Add parameters to the pattern.
7568 unsigned I = 0;
7569 for (ObjCMethodDecl::param_iterator P = Method->param_begin(),
7570 PEnd = Method->param_end();
7571 P != PEnd; (void)++P, ++I) {
7572 // Add the part of the selector name.
7573 if (I == 0)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007574 Builder.AddTypedTextChunk(":");
Douglas Gregor636a61e2010-04-07 00:21:17 +00007575 else if (I < Sel.getNumArgs()) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007576 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7577 Builder.AddTypedTextChunk(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00007578 Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":"));
Douglas Gregor636a61e2010-04-07 00:21:17 +00007579 } else
7580 break;
7581
7582 // Add the parameter type.
Douglas Gregor86b42682015-06-19 18:27:52 +00007583 QualType ParamType;
7584 if ((*P)->getObjCDeclQualifier() & Decl::OBJC_TQ_CSNullability)
7585 ParamType = (*P)->getType();
7586 else
7587 ParamType = (*P)->getOriginalType();
Douglas Gregor9b7b3e92015-07-07 06:20:27 +00007588 ParamType = ParamType.substObjCTypeArgs(Context, {},
7589 ObjCSubstitutionContext::Parameter);
Argyrios Kyrtzidisf0917ab2015-07-24 17:00:19 +00007590 AttributedType::stripOuterNullability(ParamType);
Douglas Gregor86b42682015-06-19 18:27:52 +00007591 AddObjCPassingTypeChunk(ParamType,
Douglas Gregor29979142012-04-10 18:35:07 +00007592 (*P)->getObjCDeclQualifier(),
7593 Context, Policy,
Douglas Gregor75acd922011-09-27 23:30:47 +00007594 Builder);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007595
7596 if (IdentifierInfo *Id = (*P)->getIdentifier())
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00007597 Builder.AddTextChunk(Builder.getAllocator().CopyString( Id->getName()));
Douglas Gregor636a61e2010-04-07 00:21:17 +00007598 }
7599
7600 if (Method->isVariadic()) {
7601 if (Method->param_size() > 0)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007602 Builder.AddChunk(CodeCompletionString::CK_Comma);
7603 Builder.AddTextChunk("...");
Douglas Gregor400f5972010-08-31 05:13:43 +00007604 }
Douglas Gregor636a61e2010-04-07 00:21:17 +00007605
Douglas Gregord37c59d2010-05-28 00:57:46 +00007606 if (IsInImplementation && Results.includeCodePatterns()) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00007607 // We will be defining the method here, so add a compound statement.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007608 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7609 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
7610 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
Alp Toker314cc812014-01-25 16:55:45 +00007611 if (!Method->getReturnType()->isVoidType()) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00007612 // If the result type is not void, add a return clause.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007613 Builder.AddTextChunk("return");
7614 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7615 Builder.AddPlaceholderChunk("expression");
7616 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007617 } else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007618 Builder.AddPlaceholderChunk("statements");
Douglas Gregor636a61e2010-04-07 00:21:17 +00007619
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007620 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
7621 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007622 }
7623
Douglas Gregor416b5752010-08-25 01:08:01 +00007624 unsigned Priority = CCP_CodePattern;
Benjamin Kramereb8c4462013-06-29 17:52:13 +00007625 if (!M->second.getInt())
Douglas Gregor416b5752010-08-25 01:08:01 +00007626 Priority += CCD_InBaseClass;
7627
Douglas Gregor78254c82012-03-27 23:34:16 +00007628 Results.AddResult(Result(Builder.TakeString(), Method, Priority));
Douglas Gregor636a61e2010-04-07 00:21:17 +00007629 }
7630
Douglas Gregor669a25a2011-02-17 00:22:45 +00007631 // Add Key-Value-Coding and Key-Value-Observing accessor methods for all of
7632 // the properties in this class and its categories.
David Blaikiebbafb8a2012-03-11 07:00:24 +00007633 if (Context.getLangOpts().ObjC2) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007634 SmallVector<ObjCContainerDecl *, 4> Containers;
Douglas Gregor669a25a2011-02-17 00:22:45 +00007635 Containers.push_back(SearchDecl);
7636
Douglas Gregord4a8ced2011-05-04 23:50:46 +00007637 VisitedSelectorSet KnownSelectors;
7638 for (KnownMethodsMap::iterator M = KnownMethods.begin(),
7639 MEnd = KnownMethods.end();
7640 M != MEnd; ++M)
7641 KnownSelectors.insert(M->first);
7642
7643
Douglas Gregor669a25a2011-02-17 00:22:45 +00007644 ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(SearchDecl);
7645 if (!IFace)
7646 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(SearchDecl))
7647 IFace = Category->getClassInterface();
7648
Aaron Ballman3fe486a2014-03-13 21:23:55 +00007649 if (IFace)
7650 for (auto *Cat : IFace->visible_categories())
7651 Containers.push_back(Cat);
Alex Lorenzb8740422017-10-24 16:39:37 +00007652
7653 if (IsInstanceMethod) {
7654 for (unsigned I = 0, N = Containers.size(); I != N; ++I)
7655 for (auto *P : Containers[I]->instance_properties())
7656 AddObjCKeyValueCompletions(P, *IsInstanceMethod, ReturnType, Context,
7657 KnownSelectors, Results);
7658 }
Douglas Gregor669a25a2011-02-17 00:22:45 +00007659 }
7660
Douglas Gregor636a61e2010-04-07 00:21:17 +00007661 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00007662
7663 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
7664 Results.data(), Results.size());
Douglas Gregor636a61e2010-04-07 00:21:17 +00007665}
Douglas Gregor95887f92010-07-08 23:20:03 +00007666
7667void Sema::CodeCompleteObjCMethodDeclSelector(Scope *S,
7668 bool IsInstanceMethod,
Douglas Gregor45879692010-07-08 23:37:41 +00007669 bool AtParameterName,
John McCallba7bf592010-08-24 05:47:05 +00007670 ParsedType ReturnTy,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00007671 ArrayRef<IdentifierInfo *> SelIdents) {
Douglas Gregor95887f92010-07-08 23:20:03 +00007672 // If we have an external source, load the entire class method
Sebastian Redld44cd6a2010-08-18 23:57:06 +00007673 // pool from the AST file.
Douglas Gregor95887f92010-07-08 23:20:03 +00007674 if (ExternalSource) {
7675 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
7676 I != N; ++I) {
7677 Selector Sel = ExternalSource->GetExternalSelector(I);
Sebastian Redl75d8a322010-08-02 23:18:59 +00007678 if (Sel.isNull() || MethodPool.count(Sel))
Douglas Gregor95887f92010-07-08 23:20:03 +00007679 continue;
Sebastian Redl75d8a322010-08-02 23:18:59 +00007680
7681 ReadMethodPool(Sel);
Douglas Gregor95887f92010-07-08 23:20:03 +00007682 }
7683 }
7684
7685 // Build the set of methods we can see.
John McCall276321a2010-08-25 06:19:51 +00007686 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007687 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007688 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007689 CodeCompletionContext::CCC_Other);
Douglas Gregor95887f92010-07-08 23:20:03 +00007690
7691 if (ReturnTy)
7692 Results.setPreferredType(GetTypeFromParser(ReturnTy).getNonReferenceType());
Sebastian Redl75d8a322010-08-02 23:18:59 +00007693
Douglas Gregor95887f92010-07-08 23:20:03 +00007694 Results.EnterNewScope();
Sebastian Redl75d8a322010-08-02 23:18:59 +00007695 for (GlobalMethodPool::iterator M = MethodPool.begin(),
7696 MEnd = MethodPool.end();
7697 M != MEnd; ++M) {
7698 for (ObjCMethodList *MethList = IsInstanceMethod ? &M->second.first :
7699 &M->second.second;
Nico Weber2e0c8f72014-12-27 03:58:08 +00007700 MethList && MethList->getMethod();
Argyrios Kyrtzidisd3da6e02013-04-17 00:08:58 +00007701 MethList = MethList->getNext()) {
Nico Weber2e0c8f72014-12-27 03:58:08 +00007702 if (!isAcceptableObjCMethod(MethList->getMethod(), MK_Any, SelIdents))
Douglas Gregor95887f92010-07-08 23:20:03 +00007703 continue;
7704
Douglas Gregor45879692010-07-08 23:37:41 +00007705 if (AtParameterName) {
7706 // Suggest parameter names we've seen before.
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00007707 unsigned NumSelIdents = SelIdents.size();
Nico Weber2e0c8f72014-12-27 03:58:08 +00007708 if (NumSelIdents &&
7709 NumSelIdents <= MethList->getMethod()->param_size()) {
7710 ParmVarDecl *Param =
7711 MethList->getMethod()->parameters()[NumSelIdents - 1];
Douglas Gregor45879692010-07-08 23:37:41 +00007712 if (Param->getIdentifier()) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007713 CodeCompletionBuilder Builder(Results.getAllocator(),
7714 Results.getCodeCompletionTUInfo());
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00007715 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007716 Param->getIdentifier()->getName()));
7717 Results.AddResult(Builder.TakeString());
Douglas Gregor45879692010-07-08 23:37:41 +00007718 }
7719 }
7720
7721 continue;
7722 }
Craig Topperc3ec1492014-05-26 06:22:03 +00007723
Nico Weber2e0c8f72014-12-27 03:58:08 +00007724 Result R(MethList->getMethod(),
7725 Results.getBasePriority(MethList->getMethod()), nullptr);
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00007726 R.StartParameter = SelIdents.size();
Douglas Gregor95887f92010-07-08 23:20:03 +00007727 R.AllParametersAreInformative = false;
7728 R.DeclaringEntity = true;
7729 Results.MaybeAddResult(R, CurContext);
7730 }
7731 }
7732
7733 Results.ExitScope();
Alex Lorenz847fda12017-01-03 11:56:40 +00007734
7735 if (!AtParameterName && !SelIdents.empty() &&
7736 SelIdents.front()->getName().startswith("init")) {
7737 for (const auto &M : PP.macros()) {
7738 if (M.first->getName() != "NS_DESIGNATED_INITIALIZER")
7739 continue;
7740 Results.EnterNewScope();
7741 CodeCompletionBuilder Builder(Results.getAllocator(),
7742 Results.getCodeCompletionTUInfo());
7743 Builder.AddTypedTextChunk(
7744 Builder.getAllocator().CopyString(M.first->getName()));
7745 Results.AddResult(CodeCompletionResult(Builder.TakeString(), CCP_Macro,
7746 CXCursor_MacroDefinition));
7747 Results.ExitScope();
7748 }
7749 }
7750
Eric Liuf5ba09f2018-07-04 10:01:18 +00007751 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
7752 Results.data(), Results.size());
Douglas Gregor95887f92010-07-08 23:20:03 +00007753}
Douglas Gregorb14904c2010-08-13 22:48:40 +00007754
Douglas Gregorec00a262010-08-24 22:20:20 +00007755void Sema::CodeCompletePreprocessorDirective(bool InConditional) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007756 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007757 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00007758 CodeCompletionContext::CCC_PreprocessorDirective);
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007759 Results.EnterNewScope();
7760
7761 // #if <condition>
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007762 CodeCompletionBuilder Builder(Results.getAllocator(),
7763 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007764 Builder.AddTypedTextChunk("if");
7765 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7766 Builder.AddPlaceholderChunk("condition");
7767 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007768
7769 // #ifdef <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007770 Builder.AddTypedTextChunk("ifdef");
7771 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7772 Builder.AddPlaceholderChunk("macro");
7773 Results.AddResult(Builder.TakeString());
7774
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007775 // #ifndef <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007776 Builder.AddTypedTextChunk("ifndef");
7777 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7778 Builder.AddPlaceholderChunk("macro");
7779 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007780
7781 if (InConditional) {
7782 // #elif <condition>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007783 Builder.AddTypedTextChunk("elif");
7784 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7785 Builder.AddPlaceholderChunk("condition");
7786 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007787
7788 // #else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007789 Builder.AddTypedTextChunk("else");
7790 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007791
7792 // #endif
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007793 Builder.AddTypedTextChunk("endif");
7794 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007795 }
7796
7797 // #include "header"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007798 Builder.AddTypedTextChunk("include");
7799 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7800 Builder.AddTextChunk("\"");
7801 Builder.AddPlaceholderChunk("header");
7802 Builder.AddTextChunk("\"");
7803 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007804
7805 // #include <header>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007806 Builder.AddTypedTextChunk("include");
7807 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7808 Builder.AddTextChunk("<");
7809 Builder.AddPlaceholderChunk("header");
7810 Builder.AddTextChunk(">");
7811 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007812
7813 // #define <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007814 Builder.AddTypedTextChunk("define");
7815 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7816 Builder.AddPlaceholderChunk("macro");
7817 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007818
7819 // #define <macro>(<args>)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007820 Builder.AddTypedTextChunk("define");
7821 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7822 Builder.AddPlaceholderChunk("macro");
7823 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7824 Builder.AddPlaceholderChunk("args");
7825 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7826 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007827
7828 // #undef <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007829 Builder.AddTypedTextChunk("undef");
7830 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7831 Builder.AddPlaceholderChunk("macro");
7832 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007833
7834 // #line <number>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007835 Builder.AddTypedTextChunk("line");
7836 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7837 Builder.AddPlaceholderChunk("number");
7838 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007839
7840 // #line <number> "filename"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007841 Builder.AddTypedTextChunk("line");
7842 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7843 Builder.AddPlaceholderChunk("number");
7844 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7845 Builder.AddTextChunk("\"");
7846 Builder.AddPlaceholderChunk("filename");
7847 Builder.AddTextChunk("\"");
7848 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007849
7850 // #error <message>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007851 Builder.AddTypedTextChunk("error");
7852 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7853 Builder.AddPlaceholderChunk("message");
7854 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007855
7856 // #pragma <arguments>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007857 Builder.AddTypedTextChunk("pragma");
7858 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7859 Builder.AddPlaceholderChunk("arguments");
7860 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007861
David Blaikiebbafb8a2012-03-11 07:00:24 +00007862 if (getLangOpts().ObjC1) {
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007863 // #import "header"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007864 Builder.AddTypedTextChunk("import");
7865 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7866 Builder.AddTextChunk("\"");
7867 Builder.AddPlaceholderChunk("header");
7868 Builder.AddTextChunk("\"");
7869 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007870
7871 // #import <header>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007872 Builder.AddTypedTextChunk("import");
7873 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7874 Builder.AddTextChunk("<");
7875 Builder.AddPlaceholderChunk("header");
7876 Builder.AddTextChunk(">");
7877 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007878 }
7879
7880 // #include_next "header"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007881 Builder.AddTypedTextChunk("include_next");
7882 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7883 Builder.AddTextChunk("\"");
7884 Builder.AddPlaceholderChunk("header");
7885 Builder.AddTextChunk("\"");
7886 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007887
7888 // #include_next <header>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007889 Builder.AddTypedTextChunk("include_next");
7890 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7891 Builder.AddTextChunk("<");
7892 Builder.AddPlaceholderChunk("header");
7893 Builder.AddTextChunk(">");
7894 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007895
7896 // #warning <message>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007897 Builder.AddTypedTextChunk("warning");
7898 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7899 Builder.AddPlaceholderChunk("message");
7900 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007901
7902 // Note: #ident and #sccs are such crazy anachronisms that we don't provide
7903 // completions for them. And __include_macros is a Clang-internal extension
7904 // that we don't want to encourage anyone to use.
7905
7906 // FIXME: we don't support #assert or #unassert, so don't suggest them.
7907 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00007908
7909 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007910 Results.data(), Results.size());
7911}
7912
7913void Sema::CodeCompleteInPreprocessorConditionalExclusion(Scope *S) {
Douglas Gregorec00a262010-08-24 22:20:20 +00007914 CodeCompleteOrdinaryName(S,
John McCallfaf5fb42010-08-26 23:41:50 +00007915 S->getFnParent()? Sema::PCC_RecoveryInFunction
7916 : Sema::PCC_Namespace);
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007917}
7918
Douglas Gregorec00a262010-08-24 22:20:20 +00007919void Sema::CodeCompletePreprocessorMacroName(bool IsDefinition) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007920 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007921 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00007922 IsDefinition? CodeCompletionContext::CCC_MacroName
7923 : CodeCompletionContext::CCC_MacroNameUse);
Douglas Gregor12785102010-08-24 20:21:13 +00007924 if (!IsDefinition && (!CodeCompleter || CodeCompleter->includeMacros())) {
7925 // Add just the names of macros, not their arguments.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007926 CodeCompletionBuilder Builder(Results.getAllocator(),
7927 Results.getCodeCompletionTUInfo());
Douglas Gregor12785102010-08-24 20:21:13 +00007928 Results.EnterNewScope();
7929 for (Preprocessor::macro_iterator M = PP.macro_begin(),
7930 MEnd = PP.macro_end();
7931 M != MEnd; ++M) {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00007932 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007933 M->first->getName()));
Argyrios Kyrtzidis5c8b1cd2012-09-27 00:24:09 +00007934 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
7935 CCP_CodePattern,
7936 CXCursor_MacroDefinition));
Douglas Gregor12785102010-08-24 20:21:13 +00007937 }
7938 Results.ExitScope();
7939 } else if (IsDefinition) {
7940 // FIXME: Can we detect when the user just wrote an include guard above?
7941 }
7942
Douglas Gregor0ac41382010-09-23 23:01:17 +00007943 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor12785102010-08-24 20:21:13 +00007944 Results.data(), Results.size());
7945}
7946
Douglas Gregorec00a262010-08-24 22:20:20 +00007947void Sema::CodeCompletePreprocessorExpression() {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007948 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007949 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00007950 CodeCompletionContext::CCC_PreprocessorExpression);
Douglas Gregorec00a262010-08-24 22:20:20 +00007951
7952 if (!CodeCompleter || CodeCompleter->includeMacros())
Douglas Gregor8cb17462012-10-09 16:01:50 +00007953 AddMacroResults(PP, Results, true);
Douglas Gregorec00a262010-08-24 22:20:20 +00007954
7955 // defined (<macro>)
7956 Results.EnterNewScope();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007957 CodeCompletionBuilder Builder(Results.getAllocator(),
7958 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007959 Builder.AddTypedTextChunk("defined");
7960 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7961 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7962 Builder.AddPlaceholderChunk("macro");
7963 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7964 Results.AddResult(Builder.TakeString());
Douglas Gregorec00a262010-08-24 22:20:20 +00007965 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00007966
7967 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
7968 Results.data(), Results.size());
Douglas Gregorec00a262010-08-24 22:20:20 +00007969}
7970
7971void Sema::CodeCompletePreprocessorMacroArgument(Scope *S,
7972 IdentifierInfo *Macro,
7973 MacroInfo *MacroInfo,
7974 unsigned Argument) {
7975 // FIXME: In the future, we could provide "overload" results, much like we
7976 // do for function calls.
7977
Argyrios Kyrtzidis75f6cd22011-08-18 19:41:28 +00007978 // Now just ignore this. There will be another code-completion callback
7979 // for the expanded tokens.
Douglas Gregorec00a262010-08-24 22:20:20 +00007980}
7981
Douglas Gregor11583702010-08-25 17:04:25 +00007982void Sema::CodeCompleteNaturalLanguage() {
Douglas Gregor11583702010-08-25 17:04:25 +00007983 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregorea736372010-08-25 17:10:00 +00007984 CodeCompletionContext::CCC_NaturalLanguage,
Craig Topperc3ec1492014-05-26 06:22:03 +00007985 nullptr, 0);
Douglas Gregor11583702010-08-25 17:04:25 +00007986}
7987
Alex Lorenzf7f6f822017-05-09 16:05:04 +00007988void Sema::CodeCompleteAvailabilityPlatformName() {
7989 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
7990 CodeCompleter->getCodeCompletionTUInfo(),
7991 CodeCompletionContext::CCC_Other);
7992 Results.EnterNewScope();
7993 static const char *Platforms[] = {"macOS", "iOS", "watchOS", "tvOS"};
7994 for (const char *Platform : llvm::makeArrayRef(Platforms)) {
7995 Results.AddResult(CodeCompletionResult(Platform));
7996 Results.AddResult(CodeCompletionResult(Results.getAllocator().CopyString(
7997 Twine(Platform) + "ApplicationExtension")));
7998 }
7999 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00008000 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
8001 Results.data(), Results.size());
Alex Lorenzf7f6f822017-05-09 16:05:04 +00008002}
8003
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00008004void Sema::GatherGlobalCodeCompletions(CodeCompletionAllocator &Allocator,
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008005 CodeCompletionTUInfo &CCTUInfo,
Chris Lattner0e62c1c2011-07-23 10:55:15 +00008006 SmallVectorImpl<CodeCompletionResult> &Results) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008007 ResultBuilder Builder(*this, Allocator, CCTUInfo,
8008 CodeCompletionContext::CCC_Recovery);
Douglas Gregor39982192010-08-15 06:18:01 +00008009 if (!CodeCompleter || CodeCompleter->includeGlobals()) {
8010 CodeCompletionDeclConsumer Consumer(Builder,
8011 Context.getTranslationUnitDecl());
Sam McCallbb2cf632018-01-12 14:51:47 +00008012 LookupVisibleDecls(Context.getTranslationUnitDecl(), LookupAnyName,
8013 Consumer,
8014 !CodeCompleter || CodeCompleter->loadExternal());
Douglas Gregor39982192010-08-15 06:18:01 +00008015 }
Douglas Gregorb14904c2010-08-13 22:48:40 +00008016
8017 if (!CodeCompleter || CodeCompleter->includeMacros())
Douglas Gregor8cb17462012-10-09 16:01:50 +00008018 AddMacroResults(PP, Builder, true);
Douglas Gregorb14904c2010-08-13 22:48:40 +00008019
8020 Results.clear();
8021 Results.insert(Results.end(),
8022 Builder.data(), Builder.data() + Builder.size());
8023}