blob: 66b48e775b2c63dbb38a253c88692a9ac8c8fabe [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;
Haojian Wu10d95c52018-01-17 14:29:25 +00001294
Douglas Gregorc580c522010-01-14 01:09:38 +00001295 public:
1296 CodeCompletionDeclConsumer(ResultBuilder &Results, DeclContext *CurContext)
1297 : Results(Results), CurContext(CurContext) { }
Craig Toppere14c0f82014-03-12 04:55:44 +00001298
1299 void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx,
1300 bool InBaseClass) override {
Erik Verbruggen2e657ff2011-10-06 07:27:49 +00001301 bool Accessible = true;
Douglas Gregor03ba1882011-11-03 16:51:37 +00001302 if (Ctx)
1303 Accessible = Results.getSema().IsSimplyAccessible(ND, Ctx);
Craig Topperc3ec1492014-05-26 06:22:03 +00001304
1305 ResultBuilder::Result Result(ND, Results.getBasePriority(ND), nullptr,
1306 false, Accessible);
Erik Verbruggen2e657ff2011-10-06 07:27:49 +00001307 Results.AddResult(Result, CurContext, Hiding, InBaseClass);
Douglas Gregorc580c522010-01-14 01:09:38 +00001308 }
Haojian Wu10d95c52018-01-17 14:29:25 +00001309
1310 void EnteredContext(DeclContext* Ctx) override {
1311 Results.addVisitedContext(Ctx);
1312 }
Douglas Gregorc580c522010-01-14 01:09:38 +00001313 };
Alexander Kornienkoab9db512015-06-22 23:07:51 +00001314}
Douglas Gregorc580c522010-01-14 01:09:38 +00001315
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001316/// Add type specifiers for the current language as keyword results.
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001317static void AddTypeSpecifierResults(const LangOptions &LangOpts,
Douglas Gregor3545ff42009-09-21 16:56:56 +00001318 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00001319 typedef CodeCompletionResult Result;
Douglas Gregora2db7932010-05-26 22:00:08 +00001320 Results.AddResult(Result("short", CCP_Type));
1321 Results.AddResult(Result("long", CCP_Type));
1322 Results.AddResult(Result("signed", CCP_Type));
1323 Results.AddResult(Result("unsigned", CCP_Type));
1324 Results.AddResult(Result("void", CCP_Type));
1325 Results.AddResult(Result("char", CCP_Type));
1326 Results.AddResult(Result("int", CCP_Type));
1327 Results.AddResult(Result("float", CCP_Type));
1328 Results.AddResult(Result("double", CCP_Type));
1329 Results.AddResult(Result("enum", CCP_Type));
1330 Results.AddResult(Result("struct", CCP_Type));
1331 Results.AddResult(Result("union", CCP_Type));
1332 Results.AddResult(Result("const", CCP_Type));
1333 Results.AddResult(Result("volatile", CCP_Type));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001334
Douglas Gregor3545ff42009-09-21 16:56:56 +00001335 if (LangOpts.C99) {
1336 // C99-specific
Douglas Gregora2db7932010-05-26 22:00:08 +00001337 Results.AddResult(Result("_Complex", CCP_Type));
1338 Results.AddResult(Result("_Imaginary", CCP_Type));
1339 Results.AddResult(Result("_Bool", CCP_Type));
1340 Results.AddResult(Result("restrict", CCP_Type));
Douglas Gregor3545ff42009-09-21 16:56:56 +00001341 }
1342
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00001343 CodeCompletionBuilder Builder(Results.getAllocator(),
1344 Results.getCodeCompletionTUInfo());
Douglas Gregor3545ff42009-09-21 16:56:56 +00001345 if (LangOpts.CPlusPlus) {
1346 // C++-specific
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00001347 Results.AddResult(Result("bool", CCP_Type +
1348 (LangOpts.ObjC1? CCD_bool_in_ObjC : 0)));
Douglas Gregora2db7932010-05-26 22:00:08 +00001349 Results.AddResult(Result("class", CCP_Type));
1350 Results.AddResult(Result("wchar_t", CCP_Type));
Douglas Gregor3545ff42009-09-21 16:56:56 +00001351
Douglas Gregorf4c33342010-05-28 00:22:41 +00001352 // typename qualified-id
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001353 Builder.AddTypedTextChunk("typename");
1354 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1355 Builder.AddPlaceholderChunk("qualifier");
1356 Builder.AddTextChunk("::");
1357 Builder.AddPlaceholderChunk("name");
1358 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf64acca2010-05-25 21:41:55 +00001359
Richard Smith2bf7fdb2013-01-02 11:42:31 +00001360 if (LangOpts.CPlusPlus11) {
Douglas Gregora2db7932010-05-26 22:00:08 +00001361 Results.AddResult(Result("auto", CCP_Type));
1362 Results.AddResult(Result("char16_t", CCP_Type));
1363 Results.AddResult(Result("char32_t", CCP_Type));
Douglas Gregorf4c33342010-05-28 00:22:41 +00001364
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001365 Builder.AddTypedTextChunk("decltype");
1366 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1367 Builder.AddPlaceholderChunk("expression");
1368 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1369 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor3545ff42009-09-21 16:56:56 +00001370 }
Alex Lorenz46eed9d2017-02-13 23:35:59 +00001371 } else
1372 Results.AddResult(Result("__auto_type", CCP_Type));
1373
Douglas Gregor3545ff42009-09-21 16:56:56 +00001374 // GNU extensions
1375 if (LangOpts.GNUMode) {
1376 // FIXME: Enable when we actually support decimal floating point.
Douglas Gregor78a21012010-01-14 16:01:26 +00001377 // Results.AddResult(Result("_Decimal32"));
1378 // Results.AddResult(Result("_Decimal64"));
1379 // Results.AddResult(Result("_Decimal128"));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001380
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001381 Builder.AddTypedTextChunk("typeof");
1382 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1383 Builder.AddPlaceholderChunk("expression");
1384 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00001385
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001386 Builder.AddTypedTextChunk("typeof");
1387 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1388 Builder.AddPlaceholderChunk("type");
1389 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1390 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor3545ff42009-09-21 16:56:56 +00001391 }
Douglas Gregor86b42682015-06-19 18:27:52 +00001392
1393 // Nullability
Douglas Gregoraea7afd2015-06-24 22:02:08 +00001394 Results.AddResult(Result("_Nonnull", CCP_Type));
1395 Results.AddResult(Result("_Null_unspecified", CCP_Type));
1396 Results.AddResult(Result("_Nullable", CCP_Type));
Douglas Gregor3545ff42009-09-21 16:56:56 +00001397}
1398
John McCallfaf5fb42010-08-26 23:41:50 +00001399static void AddStorageSpecifiers(Sema::ParserCompletionContext CCC,
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001400 const LangOptions &LangOpts,
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001401 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00001402 typedef CodeCompletionResult Result;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001403 // Note: we don't suggest either "auto" or "register", because both
1404 // are pointless as storage specifiers. Elsewhere, we suggest "auto"
1405 // in C++0x as a type specifier.
Douglas Gregor78a21012010-01-14 16:01:26 +00001406 Results.AddResult(Result("extern"));
1407 Results.AddResult(Result("static"));
Alex Lorenz8f4d3992017-02-13 23:19:40 +00001408
1409 if (LangOpts.CPlusPlus11) {
1410 CodeCompletionAllocator &Allocator = Results.getAllocator();
1411 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
1412
1413 // alignas
1414 Builder.AddTypedTextChunk("alignas");
1415 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1416 Builder.AddPlaceholderChunk("expression");
1417 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1418 Results.AddResult(Result(Builder.TakeString()));
1419
1420 Results.AddResult(Result("constexpr"));
1421 Results.AddResult(Result("thread_local"));
1422 }
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001423}
1424
John McCallfaf5fb42010-08-26 23:41:50 +00001425static void AddFunctionSpecifiers(Sema::ParserCompletionContext CCC,
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001426 const LangOptions &LangOpts,
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001427 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00001428 typedef CodeCompletionResult Result;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001429 switch (CCC) {
John McCallfaf5fb42010-08-26 23:41:50 +00001430 case Sema::PCC_Class:
1431 case Sema::PCC_MemberTemplate:
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001432 if (LangOpts.CPlusPlus) {
Douglas Gregor78a21012010-01-14 16:01:26 +00001433 Results.AddResult(Result("explicit"));
1434 Results.AddResult(Result("friend"));
1435 Results.AddResult(Result("mutable"));
1436 Results.AddResult(Result("virtual"));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001437 }
Adrian Prantlf3b3ccd2017-12-19 22:06:11 +00001438 LLVM_FALLTHROUGH;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001439
John McCallfaf5fb42010-08-26 23:41:50 +00001440 case Sema::PCC_ObjCInterface:
1441 case Sema::PCC_ObjCImplementation:
1442 case Sema::PCC_Namespace:
1443 case Sema::PCC_Template:
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001444 if (LangOpts.CPlusPlus || LangOpts.C99)
Douglas Gregor78a21012010-01-14 16:01:26 +00001445 Results.AddResult(Result("inline"));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001446 break;
1447
John McCallfaf5fb42010-08-26 23:41:50 +00001448 case Sema::PCC_ObjCInstanceVariableList:
1449 case Sema::PCC_Expression:
1450 case Sema::PCC_Statement:
1451 case Sema::PCC_ForInit:
1452 case Sema::PCC_Condition:
1453 case Sema::PCC_RecoveryInFunction:
1454 case Sema::PCC_Type:
Douglas Gregor5e35d592010-09-14 23:59:36 +00001455 case Sema::PCC_ParenthesizedExpression:
Douglas Gregor80039242011-02-15 20:33:25 +00001456 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001457 break;
1458 }
1459}
1460
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001461static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt);
1462static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt);
1463static void AddObjCVisibilityResults(const LangOptions &LangOpts,
Douglas Gregor48d46252010-01-13 21:54:15 +00001464 ResultBuilder &Results,
1465 bool NeedAt);
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001466static void AddObjCImplementationResults(const LangOptions &LangOpts,
Douglas Gregorf1934162010-01-13 21:24:21 +00001467 ResultBuilder &Results,
1468 bool NeedAt);
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001469static void AddObjCInterfaceResults(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 AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt);
Douglas Gregorf1934162010-01-13 21:24:21 +00001473
Douglas Gregorf4c33342010-05-28 00:22:41 +00001474static void AddTypedefResult(ResultBuilder &Results) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00001475 CodeCompletionBuilder Builder(Results.getAllocator(),
1476 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001477 Builder.AddTypedTextChunk("typedef");
1478 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1479 Builder.AddPlaceholderChunk("type");
1480 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1481 Builder.AddPlaceholderChunk("name");
1482 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00001483}
1484
John McCallfaf5fb42010-08-26 23:41:50 +00001485static bool WantTypesInContext(Sema::ParserCompletionContext CCC,
Douglas Gregor70febae2010-05-28 00:49:12 +00001486 const LangOptions &LangOpts) {
Douglas Gregor70febae2010-05-28 00:49:12 +00001487 switch (CCC) {
John McCallfaf5fb42010-08-26 23:41:50 +00001488 case Sema::PCC_Namespace:
1489 case Sema::PCC_Class:
1490 case Sema::PCC_ObjCInstanceVariableList:
1491 case Sema::PCC_Template:
1492 case Sema::PCC_MemberTemplate:
1493 case Sema::PCC_Statement:
1494 case Sema::PCC_RecoveryInFunction:
1495 case Sema::PCC_Type:
Douglas Gregor5e35d592010-09-14 23:59:36 +00001496 case Sema::PCC_ParenthesizedExpression:
Douglas Gregor80039242011-02-15 20:33:25 +00001497 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregor70febae2010-05-28 00:49:12 +00001498 return true;
1499
John McCallfaf5fb42010-08-26 23:41:50 +00001500 case Sema::PCC_Expression:
1501 case Sema::PCC_Condition:
Douglas Gregor5e35d592010-09-14 23:59:36 +00001502 return LangOpts.CPlusPlus;
1503
1504 case Sema::PCC_ObjCInterface:
1505 case Sema::PCC_ObjCImplementation:
Douglas Gregor70febae2010-05-28 00:49:12 +00001506 return false;
1507
John McCallfaf5fb42010-08-26 23:41:50 +00001508 case Sema::PCC_ForInit:
Douglas Gregor5e35d592010-09-14 23:59:36 +00001509 return LangOpts.CPlusPlus || LangOpts.ObjC1 || LangOpts.C99;
Douglas Gregor70febae2010-05-28 00:49:12 +00001510 }
David Blaikie8a40f702012-01-17 06:56:22 +00001511
1512 llvm_unreachable("Invalid ParserCompletionContext!");
Douglas Gregor70febae2010-05-28 00:49:12 +00001513}
1514
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00001515static PrintingPolicy getCompletionPrintingPolicy(const ASTContext &Context,
1516 const Preprocessor &PP) {
1517 PrintingPolicy Policy = Sema::getPrintingPolicy(Context, PP);
Douglas Gregore5c79d52011-10-18 21:20:17 +00001518 Policy.AnonymousTagLocations = false;
1519 Policy.SuppressStrongLifetime = true;
Douglas Gregor2e10cf92011-11-03 00:16:13 +00001520 Policy.SuppressUnwrittenScope = true;
Ilya Biryukovb5da91c2017-11-08 10:39:09 +00001521 Policy.SuppressScope = true;
Douglas Gregore5c79d52011-10-18 21:20:17 +00001522 return Policy;
1523}
1524
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001525/// Retrieve a printing policy suitable for code completion.
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00001526static PrintingPolicy getCompletionPrintingPolicy(Sema &S) {
1527 return getCompletionPrintingPolicy(S.Context, S.PP);
1528}
1529
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001530/// Retrieve the string representation of the given type as a string
Douglas Gregore5c79d52011-10-18 21:20:17 +00001531/// that has the appropriate lifetime for code completion.
1532///
1533/// This routine provides a fast path where we provide constant strings for
1534/// common type names.
1535static const char *GetCompletionTypeString(QualType T,
1536 ASTContext &Context,
1537 const PrintingPolicy &Policy,
1538 CodeCompletionAllocator &Allocator) {
1539 if (!T.getLocalQualifiers()) {
1540 // Built-in type names are constant strings.
1541 if (const BuiltinType *BT = dyn_cast<BuiltinType>(T))
Argyrios Kyrtzidisbbff3da2012-05-05 04:20:28 +00001542 return BT->getNameAsCString(Policy);
Douglas Gregore5c79d52011-10-18 21:20:17 +00001543
1544 // Anonymous tag types are constant strings.
1545 if (const TagType *TagT = dyn_cast<TagType>(T))
1546 if (TagDecl *Tag = TagT->getDecl())
John McCall5ea95772013-03-09 00:54:27 +00001547 if (!Tag->hasNameForLinkage()) {
Douglas Gregore5c79d52011-10-18 21:20:17 +00001548 switch (Tag->getTagKind()) {
1549 case TTK_Struct: return "struct <anonymous>";
Joao Matosdc86f942012-08-31 18:45:21 +00001550 case TTK_Interface: return "__interface <anonymous>";
1551 case TTK_Class: return "class <anonymous>";
Douglas Gregore5c79d52011-10-18 21:20:17 +00001552 case TTK_Union: return "union <anonymous>";
1553 case TTK_Enum: return "enum <anonymous>";
1554 }
1555 }
1556 }
1557
1558 // Slow path: format the type as a string.
1559 std::string Result;
1560 T.getAsStringInternal(Result, Policy);
1561 return Allocator.CopyString(Result);
1562}
1563
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001564/// Add a completion for "this", if we're in a member function.
Douglas Gregord8c61782012-02-15 15:34:24 +00001565static void addThisCompletion(Sema &S, ResultBuilder &Results) {
1566 QualType ThisTy = S.getCurrentThisType();
1567 if (ThisTy.isNull())
1568 return;
1569
1570 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00001571 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Douglas Gregord8c61782012-02-15 15:34:24 +00001572 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
1573 Builder.AddResultTypeChunk(GetCompletionTypeString(ThisTy,
1574 S.Context,
1575 Policy,
1576 Allocator));
1577 Builder.AddTypedTextChunk("this");
Joao Matosdc86f942012-08-31 18:45:21 +00001578 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
Douglas Gregord8c61782012-02-15 15:34:24 +00001579}
1580
Alex Lorenz8f4d3992017-02-13 23:19:40 +00001581static void AddStaticAssertResult(CodeCompletionBuilder &Builder,
1582 ResultBuilder &Results,
1583 const LangOptions &LangOpts) {
1584 if (!LangOpts.CPlusPlus11)
1585 return;
1586
1587 Builder.AddTypedTextChunk("static_assert");
1588 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1589 Builder.AddPlaceholderChunk("expression");
1590 Builder.AddChunk(CodeCompletionString::CK_Comma);
1591 Builder.AddPlaceholderChunk("message");
1592 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1593 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
1594}
1595
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001596/// Add language constructs that show up for "ordinary" names.
John McCallfaf5fb42010-08-26 23:41:50 +00001597static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001598 Scope *S,
1599 Sema &SemaRef,
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001600 ResultBuilder &Results) {
Douglas Gregore5c79d52011-10-18 21:20:17 +00001601 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00001602 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001603
John McCall276321a2010-08-25 06:19:51 +00001604 typedef CodeCompletionResult Result;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001605 switch (CCC) {
John McCallfaf5fb42010-08-26 23:41:50 +00001606 case Sema::PCC_Namespace:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001607 if (SemaRef.getLangOpts().CPlusPlus) {
Douglas Gregorf4c33342010-05-28 00:22:41 +00001608 if (Results.includeCodePatterns()) {
1609 // namespace <identifier> { declarations }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001610 Builder.AddTypedTextChunk("namespace");
1611 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1612 Builder.AddPlaceholderChunk("identifier");
1613 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1614 Builder.AddPlaceholderChunk("declarations");
1615 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1616 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1617 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00001618 }
1619
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001620 // namespace identifier = identifier ;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001621 Builder.AddTypedTextChunk("namespace");
1622 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1623 Builder.AddPlaceholderChunk("name");
1624 Builder.AddChunk(CodeCompletionString::CK_Equal);
1625 Builder.AddPlaceholderChunk("namespace");
1626 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001627
1628 // Using directives
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001629 Builder.AddTypedTextChunk("using");
1630 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1631 Builder.AddTextChunk("namespace");
1632 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1633 Builder.AddPlaceholderChunk("identifier");
1634 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001635
1636 // asm(string-literal)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001637 Builder.AddTypedTextChunk("asm");
1638 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1639 Builder.AddPlaceholderChunk("string-literal");
1640 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1641 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001642
Douglas Gregorf4c33342010-05-28 00:22:41 +00001643 if (Results.includeCodePatterns()) {
1644 // Explicit template instantiation
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001645 Builder.AddTypedTextChunk("template");
1646 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1647 Builder.AddPlaceholderChunk("declaration");
1648 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00001649 }
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001650 }
Douglas Gregorf1934162010-01-13 21:24:21 +00001651
David Blaikiebbafb8a2012-03-11 07:00:24 +00001652 if (SemaRef.getLangOpts().ObjC1)
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001653 AddObjCTopLevelResults(Results, true);
Douglas Gregorf1934162010-01-13 21:24:21 +00001654
Douglas Gregorf4c33342010-05-28 00:22:41 +00001655 AddTypedefResult(Results);
Adrian Prantlf3b3ccd2017-12-19 22:06:11 +00001656 LLVM_FALLTHROUGH;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001657
John McCallfaf5fb42010-08-26 23:41:50 +00001658 case Sema::PCC_Class:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001659 if (SemaRef.getLangOpts().CPlusPlus) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001660 // Using declaration
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001661 Builder.AddTypedTextChunk("using");
1662 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1663 Builder.AddPlaceholderChunk("qualifier");
1664 Builder.AddTextChunk("::");
1665 Builder.AddPlaceholderChunk("name");
1666 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001667
Douglas Gregorf4c33342010-05-28 00:22:41 +00001668 // using typename qualifier::name (only in a dependent context)
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001669 if (SemaRef.CurContext->isDependentContext()) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001670 Builder.AddTypedTextChunk("using");
1671 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1672 Builder.AddTextChunk("typename");
1673 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1674 Builder.AddPlaceholderChunk("qualifier");
1675 Builder.AddTextChunk("::");
1676 Builder.AddPlaceholderChunk("name");
1677 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001678 }
1679
Alex Lorenz8f4d3992017-02-13 23:19:40 +00001680 AddStaticAssertResult(Builder, Results, SemaRef.getLangOpts());
1681
John McCallfaf5fb42010-08-26 23:41:50 +00001682 if (CCC == Sema::PCC_Class) {
Douglas Gregorf4c33342010-05-28 00:22:41 +00001683 AddTypedefResult(Results);
1684
Erik Verbruggen6524c052017-10-24 13:46:58 +00001685 bool IsNotInheritanceScope =
1686 !(S->getFlags() & Scope::ClassInheritanceScope);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001687 // public:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001688 Builder.AddTypedTextChunk("public");
Erik Verbruggen6524c052017-10-24 13:46:58 +00001689 if (IsNotInheritanceScope && Results.includeCodePatterns())
Douglas Gregor9489cdf2012-04-10 17:56:28 +00001690 Builder.AddChunk(CodeCompletionString::CK_Colon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001691 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001692
1693 // protected:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001694 Builder.AddTypedTextChunk("protected");
Erik Verbruggen6524c052017-10-24 13:46:58 +00001695 if (IsNotInheritanceScope && Results.includeCodePatterns())
Douglas Gregor9489cdf2012-04-10 17:56:28 +00001696 Builder.AddChunk(CodeCompletionString::CK_Colon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001697 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001698
1699 // private:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001700 Builder.AddTypedTextChunk("private");
Erik Verbruggen6524c052017-10-24 13:46:58 +00001701 if (IsNotInheritanceScope && Results.includeCodePatterns())
Douglas Gregor9489cdf2012-04-10 17:56:28 +00001702 Builder.AddChunk(CodeCompletionString::CK_Colon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001703 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001704 }
1705 }
Adrian Prantlf3b3ccd2017-12-19 22:06:11 +00001706 LLVM_FALLTHROUGH;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001707
John McCallfaf5fb42010-08-26 23:41:50 +00001708 case Sema::PCC_Template:
1709 case Sema::PCC_MemberTemplate:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001710 if (SemaRef.getLangOpts().CPlusPlus && Results.includeCodePatterns()) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001711 // template < parameters >
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001712 Builder.AddTypedTextChunk("template");
1713 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1714 Builder.AddPlaceholderChunk("parameters");
1715 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1716 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001717 }
1718
David Blaikiebbafb8a2012-03-11 07:00:24 +00001719 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
1720 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001721 break;
1722
John McCallfaf5fb42010-08-26 23:41:50 +00001723 case Sema::PCC_ObjCInterface:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001724 AddObjCInterfaceResults(SemaRef.getLangOpts(), Results, true);
1725 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
1726 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregorf1934162010-01-13 21:24:21 +00001727 break;
1728
John McCallfaf5fb42010-08-26 23:41:50 +00001729 case Sema::PCC_ObjCImplementation:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001730 AddObjCImplementationResults(SemaRef.getLangOpts(), Results, true);
1731 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
1732 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregorf1934162010-01-13 21:24:21 +00001733 break;
1734
John McCallfaf5fb42010-08-26 23:41:50 +00001735 case Sema::PCC_ObjCInstanceVariableList:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001736 AddObjCVisibilityResults(SemaRef.getLangOpts(), Results, true);
Douglas Gregor48d46252010-01-13 21:54:15 +00001737 break;
1738
John McCallfaf5fb42010-08-26 23:41:50 +00001739 case Sema::PCC_RecoveryInFunction:
1740 case Sema::PCC_Statement: {
Douglas Gregorf4c33342010-05-28 00:22:41 +00001741 AddTypedefResult(Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001742
David Blaikiebbafb8a2012-03-11 07:00:24 +00001743 if (SemaRef.getLangOpts().CPlusPlus && Results.includeCodePatterns() &&
1744 SemaRef.getLangOpts().CXXExceptions) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001745 Builder.AddTypedTextChunk("try");
1746 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1747 Builder.AddPlaceholderChunk("statements");
1748 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1749 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1750 Builder.AddTextChunk("catch");
1751 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1752 Builder.AddPlaceholderChunk("declaration");
1753 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1754 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1755 Builder.AddPlaceholderChunk("statements");
1756 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1757 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1758 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001759 }
David Blaikiebbafb8a2012-03-11 07:00:24 +00001760 if (SemaRef.getLangOpts().ObjC1)
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001761 AddObjCStatementResults(Results, true);
Douglas Gregorf1934162010-01-13 21:24:21 +00001762
Douglas Gregorf64acca2010-05-25 21:41:55 +00001763 if (Results.includeCodePatterns()) {
1764 // if (condition) { statements }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001765 Builder.AddTypedTextChunk("if");
1766 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00001767 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001768 Builder.AddPlaceholderChunk("condition");
Douglas Gregorf64acca2010-05-25 21:41:55 +00001769 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001770 Builder.AddPlaceholderChunk("expression");
1771 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1772 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1773 Builder.AddPlaceholderChunk("statements");
1774 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1775 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1776 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001777
Douglas Gregorf64acca2010-05-25 21:41:55 +00001778 // switch (condition) { }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001779 Builder.AddTypedTextChunk("switch");
1780 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00001781 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001782 Builder.AddPlaceholderChunk("condition");
Douglas Gregorf64acca2010-05-25 21:41:55 +00001783 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001784 Builder.AddPlaceholderChunk("expression");
1785 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1786 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1787 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1788 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1789 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf64acca2010-05-25 21:41:55 +00001790 }
1791
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001792 // Switch-specific statements.
John McCallaab3e412010-08-25 08:40:02 +00001793 if (!SemaRef.getCurFunction()->SwitchStack.empty()) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001794 // case expression:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001795 Builder.AddTypedTextChunk("case");
1796 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1797 Builder.AddPlaceholderChunk("expression");
1798 Builder.AddChunk(CodeCompletionString::CK_Colon);
1799 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001800
1801 // default:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001802 Builder.AddTypedTextChunk("default");
1803 Builder.AddChunk(CodeCompletionString::CK_Colon);
1804 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001805 }
1806
Douglas Gregorf64acca2010-05-25 21:41:55 +00001807 if (Results.includeCodePatterns()) {
1808 /// while (condition) { statements }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001809 Builder.AddTypedTextChunk("while");
1810 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00001811 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001812 Builder.AddPlaceholderChunk("condition");
Douglas Gregorf64acca2010-05-25 21:41:55 +00001813 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001814 Builder.AddPlaceholderChunk("expression");
1815 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1816 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1817 Builder.AddPlaceholderChunk("statements");
1818 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1819 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1820 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf64acca2010-05-25 21:41:55 +00001821
1822 // do { statements } while ( expression );
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001823 Builder.AddTypedTextChunk("do");
1824 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1825 Builder.AddPlaceholderChunk("statements");
1826 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1827 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1828 Builder.AddTextChunk("while");
1829 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1830 Builder.AddPlaceholderChunk("expression");
1831 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1832 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001833
Douglas Gregorf64acca2010-05-25 21:41:55 +00001834 // for ( for-init-statement ; condition ; expression ) { statements }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001835 Builder.AddTypedTextChunk("for");
1836 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00001837 if (SemaRef.getLangOpts().CPlusPlus || SemaRef.getLangOpts().C99)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001838 Builder.AddPlaceholderChunk("init-statement");
Douglas Gregorf64acca2010-05-25 21:41:55 +00001839 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001840 Builder.AddPlaceholderChunk("init-expression");
1841 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
1842 Builder.AddPlaceholderChunk("condition");
1843 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
1844 Builder.AddPlaceholderChunk("inc-expression");
1845 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1846 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1847 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1848 Builder.AddPlaceholderChunk("statements");
1849 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1850 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1851 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf64acca2010-05-25 21:41:55 +00001852 }
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001853
1854 if (S->getContinueParent()) {
1855 // continue ;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001856 Builder.AddTypedTextChunk("continue");
1857 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001858 }
1859
1860 if (S->getBreakParent()) {
1861 // break ;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001862 Builder.AddTypedTextChunk("break");
1863 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001864 }
1865
1866 // "return expression ;" or "return ;", depending on whether we
1867 // know the function is void or not.
1868 bool isVoid = false;
1869 if (FunctionDecl *Function = dyn_cast<FunctionDecl>(SemaRef.CurContext))
Alp Toker314cc812014-01-25 16:55:45 +00001870 isVoid = Function->getReturnType()->isVoidType();
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001871 else if (ObjCMethodDecl *Method
1872 = dyn_cast<ObjCMethodDecl>(SemaRef.CurContext))
Alp Toker314cc812014-01-25 16:55:45 +00001873 isVoid = Method->getReturnType()->isVoidType();
Douglas Gregor9a28e842010-03-01 23:15:13 +00001874 else if (SemaRef.getCurBlock() &&
1875 !SemaRef.getCurBlock()->ReturnType.isNull())
1876 isVoid = SemaRef.getCurBlock()->ReturnType->isVoidType();
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001877 Builder.AddTypedTextChunk("return");
Douglas Gregor44272ca2010-02-18 04:06:48 +00001878 if (!isVoid) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001879 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1880 Builder.AddPlaceholderChunk("expression");
Douglas Gregor44272ca2010-02-18 04:06:48 +00001881 }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001882 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001883
Douglas Gregorf4c33342010-05-28 00:22:41 +00001884 // goto identifier ;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001885 Builder.AddTypedTextChunk("goto");
1886 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1887 Builder.AddPlaceholderChunk("label");
1888 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001889
Douglas Gregorf4c33342010-05-28 00:22:41 +00001890 // Using directives
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001891 Builder.AddTypedTextChunk("using");
1892 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1893 Builder.AddTextChunk("namespace");
1894 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1895 Builder.AddPlaceholderChunk("identifier");
1896 Results.AddResult(Result(Builder.TakeString()));
Alex Lorenz8f4d3992017-02-13 23:19:40 +00001897
1898 AddStaticAssertResult(Builder, Results, SemaRef.getLangOpts());
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001899 }
Galina Kistanovabe3ba9da2017-06-07 06:31:55 +00001900 LLVM_FALLTHROUGH;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001901
1902 // Fall through (for statement expressions).
John McCallfaf5fb42010-08-26 23:41:50 +00001903 case Sema::PCC_ForInit:
1904 case Sema::PCC_Condition:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001905 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001906 // Fall through: conditions and statements can have expressions.
Galina Kistanova33399112017-06-03 06:35:06 +00001907 LLVM_FALLTHROUGH;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001908
Douglas Gregor5e35d592010-09-14 23:59:36 +00001909 case Sema::PCC_ParenthesizedExpression:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001910 if (SemaRef.getLangOpts().ObjCAutoRefCount &&
John McCall31168b02011-06-15 23:02:42 +00001911 CCC == Sema::PCC_ParenthesizedExpression) {
1912 // (__bridge <type>)<expression>
1913 Builder.AddTypedTextChunk("__bridge");
1914 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1915 Builder.AddPlaceholderChunk("type");
1916 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1917 Builder.AddPlaceholderChunk("expression");
1918 Results.AddResult(Result(Builder.TakeString()));
1919
1920 // (__bridge_transfer <Objective-C type>)<expression>
1921 Builder.AddTypedTextChunk("__bridge_transfer");
1922 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1923 Builder.AddPlaceholderChunk("Objective-C type");
1924 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1925 Builder.AddPlaceholderChunk("expression");
1926 Results.AddResult(Result(Builder.TakeString()));
1927
1928 // (__bridge_retained <CF type>)<expression>
1929 Builder.AddTypedTextChunk("__bridge_retained");
1930 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1931 Builder.AddPlaceholderChunk("CF type");
1932 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1933 Builder.AddPlaceholderChunk("expression");
1934 Results.AddResult(Result(Builder.TakeString()));
1935 }
1936 // Fall through
Galina Kistanova33399112017-06-03 06:35:06 +00001937 LLVM_FALLTHROUGH;
John McCall31168b02011-06-15 23:02:42 +00001938
John McCallfaf5fb42010-08-26 23:41:50 +00001939 case Sema::PCC_Expression: {
David Blaikiebbafb8a2012-03-11 07:00:24 +00001940 if (SemaRef.getLangOpts().CPlusPlus) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001941 // 'this', if we're in a non-static member function.
Douglas Gregord8c61782012-02-15 15:34:24 +00001942 addThisCompletion(SemaRef, Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001943
Douglas Gregore5c79d52011-10-18 21:20:17 +00001944 // true
1945 Builder.AddResultTypeChunk("bool");
1946 Builder.AddTypedTextChunk("true");
1947 Results.AddResult(Result(Builder.TakeString()));
1948
1949 // false
1950 Builder.AddResultTypeChunk("bool");
1951 Builder.AddTypedTextChunk("false");
1952 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001953
David Blaikiebbafb8a2012-03-11 07:00:24 +00001954 if (SemaRef.getLangOpts().RTTI) {
Douglas Gregorc05f6572011-04-12 02:47:21 +00001955 // dynamic_cast < type-id > ( expression )
1956 Builder.AddTypedTextChunk("dynamic_cast");
1957 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1958 Builder.AddPlaceholderChunk("type");
1959 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1960 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1961 Builder.AddPlaceholderChunk("expression");
1962 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1963 Results.AddResult(Result(Builder.TakeString()));
1964 }
Douglas Gregorf4c33342010-05-28 00:22:41 +00001965
1966 // static_cast < type-id > ( expression )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001967 Builder.AddTypedTextChunk("static_cast");
1968 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1969 Builder.AddPlaceholderChunk("type");
1970 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1971 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1972 Builder.AddPlaceholderChunk("expression");
1973 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1974 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001975
Douglas Gregorf4c33342010-05-28 00:22:41 +00001976 // reinterpret_cast < type-id > ( expression )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001977 Builder.AddTypedTextChunk("reinterpret_cast");
1978 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1979 Builder.AddPlaceholderChunk("type");
1980 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1981 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1982 Builder.AddPlaceholderChunk("expression");
1983 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1984 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001985
Douglas Gregorf4c33342010-05-28 00:22:41 +00001986 // const_cast < type-id > ( expression )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001987 Builder.AddTypedTextChunk("const_cast");
1988 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1989 Builder.AddPlaceholderChunk("type");
1990 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1991 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1992 Builder.AddPlaceholderChunk("expression");
1993 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1994 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001995
David Blaikiebbafb8a2012-03-11 07:00:24 +00001996 if (SemaRef.getLangOpts().RTTI) {
Douglas Gregorc05f6572011-04-12 02:47:21 +00001997 // typeid ( expression-or-type )
Douglas Gregore5c79d52011-10-18 21:20:17 +00001998 Builder.AddResultTypeChunk("std::type_info");
Douglas Gregorc05f6572011-04-12 02:47:21 +00001999 Builder.AddTypedTextChunk("typeid");
2000 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2001 Builder.AddPlaceholderChunk("expression-or-type");
2002 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2003 Results.AddResult(Result(Builder.TakeString()));
2004 }
2005
Douglas Gregorf4c33342010-05-28 00:22:41 +00002006 // new T ( ... )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002007 Builder.AddTypedTextChunk("new");
2008 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2009 Builder.AddPlaceholderChunk("type");
2010 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2011 Builder.AddPlaceholderChunk("expressions");
2012 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2013 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002014
Douglas Gregorf4c33342010-05-28 00:22:41 +00002015 // new T [ ] ( ... )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002016 Builder.AddTypedTextChunk("new");
2017 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2018 Builder.AddPlaceholderChunk("type");
2019 Builder.AddChunk(CodeCompletionString::CK_LeftBracket);
2020 Builder.AddPlaceholderChunk("size");
2021 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
2022 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2023 Builder.AddPlaceholderChunk("expressions");
2024 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2025 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002026
Douglas Gregorf4c33342010-05-28 00:22:41 +00002027 // delete expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00002028 Builder.AddResultTypeChunk("void");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002029 Builder.AddTypedTextChunk("delete");
2030 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2031 Builder.AddPlaceholderChunk("expression");
2032 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002033
Douglas Gregorf4c33342010-05-28 00:22:41 +00002034 // delete [] expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00002035 Builder.AddResultTypeChunk("void");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002036 Builder.AddTypedTextChunk("delete");
2037 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2038 Builder.AddChunk(CodeCompletionString::CK_LeftBracket);
2039 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
2040 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2041 Builder.AddPlaceholderChunk("expression");
2042 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002043
David Blaikiebbafb8a2012-03-11 07:00:24 +00002044 if (SemaRef.getLangOpts().CXXExceptions) {
Douglas Gregorc05f6572011-04-12 02:47:21 +00002045 // throw expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00002046 Builder.AddResultTypeChunk("void");
Douglas Gregorc05f6572011-04-12 02:47:21 +00002047 Builder.AddTypedTextChunk("throw");
2048 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2049 Builder.AddPlaceholderChunk("expression");
2050 Results.AddResult(Result(Builder.TakeString()));
2051 }
Douglas Gregor4205fef2011-10-18 16:29:03 +00002052
Douglas Gregora2db7932010-05-26 22:00:08 +00002053 // FIXME: Rethrow?
Douglas Gregor4205fef2011-10-18 16:29:03 +00002054
Richard Smith2bf7fdb2013-01-02 11:42:31 +00002055 if (SemaRef.getLangOpts().CPlusPlus11) {
Douglas Gregor4205fef2011-10-18 16:29:03 +00002056 // nullptr
Douglas Gregore5c79d52011-10-18 21:20:17 +00002057 Builder.AddResultTypeChunk("std::nullptr_t");
Douglas Gregor4205fef2011-10-18 16:29:03 +00002058 Builder.AddTypedTextChunk("nullptr");
2059 Results.AddResult(Result(Builder.TakeString()));
2060
2061 // alignof
Douglas Gregore5c79d52011-10-18 21:20:17 +00002062 Builder.AddResultTypeChunk("size_t");
Douglas Gregor4205fef2011-10-18 16:29:03 +00002063 Builder.AddTypedTextChunk("alignof");
2064 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2065 Builder.AddPlaceholderChunk("type");
2066 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2067 Results.AddResult(Result(Builder.TakeString()));
2068
2069 // noexcept
Douglas Gregore5c79d52011-10-18 21:20:17 +00002070 Builder.AddResultTypeChunk("bool");
Douglas Gregor4205fef2011-10-18 16:29:03 +00002071 Builder.AddTypedTextChunk("noexcept");
2072 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2073 Builder.AddPlaceholderChunk("expression");
2074 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2075 Results.AddResult(Result(Builder.TakeString()));
2076
2077 // sizeof... expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00002078 Builder.AddResultTypeChunk("size_t");
Douglas Gregor4205fef2011-10-18 16:29:03 +00002079 Builder.AddTypedTextChunk("sizeof...");
2080 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2081 Builder.AddPlaceholderChunk("parameter-pack");
2082 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2083 Results.AddResult(Result(Builder.TakeString()));
2084 }
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002085 }
2086
David Blaikiebbafb8a2012-03-11 07:00:24 +00002087 if (SemaRef.getLangOpts().ObjC1) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002088 // Add "super", if we're in an Objective-C class with a superclass.
Ted Kremenek305a0a72010-05-31 21:43:10 +00002089 if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl()) {
2090 // The interface can be NULL.
2091 if (ObjCInterfaceDecl *ID = Method->getClassInterface())
Douglas Gregore5c79d52011-10-18 21:20:17 +00002092 if (ID->getSuperClass()) {
2093 std::string SuperType;
2094 SuperType = ID->getSuperClass()->getNameAsString();
2095 if (Method->isInstanceMethod())
2096 SuperType += " *";
2097
2098 Builder.AddResultTypeChunk(Allocator.CopyString(SuperType));
2099 Builder.AddTypedTextChunk("super");
2100 Results.AddResult(Result(Builder.TakeString()));
2101 }
Ted Kremenek305a0a72010-05-31 21:43:10 +00002102 }
2103
Douglas Gregorf98e6a22010-01-13 23:51:12 +00002104 AddObjCExpressionResults(Results, true);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002105 }
2106
Jordan Rose58d54722012-06-30 21:33:57 +00002107 if (SemaRef.getLangOpts().C11) {
2108 // _Alignof
2109 Builder.AddResultTypeChunk("size_t");
Richard Smith20e883e2015-04-29 23:20:19 +00002110 if (SemaRef.PP.isMacroDefined("alignof"))
Jordan Rose58d54722012-06-30 21:33:57 +00002111 Builder.AddTypedTextChunk("alignof");
2112 else
2113 Builder.AddTypedTextChunk("_Alignof");
2114 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2115 Builder.AddPlaceholderChunk("type");
2116 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2117 Results.AddResult(Result(Builder.TakeString()));
2118 }
2119
Douglas Gregorf4c33342010-05-28 00:22:41 +00002120 // sizeof expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00002121 Builder.AddResultTypeChunk("size_t");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002122 Builder.AddTypedTextChunk("sizeof");
2123 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2124 Builder.AddPlaceholderChunk("expression-or-type");
2125 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2126 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002127 break;
2128 }
Douglas Gregor99fa2642010-08-24 01:06:58 +00002129
John McCallfaf5fb42010-08-26 23:41:50 +00002130 case Sema::PCC_Type:
Douglas Gregor80039242011-02-15 20:33:25 +00002131 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregor99fa2642010-08-24 01:06:58 +00002132 break;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002133 }
2134
David Blaikiebbafb8a2012-03-11 07:00:24 +00002135 if (WantTypesInContext(CCC, SemaRef.getLangOpts()))
2136 AddTypeSpecifierResults(SemaRef.getLangOpts(), Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002137
David Blaikiebbafb8a2012-03-11 07:00:24 +00002138 if (SemaRef.getLangOpts().CPlusPlus && CCC != Sema::PCC_Type)
Douglas Gregor78a21012010-01-14 16:01:26 +00002139 Results.AddResult(Result("operator"));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002140}
2141
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002142/// If the given declaration has an associated type, add it as a result
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002143/// type chunk.
2144static void AddResultTypeChunk(ASTContext &Context,
Douglas Gregor75acd922011-09-27 23:30:47 +00002145 const PrintingPolicy &Policy,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002146 const NamedDecl *ND,
Douglas Gregorc3425b12015-07-07 06:20:19 +00002147 QualType BaseType,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002148 CodeCompletionBuilder &Result) {
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002149 if (!ND)
2150 return;
Douglas Gregor0212fd72010-09-21 16:06:22 +00002151
2152 // Skip constructors and conversion functions, which have their return types
2153 // built into their names.
Sam McCall63c59722018-01-22 20:44:47 +00002154 if (isConstructor(ND) || isa<CXXConversionDecl>(ND))
Douglas Gregor0212fd72010-09-21 16:06:22 +00002155 return;
2156
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002157 // Determine the type of the declaration (if it has a type).
Alp Tokera2794f92014-01-22 07:29:52 +00002158 QualType T;
2159 if (const FunctionDecl *Function = ND->getAsFunction())
Alp Toker314cc812014-01-25 16:55:45 +00002160 T = Function->getReturnType();
Douglas Gregorc3425b12015-07-07 06:20:19 +00002161 else if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND)) {
2162 if (!BaseType.isNull())
2163 T = Method->getSendResultType(BaseType);
2164 else
2165 T = Method->getReturnType();
Ilya Biryukovb5da91c2017-11-08 10:39:09 +00002166 } else if (const EnumConstantDecl *Enumerator = dyn_cast<EnumConstantDecl>(ND)) {
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002167 T = Context.getTypeDeclType(cast<TypeDecl>(Enumerator->getDeclContext()));
Ilya Biryukovb5da91c2017-11-08 10:39:09 +00002168 T = clang::TypeName::getFullyQualifiedType(T, Context);
2169 } else if (isa<UnresolvedUsingValueDecl>(ND)) {
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002170 /* Do nothing: ignore unresolved using declarations*/
Douglas Gregorc3425b12015-07-07 06:20:19 +00002171 } else if (const ObjCIvarDecl *Ivar = dyn_cast<ObjCIvarDecl>(ND)) {
2172 if (!BaseType.isNull())
2173 T = Ivar->getUsageType(BaseType);
2174 else
2175 T = Ivar->getType();
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002176 } else if (const ValueDecl *Value = dyn_cast<ValueDecl>(ND)) {
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002177 T = Value->getType();
Douglas Gregorc3425b12015-07-07 06:20:19 +00002178 } else if (const ObjCPropertyDecl *Property = dyn_cast<ObjCPropertyDecl>(ND)) {
2179 if (!BaseType.isNull())
2180 T = Property->getUsageType(BaseType);
2181 else
2182 T = Property->getType();
2183 }
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002184
2185 if (T.isNull() || Context.hasSameType(T, Context.DependentTy))
2186 return;
2187
Douglas Gregor75acd922011-09-27 23:30:47 +00002188 Result.AddResultTypeChunk(GetCompletionTypeString(T, Context, Policy,
Douglas Gregor304f9b02011-02-01 21:15:40 +00002189 Result.getAllocator()));
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002190}
2191
Richard Smith20e883e2015-04-29 23:20:19 +00002192static void MaybeAddSentinel(Preprocessor &PP,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002193 const NamedDecl *FunctionOrMethod,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002194 CodeCompletionBuilder &Result) {
Douglas Gregordbb71db2010-08-23 23:51:41 +00002195 if (SentinelAttr *Sentinel = FunctionOrMethod->getAttr<SentinelAttr>())
2196 if (Sentinel->getSentinel() == 0) {
Richard Smith20e883e2015-04-29 23:20:19 +00002197 if (PP.getLangOpts().ObjC1 && PP.isMacroDefined("nil"))
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002198 Result.AddTextChunk(", nil");
Richard Smith20e883e2015-04-29 23:20:19 +00002199 else if (PP.isMacroDefined("NULL"))
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002200 Result.AddTextChunk(", NULL");
Douglas Gregordbb71db2010-08-23 23:51:41 +00002201 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002202 Result.AddTextChunk(", (void*)0");
Douglas Gregordbb71db2010-08-23 23:51:41 +00002203 }
2204}
2205
Douglas Gregor86b42682015-06-19 18:27:52 +00002206static std::string formatObjCParamQualifiers(unsigned ObjCQuals,
2207 QualType &Type) {
Douglas Gregor8f08d742011-07-30 07:55:26 +00002208 std::string Result;
2209 if (ObjCQuals & Decl::OBJC_TQ_In)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002210 Result += "in ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002211 else if (ObjCQuals & Decl::OBJC_TQ_Inout)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002212 Result += "inout ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002213 else if (ObjCQuals & Decl::OBJC_TQ_Out)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002214 Result += "out ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002215 if (ObjCQuals & Decl::OBJC_TQ_Bycopy)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002216 Result += "bycopy ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002217 else if (ObjCQuals & Decl::OBJC_TQ_Byref)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002218 Result += "byref ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002219 if (ObjCQuals & Decl::OBJC_TQ_Oneway)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002220 Result += "oneway ";
Douglas Gregor86b42682015-06-19 18:27:52 +00002221 if (ObjCQuals & Decl::OBJC_TQ_CSNullability) {
2222 if (auto nullability = AttributedType::stripOuterNullability(Type)) {
2223 switch (*nullability) {
2224 case NullabilityKind::NonNull:
2225 Result += "nonnull ";
2226 break;
2227
2228 case NullabilityKind::Nullable:
2229 Result += "nullable ";
2230 break;
2231
2232 case NullabilityKind::Unspecified:
2233 Result += "null_unspecified ";
2234 break;
2235 }
2236 }
2237 }
Douglas Gregor8f08d742011-07-30 07:55:26 +00002238 return Result;
2239}
2240
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002241/// Tries to find the most appropriate type location for an Objective-C
Alex Lorenza1951202016-10-18 10:35:27 +00002242/// block placeholder.
2243///
2244/// This function ignores things like typedefs and qualifiers in order to
2245/// present the most relevant and accurate block placeholders in code completion
2246/// results.
2247static void findTypeLocationForBlockDecl(const TypeSourceInfo *TSInfo,
2248 FunctionTypeLoc &Block,
2249 FunctionProtoTypeLoc &BlockProto,
2250 bool SuppressBlock = false) {
2251 if (!TSInfo)
2252 return;
2253 TypeLoc TL = TSInfo->getTypeLoc().getUnqualifiedLoc();
2254 while (true) {
2255 // Look through typedefs.
2256 if (!SuppressBlock) {
2257 if (TypedefTypeLoc TypedefTL = TL.getAs<TypedefTypeLoc>()) {
2258 if (TypeSourceInfo *InnerTSInfo =
2259 TypedefTL.getTypedefNameDecl()->getTypeSourceInfo()) {
2260 TL = InnerTSInfo->getTypeLoc().getUnqualifiedLoc();
2261 continue;
2262 }
2263 }
2264
2265 // Look through qualified types
2266 if (QualifiedTypeLoc QualifiedTL = TL.getAs<QualifiedTypeLoc>()) {
2267 TL = QualifiedTL.getUnqualifiedLoc();
2268 continue;
2269 }
2270
2271 if (AttributedTypeLoc AttrTL = TL.getAs<AttributedTypeLoc>()) {
2272 TL = AttrTL.getModifiedLoc();
2273 continue;
2274 }
2275 }
2276
2277 // Try to get the function prototype behind the block pointer type,
2278 // then we're done.
2279 if (BlockPointerTypeLoc BlockPtr = TL.getAs<BlockPointerTypeLoc>()) {
2280 TL = BlockPtr.getPointeeLoc().IgnoreParens();
2281 Block = TL.getAs<FunctionTypeLoc>();
2282 BlockProto = TL.getAs<FunctionProtoTypeLoc>();
2283 }
2284 break;
2285 }
2286}
2287
Alex Lorenz920ae142016-10-18 10:38:58 +00002288static std::string
2289formatBlockPlaceholder(const PrintingPolicy &Policy, const NamedDecl *BlockDecl,
2290 FunctionTypeLoc &Block, FunctionProtoTypeLoc &BlockProto,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002291 bool SuppressBlockName = false,
Alex Lorenz920ae142016-10-18 10:38:58 +00002292 bool SuppressBlock = false,
2293 Optional<ArrayRef<QualType>> ObjCSubsts = None);
2294
Richard Smith20e883e2015-04-29 23:20:19 +00002295static std::string FormatFunctionParameter(const PrintingPolicy &Policy,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002296 const ParmVarDecl *Param,
Douglas Gregord793e7c2011-10-18 04:23:19 +00002297 bool SuppressName = false,
Douglas Gregorc3425b12015-07-07 06:20:19 +00002298 bool SuppressBlock = false,
2299 Optional<ArrayRef<QualType>> ObjCSubsts = None) {
Douglas Gregore90dd002010-08-24 16:15:59 +00002300 bool ObjCMethodParam = isa<ObjCMethodDecl>(Param->getDeclContext());
2301 if (Param->getType()->isDependentType() ||
2302 !Param->getType()->isBlockPointerType()) {
2303 // The argument for a dependent or non-block parameter is a placeholder
2304 // containing that parameter's type.
2305 std::string Result;
2306
Douglas Gregor981a0c42010-08-29 19:47:46 +00002307 if (Param->getIdentifier() && !ObjCMethodParam && !SuppressName)
Douglas Gregore90dd002010-08-24 16:15:59 +00002308 Result = Param->getIdentifier()->getName();
2309
Douglas Gregor86b42682015-06-19 18:27:52 +00002310 QualType Type = Param->getType();
Douglas Gregorc3425b12015-07-07 06:20:19 +00002311 if (ObjCSubsts)
2312 Type = Type.substObjCTypeArgs(Param->getASTContext(), *ObjCSubsts,
2313 ObjCSubstitutionContext::Parameter);
Douglas Gregore90dd002010-08-24 16:15:59 +00002314 if (ObjCMethodParam) {
Douglas Gregor86b42682015-06-19 18:27:52 +00002315 Result = "(" + formatObjCParamQualifiers(Param->getObjCDeclQualifier(),
2316 Type);
2317 Result += Type.getAsString(Policy) + ")";
Douglas Gregor981a0c42010-08-29 19:47:46 +00002318 if (Param->getIdentifier() && !SuppressName)
Douglas Gregore90dd002010-08-24 16:15:59 +00002319 Result += Param->getIdentifier()->getName();
Douglas Gregor86b42682015-06-19 18:27:52 +00002320 } else {
2321 Type.getAsStringInternal(Result, Policy);
Douglas Gregore90dd002010-08-24 16:15:59 +00002322 }
2323 return Result;
2324 }
Alex Lorenza1951202016-10-18 10:35:27 +00002325
Douglas Gregore90dd002010-08-24 16:15:59 +00002326 // The argument for a block pointer parameter is a block literal with
2327 // the appropriate type.
David Blaikie6adc78e2013-02-18 22:06:02 +00002328 FunctionTypeLoc Block;
2329 FunctionProtoTypeLoc BlockProto;
Alex Lorenza1951202016-10-18 10:35:27 +00002330 findTypeLocationForBlockDecl(Param->getTypeSourceInfo(), Block, BlockProto,
2331 SuppressBlock);
Alex Lorenz6bf4a582017-03-13 15:43:42 +00002332 // Try to retrieve the block type information from the property if this is a
2333 // parameter in a setter.
2334 if (!Block && ObjCMethodParam &&
2335 cast<ObjCMethodDecl>(Param->getDeclContext())->isPropertyAccessor()) {
2336 if (const auto *PD = cast<ObjCMethodDecl>(Param->getDeclContext())
2337 ->findPropertyDecl(/*CheckOverrides=*/false))
2338 findTypeLocationForBlockDecl(PD->getTypeSourceInfo(), Block, BlockProto,
2339 SuppressBlock);
2340 }
Douglas Gregore90dd002010-08-24 16:15:59 +00002341
2342 if (!Block) {
2343 // We were unable to find a FunctionProtoTypeLoc with parameter names
2344 // for the block; just use the parameter type as a placeholder.
2345 std::string Result;
Douglas Gregord793e7c2011-10-18 04:23:19 +00002346 if (!ObjCMethodParam && Param->getIdentifier())
2347 Result = Param->getIdentifier()->getName();
2348
Douglas Gregor86b42682015-06-19 18:27:52 +00002349 QualType Type = Param->getType().getUnqualifiedType();
Douglas Gregore90dd002010-08-24 16:15:59 +00002350
2351 if (ObjCMethodParam) {
Alex Lorenz01bcfc12016-11-23 16:28:34 +00002352 Result = Type.getAsString(Policy);
2353 std::string Quals =
2354 formatObjCParamQualifiers(Param->getObjCDeclQualifier(), Type);
2355 if (!Quals.empty())
2356 Result = "(" + Quals + " " + Result + ")";
2357 if (Result.back() != ')')
2358 Result += " ";
Douglas Gregore90dd002010-08-24 16:15:59 +00002359 if (Param->getIdentifier())
2360 Result += Param->getIdentifier()->getName();
Douglas Gregor86b42682015-06-19 18:27:52 +00002361 } else {
2362 Type.getAsStringInternal(Result, Policy);
Douglas Gregore90dd002010-08-24 16:15:59 +00002363 }
2364
2365 return Result;
2366 }
Alex Lorenz01bcfc12016-11-23 16:28:34 +00002367
Douglas Gregore90dd002010-08-24 16:15:59 +00002368 // We have the function prototype behind the block pointer type, as it was
2369 // written in the source.
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002370 return formatBlockPlaceholder(Policy, Param, Block, BlockProto,
2371 /*SuppressBlockName=*/false, SuppressBlock,
Alex Lorenz920ae142016-10-18 10:38:58 +00002372 ObjCSubsts);
2373}
2374
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002375/// Returns a placeholder string that corresponds to an Objective-C block
Alex Lorenz920ae142016-10-18 10:38:58 +00002376/// declaration.
2377///
2378/// \param BlockDecl A declaration with an Objective-C block type.
2379///
2380/// \param Block The most relevant type location for that block type.
2381///
Alexander Kornienko2a8c18d2018-04-06 15:14:32 +00002382/// \param SuppressBlockName Determines whether or not the name of the block
Alex Lorenz920ae142016-10-18 10:38:58 +00002383/// declaration is included in the resulting string.
2384static std::string
2385formatBlockPlaceholder(const PrintingPolicy &Policy, const NamedDecl *BlockDecl,
2386 FunctionTypeLoc &Block, FunctionProtoTypeLoc &BlockProto,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002387 bool SuppressBlockName, bool SuppressBlock,
Alex Lorenz920ae142016-10-18 10:38:58 +00002388 Optional<ArrayRef<QualType>> ObjCSubsts) {
Douglas Gregor67da50e2010-09-08 22:47:51 +00002389 std::string Result;
Alp Toker314cc812014-01-25 16:55:45 +00002390 QualType ResultType = Block.getTypePtr()->getReturnType();
Douglas Gregorc3425b12015-07-07 06:20:19 +00002391 if (ObjCSubsts)
Alex Lorenz920ae142016-10-18 10:38:58 +00002392 ResultType =
2393 ResultType.substObjCTypeArgs(BlockDecl->getASTContext(), *ObjCSubsts,
2394 ObjCSubstitutionContext::Result);
Douglas Gregord793e7c2011-10-18 04:23:19 +00002395 if (!ResultType->isVoidType() || SuppressBlock)
John McCall31168b02011-06-15 23:02:42 +00002396 ResultType.getAsStringInternal(Result, Policy);
Douglas Gregord793e7c2011-10-18 04:23:19 +00002397
2398 // Format the parameter list.
2399 std::string Params;
Alp Tokerb3fd5cf2014-01-21 00:32:38 +00002400 if (!BlockProto || Block.getNumParams() == 0) {
David Blaikie6adc78e2013-02-18 22:06:02 +00002401 if (BlockProto && BlockProto.getTypePtr()->isVariadic())
Douglas Gregord793e7c2011-10-18 04:23:19 +00002402 Params = "(...)";
Douglas Gregoraf25cfa2010-10-02 23:49:58 +00002403 else
Douglas Gregord793e7c2011-10-18 04:23:19 +00002404 Params = "(void)";
Douglas Gregor67da50e2010-09-08 22:47:51 +00002405 } else {
Douglas Gregord793e7c2011-10-18 04:23:19 +00002406 Params += "(";
Alp Tokerb3fd5cf2014-01-21 00:32:38 +00002407 for (unsigned I = 0, N = Block.getNumParams(); I != N; ++I) {
Douglas Gregor67da50e2010-09-08 22:47:51 +00002408 if (I)
Douglas Gregord793e7c2011-10-18 04:23:19 +00002409 Params += ", ";
Richard Smith20e883e2015-04-29 23:20:19 +00002410 Params += FormatFunctionParameter(Policy, Block.getParam(I),
Alp Tokerb3fd5cf2014-01-21 00:32:38 +00002411 /*SuppressName=*/false,
Alex Lorenz920ae142016-10-18 10:38:58 +00002412 /*SuppressBlock=*/true, ObjCSubsts);
Alp Tokerb3fd5cf2014-01-21 00:32:38 +00002413
David Blaikie6adc78e2013-02-18 22:06:02 +00002414 if (I == N - 1 && BlockProto.getTypePtr()->isVariadic())
Douglas Gregord793e7c2011-10-18 04:23:19 +00002415 Params += ", ...";
Douglas Gregor67da50e2010-09-08 22:47:51 +00002416 }
Douglas Gregord793e7c2011-10-18 04:23:19 +00002417 Params += ")";
Douglas Gregor400f5972010-08-31 05:13:43 +00002418 }
Alex Lorenz920ae142016-10-18 10:38:58 +00002419
Douglas Gregord793e7c2011-10-18 04:23:19 +00002420 if (SuppressBlock) {
2421 // Format as a parameter.
2422 Result = Result + " (^";
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002423 if (!SuppressBlockName && BlockDecl->getIdentifier())
Alex Lorenz920ae142016-10-18 10:38:58 +00002424 Result += BlockDecl->getIdentifier()->getName();
Douglas Gregord793e7c2011-10-18 04:23:19 +00002425 Result += ")";
2426 Result += Params;
2427 } else {
2428 // Format as a block literal argument.
2429 Result = '^' + Result;
2430 Result += Params;
Alex Lorenz920ae142016-10-18 10:38:58 +00002431
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002432 if (!SuppressBlockName && BlockDecl->getIdentifier())
Alex Lorenz920ae142016-10-18 10:38:58 +00002433 Result += BlockDecl->getIdentifier()->getName();
Douglas Gregord793e7c2011-10-18 04:23:19 +00002434 }
Alex Lorenz920ae142016-10-18 10:38:58 +00002435
Douglas Gregore90dd002010-08-24 16:15:59 +00002436 return Result;
2437}
2438
Erik Verbruggen11338c52017-07-19 10:45:40 +00002439static std::string GetDefaultValueString(const ParmVarDecl *Param,
2440 const SourceManager &SM,
2441 const LangOptions &LangOpts) {
Ilya Biryukovb6d1ec82017-07-21 09:24:00 +00002442 const SourceRange SrcRange = Param->getDefaultArgRange();
Erik Verbruggen11338c52017-07-19 10:45:40 +00002443 CharSourceRange CharSrcRange = CharSourceRange::getTokenRange(SrcRange);
2444 bool Invalid = CharSrcRange.isInvalid();
2445 if (Invalid)
2446 return "";
2447 StringRef srcText = Lexer::getSourceText(CharSrcRange, SM, LangOpts, &Invalid);
2448 if (Invalid)
2449 return "";
2450
2451 if (srcText.empty() || srcText == "=") {
2452 // Lexer can't determine the value.
2453 // This happens if the code is incorrect (for example class is forward declared).
2454 return "";
2455 }
Erik Verbruggen797980e2017-07-19 11:15:36 +00002456 std::string DefValue(srcText.str());
Erik Verbruggen11338c52017-07-19 10:45:40 +00002457 // FIXME: remove this check if the Lexer::getSourceText value is fixed and
2458 // this value always has (or always does not have) '=' in front of it
2459 if (DefValue.at(0) != '=') {
2460 // If we don't have '=' in front of value.
2461 // Lexer returns built-in types values without '=' and user-defined types values with it.
2462 return " = " + DefValue;
2463 }
2464 return " " + DefValue;
2465}
2466
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002467/// Add function parameter chunks to the given code completion string.
Richard Smith20e883e2015-04-29 23:20:19 +00002468static void AddFunctionParameterChunks(Preprocessor &PP,
Douglas Gregor75acd922011-09-27 23:30:47 +00002469 const PrintingPolicy &Policy,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002470 const FunctionDecl *Function,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002471 CodeCompletionBuilder &Result,
2472 unsigned Start = 0,
2473 bool InOptional = false) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002474 bool FirstParameter = true;
Douglas Gregor9eb77012009-11-07 00:00:49 +00002475
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002476 for (unsigned P = Start, N = Function->getNumParams(); P != N; ++P) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002477 const ParmVarDecl *Param = Function->getParamDecl(P);
Douglas Gregor3545ff42009-09-21 16:56:56 +00002478
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002479 if (Param->hasDefaultArg() && !InOptional) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002480 // When we see an optional default argument, put that argument and
2481 // the remaining default arguments into a new, optional string.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00002482 CodeCompletionBuilder Opt(Result.getAllocator(),
2483 Result.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002484 if (!FirstParameter)
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002485 Opt.AddChunk(CodeCompletionString::CK_Comma);
Richard Smith20e883e2015-04-29 23:20:19 +00002486 AddFunctionParameterChunks(PP, Policy, Function, Opt, P, true);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002487 Result.AddOptionalChunk(Opt.TakeString());
2488 break;
Douglas Gregor3545ff42009-09-21 16:56:56 +00002489 }
2490
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002491 if (FirstParameter)
2492 FirstParameter = false;
2493 else
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002494 Result.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002495
2496 InOptional = false;
Douglas Gregor3545ff42009-09-21 16:56:56 +00002497
2498 // Format the placeholder string.
Richard Smith20e883e2015-04-29 23:20:19 +00002499 std::string PlaceholderStr = FormatFunctionParameter(Policy, Param);
Erik Verbruggen11338c52017-07-19 10:45:40 +00002500 if (Param->hasDefaultArg())
2501 PlaceholderStr += GetDefaultValueString(Param, PP.getSourceManager(), PP.getLangOpts());
Richard Smith20e883e2015-04-29 23:20:19 +00002502
Douglas Gregor400f5972010-08-31 05:13:43 +00002503 if (Function->isVariadic() && P == N - 1)
2504 PlaceholderStr += ", ...";
2505
Douglas Gregor3545ff42009-09-21 16:56:56 +00002506 // Add the placeholder string.
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002507 Result.AddPlaceholderChunk(
2508 Result.getAllocator().CopyString(PlaceholderStr));
Douglas Gregor3545ff42009-09-21 16:56:56 +00002509 }
Douglas Gregorba449032009-09-22 21:42:17 +00002510
2511 if (const FunctionProtoType *Proto
2512 = Function->getType()->getAs<FunctionProtoType>())
Douglas Gregordbb71db2010-08-23 23:51:41 +00002513 if (Proto->isVariadic()) {
Alp Toker9cacbab2014-01-20 20:26:09 +00002514 if (Proto->getNumParams() == 0)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002515 Result.AddPlaceholderChunk("...");
Douglas Gregordbb71db2010-08-23 23:51:41 +00002516
Richard Smith20e883e2015-04-29 23:20:19 +00002517 MaybeAddSentinel(PP, Function, Result);
Douglas Gregordbb71db2010-08-23 23:51:41 +00002518 }
Douglas Gregor3545ff42009-09-21 16:56:56 +00002519}
2520
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002521/// Add template parameter chunks to the given code completion string.
Douglas Gregor3545ff42009-09-21 16:56:56 +00002522static void AddTemplateParameterChunks(ASTContext &Context,
Douglas Gregor75acd922011-09-27 23:30:47 +00002523 const PrintingPolicy &Policy,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002524 const TemplateDecl *Template,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002525 CodeCompletionBuilder &Result,
2526 unsigned MaxParameters = 0,
2527 unsigned Start = 0,
2528 bool InDefaultArg = false) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002529 bool FirstParameter = true;
Richard Smith6eece292015-01-15 02:27:20 +00002530
2531 // Prefer to take the template parameter names from the first declaration of
2532 // the template.
2533 Template = cast<TemplateDecl>(Template->getCanonicalDecl());
2534
Douglas Gregor3545ff42009-09-21 16:56:56 +00002535 TemplateParameterList *Params = Template->getTemplateParameters();
2536 TemplateParameterList::iterator PEnd = Params->end();
2537 if (MaxParameters)
2538 PEnd = Params->begin() + MaxParameters;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002539 for (TemplateParameterList::iterator P = Params->begin() + Start;
2540 P != PEnd; ++P) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002541 bool HasDefaultArg = false;
2542 std::string PlaceholderStr;
2543 if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*P)) {
2544 if (TTP->wasDeclaredWithTypename())
2545 PlaceholderStr = "typename";
2546 else
2547 PlaceholderStr = "class";
2548
2549 if (TTP->getIdentifier()) {
2550 PlaceholderStr += ' ';
2551 PlaceholderStr += TTP->getIdentifier()->getName();
2552 }
2553
2554 HasDefaultArg = TTP->hasDefaultArgument();
2555 } else if (NonTypeTemplateParmDecl *NTTP
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002556 = dyn_cast<NonTypeTemplateParmDecl>(*P)) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002557 if (NTTP->getIdentifier())
2558 PlaceholderStr = NTTP->getIdentifier()->getName();
John McCall31168b02011-06-15 23:02:42 +00002559 NTTP->getType().getAsStringInternal(PlaceholderStr, Policy);
Douglas Gregor3545ff42009-09-21 16:56:56 +00002560 HasDefaultArg = NTTP->hasDefaultArgument();
2561 } else {
2562 assert(isa<TemplateTemplateParmDecl>(*P));
2563 TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*P);
2564
2565 // Since putting the template argument list into the placeholder would
2566 // be very, very long, we just use an abbreviation.
2567 PlaceholderStr = "template<...> class";
2568 if (TTP->getIdentifier()) {
2569 PlaceholderStr += ' ';
2570 PlaceholderStr += TTP->getIdentifier()->getName();
2571 }
2572
2573 HasDefaultArg = TTP->hasDefaultArgument();
2574 }
2575
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002576 if (HasDefaultArg && !InDefaultArg) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002577 // When we see an optional default argument, put that argument and
2578 // the remaining default arguments into a new, optional string.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00002579 CodeCompletionBuilder Opt(Result.getAllocator(),
2580 Result.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002581 if (!FirstParameter)
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002582 Opt.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor75acd922011-09-27 23:30:47 +00002583 AddTemplateParameterChunks(Context, Policy, Template, Opt, MaxParameters,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002584 P - Params->begin(), true);
2585 Result.AddOptionalChunk(Opt.TakeString());
2586 break;
Douglas Gregor3545ff42009-09-21 16:56:56 +00002587 }
2588
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002589 InDefaultArg = false;
2590
Douglas Gregor3545ff42009-09-21 16:56:56 +00002591 if (FirstParameter)
2592 FirstParameter = false;
2593 else
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002594 Result.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor3545ff42009-09-21 16:56:56 +00002595
2596 // Add the placeholder string.
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002597 Result.AddPlaceholderChunk(
2598 Result.getAllocator().CopyString(PlaceholderStr));
Douglas Gregor3545ff42009-09-21 16:56:56 +00002599 }
2600}
2601
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002602/// Add a qualifier to the given code-completion string, if the
Douglas Gregorf2510672009-09-21 19:57:38 +00002603/// provided nested-name-specifier is non-NULL.
Douglas Gregor0f622362009-12-11 18:44:16 +00002604static void
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002605AddQualifierToCompletionString(CodeCompletionBuilder &Result,
Douglas Gregor0f622362009-12-11 18:44:16 +00002606 NestedNameSpecifier *Qualifier,
2607 bool QualifierIsInformative,
Douglas Gregor75acd922011-09-27 23:30:47 +00002608 ASTContext &Context,
2609 const PrintingPolicy &Policy) {
Douglas Gregorf2510672009-09-21 19:57:38 +00002610 if (!Qualifier)
2611 return;
2612
2613 std::string PrintedNNS;
2614 {
2615 llvm::raw_string_ostream OS(PrintedNNS);
Douglas Gregor75acd922011-09-27 23:30:47 +00002616 Qualifier->print(OS, Policy);
Douglas Gregorf2510672009-09-21 19:57:38 +00002617 }
Douglas Gregor5bf52692009-09-22 23:15:58 +00002618 if (QualifierIsInformative)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002619 Result.AddInformativeChunk(Result.getAllocator().CopyString(PrintedNNS));
Douglas Gregor5bf52692009-09-22 23:15:58 +00002620 else
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002621 Result.AddTextChunk(Result.getAllocator().CopyString(PrintedNNS));
Douglas Gregorf2510672009-09-21 19:57:38 +00002622}
2623
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002624static void
2625AddFunctionTypeQualsToCompletionString(CodeCompletionBuilder &Result,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002626 const FunctionDecl *Function) {
Douglas Gregor0f622362009-12-11 18:44:16 +00002627 const FunctionProtoType *Proto
2628 = Function->getType()->getAs<FunctionProtoType>();
2629 if (!Proto || !Proto->getTypeQuals())
2630 return;
2631
Douglas Gregor304f9b02011-02-01 21:15:40 +00002632 // FIXME: Add ref-qualifier!
2633
2634 // Handle single qualifiers without copying
2635 if (Proto->getTypeQuals() == Qualifiers::Const) {
2636 Result.AddInformativeChunk(" const");
2637 return;
2638 }
2639
2640 if (Proto->getTypeQuals() == Qualifiers::Volatile) {
2641 Result.AddInformativeChunk(" volatile");
2642 return;
2643 }
2644
2645 if (Proto->getTypeQuals() == Qualifiers::Restrict) {
2646 Result.AddInformativeChunk(" restrict");
2647 return;
2648 }
2649
2650 // Handle multiple qualifiers.
Douglas Gregor0f622362009-12-11 18:44:16 +00002651 std::string QualsStr;
David Blaikief5697e52012-08-10 00:55:35 +00002652 if (Proto->isConst())
Douglas Gregor0f622362009-12-11 18:44:16 +00002653 QualsStr += " const";
David Blaikief5697e52012-08-10 00:55:35 +00002654 if (Proto->isVolatile())
Douglas Gregor0f622362009-12-11 18:44:16 +00002655 QualsStr += " volatile";
David Blaikief5697e52012-08-10 00:55:35 +00002656 if (Proto->isRestrict())
Douglas Gregor0f622362009-12-11 18:44:16 +00002657 QualsStr += " restrict";
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002658 Result.AddInformativeChunk(Result.getAllocator().CopyString(QualsStr));
Douglas Gregor0f622362009-12-11 18:44:16 +00002659}
2660
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002661/// Add the name of the given declaration
Douglas Gregor75acd922011-09-27 23:30:47 +00002662static void AddTypedNameChunk(ASTContext &Context, const PrintingPolicy &Policy,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002663 const NamedDecl *ND,
2664 CodeCompletionBuilder &Result) {
Douglas Gregor0212fd72010-09-21 16:06:22 +00002665 DeclarationName Name = ND->getDeclName();
2666 if (!Name)
2667 return;
2668
2669 switch (Name.getNameKind()) {
Douglas Gregor304f9b02011-02-01 21:15:40 +00002670 case DeclarationName::CXXOperatorName: {
Craig Topperc3ec1492014-05-26 06:22:03 +00002671 const char *OperatorName = nullptr;
Douglas Gregor304f9b02011-02-01 21:15:40 +00002672 switch (Name.getCXXOverloadedOperator()) {
2673 case OO_None:
2674 case OO_Conditional:
2675 case NUM_OVERLOADED_OPERATORS:
2676 OperatorName = "operator";
2677 break;
2678
2679#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
2680 case OO_##Name: OperatorName = "operator" Spelling; break;
2681#define OVERLOADED_OPERATOR_MULTI(Name,Spelling,Unary,Binary,MemberOnly)
2682#include "clang/Basic/OperatorKinds.def"
2683
2684 case OO_New: OperatorName = "operator new"; break;
2685 case OO_Delete: OperatorName = "operator delete"; break;
2686 case OO_Array_New: OperatorName = "operator new[]"; break;
2687 case OO_Array_Delete: OperatorName = "operator delete[]"; break;
2688 case OO_Call: OperatorName = "operator()"; break;
2689 case OO_Subscript: OperatorName = "operator[]"; break;
2690 }
2691 Result.AddTypedTextChunk(OperatorName);
2692 break;
2693 }
2694
Douglas Gregor0212fd72010-09-21 16:06:22 +00002695 case DeclarationName::Identifier:
2696 case DeclarationName::CXXConversionFunctionName:
Douglas Gregor0212fd72010-09-21 16:06:22 +00002697 case DeclarationName::CXXDestructorName:
2698 case DeclarationName::CXXLiteralOperatorName:
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002699 Result.AddTypedTextChunk(
2700 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor0212fd72010-09-21 16:06:22 +00002701 break;
2702
Richard Smith35845152017-02-07 01:37:30 +00002703 case DeclarationName::CXXDeductionGuideName:
Douglas Gregor0212fd72010-09-21 16:06:22 +00002704 case DeclarationName::CXXUsingDirective:
2705 case DeclarationName::ObjCZeroArgSelector:
2706 case DeclarationName::ObjCOneArgSelector:
2707 case DeclarationName::ObjCMultiArgSelector:
2708 break;
2709
2710 case DeclarationName::CXXConstructorName: {
Craig Topperc3ec1492014-05-26 06:22:03 +00002711 CXXRecordDecl *Record = nullptr;
Douglas Gregor0212fd72010-09-21 16:06:22 +00002712 QualType Ty = Name.getCXXNameType();
2713 if (const RecordType *RecordTy = Ty->getAs<RecordType>())
2714 Record = cast<CXXRecordDecl>(RecordTy->getDecl());
2715 else if (const InjectedClassNameType *InjectedTy
2716 = Ty->getAs<InjectedClassNameType>())
2717 Record = InjectedTy->getDecl();
2718 else {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002719 Result.AddTypedTextChunk(
2720 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor0212fd72010-09-21 16:06:22 +00002721 break;
2722 }
2723
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002724 Result.AddTypedTextChunk(
2725 Result.getAllocator().CopyString(Record->getNameAsString()));
Douglas Gregor0212fd72010-09-21 16:06:22 +00002726 if (ClassTemplateDecl *Template = Record->getDescribedClassTemplate()) {
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002727 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Douglas Gregor75acd922011-09-27 23:30:47 +00002728 AddTemplateParameterChunks(Context, Policy, Template, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002729 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregor0212fd72010-09-21 16:06:22 +00002730 }
2731 break;
2732 }
2733 }
2734}
2735
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002736CodeCompletionString *CodeCompletionResult::CreateCodeCompletionString(Sema &S,
Douglas Gregorc3425b12015-07-07 06:20:19 +00002737 const CodeCompletionContext &CCContext,
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00002738 CodeCompletionAllocator &Allocator,
Dmitri Gribenko3292d062012-07-02 17:35:10 +00002739 CodeCompletionTUInfo &CCTUInfo,
2740 bool IncludeBriefComments) {
Douglas Gregorc3425b12015-07-07 06:20:19 +00002741 return CreateCodeCompletionString(S.Context, S.PP, CCContext, Allocator,
2742 CCTUInfo, IncludeBriefComments);
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002743}
2744
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002745/// If possible, create a new code completion string for the given
Douglas Gregor3545ff42009-09-21 16:56:56 +00002746/// result.
2747///
2748/// \returns Either a new, heap-allocated code completion string describing
2749/// how to use this result, or NULL to indicate that the string or name of the
2750/// result is all that is needed.
2751CodeCompletionString *
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002752CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx,
2753 Preprocessor &PP,
Douglas Gregorc3425b12015-07-07 06:20:19 +00002754 const CodeCompletionContext &CCContext,
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00002755 CodeCompletionAllocator &Allocator,
Dmitri Gribenko3292d062012-07-02 17:35:10 +00002756 CodeCompletionTUInfo &CCTUInfo,
2757 bool IncludeBriefComments) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00002758 CodeCompletionBuilder Result(Allocator, CCTUInfo, Priority, Availability);
Douglas Gregor9eb77012009-11-07 00:00:49 +00002759
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002760 PrintingPolicy Policy = getCompletionPrintingPolicy(Ctx, PP);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002761 if (Kind == RK_Pattern) {
2762 Pattern->Priority = Priority;
2763 Pattern->Availability = Availability;
Douglas Gregor78254c82012-03-27 23:34:16 +00002764
2765 if (Declaration) {
2766 Result.addParentContext(Declaration->getDeclContext());
Douglas Gregor78254c82012-03-27 23:34:16 +00002767 Pattern->ParentName = Result.getParentName();
Fariborz Jahanian1fcf4922013-03-22 17:55:27 +00002768 // Provide code completion comment for self.GetterName where
2769 // GetterName is the getter method for a property with name
2770 // different from the property name (declared via a property
2771 // getter attribute.
2772 const NamedDecl *ND = Declaration;
2773 if (const ObjCMethodDecl *M = dyn_cast<ObjCMethodDecl>(ND))
2774 if (M->isPropertyAccessor())
2775 if (const ObjCPropertyDecl *PDecl = M->findPropertyDecl())
2776 if (PDecl->getGetterName() == M->getSelector() &&
Fariborz Jahanianbe8bc672013-03-23 01:10:45 +00002777 PDecl->getIdentifier() != M->getIdentifier()) {
2778 if (const RawComment *RC =
2779 Ctx.getRawCommentForAnyRedecl(M)) {
Fariborz Jahanian1fcf4922013-03-22 17:55:27 +00002780 Result.addBriefComment(RC->getBriefText(Ctx));
2781 Pattern->BriefComment = Result.getBriefComment();
2782 }
Fariborz Jahanianbe8bc672013-03-23 01:10:45 +00002783 else if (const RawComment *RC =
2784 Ctx.getRawCommentForAnyRedecl(PDecl)) {
2785 Result.addBriefComment(RC->getBriefText(Ctx));
2786 Pattern->BriefComment = Result.getBriefComment();
2787 }
2788 }
Douglas Gregor78254c82012-03-27 23:34:16 +00002789 }
2790
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002791 return Pattern;
2792 }
Douglas Gregorf09935f2009-12-01 05:55:20 +00002793
Douglas Gregorf09935f2009-12-01 05:55:20 +00002794 if (Kind == RK_Keyword) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002795 Result.AddTypedTextChunk(Keyword);
2796 return Result.TakeString();
Douglas Gregorf09935f2009-12-01 05:55:20 +00002797 }
Douglas Gregor3545ff42009-09-21 16:56:56 +00002798
Douglas Gregorf329c7c2009-10-30 16:50:04 +00002799 if (Kind == RK_Macro) {
Richard Smith20e883e2015-04-29 23:20:19 +00002800 const MacroInfo *MI = PP.getMacroInfo(Macro);
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002801 Result.AddTypedTextChunk(
2802 Result.getAllocator().CopyString(Macro->getName()));
Douglas Gregorf09935f2009-12-01 05:55:20 +00002803
Ben Langmuirc28ce3a2014-09-30 20:00:18 +00002804 if (!MI || !MI->isFunctionLike())
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002805 return Result.TakeString();
Douglas Gregorf329c7c2009-10-30 16:50:04 +00002806
2807 // Format a function-like macro with placeholders for the arguments.
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002808 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Faisal Valiac506d72017-07-17 17:18:43 +00002809 MacroInfo::param_iterator A = MI->param_begin(), AEnd = MI->param_end();
Douglas Gregor3aa55262012-01-21 00:43:38 +00002810
2811 // C99 variadic macros add __VA_ARGS__ at the end. Skip it.
2812 if (MI->isC99Varargs()) {
2813 --AEnd;
2814
2815 if (A == AEnd) {
2816 Result.AddPlaceholderChunk("...");
2817 }
Douglas Gregor0c505312011-07-30 08:17:44 +00002818 }
Douglas Gregor3aa55262012-01-21 00:43:38 +00002819
Faisal Valiac506d72017-07-17 17:18:43 +00002820 for (MacroInfo::param_iterator A = MI->param_begin(); A != AEnd; ++A) {
2821 if (A != MI->param_begin())
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002822 Result.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor3aa55262012-01-21 00:43:38 +00002823
2824 if (MI->isVariadic() && (A+1) == AEnd) {
Dylan Noblesmith2c1dd272012-02-05 02:13:05 +00002825 SmallString<32> Arg = (*A)->getName();
Douglas Gregor3aa55262012-01-21 00:43:38 +00002826 if (MI->isC99Varargs())
2827 Arg += ", ...";
2828 else
2829 Arg += "...";
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002830 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregor3aa55262012-01-21 00:43:38 +00002831 break;
Douglas Gregorf329c7c2009-10-30 16:50:04 +00002832 }
Douglas Gregor3aa55262012-01-21 00:43:38 +00002833
2834 // Non-variadic macros are simple.
2835 Result.AddPlaceholderChunk(
2836 Result.getAllocator().CopyString((*A)->getName()));
Douglas Gregor0c505312011-07-30 08:17:44 +00002837 }
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002838 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002839 return Result.TakeString();
Douglas Gregorf329c7c2009-10-30 16:50:04 +00002840 }
2841
Douglas Gregorf64acca2010-05-25 21:41:55 +00002842 assert(Kind == RK_Declaration && "Missed a result kind?");
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002843 const NamedDecl *ND = Declaration;
Douglas Gregor78254c82012-03-27 23:34:16 +00002844 Result.addParentContext(ND->getDeclContext());
Dmitri Gribenko3292d062012-07-02 17:35:10 +00002845
2846 if (IncludeBriefComments) {
2847 // Add documentation comment, if it exists.
Dmitri Gribenkoa43ec182012-08-11 00:51:43 +00002848 if (const RawComment *RC = Ctx.getRawCommentForAnyRedecl(ND)) {
Dmitri Gribenko3292d062012-07-02 17:35:10 +00002849 Result.addBriefComment(RC->getBriefText(Ctx));
Fariborz Jahanian15a0b552013-02-28 17:47:14 +00002850 }
2851 else if (const ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(ND))
2852 if (OMD->isPropertyAccessor())
2853 if (const ObjCPropertyDecl *PDecl = OMD->findPropertyDecl())
2854 if (const RawComment *RC = Ctx.getRawCommentForAnyRedecl(PDecl))
2855 Result.addBriefComment(RC->getBriefText(Ctx));
Dmitri Gribenko3292d062012-07-02 17:35:10 +00002856 }
2857
Douglas Gregor9eb77012009-11-07 00:00:49 +00002858 if (StartsNestedNameSpecifier) {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002859 Result.AddTypedTextChunk(
2860 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002861 Result.AddTextChunk("::");
2862 return Result.TakeString();
Douglas Gregor9eb77012009-11-07 00:00:49 +00002863 }
Erik Verbruggen98ea7f62011-10-14 15:31:08 +00002864
Aaron Ballmanbe22bcb2014-03-10 17:08:28 +00002865 for (const auto *I : ND->specific_attrs<AnnotateAttr>())
2866 Result.AddAnnotation(Result.getAllocator().CopyString(I->getAnnotation()));
Aaron Ballmanb97112e2014-03-08 22:19:01 +00002867
Douglas Gregorc3425b12015-07-07 06:20:19 +00002868 AddResultTypeChunk(Ctx, Policy, ND, CCContext.getBaseType(), Result);
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002869
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002870 if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(ND)) {
Douglas Gregor5bf52692009-09-22 23:15:58 +00002871 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002872 Ctx, Policy);
2873 AddTypedNameChunk(Ctx, Policy, ND, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002874 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Richard Smith20e883e2015-04-29 23:20:19 +00002875 AddFunctionParameterChunks(PP, Policy, Function, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002876 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor0f622362009-12-11 18:44:16 +00002877 AddFunctionTypeQualsToCompletionString(Result, Function);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002878 return Result.TakeString();
Douglas Gregor3545ff42009-09-21 16:56:56 +00002879 }
2880
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002881 if (const FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND)) {
Douglas Gregor5bf52692009-09-22 23:15:58 +00002882 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002883 Ctx, Policy);
Douglas Gregor3545ff42009-09-21 16:56:56 +00002884 FunctionDecl *Function = FunTmpl->getTemplatedDecl();
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002885 AddTypedNameChunk(Ctx, Policy, Function, Result);
Douglas Gregor0212fd72010-09-21 16:06:22 +00002886
Douglas Gregor3545ff42009-09-21 16:56:56 +00002887 // Figure out which template parameters are deduced (or have default
2888 // arguments).
Benjamin Kramere0513cb2012-01-30 16:17:39 +00002889 llvm::SmallBitVector Deduced;
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002890 Sema::MarkDeducedTemplateParameters(Ctx, FunTmpl, Deduced);
Douglas Gregor3545ff42009-09-21 16:56:56 +00002891 unsigned LastDeducibleArgument;
2892 for (LastDeducibleArgument = Deduced.size(); LastDeducibleArgument > 0;
2893 --LastDeducibleArgument) {
2894 if (!Deduced[LastDeducibleArgument - 1]) {
2895 // C++0x: Figure out if the template argument has a default. If so,
2896 // the user doesn't need to type this argument.
2897 // FIXME: We need to abstract template parameters better!
2898 bool HasDefaultArg = false;
2899 NamedDecl *Param = FunTmpl->getTemplateParameters()->getParam(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002900 LastDeducibleArgument - 1);
Douglas Gregor3545ff42009-09-21 16:56:56 +00002901 if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param))
2902 HasDefaultArg = TTP->hasDefaultArgument();
2903 else if (NonTypeTemplateParmDecl *NTTP
2904 = dyn_cast<NonTypeTemplateParmDecl>(Param))
2905 HasDefaultArg = NTTP->hasDefaultArgument();
2906 else {
2907 assert(isa<TemplateTemplateParmDecl>(Param));
2908 HasDefaultArg
Douglas Gregor9eb77012009-11-07 00:00:49 +00002909 = cast<TemplateTemplateParmDecl>(Param)->hasDefaultArgument();
Douglas Gregor3545ff42009-09-21 16:56:56 +00002910 }
2911
2912 if (!HasDefaultArg)
2913 break;
2914 }
2915 }
2916
2917 if (LastDeducibleArgument) {
2918 // Some of the function template arguments cannot be deduced from a
2919 // function call, so we introduce an explicit template argument list
2920 // containing all of the arguments up to the first deducible argument.
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002921 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002922 AddTemplateParameterChunks(Ctx, Policy, FunTmpl, Result,
Douglas Gregor3545ff42009-09-21 16:56:56 +00002923 LastDeducibleArgument);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002924 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregor3545ff42009-09-21 16:56:56 +00002925 }
2926
2927 // Add the function parameters
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002928 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Richard Smith20e883e2015-04-29 23:20:19 +00002929 AddFunctionParameterChunks(PP, Policy, Function, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002930 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor0f622362009-12-11 18:44:16 +00002931 AddFunctionTypeQualsToCompletionString(Result, Function);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002932 return Result.TakeString();
Douglas Gregor3545ff42009-09-21 16:56:56 +00002933 }
2934
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002935 if (const TemplateDecl *Template = dyn_cast<TemplateDecl>(ND)) {
Douglas Gregor5bf52692009-09-22 23:15:58 +00002936 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002937 Ctx, Policy);
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002938 Result.AddTypedTextChunk(
2939 Result.getAllocator().CopyString(Template->getNameAsString()));
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002940 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002941 AddTemplateParameterChunks(Ctx, Policy, Template, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002942 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002943 return Result.TakeString();
Douglas Gregor3545ff42009-09-21 16:56:56 +00002944 }
2945
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002946 if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND)) {
Douglas Gregord3c5d792009-11-17 16:44:22 +00002947 Selector Sel = Method->getSelector();
2948 if (Sel.isUnarySelector()) {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002949 Result.AddTypedTextChunk(Result.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00002950 Sel.getNameForSlot(0)));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002951 return Result.TakeString();
Douglas Gregord3c5d792009-11-17 16:44:22 +00002952 }
2953
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00002954 std::string SelName = Sel.getNameForSlot(0).str();
Douglas Gregor1b605f72009-11-19 01:08:35 +00002955 SelName += ':';
2956 if (StartParameter == 0)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002957 Result.AddTypedTextChunk(Result.getAllocator().CopyString(SelName));
Douglas Gregor1b605f72009-11-19 01:08:35 +00002958 else {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002959 Result.AddInformativeChunk(Result.getAllocator().CopyString(SelName));
Douglas Gregor1b605f72009-11-19 01:08:35 +00002960
2961 // If there is only one parameter, and we're past it, add an empty
2962 // typed-text chunk since there is nothing to type.
2963 if (Method->param_size() == 1)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002964 Result.AddTypedTextChunk("");
Douglas Gregor1b605f72009-11-19 01:08:35 +00002965 }
Douglas Gregord3c5d792009-11-17 16:44:22 +00002966 unsigned Idx = 0;
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002967 for (ObjCMethodDecl::param_const_iterator P = Method->param_begin(),
2968 PEnd = Method->param_end();
Douglas Gregord3c5d792009-11-17 16:44:22 +00002969 P != PEnd; (void)++P, ++Idx) {
2970 if (Idx > 0) {
Douglas Gregor1b605f72009-11-19 01:08:35 +00002971 std::string Keyword;
2972 if (Idx > StartParameter)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002973 Result.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregord3c5d792009-11-17 16:44:22 +00002974 if (IdentifierInfo *II = Sel.getIdentifierInfoForSlot(Idx))
Benjamin Kramer632500c2011-07-26 16:59:25 +00002975 Keyword += II->getName();
Douglas Gregord3c5d792009-11-17 16:44:22 +00002976 Keyword += ":";
Douglas Gregor95887f92010-07-08 23:20:03 +00002977 if (Idx < StartParameter || AllParametersAreInformative)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002978 Result.AddInformativeChunk(Result.getAllocator().CopyString(Keyword));
Douglas Gregor8e3e8742010-10-18 21:05:04 +00002979 else
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002980 Result.AddTypedTextChunk(Result.getAllocator().CopyString(Keyword));
Douglas Gregord3c5d792009-11-17 16:44:22 +00002981 }
Douglas Gregor1b605f72009-11-19 01:08:35 +00002982
2983 // If we're before the starting parameter, skip the placeholder.
2984 if (Idx < StartParameter)
2985 continue;
Douglas Gregord3c5d792009-11-17 16:44:22 +00002986
2987 std::string Arg;
Douglas Gregorc3425b12015-07-07 06:20:19 +00002988 QualType ParamType = (*P)->getType();
2989 Optional<ArrayRef<QualType>> ObjCSubsts;
2990 if (!CCContext.getBaseType().isNull())
2991 ObjCSubsts = CCContext.getBaseType()->getObjCSubstitutions(Method);
2992
2993 if (ParamType->isBlockPointerType() && !DeclaringEntity)
2994 Arg = FormatFunctionParameter(Policy, *P, true,
2995 /*SuppressBlock=*/false,
2996 ObjCSubsts);
Douglas Gregore90dd002010-08-24 16:15:59 +00002997 else {
Douglas Gregorc3425b12015-07-07 06:20:19 +00002998 if (ObjCSubsts)
2999 ParamType = ParamType.substObjCTypeArgs(Ctx, *ObjCSubsts,
3000 ObjCSubstitutionContext::Parameter);
Douglas Gregor86b42682015-06-19 18:27:52 +00003001 Arg = "(" + formatObjCParamQualifiers((*P)->getObjCDeclQualifier(),
Douglas Gregorc3425b12015-07-07 06:20:19 +00003002 ParamType);
3003 Arg += ParamType.getAsString(Policy) + ")";
Douglas Gregore90dd002010-08-24 16:15:59 +00003004 if (IdentifierInfo *II = (*P)->getIdentifier())
Douglas Gregor981a0c42010-08-29 19:47:46 +00003005 if (DeclaringEntity || AllParametersAreInformative)
Benjamin Kramer632500c2011-07-26 16:59:25 +00003006 Arg += II->getName();
Douglas Gregore90dd002010-08-24 16:15:59 +00003007 }
3008
Douglas Gregor400f5972010-08-31 05:13:43 +00003009 if (Method->isVariadic() && (P + 1) == PEnd)
3010 Arg += ", ...";
3011
Douglas Gregor95887f92010-07-08 23:20:03 +00003012 if (DeclaringEntity)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003013 Result.AddTextChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregor95887f92010-07-08 23:20:03 +00003014 else if (AllParametersAreInformative)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003015 Result.AddInformativeChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregorc8537c52009-11-19 07:41:15 +00003016 else
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003017 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregord3c5d792009-11-17 16:44:22 +00003018 }
3019
Douglas Gregor04c5f972009-12-23 00:21:46 +00003020 if (Method->isVariadic()) {
Douglas Gregor400f5972010-08-31 05:13:43 +00003021 if (Method->param_size() == 0) {
3022 if (DeclaringEntity)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003023 Result.AddTextChunk(", ...");
Douglas Gregor400f5972010-08-31 05:13:43 +00003024 else if (AllParametersAreInformative)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003025 Result.AddInformativeChunk(", ...");
Douglas Gregor400f5972010-08-31 05:13:43 +00003026 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003027 Result.AddPlaceholderChunk(", ...");
Douglas Gregor400f5972010-08-31 05:13:43 +00003028 }
Douglas Gregordbb71db2010-08-23 23:51:41 +00003029
Richard Smith20e883e2015-04-29 23:20:19 +00003030 MaybeAddSentinel(PP, Method, Result);
Douglas Gregor04c5f972009-12-23 00:21:46 +00003031 }
3032
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003033 return Result.TakeString();
Douglas Gregord3c5d792009-11-17 16:44:22 +00003034 }
3035
Douglas Gregorf09935f2009-12-01 05:55:20 +00003036 if (Qualifier)
Douglas Gregor5bf52692009-09-22 23:15:58 +00003037 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003038 Ctx, Policy);
Douglas Gregorf09935f2009-12-01 05:55:20 +00003039
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003040 Result.AddTypedTextChunk(
3041 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003042 return Result.TakeString();
Douglas Gregor3545ff42009-09-21 16:56:56 +00003043}
3044
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003045/// Add function overload parameter chunks to the given code completion
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003046/// string.
3047static void AddOverloadParameterChunks(ASTContext &Context,
3048 const PrintingPolicy &Policy,
3049 const FunctionDecl *Function,
3050 const FunctionProtoType *Prototype,
3051 CodeCompletionBuilder &Result,
3052 unsigned CurrentArg,
3053 unsigned Start = 0,
3054 bool InOptional = false) {
3055 bool FirstParameter = true;
3056 unsigned NumParams = Function ? Function->getNumParams()
3057 : Prototype->getNumParams();
3058
3059 for (unsigned P = Start; P != NumParams; ++P) {
3060 if (Function && Function->getParamDecl(P)->hasDefaultArg() && !InOptional) {
3061 // When we see an optional default argument, put that argument and
3062 // the remaining default arguments into a new, optional string.
3063 CodeCompletionBuilder Opt(Result.getAllocator(),
3064 Result.getCodeCompletionTUInfo());
3065 if (!FirstParameter)
3066 Opt.AddChunk(CodeCompletionString::CK_Comma);
3067 // Optional sections are nested.
3068 AddOverloadParameterChunks(Context, Policy, Function, Prototype, Opt,
3069 CurrentArg, P, /*InOptional=*/true);
3070 Result.AddOptionalChunk(Opt.TakeString());
3071 return;
3072 }
3073
3074 if (FirstParameter)
3075 FirstParameter = false;
3076 else
3077 Result.AddChunk(CodeCompletionString::CK_Comma);
3078
3079 InOptional = false;
3080
3081 // Format the placeholder string.
3082 std::string Placeholder;
Erik Verbruggen11338c52017-07-19 10:45:40 +00003083 if (Function) {
3084 const ParmVarDecl *Param = Function->getParamDecl(P);
3085 Placeholder = FormatFunctionParameter(Policy, Param);
3086 if (Param->hasDefaultArg())
3087 Placeholder += GetDefaultValueString(Param, Context.getSourceManager(), Context.getLangOpts());
3088 } else {
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003089 Placeholder = Prototype->getParamType(P).getAsString(Policy);
Erik Verbruggen11338c52017-07-19 10:45:40 +00003090 }
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003091
3092 if (P == CurrentArg)
3093 Result.AddCurrentParameterChunk(
3094 Result.getAllocator().CopyString(Placeholder));
3095 else
3096 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Placeholder));
3097 }
3098
3099 if (Prototype && Prototype->isVariadic()) {
3100 CodeCompletionBuilder Opt(Result.getAllocator(),
3101 Result.getCodeCompletionTUInfo());
3102 if (!FirstParameter)
3103 Opt.AddChunk(CodeCompletionString::CK_Comma);
3104
3105 if (CurrentArg < NumParams)
3106 Opt.AddPlaceholderChunk("...");
3107 else
3108 Opt.AddCurrentParameterChunk("...");
3109
3110 Result.AddOptionalChunk(Opt.TakeString());
3111 }
3112}
3113
Douglas Gregorf0f51982009-09-23 00:34:09 +00003114CodeCompletionString *
3115CodeCompleteConsumer::OverloadCandidate::CreateSignatureString(
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003116 unsigned CurrentArg, Sema &S,
3117 CodeCompletionAllocator &Allocator,
3118 CodeCompletionTUInfo &CCTUInfo,
3119 bool IncludeBriefComments) const {
Douglas Gregor75acd922011-09-27 23:30:47 +00003120 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
John McCall31168b02011-06-15 23:02:42 +00003121
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003122 // FIXME: Set priority, availability appropriately.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003123 CodeCompletionBuilder Result(Allocator,CCTUInfo, 1, CXAvailability_Available);
Douglas Gregorf0f51982009-09-23 00:34:09 +00003124 FunctionDecl *FDecl = getFunction();
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003125 const FunctionProtoType *Proto
Douglas Gregorf0f51982009-09-23 00:34:09 +00003126 = dyn_cast<FunctionProtoType>(getFunctionType());
3127 if (!FDecl && !Proto) {
3128 // Function without a prototype. Just give the return type and a
3129 // highlighted ellipsis.
3130 const FunctionType *FT = getFunctionType();
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003131 Result.AddResultTypeChunk(Result.getAllocator().CopyString(
3132 FT->getReturnType().getAsString(Policy)));
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003133 Result.AddChunk(CodeCompletionString::CK_LeftParen);
3134 Result.AddChunk(CodeCompletionString::CK_CurrentParameter, "...");
3135 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003136 return Result.TakeString();
Douglas Gregorf0f51982009-09-23 00:34:09 +00003137 }
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003138
3139 if (FDecl) {
3140 if (IncludeBriefComments && CurrentArg < FDecl->getNumParams())
3141 if (auto RC = S.getASTContext().getRawCommentForAnyRedecl(
3142 FDecl->getParamDecl(CurrentArg)))
3143 Result.addBriefComment(RC->getBriefText(S.getASTContext()));
Douglas Gregorc3425b12015-07-07 06:20:19 +00003144 AddResultTypeChunk(S.Context, Policy, FDecl, QualType(), Result);
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003145 Result.AddTextChunk(
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003146 Result.getAllocator().CopyString(FDecl->getNameAsString()));
3147 } else {
3148 Result.AddResultTypeChunk(
3149 Result.getAllocator().CopyString(
Alp Toker314cc812014-01-25 16:55:45 +00003150 Proto->getReturnType().getAsString(Policy)));
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003151 }
Alp Toker314cc812014-01-25 16:55:45 +00003152
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003153 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003154 AddOverloadParameterChunks(S.getASTContext(), Policy, FDecl, Proto, Result,
3155 CurrentArg);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003156 Result.AddChunk(CodeCompletionString::CK_RightParen);
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003157
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003158 return Result.TakeString();
Douglas Gregorf0f51982009-09-23 00:34:09 +00003159}
3160
Chris Lattner0e62c1c2011-07-23 10:55:15 +00003161unsigned clang::getMacroUsagePriority(StringRef MacroName,
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00003162 const LangOptions &LangOpts,
Douglas Gregor6e240332010-08-16 16:18:59 +00003163 bool PreferredTypeIsPointer) {
3164 unsigned Priority = CCP_Macro;
3165
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00003166 // Treat the "nil", "Nil" and "NULL" macros as null pointer constants.
3167 if (MacroName.equals("nil") || MacroName.equals("NULL") ||
3168 MacroName.equals("Nil")) {
Douglas Gregor6e240332010-08-16 16:18:59 +00003169 Priority = CCP_Constant;
3170 if (PreferredTypeIsPointer)
3171 Priority = Priority / CCF_SimilarTypeMatch;
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00003172 }
3173 // Treat "YES", "NO", "true", and "false" as constants.
3174 else if (MacroName.equals("YES") || MacroName.equals("NO") ||
3175 MacroName.equals("true") || MacroName.equals("false"))
3176 Priority = CCP_Constant;
3177 // Treat "bool" as a type.
3178 else if (MacroName.equals("bool"))
3179 Priority = CCP_Type + (LangOpts.ObjC1? CCD_bool_in_ObjC : 0);
3180
Douglas Gregor6e240332010-08-16 16:18:59 +00003181
3182 return Priority;
3183}
3184
Dmitri Gribenkobdc80de2013-01-11 20:32:41 +00003185CXCursorKind clang::getCursorKindForDecl(const Decl *D) {
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003186 if (!D)
3187 return CXCursor_UnexposedDecl;
3188
3189 switch (D->getKind()) {
3190 case Decl::Enum: return CXCursor_EnumDecl;
3191 case Decl::EnumConstant: return CXCursor_EnumConstantDecl;
3192 case Decl::Field: return CXCursor_FieldDecl;
3193 case Decl::Function:
3194 return CXCursor_FunctionDecl;
3195 case Decl::ObjCCategory: return CXCursor_ObjCCategoryDecl;
3196 case Decl::ObjCCategoryImpl: return CXCursor_ObjCCategoryImplDecl;
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003197 case Decl::ObjCImplementation: return CXCursor_ObjCImplementationDecl;
Douglas Gregordeafd0b2011-12-27 22:43:10 +00003198
Argyrios Kyrtzidis3698cef2012-01-24 21:39:26 +00003199 case Decl::ObjCInterface: return CXCursor_ObjCInterfaceDecl;
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003200 case Decl::ObjCIvar: return CXCursor_ObjCIvarDecl;
3201 case Decl::ObjCMethod:
3202 return cast<ObjCMethodDecl>(D)->isInstanceMethod()
3203 ? CXCursor_ObjCInstanceMethodDecl : CXCursor_ObjCClassMethodDecl;
3204 case Decl::CXXMethod: return CXCursor_CXXMethod;
3205 case Decl::CXXConstructor: return CXCursor_Constructor;
3206 case Decl::CXXDestructor: return CXCursor_Destructor;
3207 case Decl::CXXConversion: return CXCursor_ConversionFunction;
3208 case Decl::ObjCProperty: return CXCursor_ObjCPropertyDecl;
Argyrios Kyrtzidis3698cef2012-01-24 21:39:26 +00003209 case Decl::ObjCProtocol: return CXCursor_ObjCProtocolDecl;
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003210 case Decl::ParmVar: return CXCursor_ParmDecl;
3211 case Decl::Typedef: return CXCursor_TypedefDecl;
Richard Smithdda56e42011-04-15 14:24:37 +00003212 case Decl::TypeAlias: return CXCursor_TypeAliasDecl;
Sergey Kalinichev8f3b1872015-11-15 13:48:32 +00003213 case Decl::TypeAliasTemplate: return CXCursor_TypeAliasTemplateDecl;
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003214 case Decl::Var: return CXCursor_VarDecl;
3215 case Decl::Namespace: return CXCursor_Namespace;
3216 case Decl::NamespaceAlias: return CXCursor_NamespaceAlias;
3217 case Decl::TemplateTypeParm: return CXCursor_TemplateTypeParameter;
3218 case Decl::NonTypeTemplateParm:return CXCursor_NonTypeTemplateParameter;
3219 case Decl::TemplateTemplateParm:return CXCursor_TemplateTemplateParameter;
3220 case Decl::FunctionTemplate: return CXCursor_FunctionTemplate;
3221 case Decl::ClassTemplate: return CXCursor_ClassTemplate;
Argyrios Kyrtzidis12afd702011-09-30 17:58:23 +00003222 case Decl::AccessSpec: return CXCursor_CXXAccessSpecifier;
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003223 case Decl::ClassTemplatePartialSpecialization:
3224 return CXCursor_ClassTemplatePartialSpecialization;
3225 case Decl::UsingDirective: return CXCursor_UsingDirective;
Olivier Goffart81978012016-06-09 16:15:55 +00003226 case Decl::StaticAssert: return CXCursor_StaticAssert;
Olivier Goffartd211c642016-11-04 06:29:27 +00003227 case Decl::Friend: return CXCursor_FriendDecl;
Douglas Gregor3e653b32012-04-30 23:41:16 +00003228 case Decl::TranslationUnit: return CXCursor_TranslationUnit;
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003229
3230 case Decl::Using:
3231 case Decl::UnresolvedUsingValue:
3232 case Decl::UnresolvedUsingTypename:
3233 return CXCursor_UsingDeclaration;
3234
Douglas Gregor4cd65962011-06-03 23:08:58 +00003235 case Decl::ObjCPropertyImpl:
3236 switch (cast<ObjCPropertyImplDecl>(D)->getPropertyImplementation()) {
3237 case ObjCPropertyImplDecl::Dynamic:
3238 return CXCursor_ObjCDynamicDecl;
3239
3240 case ObjCPropertyImplDecl::Synthesize:
3241 return CXCursor_ObjCSynthesizeDecl;
3242 }
Argyrios Kyrtzidis50e5b1d2012-10-05 00:22:24 +00003243
3244 case Decl::Import:
3245 return CXCursor_ModuleImportDecl;
Douglas Gregor85f3f952015-07-07 03:57:15 +00003246
3247 case Decl::ObjCTypeParam: return CXCursor_TemplateTypeParameter;
3248
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003249 default:
Dmitri Gribenkobdc80de2013-01-11 20:32:41 +00003250 if (const TagDecl *TD = dyn_cast<TagDecl>(D)) {
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003251 switch (TD->getTagKind()) {
Joao Matosdc86f942012-08-31 18:45:21 +00003252 case TTK_Interface: // fall through
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003253 case TTK_Struct: return CXCursor_StructDecl;
3254 case TTK_Class: return CXCursor_ClassDecl;
3255 case TTK_Union: return CXCursor_UnionDecl;
3256 case TTK_Enum: return CXCursor_EnumDecl;
3257 }
3258 }
3259 }
3260
3261 return CXCursor_UnexposedDecl;
3262}
3263
Douglas Gregor55b037b2010-07-08 20:55:51 +00003264static void AddMacroResults(Preprocessor &PP, ResultBuilder &Results,
Douglas Gregor8cb17462012-10-09 16:01:50 +00003265 bool IncludeUndefined,
Douglas Gregor55b037b2010-07-08 20:55:51 +00003266 bool TargetTypeIsPointer = false) {
John McCall276321a2010-08-25 06:19:51 +00003267 typedef CodeCompletionResult Result;
Douglas Gregor55b037b2010-07-08 20:55:51 +00003268
Douglas Gregorf329c7c2009-10-30 16:50:04 +00003269 Results.EnterNewScope();
Douglas Gregor8e3e8742010-10-18 21:05:04 +00003270
Douglas Gregor9eb77012009-11-07 00:00:49 +00003271 for (Preprocessor::macro_iterator M = PP.macro_begin(),
3272 MEnd = PP.macro_end();
Douglas Gregor55b037b2010-07-08 20:55:51 +00003273 M != MEnd; ++M) {
Richard Smith20e883e2015-04-29 23:20:19 +00003274 auto MD = PP.getMacroDefinition(M->first);
3275 if (IncludeUndefined || MD) {
3276 if (MacroInfo *MI = MD.getMacroInfo())
Argyrios Kyrtzidis9ef53ce2014-04-09 18:21:23 +00003277 if (MI->isUsedForHeaderGuard())
3278 continue;
3279
Douglas Gregor8cb17462012-10-09 16:01:50 +00003280 Results.AddResult(Result(M->first,
Douglas Gregor6e240332010-08-16 16:18:59 +00003281 getMacroUsagePriority(M->first->getName(),
David Blaikiebbafb8a2012-03-11 07:00:24 +00003282 PP.getLangOpts(),
Douglas Gregor6e240332010-08-16 16:18:59 +00003283 TargetTypeIsPointer)));
Argyrios Kyrtzidis9ef53ce2014-04-09 18:21:23 +00003284 }
Douglas Gregor55b037b2010-07-08 20:55:51 +00003285 }
Douglas Gregor8e3e8742010-10-18 21:05:04 +00003286
Douglas Gregorf329c7c2009-10-30 16:50:04 +00003287 Results.ExitScope();
Douglas Gregor8e3e8742010-10-18 21:05:04 +00003288
Douglas Gregorf329c7c2009-10-30 16:50:04 +00003289}
3290
Douglas Gregorce0e8562010-08-23 21:54:33 +00003291static void AddPrettyFunctionResults(const LangOptions &LangOpts,
3292 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00003293 typedef CodeCompletionResult Result;
Douglas Gregorce0e8562010-08-23 21:54:33 +00003294
3295 Results.EnterNewScope();
Douglas Gregor8e3e8742010-10-18 21:05:04 +00003296
Douglas Gregorce0e8562010-08-23 21:54:33 +00003297 Results.AddResult(Result("__PRETTY_FUNCTION__", CCP_Constant));
3298 Results.AddResult(Result("__FUNCTION__", CCP_Constant));
Richard Smith2bf7fdb2013-01-02 11:42:31 +00003299 if (LangOpts.C99 || LangOpts.CPlusPlus11)
Douglas Gregorce0e8562010-08-23 21:54:33 +00003300 Results.AddResult(Result("__func__", CCP_Constant));
3301 Results.ExitScope();
3302}
3303
Daniel Dunbar242ea9a2009-11-13 08:58:20 +00003304static void HandleCodeCompleteResults(Sema *S,
3305 CodeCompleteConsumer *CodeCompleter,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003306 CodeCompletionContext Context,
John McCall276321a2010-08-25 06:19:51 +00003307 CodeCompletionResult *Results,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003308 unsigned NumResults) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00003309 if (CodeCompleter)
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003310 CodeCompleter->ProcessCodeCompleteResults(*S, Context, Results, NumResults);
Douglas Gregor3545ff42009-09-21 16:56:56 +00003311}
3312
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003313static enum CodeCompletionContext::Kind mapCodeCompletionContext(Sema &S,
3314 Sema::ParserCompletionContext PCC) {
3315 switch (PCC) {
John McCallfaf5fb42010-08-26 23:41:50 +00003316 case Sema::PCC_Namespace:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003317 return CodeCompletionContext::CCC_TopLevel;
3318
John McCallfaf5fb42010-08-26 23:41:50 +00003319 case Sema::PCC_Class:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003320 return CodeCompletionContext::CCC_ClassStructUnion;
3321
John McCallfaf5fb42010-08-26 23:41:50 +00003322 case Sema::PCC_ObjCInterface:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003323 return CodeCompletionContext::CCC_ObjCInterface;
3324
John McCallfaf5fb42010-08-26 23:41:50 +00003325 case Sema::PCC_ObjCImplementation:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003326 return CodeCompletionContext::CCC_ObjCImplementation;
3327
John McCallfaf5fb42010-08-26 23:41:50 +00003328 case Sema::PCC_ObjCInstanceVariableList:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003329 return CodeCompletionContext::CCC_ObjCIvarList;
3330
John McCallfaf5fb42010-08-26 23:41:50 +00003331 case Sema::PCC_Template:
3332 case Sema::PCC_MemberTemplate:
Douglas Gregor0ac41382010-09-23 23:01:17 +00003333 if (S.CurContext->isFileContext())
3334 return CodeCompletionContext::CCC_TopLevel;
David Blaikie8a40f702012-01-17 06:56:22 +00003335 if (S.CurContext->isRecord())
Douglas Gregor0ac41382010-09-23 23:01:17 +00003336 return CodeCompletionContext::CCC_ClassStructUnion;
David Blaikie8a40f702012-01-17 06:56:22 +00003337 return CodeCompletionContext::CCC_Other;
Douglas Gregor0ac41382010-09-23 23:01:17 +00003338
John McCallfaf5fb42010-08-26 23:41:50 +00003339 case Sema::PCC_RecoveryInFunction:
Douglas Gregor0ac41382010-09-23 23:01:17 +00003340 return CodeCompletionContext::CCC_Recovery;
Douglas Gregorc769d6e2010-10-18 22:01:46 +00003341
John McCallfaf5fb42010-08-26 23:41:50 +00003342 case Sema::PCC_ForInit:
David Blaikiebbafb8a2012-03-11 07:00:24 +00003343 if (S.getLangOpts().CPlusPlus || S.getLangOpts().C99 ||
3344 S.getLangOpts().ObjC1)
Douglas Gregorc769d6e2010-10-18 22:01:46 +00003345 return CodeCompletionContext::CCC_ParenthesizedExpression;
3346 else
3347 return CodeCompletionContext::CCC_Expression;
3348
3349 case Sema::PCC_Expression:
John McCallfaf5fb42010-08-26 23:41:50 +00003350 case Sema::PCC_Condition:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003351 return CodeCompletionContext::CCC_Expression;
3352
John McCallfaf5fb42010-08-26 23:41:50 +00003353 case Sema::PCC_Statement:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003354 return CodeCompletionContext::CCC_Statement;
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003355
John McCallfaf5fb42010-08-26 23:41:50 +00003356 case Sema::PCC_Type:
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003357 return CodeCompletionContext::CCC_Type;
Douglas Gregor5e35d592010-09-14 23:59:36 +00003358
3359 case Sema::PCC_ParenthesizedExpression:
3360 return CodeCompletionContext::CCC_ParenthesizedExpression;
Douglas Gregor80039242011-02-15 20:33:25 +00003361
3362 case Sema::PCC_LocalDeclarationSpecifiers:
3363 return CodeCompletionContext::CCC_Type;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003364 }
David Blaikie8a40f702012-01-17 06:56:22 +00003365
3366 llvm_unreachable("Invalid ParserCompletionContext!");
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003367}
3368
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003369/// If we're in a C++ virtual member function, add completion results
Douglas Gregorac322ec2010-08-27 21:18:54 +00003370/// that invoke the functions we override, since it's common to invoke the
3371/// overridden function as well as adding new functionality.
3372///
3373/// \param S The semantic analysis object for which we are generating results.
3374///
3375/// \param InContext This context in which the nested-name-specifier preceding
3376/// the code-completion point
3377static void MaybeAddOverrideCalls(Sema &S, DeclContext *InContext,
3378 ResultBuilder &Results) {
3379 // Look through blocks.
3380 DeclContext *CurContext = S.CurContext;
3381 while (isa<BlockDecl>(CurContext))
3382 CurContext = CurContext->getParent();
3383
3384
3385 CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(CurContext);
3386 if (!Method || !Method->isVirtual())
3387 return;
3388
3389 // We need to have names for all of the parameters, if we're going to
3390 // generate a forwarding call.
David Majnemer59f77922016-06-24 04:05:48 +00003391 for (auto P : Method->parameters())
Aaron Ballman43b68be2014-03-07 17:50:17 +00003392 if (!P->getDeclName())
Douglas Gregorac322ec2010-08-27 21:18:54 +00003393 return;
Douglas Gregorac322ec2010-08-27 21:18:54 +00003394
Douglas Gregor75acd922011-09-27 23:30:47 +00003395 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
Benjamin Krameracfa3392017-12-17 23:52:45 +00003396 for (const CXXMethodDecl *Overridden : Method->overridden_methods()) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003397 CodeCompletionBuilder Builder(Results.getAllocator(),
3398 Results.getCodeCompletionTUInfo());
Douglas Gregorac322ec2010-08-27 21:18:54 +00003399 if (Overridden->getCanonicalDecl() == Method->getCanonicalDecl())
3400 continue;
3401
3402 // If we need a nested-name-specifier, add one now.
3403 if (!InContext) {
3404 NestedNameSpecifier *NNS
3405 = getRequiredQualification(S.Context, CurContext,
3406 Overridden->getDeclContext());
3407 if (NNS) {
3408 std::string Str;
3409 llvm::raw_string_ostream OS(Str);
Douglas Gregor75acd922011-09-27 23:30:47 +00003410 NNS->print(OS, Policy);
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003411 Builder.AddTextChunk(Results.getAllocator().CopyString(OS.str()));
Douglas Gregorac322ec2010-08-27 21:18:54 +00003412 }
3413 } else if (!InContext->Equals(Overridden->getDeclContext()))
3414 continue;
3415
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003416 Builder.AddTypedTextChunk(Results.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003417 Overridden->getNameAsString()));
3418 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregorac322ec2010-08-27 21:18:54 +00003419 bool FirstParam = true;
David Majnemer59f77922016-06-24 04:05:48 +00003420 for (auto P : Method->parameters()) {
Douglas Gregorac322ec2010-08-27 21:18:54 +00003421 if (FirstParam)
3422 FirstParam = false;
3423 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003424 Builder.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregorac322ec2010-08-27 21:18:54 +00003425
Aaron Ballman43b68be2014-03-07 17:50:17 +00003426 Builder.AddPlaceholderChunk(
3427 Results.getAllocator().CopyString(P->getIdentifier()->getName()));
Douglas Gregorac322ec2010-08-27 21:18:54 +00003428 }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003429 Builder.AddChunk(CodeCompletionString::CK_RightParen);
3430 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregorac322ec2010-08-27 21:18:54 +00003431 CCP_SuperCompletion,
Douglas Gregor78254c82012-03-27 23:34:16 +00003432 CXCursor_CXXMethod,
3433 CXAvailability_Available,
3434 Overridden));
Douglas Gregorac322ec2010-08-27 21:18:54 +00003435 Results.Ignore(Overridden);
3436 }
3437}
3438
Douglas Gregor07f43572012-01-29 18:15:03 +00003439void Sema::CodeCompleteModuleImport(SourceLocation ImportLoc,
3440 ModuleIdPath Path) {
3441 typedef CodeCompletionResult Result;
3442 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003443 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor07f43572012-01-29 18:15:03 +00003444 CodeCompletionContext::CCC_Other);
3445 Results.EnterNewScope();
3446
3447 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003448 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Douglas Gregor07f43572012-01-29 18:15:03 +00003449 typedef CodeCompletionResult Result;
3450 if (Path.empty()) {
3451 // Enumerate all top-level modules.
Dmitri Gribenkof8579502013-01-12 19:30:44 +00003452 SmallVector<Module *, 8> Modules;
Douglas Gregor07f43572012-01-29 18:15:03 +00003453 PP.getHeaderSearchInfo().collectAllModules(Modules);
3454 for (unsigned I = 0, N = Modules.size(); I != N; ++I) {
3455 Builder.AddTypedTextChunk(
3456 Builder.getAllocator().CopyString(Modules[I]->Name));
3457 Results.AddResult(Result(Builder.TakeString(),
3458 CCP_Declaration,
Argyrios Kyrtzidis345d05f2013-05-29 18:50:15 +00003459 CXCursor_ModuleImportDecl,
Douglas Gregor07f43572012-01-29 18:15:03 +00003460 Modules[I]->isAvailable()
3461 ? CXAvailability_Available
3462 : CXAvailability_NotAvailable));
3463 }
Daniel Jasper07e6c402013-08-05 20:26:17 +00003464 } else if (getLangOpts().Modules) {
Douglas Gregor07f43572012-01-29 18:15:03 +00003465 // Load the named module.
3466 Module *Mod = PP.getModuleLoader().loadModule(ImportLoc, Path,
3467 Module::AllVisible,
3468 /*IsInclusionDirective=*/false);
3469 // Enumerate submodules.
3470 if (Mod) {
3471 for (Module::submodule_iterator Sub = Mod->submodule_begin(),
3472 SubEnd = Mod->submodule_end();
3473 Sub != SubEnd; ++Sub) {
3474
3475 Builder.AddTypedTextChunk(
3476 Builder.getAllocator().CopyString((*Sub)->Name));
3477 Results.AddResult(Result(Builder.TakeString(),
3478 CCP_Declaration,
Argyrios Kyrtzidis345d05f2013-05-29 18:50:15 +00003479 CXCursor_ModuleImportDecl,
Douglas Gregor07f43572012-01-29 18:15:03 +00003480 (*Sub)->isAvailable()
3481 ? CXAvailability_Available
3482 : CXAvailability_NotAvailable));
3483 }
3484 }
3485 }
3486 Results.ExitScope();
3487 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
3488 Results.data(),Results.size());
3489}
3490
Douglas Gregor504a6ae2010-01-10 23:08:15 +00003491void Sema::CodeCompleteOrdinaryName(Scope *S,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003492 ParserCompletionContext CompletionContext) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003493 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003494 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00003495 mapCodeCompletionContext(*this, CompletionContext));
Douglas Gregorac322ec2010-08-27 21:18:54 +00003496 Results.EnterNewScope();
Douglas Gregor50832e02010-09-20 22:39:41 +00003497
Douglas Gregor504a6ae2010-01-10 23:08:15 +00003498 // Determine how to filter results, e.g., so that the names of
3499 // values (functions, enumerators, function templates, etc.) are
3500 // only allowed where we can have an expression.
3501 switch (CompletionContext) {
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003502 case PCC_Namespace:
3503 case PCC_Class:
3504 case PCC_ObjCInterface:
3505 case PCC_ObjCImplementation:
3506 case PCC_ObjCInstanceVariableList:
3507 case PCC_Template:
3508 case PCC_MemberTemplate:
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003509 case PCC_Type:
Douglas Gregor80039242011-02-15 20:33:25 +00003510 case PCC_LocalDeclarationSpecifiers:
Douglas Gregor504a6ae2010-01-10 23:08:15 +00003511 Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
3512 break;
3513
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003514 case PCC_Statement:
Douglas Gregor5e35d592010-09-14 23:59:36 +00003515 case PCC_ParenthesizedExpression:
Douglas Gregor4d755e82010-08-24 23:58:17 +00003516 case PCC_Expression:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003517 case PCC_ForInit:
3518 case PCC_Condition:
David Blaikiebbafb8a2012-03-11 07:00:24 +00003519 if (WantTypesInContext(CompletionContext, getLangOpts()))
Douglas Gregor70febae2010-05-28 00:49:12 +00003520 Results.setFilter(&ResultBuilder::IsOrdinaryName);
3521 else
3522 Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
Douglas Gregorac322ec2010-08-27 21:18:54 +00003523
David Blaikiebbafb8a2012-03-11 07:00:24 +00003524 if (getLangOpts().CPlusPlus)
Craig Topperc3ec1492014-05-26 06:22:03 +00003525 MaybeAddOverrideCalls(*this, /*InContext=*/nullptr, Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00003526 break;
Douglas Gregor6da3db42010-05-25 05:58:43 +00003527
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003528 case PCC_RecoveryInFunction:
Douglas Gregor6da3db42010-05-25 05:58:43 +00003529 // Unfiltered
3530 break;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00003531 }
3532
Douglas Gregor9be0ed42010-08-26 16:36:48 +00003533 // If we are in a C++ non-static member function, check the qualifiers on
3534 // the member function to filter/prioritize the results list.
3535 if (CXXMethodDecl *CurMethod = dyn_cast<CXXMethodDecl>(CurContext))
3536 if (CurMethod->isInstance())
3537 Results.setObjectTypeQualifiers(
3538 Qualifiers::fromCVRMask(CurMethod->getTypeQualifiers()));
3539
Douglas Gregorc580c522010-01-14 01:09:38 +00003540 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00003541 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00003542 CodeCompleter->includeGlobals(),
3543 CodeCompleter->loadExternal());
Douglas Gregor92253692009-12-07 09:54:55 +00003544
Douglas Gregorf98e6a22010-01-13 23:51:12 +00003545 AddOrdinaryNameResults(CompletionContext, S, *this, Results);
Douglas Gregor92253692009-12-07 09:54:55 +00003546 Results.ExitScope();
3547
Douglas Gregorce0e8562010-08-23 21:54:33 +00003548 switch (CompletionContext) {
Douglas Gregor5e35d592010-09-14 23:59:36 +00003549 case PCC_ParenthesizedExpression:
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003550 case PCC_Expression:
3551 case PCC_Statement:
3552 case PCC_RecoveryInFunction:
3553 if (S->getFnParent())
Craig Topper12126262015-11-15 17:27:57 +00003554 AddPrettyFunctionResults(getLangOpts(), Results);
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003555 break;
3556
3557 case PCC_Namespace:
3558 case PCC_Class:
3559 case PCC_ObjCInterface:
3560 case PCC_ObjCImplementation:
3561 case PCC_ObjCInstanceVariableList:
3562 case PCC_Template:
3563 case PCC_MemberTemplate:
3564 case PCC_ForInit:
3565 case PCC_Condition:
3566 case PCC_Type:
Douglas Gregor80039242011-02-15 20:33:25 +00003567 case PCC_LocalDeclarationSpecifiers:
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003568 break;
Douglas Gregorce0e8562010-08-23 21:54:33 +00003569 }
3570
Douglas Gregor9eb77012009-11-07 00:00:49 +00003571 if (CodeCompleter->includeMacros())
Douglas Gregor8cb17462012-10-09 16:01:50 +00003572 AddMacroResults(PP, Results, false);
Douglas Gregorce0e8562010-08-23 21:54:33 +00003573
Douglas Gregor50832e02010-09-20 22:39:41 +00003574 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003575 Results.data(),Results.size());
Douglas Gregor9d64c5e2009-09-21 20:51:25 +00003576}
3577
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003578static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
3579 ParsedType Receiver,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00003580 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00003581 bool AtArgumentExpression,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003582 bool IsSuper,
3583 ResultBuilder &Results);
3584
3585void Sema::CodeCompleteDeclSpec(Scope *S, DeclSpec &DS,
3586 bool AllowNonIdentifiers,
3587 bool AllowNestedNameSpecifiers) {
John McCall276321a2010-08-25 06:19:51 +00003588 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003589 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003590 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00003591 AllowNestedNameSpecifiers
3592 ? CodeCompletionContext::CCC_PotentiallyQualifiedName
3593 : CodeCompletionContext::CCC_Name);
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003594 Results.EnterNewScope();
3595
3596 // Type qualifiers can come after names.
3597 Results.AddResult(Result("const"));
3598 Results.AddResult(Result("volatile"));
David Blaikiebbafb8a2012-03-11 07:00:24 +00003599 if (getLangOpts().C99)
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003600 Results.AddResult(Result("restrict"));
3601
David Blaikiebbafb8a2012-03-11 07:00:24 +00003602 if (getLangOpts().CPlusPlus) {
Alex Lorenz8f4d3992017-02-13 23:19:40 +00003603 if (getLangOpts().CPlusPlus11 &&
3604 (DS.getTypeSpecType() == DeclSpec::TST_class ||
3605 DS.getTypeSpecType() == DeclSpec::TST_struct))
3606 Results.AddResult("final");
3607
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003608 if (AllowNonIdentifiers) {
3609 Results.AddResult(Result("operator"));
3610 }
3611
3612 // Add nested-name-specifiers.
3613 if (AllowNestedNameSpecifiers) {
3614 Results.allowNestedNameSpecifiers();
Douglas Gregor0ac41382010-09-23 23:01:17 +00003615 Results.setFilter(&ResultBuilder::IsImpossibleToSatisfy);
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003616 CodeCompletionDeclConsumer Consumer(Results, CurContext);
3617 LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00003618 CodeCompleter->includeGlobals(),
3619 CodeCompleter->loadExternal());
Craig Topperc3ec1492014-05-26 06:22:03 +00003620 Results.setFilter(nullptr);
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003621 }
3622 }
3623 Results.ExitScope();
3624
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003625 // If we're in a context where we might have an expression (rather than a
3626 // declaration), and what we've seen so far is an Objective-C type that could
3627 // be a receiver of a class message, this may be a class message send with
3628 // the initial opening bracket '[' missing. Add appropriate completions.
3629 if (AllowNonIdentifiers && !AllowNestedNameSpecifiers &&
Richard Smithb4a9e862013-04-12 22:46:28 +00003630 DS.getParsedSpecifiers() == DeclSpec::PQ_TypeSpecifier &&
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003631 DS.getTypeSpecType() == DeclSpec::TST_typename &&
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003632 DS.getTypeSpecComplex() == DeclSpec::TSC_unspecified &&
3633 DS.getTypeSpecSign() == DeclSpec::TSS_unspecified &&
Richard Smithb4a9e862013-04-12 22:46:28 +00003634 !DS.isTypeAltiVecVector() &&
3635 S &&
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003636 (S->getFlags() & Scope::DeclScope) != 0 &&
3637 (S->getFlags() & (Scope::ClassScope | Scope::TemplateParamScope |
3638 Scope::FunctionPrototypeScope |
3639 Scope::AtCatchScope)) == 0) {
3640 ParsedType T = DS.getRepAsType();
3641 if (!T.get().isNull() && T.get()->isObjCObjectOrInterfaceType())
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00003642 AddClassMessageCompletions(*this, S, T, None, false, false, Results);
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003643 }
3644
Douglas Gregor56ccce02010-08-24 04:59:56 +00003645 // Note that we intentionally suppress macro results here, since we do not
3646 // encourage using macros to produce the names of entities.
3647
Douglas Gregor0ac41382010-09-23 23:01:17 +00003648 HandleCodeCompleteResults(this, CodeCompleter,
3649 Results.getCompletionContext(),
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003650 Results.data(), Results.size());
3651}
3652
Douglas Gregor68762e72010-08-23 21:17:50 +00003653struct Sema::CodeCompleteExpressionData {
3654 CodeCompleteExpressionData(QualType PreferredType = QualType())
3655 : PreferredType(PreferredType), IntegralConstantExpression(false),
3656 ObjCCollection(false) { }
3657
3658 QualType PreferredType;
3659 bool IntegralConstantExpression;
3660 bool ObjCCollection;
Chris Lattner0e62c1c2011-07-23 10:55:15 +00003661 SmallVector<Decl *, 4> IgnoreDecls;
Douglas Gregor68762e72010-08-23 21:17:50 +00003662};
3663
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003664/// Perform code-completion in an expression context when we know what
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003665/// type we're looking for.
Douglas Gregor68762e72010-08-23 21:17:50 +00003666void Sema::CodeCompleteExpression(Scope *S,
3667 const CodeCompleteExpressionData &Data) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003668 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003669 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003670 CodeCompletionContext::CCC_Expression);
Douglas Gregor68762e72010-08-23 21:17:50 +00003671 if (Data.ObjCCollection)
3672 Results.setFilter(&ResultBuilder::IsObjCCollection);
3673 else if (Data.IntegralConstantExpression)
Douglas Gregor85b50632010-07-28 21:50:18 +00003674 Results.setFilter(&ResultBuilder::IsIntegralConstantValue);
David Blaikiebbafb8a2012-03-11 07:00:24 +00003675 else if (WantTypesInContext(PCC_Expression, getLangOpts()))
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003676 Results.setFilter(&ResultBuilder::IsOrdinaryName);
3677 else
3678 Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
Douglas Gregor68762e72010-08-23 21:17:50 +00003679
3680 if (!Data.PreferredType.isNull())
3681 Results.setPreferredType(Data.PreferredType.getNonReferenceType());
3682
3683 // Ignore any declarations that we were told that we don't care about.
3684 for (unsigned I = 0, N = Data.IgnoreDecls.size(); I != N; ++I)
3685 Results.Ignore(Data.IgnoreDecls[I]);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003686
3687 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00003688 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00003689 CodeCompleter->includeGlobals(),
3690 CodeCompleter->loadExternal());
3691
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003692 Results.EnterNewScope();
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003693 AddOrdinaryNameResults(PCC_Expression, S, *this, Results);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003694 Results.ExitScope();
3695
Douglas Gregor55b037b2010-07-08 20:55:51 +00003696 bool PreferredTypeIsPointer = false;
Douglas Gregor68762e72010-08-23 21:17:50 +00003697 if (!Data.PreferredType.isNull())
3698 PreferredTypeIsPointer = Data.PreferredType->isAnyPointerType()
3699 || Data.PreferredType->isMemberPointerType()
3700 || Data.PreferredType->isBlockPointerType();
Douglas Gregor55b037b2010-07-08 20:55:51 +00003701
Douglas Gregorce0e8562010-08-23 21:54:33 +00003702 if (S->getFnParent() &&
3703 !Data.ObjCCollection &&
3704 !Data.IntegralConstantExpression)
Craig Topper12126262015-11-15 17:27:57 +00003705 AddPrettyFunctionResults(getLangOpts(), Results);
Douglas Gregorce0e8562010-08-23 21:54:33 +00003706
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003707 if (CodeCompleter->includeMacros())
Douglas Gregor8cb17462012-10-09 16:01:50 +00003708 AddMacroResults(PP, Results, false, PreferredTypeIsPointer);
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003709 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor68762e72010-08-23 21:17:50 +00003710 CodeCompletionContext(CodeCompletionContext::CCC_Expression,
3711 Data.PreferredType),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003712 Results.data(),Results.size());
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003713}
3714
Douglas Gregoreda7e542010-09-18 01:28:11 +00003715void Sema::CodeCompletePostfixExpression(Scope *S, ExprResult E) {
3716 if (E.isInvalid())
3717 CodeCompleteOrdinaryName(S, PCC_RecoveryInFunction);
David Blaikiebbafb8a2012-03-11 07:00:24 +00003718 else if (getLangOpts().ObjC1)
Nikola Smiljanic01a75982014-05-29 10:55:11 +00003719 CodeCompleteObjCInstanceMessage(S, E.get(), None, false);
Douglas Gregored0b69d2010-09-15 16:23:04 +00003720}
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003721
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003722/// The set of properties that have already been added, referenced by
Douglas Gregorb888acf2010-12-09 23:01:55 +00003723/// property name.
3724typedef llvm::SmallPtrSet<IdentifierInfo*, 16> AddedPropertiesSet;
3725
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003726/// Retrieve the container definition, if any?
Douglas Gregor9b4f3702012-06-12 13:44:08 +00003727static ObjCContainerDecl *getContainerDef(ObjCContainerDecl *Container) {
3728 if (ObjCInterfaceDecl *Interface = dyn_cast<ObjCInterfaceDecl>(Container)) {
3729 if (Interface->hasDefinition())
3730 return Interface->getDefinition();
3731
3732 return Interface;
3733 }
3734
3735 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
3736 if (Protocol->hasDefinition())
3737 return Protocol->getDefinition();
3738
3739 return Protocol;
3740 }
3741 return Container;
3742}
3743
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003744/// Adds a block invocation code completion result for the given block
Alex Lorenzbaef8022016-11-09 13:43:18 +00003745/// declaration \p BD.
3746static void AddObjCBlockCall(ASTContext &Context, const PrintingPolicy &Policy,
3747 CodeCompletionBuilder &Builder,
3748 const NamedDecl *BD,
3749 const FunctionTypeLoc &BlockLoc,
3750 const FunctionProtoTypeLoc &BlockProtoLoc) {
3751 Builder.AddResultTypeChunk(
3752 GetCompletionTypeString(BlockLoc.getReturnLoc().getType(), Context,
3753 Policy, Builder.getAllocator()));
3754
3755 AddTypedNameChunk(Context, Policy, BD, Builder);
3756 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
3757
3758 if (BlockProtoLoc && BlockProtoLoc.getTypePtr()->isVariadic()) {
3759 Builder.AddPlaceholderChunk("...");
3760 } else {
3761 for (unsigned I = 0, N = BlockLoc.getNumParams(); I != N; ++I) {
3762 if (I)
3763 Builder.AddChunk(CodeCompletionString::CK_Comma);
3764
3765 // Format the placeholder string.
3766 std::string PlaceholderStr =
3767 FormatFunctionParameter(Policy, BlockLoc.getParam(I));
3768
3769 if (I == N - 1 && BlockProtoLoc &&
3770 BlockProtoLoc.getTypePtr()->isVariadic())
3771 PlaceholderStr += ", ...";
3772
3773 // Add the placeholder string.
3774 Builder.AddPlaceholderChunk(
3775 Builder.getAllocator().CopyString(PlaceholderStr));
3776 }
3777 }
3778
3779 Builder.AddChunk(CodeCompletionString::CK_RightParen);
3780}
3781
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003782static void AddObjCProperties(
3783 const CodeCompletionContext &CCContext, ObjCContainerDecl *Container,
3784 bool AllowCategories, bool AllowNullaryMethods, DeclContext *CurContext,
3785 AddedPropertiesSet &AddedProperties, ResultBuilder &Results,
3786 bool IsBaseExprStatement = false, bool IsClassProperty = false) {
John McCall276321a2010-08-25 06:19:51 +00003787 typedef CodeCompletionResult Result;
Douglas Gregor9291bad2009-11-18 01:29:26 +00003788
Douglas Gregor9b4f3702012-06-12 13:44:08 +00003789 // Retrieve the definition.
3790 Container = getContainerDef(Container);
3791
Douglas Gregor9291bad2009-11-18 01:29:26 +00003792 // Add properties in this container.
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003793 const auto AddProperty = [&](const ObjCPropertyDecl *P) {
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003794 if (!AddedProperties.insert(P->getIdentifier()).second)
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003795 return;
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003796
Alex Lorenzbaef8022016-11-09 13:43:18 +00003797 // FIXME: Provide block invocation completion for non-statement
3798 // expressions.
3799 if (!P->getType().getTypePtr()->isBlockPointerType() ||
3800 !IsBaseExprStatement) {
3801 Results.MaybeAddResult(Result(P, Results.getBasePriority(P), nullptr),
3802 CurContext);
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003803 return;
Alex Lorenzbaef8022016-11-09 13:43:18 +00003804 }
3805
3806 // Block setter and invocation completion is provided only when we are able
3807 // to find the FunctionProtoTypeLoc with parameter names for the block.
3808 FunctionTypeLoc BlockLoc;
3809 FunctionProtoTypeLoc BlockProtoLoc;
3810 findTypeLocationForBlockDecl(P->getTypeSourceInfo(), BlockLoc,
3811 BlockProtoLoc);
3812 if (!BlockLoc) {
3813 Results.MaybeAddResult(Result(P, Results.getBasePriority(P), nullptr),
3814 CurContext);
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003815 return;
Alex Lorenzbaef8022016-11-09 13:43:18 +00003816 }
3817
3818 // The default completion result for block properties should be the block
3819 // invocation completion when the base expression is a statement.
3820 CodeCompletionBuilder Builder(Results.getAllocator(),
3821 Results.getCodeCompletionTUInfo());
3822 AddObjCBlockCall(Container->getASTContext(),
3823 getCompletionPrintingPolicy(Results.getSema()), Builder, P,
3824 BlockLoc, BlockProtoLoc);
3825 Results.MaybeAddResult(
3826 Result(Builder.TakeString(), P, Results.getBasePriority(P)),
3827 CurContext);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003828
3829 // Provide additional block setter completion iff the base expression is a
Alex Lorenzbaef8022016-11-09 13:43:18 +00003830 // statement and the block property is mutable.
3831 if (!P->isReadOnly()) {
3832 CodeCompletionBuilder Builder(Results.getAllocator(),
3833 Results.getCodeCompletionTUInfo());
3834 AddResultTypeChunk(Container->getASTContext(),
3835 getCompletionPrintingPolicy(Results.getSema()), P,
3836 CCContext.getBaseType(), Builder);
3837 Builder.AddTypedTextChunk(
3838 Results.getAllocator().CopyString(P->getName()));
3839 Builder.AddChunk(CodeCompletionString::CK_Equal);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003840
Alex Lorenzbaef8022016-11-09 13:43:18 +00003841 std::string PlaceholderStr = formatBlockPlaceholder(
3842 getCompletionPrintingPolicy(Results.getSema()), P, BlockLoc,
3843 BlockProtoLoc, /*SuppressBlockName=*/true);
3844 // Add the placeholder string.
3845 Builder.AddPlaceholderChunk(
3846 Builder.getAllocator().CopyString(PlaceholderStr));
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003847
Alex Lorenz6e0f3932017-01-06 12:00:44 +00003848 // When completing blocks properties that return void the default
3849 // property completion result should show up before the setter,
3850 // otherwise the setter completion should show up before the default
3851 // property completion, as we normally want to use the result of the
3852 // call.
Alex Lorenzbaef8022016-11-09 13:43:18 +00003853 Results.MaybeAddResult(
3854 Result(Builder.TakeString(), P,
Alex Lorenz6e0f3932017-01-06 12:00:44 +00003855 Results.getBasePriority(P) +
3856 (BlockLoc.getTypePtr()->getReturnType()->isVoidType()
3857 ? CCD_BlockPropertySetter
3858 : -CCD_BlockPropertySetter)),
Alex Lorenzbaef8022016-11-09 13:43:18 +00003859 CurContext);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003860 }
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003861 };
3862
3863 if (IsClassProperty) {
3864 for (const auto *P : Container->class_properties())
3865 AddProperty(P);
3866 } else {
3867 for (const auto *P : Container->instance_properties())
3868 AddProperty(P);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003869 }
Craig Topperc3ec1492014-05-26 06:22:03 +00003870
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003871 // Add nullary methods or implicit class properties
Douglas Gregor95147142011-05-05 15:50:42 +00003872 if (AllowNullaryMethods) {
3873 ASTContext &Context = Container->getASTContext();
Douglas Gregor75acd922011-09-27 23:30:47 +00003874 PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema());
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003875 // Adds a method result
3876 const auto AddMethod = [&](const ObjCMethodDecl *M) {
3877 IdentifierInfo *Name = M->getSelector().getIdentifierInfoForSlot(0);
3878 if (!Name)
3879 return;
3880 if (!AddedProperties.insert(Name).second)
3881 return;
3882 CodeCompletionBuilder Builder(Results.getAllocator(),
3883 Results.getCodeCompletionTUInfo());
3884 AddResultTypeChunk(Context, Policy, M, CCContext.getBaseType(), Builder);
3885 Builder.AddTypedTextChunk(
3886 Results.getAllocator().CopyString(Name->getName()));
3887 Results.MaybeAddResult(
3888 Result(Builder.TakeString(), M,
3889 CCP_MemberDeclaration + CCD_MethodAsProperty),
3890 CurContext);
3891 };
3892
3893 if (IsClassProperty) {
3894 for (const auto *M : Container->methods()) {
3895 // Gather the class method that can be used as implicit property
3896 // getters. Methods with arguments or methods that return void aren't
3897 // added to the results as they can't be used as a getter.
3898 if (!M->getSelector().isUnarySelector() ||
3899 M->getReturnType()->isVoidType() || M->isInstanceMethod())
3900 continue;
3901 AddMethod(M);
3902 }
3903 } else {
3904 for (auto *M : Container->methods()) {
3905 if (M->getSelector().isUnarySelector())
3906 AddMethod(M);
3907 }
Douglas Gregor95147142011-05-05 15:50:42 +00003908 }
3909 }
Douglas Gregor95147142011-05-05 15:50:42 +00003910
Douglas Gregor9291bad2009-11-18 01:29:26 +00003911 // Add properties in referenced protocols.
3912 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Aaron Ballman0f6e64d2014-03-13 22:58:06 +00003913 for (auto *P : Protocol->protocols())
Douglas Gregorc3425b12015-07-07 06:20:19 +00003914 AddObjCProperties(CCContext, P, AllowCategories, AllowNullaryMethods,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003915 CurContext, AddedProperties, Results,
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003916 IsBaseExprStatement, IsClassProperty);
Douglas Gregor9291bad2009-11-18 01:29:26 +00003917 } else if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)){
Douglas Gregor5d649882009-11-18 22:32:06 +00003918 if (AllowCategories) {
3919 // Look through categories.
Aaron Ballman15063e12014-03-13 21:35:02 +00003920 for (auto *Cat : IFace->known_categories())
Douglas Gregorc3425b12015-07-07 06:20:19 +00003921 AddObjCProperties(CCContext, Cat, AllowCategories, AllowNullaryMethods,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003922 CurContext, AddedProperties, Results,
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003923 IsBaseExprStatement, IsClassProperty);
Douglas Gregor5d649882009-11-18 22:32:06 +00003924 }
Aaron Ballman15063e12014-03-13 21:35:02 +00003925
Douglas Gregor9291bad2009-11-18 01:29:26 +00003926 // Look through protocols.
Aaron Ballmana9f49e32014-03-13 20:55:22 +00003927 for (auto *I : IFace->all_referenced_protocols())
Douglas Gregorc3425b12015-07-07 06:20:19 +00003928 AddObjCProperties(CCContext, I, AllowCategories, AllowNullaryMethods,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003929 CurContext, AddedProperties, Results,
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003930 IsBaseExprStatement, IsClassProperty);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003931
Douglas Gregor9291bad2009-11-18 01:29:26 +00003932 // Look in the superclass.
3933 if (IFace->getSuperClass())
Douglas Gregorc3425b12015-07-07 06:20:19 +00003934 AddObjCProperties(CCContext, IFace->getSuperClass(), AllowCategories,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003935 AllowNullaryMethods, CurContext, AddedProperties,
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003936 Results, IsBaseExprStatement, IsClassProperty);
Douglas Gregor9291bad2009-11-18 01:29:26 +00003937 } else if (const ObjCCategoryDecl *Category
3938 = dyn_cast<ObjCCategoryDecl>(Container)) {
3939 // Look through protocols.
Aaron Ballman19a41762014-03-14 12:55:57 +00003940 for (auto *P : Category->protocols())
Douglas Gregorc3425b12015-07-07 06:20:19 +00003941 AddObjCProperties(CCContext, P, AllowCategories, AllowNullaryMethods,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003942 CurContext, AddedProperties, Results,
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003943 IsBaseExprStatement, IsClassProperty);
Douglas Gregor9291bad2009-11-18 01:29:26 +00003944 }
3945}
3946
Alex Lorenz0fe0d982017-05-11 13:41:00 +00003947static void AddRecordMembersCompletionResults(Sema &SemaRef,
3948 ResultBuilder &Results, Scope *S,
3949 QualType BaseType,
3950 RecordDecl *RD) {
3951 // Indicate that we are performing a member access, and the cv-qualifiers
3952 // for the base object type.
3953 Results.setObjectTypeQualifiers(BaseType.getQualifiers());
3954
3955 // Access to a C/C++ class, struct, or union.
3956 Results.allowNestedNameSpecifiers();
3957 CodeCompletionDeclConsumer Consumer(Results, SemaRef.CurContext);
3958 SemaRef.LookupVisibleDecls(RD, Sema::LookupMemberName, Consumer,
Alex Lorenze6afa392017-05-11 13:48:57 +00003959 SemaRef.CodeCompleter->includeGlobals(),
Sam McCallbb2cf632018-01-12 14:51:47 +00003960 /*IncludeDependentBases=*/true,
3961 SemaRef.CodeCompleter->loadExternal());
Alex Lorenz0fe0d982017-05-11 13:41:00 +00003962
3963 if (SemaRef.getLangOpts().CPlusPlus) {
3964 if (!Results.empty()) {
3965 // The "template" keyword can follow "->" or "." in the grammar.
3966 // However, we only want to suggest the template keyword if something
3967 // is dependent.
3968 bool IsDependent = BaseType->isDependentType();
3969 if (!IsDependent) {
3970 for (Scope *DepScope = S; DepScope; DepScope = DepScope->getParent())
3971 if (DeclContext *Ctx = DepScope->getEntity()) {
3972 IsDependent = Ctx->isDependentContext();
3973 break;
3974 }
3975 }
3976
3977 if (IsDependent)
3978 Results.AddResult(CodeCompletionResult("template"));
3979 }
3980 }
3981}
3982
Douglas Gregor1cc88a92012-01-23 15:59:30 +00003983void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003984 SourceLocation OpLoc, bool IsArrow,
3985 bool IsBaseExprStatement) {
Douglas Gregor1cc88a92012-01-23 15:59:30 +00003986 if (!Base || !CodeCompleter)
Douglas Gregor2436e712009-09-17 21:32:03 +00003987 return;
3988
Douglas Gregor1cc88a92012-01-23 15:59:30 +00003989 ExprResult ConvertedBase = PerformMemberExprBaseConversion(Base, IsArrow);
3990 if (ConvertedBase.isInvalid())
3991 return;
3992 Base = ConvertedBase.get();
Douglas Gregor3545ff42009-09-21 16:56:56 +00003993
Douglas Gregor2436e712009-09-17 21:32:03 +00003994 QualType BaseType = Base->getType();
Douglas Gregor3545ff42009-09-21 16:56:56 +00003995
3996 if (IsArrow) {
3997 if (const PointerType *Ptr = BaseType->getAs<PointerType>())
3998 BaseType = Ptr->getPointeeType();
3999 else if (BaseType->isObjCObjectPointerType())
Douglas Gregor9be0ed42010-08-26 16:36:48 +00004000 /*Do nothing*/ ;
Douglas Gregor3545ff42009-09-21 16:56:56 +00004001 else
4002 return;
4003 }
4004
Douglas Gregor21325842011-07-07 16:03:39 +00004005 enum CodeCompletionContext::Kind contextKind;
4006
4007 if (IsArrow) {
4008 contextKind = CodeCompletionContext::CCC_ArrowMemberAccess;
4009 }
4010 else {
4011 if (BaseType->isObjCObjectPointerType() ||
4012 BaseType->isObjCObjectOrInterfaceType()) {
4013 contextKind = CodeCompletionContext::CCC_ObjCPropertyAccess;
4014 }
4015 else {
4016 contextKind = CodeCompletionContext::CCC_DotMemberAccess;
4017 }
4018 }
Douglas Gregorc3425b12015-07-07 06:20:19 +00004019
4020 CodeCompletionContext CCContext(contextKind, BaseType);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004021 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004022 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorc3425b12015-07-07 06:20:19 +00004023 CCContext,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004024 &ResultBuilder::IsMember);
Douglas Gregor9291bad2009-11-18 01:29:26 +00004025 Results.EnterNewScope();
4026 if (const RecordType *Record = BaseType->getAs<RecordType>()) {
Alex Lorenz0fe0d982017-05-11 13:41:00 +00004027 AddRecordMembersCompletionResults(*this, Results, S, BaseType,
4028 Record->getDecl());
Alex Lorenze6afa392017-05-11 13:48:57 +00004029 } else if (const auto *TST = BaseType->getAs<TemplateSpecializationType>()) {
4030 TemplateName TN = TST->getTemplateName();
4031 if (const auto *TD =
4032 dyn_cast_or_null<ClassTemplateDecl>(TN.getAsTemplateDecl())) {
4033 CXXRecordDecl *RD = TD->getTemplatedDecl();
4034 AddRecordMembersCompletionResults(*this, Results, S, BaseType, RD);
4035 }
4036 } else if (const auto *ICNT = BaseType->getAs<InjectedClassNameType>()) {
4037 if (auto *RD = ICNT->getDecl())
4038 AddRecordMembersCompletionResults(*this, Results, S, BaseType, RD);
Alex Lorenz06cfa992016-10-12 11:40:15 +00004039 } else if (!IsArrow && BaseType->isObjCObjectPointerType()) {
Douglas Gregor9291bad2009-11-18 01:29:26 +00004040 // Objective-C property reference.
Douglas Gregorb888acf2010-12-09 23:01:55 +00004041 AddedPropertiesSet AddedProperties;
Alex Lorenz06cfa992016-10-12 11:40:15 +00004042
4043 if (const ObjCObjectPointerType *ObjCPtr =
4044 BaseType->getAsObjCInterfacePointerType()) {
4045 // Add property results based on our interface.
4046 assert(ObjCPtr && "Non-NULL pointer guaranteed above!");
4047 AddObjCProperties(CCContext, ObjCPtr->getInterfaceDecl(), true,
4048 /*AllowNullaryMethods=*/true, CurContext,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004049 AddedProperties, Results, IsBaseExprStatement);
Alex Lorenz06cfa992016-10-12 11:40:15 +00004050 }
4051
Douglas Gregor9291bad2009-11-18 01:29:26 +00004052 // Add properties from the protocols in a qualified interface.
Alex Lorenz06cfa992016-10-12 11:40:15 +00004053 for (auto *I : BaseType->getAs<ObjCObjectPointerType>()->quals())
Douglas Gregorc3425b12015-07-07 06:20:19 +00004054 AddObjCProperties(CCContext, I, true, /*AllowNullaryMethods=*/true,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004055 CurContext, AddedProperties, Results,
4056 IsBaseExprStatement);
Douglas Gregor9291bad2009-11-18 01:29:26 +00004057 } else if ((IsArrow && BaseType->isObjCObjectPointerType()) ||
John McCall8b07ec22010-05-15 11:32:37 +00004058 (!IsArrow && BaseType->isObjCObjectType())) {
Douglas Gregor9291bad2009-11-18 01:29:26 +00004059 // Objective-C instance variable access.
Craig Topperc3ec1492014-05-26 06:22:03 +00004060 ObjCInterfaceDecl *Class = nullptr;
Douglas Gregor9291bad2009-11-18 01:29:26 +00004061 if (const ObjCObjectPointerType *ObjCPtr
4062 = BaseType->getAs<ObjCObjectPointerType>())
4063 Class = ObjCPtr->getInterfaceDecl();
4064 else
John McCall8b07ec22010-05-15 11:32:37 +00004065 Class = BaseType->getAs<ObjCObjectType>()->getInterface();
Douglas Gregor9291bad2009-11-18 01:29:26 +00004066
4067 // Add all ivars from this class and its superclasses.
Douglas Gregor2b8162b2010-01-14 16:08:12 +00004068 if (Class) {
4069 CodeCompletionDeclConsumer Consumer(Results, CurContext);
4070 Results.setFilter(&ResultBuilder::IsObjCIvar);
Sam McCallbb2cf632018-01-12 14:51:47 +00004071 LookupVisibleDecls(
4072 Class, LookupMemberName, Consumer, CodeCompleter->includeGlobals(),
4073 /*IncludeDependentBases=*/false, CodeCompleter->loadExternal());
Douglas Gregor9291bad2009-11-18 01:29:26 +00004074 }
Douglas Gregor3545ff42009-09-21 16:56:56 +00004075 }
Douglas Gregor9291bad2009-11-18 01:29:26 +00004076
4077 // FIXME: How do we cope with isa?
4078
4079 Results.ExitScope();
Daniel Dunbar242ea9a2009-11-13 08:58:20 +00004080
Daniel Dunbar242ea9a2009-11-13 08:58:20 +00004081 // Hand off the results found for code completion.
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004082 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004083 Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004084 Results.data(),Results.size());
Douglas Gregor2436e712009-09-17 21:32:03 +00004085}
4086
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004087void Sema::CodeCompleteObjCClassPropertyRefExpr(Scope *S,
4088 IdentifierInfo &ClassName,
4089 SourceLocation ClassNameLoc,
4090 bool IsBaseExprStatement) {
4091 IdentifierInfo *ClassNamePtr = &ClassName;
4092 ObjCInterfaceDecl *IFace = getObjCInterfaceDecl(ClassNamePtr, ClassNameLoc);
4093 if (!IFace)
4094 return;
4095 CodeCompletionContext CCContext(
4096 CodeCompletionContext::CCC_ObjCPropertyAccess);
4097 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4098 CodeCompleter->getCodeCompletionTUInfo(), CCContext,
4099 &ResultBuilder::IsMember);
4100 Results.EnterNewScope();
4101 AddedPropertiesSet AddedProperties;
4102 AddObjCProperties(CCContext, IFace, true,
4103 /*AllowNullaryMethods=*/true, CurContext, AddedProperties,
4104 Results, IsBaseExprStatement,
4105 /*IsClassProperty=*/true);
4106 Results.ExitScope();
4107 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4108 Results.data(), Results.size());
4109}
4110
Faisal Vali090da2d2018-01-01 18:23:28 +00004111void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) {
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004112 if (!CodeCompleter)
4113 return;
Craig Topperc3ec1492014-05-26 06:22:03 +00004114
4115 ResultBuilder::LookupFilter Filter = nullptr;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004116 enum CodeCompletionContext::Kind ContextKind
4117 = CodeCompletionContext::CCC_Other;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004118 switch ((DeclSpec::TST)TagSpec) {
4119 case DeclSpec::TST_enum:
Douglas Gregor3545ff42009-09-21 16:56:56 +00004120 Filter = &ResultBuilder::IsEnum;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004121 ContextKind = CodeCompletionContext::CCC_EnumTag;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004122 break;
4123
4124 case DeclSpec::TST_union:
Douglas Gregor3545ff42009-09-21 16:56:56 +00004125 Filter = &ResultBuilder::IsUnion;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004126 ContextKind = CodeCompletionContext::CCC_UnionTag;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004127 break;
4128
4129 case DeclSpec::TST_struct:
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004130 case DeclSpec::TST_class:
Joao Matosdc86f942012-08-31 18:45:21 +00004131 case DeclSpec::TST_interface:
Douglas Gregor3545ff42009-09-21 16:56:56 +00004132 Filter = &ResultBuilder::IsClassOrStruct;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004133 ContextKind = CodeCompletionContext::CCC_ClassOrStructTag;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004134 break;
4135
4136 default:
David Blaikie83d382b2011-09-23 05:06:16 +00004137 llvm_unreachable("Unknown type specifier kind in CodeCompleteTag");
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004138 }
Douglas Gregor3545ff42009-09-21 16:56:56 +00004139
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004140 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4141 CodeCompleter->getCodeCompletionTUInfo(), ContextKind);
Douglas Gregora6e2edc2010-01-14 03:27:13 +00004142 CodeCompletionDeclConsumer Consumer(Results, CurContext);
John McCalle87beb22010-04-23 18:46:30 +00004143
4144 // First pass: look for tags.
4145 Results.setFilter(Filter);
Douglas Gregor39982192010-08-15 06:18:01 +00004146 LookupVisibleDecls(S, LookupTagName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00004147 CodeCompleter->includeGlobals(),
4148 CodeCompleter->loadExternal());
John McCalle87beb22010-04-23 18:46:30 +00004149
Douglas Gregor39982192010-08-15 06:18:01 +00004150 if (CodeCompleter->includeGlobals()) {
4151 // Second pass: look for nested name specifiers.
4152 Results.setFilter(&ResultBuilder::IsNestedNameSpecifier);
Sam McCallbb2cf632018-01-12 14:51:47 +00004153 LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer,
4154 CodeCompleter->includeGlobals(),
4155 CodeCompleter->loadExternal());
Douglas Gregor39982192010-08-15 06:18:01 +00004156 }
Douglas Gregor3545ff42009-09-21 16:56:56 +00004157
Douglas Gregor0ac41382010-09-23 23:01:17 +00004158 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004159 Results.data(),Results.size());
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004160}
4161
Alex Lorenz8f4d3992017-02-13 23:19:40 +00004162static void AddTypeQualifierResults(DeclSpec &DS, ResultBuilder &Results,
4163 const LangOptions &LangOpts) {
4164 if (!(DS.getTypeQualifiers() & DeclSpec::TQ_const))
4165 Results.AddResult("const");
4166 if (!(DS.getTypeQualifiers() & DeclSpec::TQ_volatile))
4167 Results.AddResult("volatile");
4168 if (LangOpts.C99 && !(DS.getTypeQualifiers() & DeclSpec::TQ_restrict))
4169 Results.AddResult("restrict");
4170 if (LangOpts.C11 && !(DS.getTypeQualifiers() & DeclSpec::TQ_atomic))
4171 Results.AddResult("_Atomic");
4172 if (LangOpts.MSVCCompat && !(DS.getTypeQualifiers() & DeclSpec::TQ_unaligned))
4173 Results.AddResult("__unaligned");
4174}
4175
Douglas Gregor28c78432010-08-27 17:35:51 +00004176void Sema::CodeCompleteTypeQualifiers(DeclSpec &DS) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004177 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004178 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004179 CodeCompletionContext::CCC_TypeQualifiers);
Douglas Gregor28c78432010-08-27 17:35:51 +00004180 Results.EnterNewScope();
Alex Lorenz8f4d3992017-02-13 23:19:40 +00004181 AddTypeQualifierResults(DS, Results, LangOpts);
Douglas Gregor28c78432010-08-27 17:35:51 +00004182 Results.ExitScope();
4183 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004184 Results.getCompletionContext(),
Douglas Gregor28c78432010-08-27 17:35:51 +00004185 Results.data(), Results.size());
4186}
4187
Alex Lorenz8f4d3992017-02-13 23:19:40 +00004188void Sema::CodeCompleteFunctionQualifiers(DeclSpec &DS, Declarator &D,
4189 const VirtSpecifiers *VS) {
4190 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4191 CodeCompleter->getCodeCompletionTUInfo(),
4192 CodeCompletionContext::CCC_TypeQualifiers);
4193 Results.EnterNewScope();
4194 AddTypeQualifierResults(DS, Results, LangOpts);
4195 if (LangOpts.CPlusPlus11) {
4196 Results.AddResult("noexcept");
Faisal Vali421b2d12017-12-29 05:41:00 +00004197 if (D.getContext() == DeclaratorContext::MemberContext &&
4198 !D.isCtorOrDtor() && !D.isStaticMember()) {
Alex Lorenz8f4d3992017-02-13 23:19:40 +00004199 if (!VS || !VS->isFinalSpecified())
4200 Results.AddResult("final");
4201 if (!VS || !VS->isOverrideSpecified())
4202 Results.AddResult("override");
4203 }
4204 }
4205 Results.ExitScope();
4206 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4207 Results.data(), Results.size());
4208}
4209
Benjamin Kramer72dae622016-02-18 15:30:24 +00004210void Sema::CodeCompleteBracketDeclarator(Scope *S) {
4211 CodeCompleteExpression(S, QualType(getASTContext().getSizeType()));
4212}
4213
Douglas Gregord328d572009-09-21 18:10:23 +00004214void Sema::CodeCompleteCase(Scope *S) {
John McCallaab3e412010-08-25 08:40:02 +00004215 if (getCurFunction()->SwitchStack.empty() || !CodeCompleter)
Douglas Gregord328d572009-09-21 18:10:23 +00004216 return;
John McCall5939b162011-08-06 07:30:58 +00004217
John McCallaab3e412010-08-25 08:40:02 +00004218 SwitchStmt *Switch = getCurFunction()->SwitchStack.back();
John McCall5939b162011-08-06 07:30:58 +00004219 QualType type = Switch->getCond()->IgnoreImplicit()->getType();
4220 if (!type->isEnumeralType()) {
4221 CodeCompleteExpressionData Data(type);
Douglas Gregor68762e72010-08-23 21:17:50 +00004222 Data.IntegralConstantExpression = true;
4223 CodeCompleteExpression(S, Data);
Douglas Gregord328d572009-09-21 18:10:23 +00004224 return;
Douglas Gregor85b50632010-07-28 21:50:18 +00004225 }
Douglas Gregord328d572009-09-21 18:10:23 +00004226
4227 // Code-complete the cases of a switch statement over an enumeration type
4228 // by providing the list of
John McCall5939b162011-08-06 07:30:58 +00004229 EnumDecl *Enum = type->castAs<EnumType>()->getDecl();
Douglas Gregor9b4f3702012-06-12 13:44:08 +00004230 if (EnumDecl *Def = Enum->getDefinition())
4231 Enum = Def;
Douglas Gregord328d572009-09-21 18:10:23 +00004232
4233 // Determine which enumerators we have already seen in the switch statement.
4234 // FIXME: Ideally, we would also be able to look *past* the code-completion
4235 // token, in case we are code-completing in the middle of the switch and not
4236 // at the end. However, we aren't able to do so at the moment.
4237 llvm::SmallPtrSet<EnumConstantDecl *, 8> EnumeratorsSeen;
Craig Topperc3ec1492014-05-26 06:22:03 +00004238 NestedNameSpecifier *Qualifier = nullptr;
Douglas Gregord328d572009-09-21 18:10:23 +00004239 for (SwitchCase *SC = Switch->getSwitchCaseList(); SC;
4240 SC = SC->getNextSwitchCase()) {
4241 CaseStmt *Case = dyn_cast<CaseStmt>(SC);
4242 if (!Case)
4243 continue;
4244
4245 Expr *CaseVal = Case->getLHS()->IgnoreParenCasts();
4246 if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CaseVal))
4247 if (EnumConstantDecl *Enumerator
4248 = dyn_cast<EnumConstantDecl>(DRE->getDecl())) {
4249 // We look into the AST of the case statement to determine which
4250 // enumerator was named. Alternatively, we could compute the value of
4251 // the integral constant expression, then compare it against the
4252 // values of each enumerator. However, value-based approach would not
4253 // work as well with C++ templates where enumerators declared within a
4254 // template are type- and value-dependent.
4255 EnumeratorsSeen.insert(Enumerator);
4256
Douglas Gregorf2510672009-09-21 19:57:38 +00004257 // If this is a qualified-id, keep track of the nested-name-specifier
4258 // so that we can reproduce it as part of code completion, e.g.,
Douglas Gregord328d572009-09-21 18:10:23 +00004259 //
4260 // switch (TagD.getKind()) {
4261 // case TagDecl::TK_enum:
4262 // break;
4263 // case XXX
4264 //
Douglas Gregorf2510672009-09-21 19:57:38 +00004265 // At the XXX, our completions are TagDecl::TK_union,
Douglas Gregord328d572009-09-21 18:10:23 +00004266 // TagDecl::TK_struct, and TagDecl::TK_class, rather than TK_union,
4267 // TK_struct, and TK_class.
Douglas Gregor4bd90e52009-10-23 18:54:35 +00004268 Qualifier = DRE->getQualifier();
Douglas Gregord328d572009-09-21 18:10:23 +00004269 }
4270 }
4271
David Blaikiebbafb8a2012-03-11 07:00:24 +00004272 if (getLangOpts().CPlusPlus && !Qualifier && EnumeratorsSeen.empty()) {
Douglas Gregorf2510672009-09-21 19:57:38 +00004273 // If there are no prior enumerators in C++, check whether we have to
4274 // qualify the names of the enumerators that we suggest, because they
4275 // may not be visible in this scope.
Douglas Gregord3cebdb2012-02-01 05:02:47 +00004276 Qualifier = getRequiredQualification(Context, CurContext, Enum);
Douglas Gregorf2510672009-09-21 19:57:38 +00004277 }
4278
Douglas Gregord328d572009-09-21 18:10:23 +00004279 // Add any enumerators that have not yet been mentioned.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004280 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004281 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004282 CodeCompletionContext::CCC_Expression);
Douglas Gregord328d572009-09-21 18:10:23 +00004283 Results.EnterNewScope();
Aaron Ballman23a6dcb2014-03-08 18:45:14 +00004284 for (auto *E : Enum->enumerators()) {
4285 if (EnumeratorsSeen.count(E))
Douglas Gregord328d572009-09-21 18:10:23 +00004286 continue;
4287
Aaron Ballman23a6dcb2014-03-08 18:45:14 +00004288 CodeCompletionResult R(E, CCP_EnumInCase, Qualifier);
Craig Topperc3ec1492014-05-26 06:22:03 +00004289 Results.AddResult(R, CurContext, nullptr, false);
Douglas Gregord328d572009-09-21 18:10:23 +00004290 }
4291 Results.ExitScope();
Douglas Gregor285560922010-04-06 20:02:15 +00004292
Douglas Gregor21325842011-07-07 16:03:39 +00004293 //We need to make sure we're setting the right context,
4294 //so only say we include macros if the code completer says we do
4295 enum CodeCompletionContext::Kind kind = CodeCompletionContext::CCC_Other;
4296 if (CodeCompleter->includeMacros()) {
Douglas Gregor8cb17462012-10-09 16:01:50 +00004297 AddMacroResults(PP, Results, false);
Douglas Gregor21325842011-07-07 16:03:39 +00004298 kind = CodeCompletionContext::CCC_OtherWithMacros;
4299 }
4300
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004301 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor21325842011-07-07 16:03:39 +00004302 kind,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004303 Results.data(),Results.size());
Douglas Gregord328d572009-09-21 18:10:23 +00004304}
4305
Robert Wilhelm16e94b92013-08-09 18:02:13 +00004306static bool anyNullArguments(ArrayRef<Expr *> Args) {
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00004307 if (Args.size() && !Args.data())
Douglas Gregor6ed3eb82010-05-30 06:10:08 +00004308 return true;
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00004309
4310 for (unsigned I = 0; I != Args.size(); ++I)
Douglas Gregor6ed3eb82010-05-30 06:10:08 +00004311 if (!Args[I])
4312 return true;
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00004313
Douglas Gregor6ed3eb82010-05-30 06:10:08 +00004314 return false;
4315}
4316
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004317typedef CodeCompleteConsumer::OverloadCandidate ResultCandidate;
4318
Francisco Lopes da Silva8cafefa2015-01-29 05:54:59 +00004319static void mergeCandidatesWithResults(Sema &SemaRef,
4320 SmallVectorImpl<ResultCandidate> &Results,
4321 OverloadCandidateSet &CandidateSet,
4322 SourceLocation Loc) {
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004323 if (!CandidateSet.empty()) {
4324 // Sort the overload candidate set by placing the best overloads first.
4325 std::stable_sort(
4326 CandidateSet.begin(), CandidateSet.end(),
4327 [&](const OverloadCandidate &X, const OverloadCandidate &Y) {
Richard Smith67ef14f2017-09-26 18:37:55 +00004328 return isBetterOverloadCandidate(SemaRef, X, Y, Loc,
4329 CandidateSet.getKind());
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004330 });
4331
4332 // Add the remaining viable overload candidates as code-completion results.
Erik Verbruggen7ec91072017-09-08 10:23:08 +00004333 for (auto &Candidate : CandidateSet) {
4334 if (Candidate.Function && Candidate.Function->isDeleted())
4335 continue;
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004336 if (Candidate.Viable)
4337 Results.push_back(ResultCandidate(Candidate.Function));
Erik Verbruggen7ec91072017-09-08 10:23:08 +00004338 }
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004339 }
4340}
4341
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00004342/// Get the type of the Nth parameter from a given set of overload
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004343/// candidates.
Francisco Lopes da Silva8cafefa2015-01-29 05:54:59 +00004344static QualType getParamType(Sema &SemaRef,
4345 ArrayRef<ResultCandidate> Candidates,
4346 unsigned N) {
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004347
4348 // Given the overloads 'Candidates' for a function call matching all arguments
4349 // up to N, return the type of the Nth parameter if it is the same for all
4350 // overload candidates.
4351 QualType ParamType;
4352 for (auto &Candidate : Candidates) {
4353 if (auto FType = Candidate.getFunctionType())
4354 if (auto Proto = dyn_cast<FunctionProtoType>(FType))
4355 if (N < Proto->getNumParams()) {
4356 if (ParamType.isNull())
4357 ParamType = Proto->getParamType(N);
4358 else if (!SemaRef.Context.hasSameUnqualifiedType(
4359 ParamType.getNonReferenceType(),
4360 Proto->getParamType(N).getNonReferenceType()))
4361 // Otherwise return a default-constructed QualType.
4362 return QualType();
4363 }
4364 }
4365
4366 return ParamType;
4367}
4368
Francisco Lopes da Silva8cafefa2015-01-29 05:54:59 +00004369static void CodeCompleteOverloadResults(Sema &SemaRef, Scope *S,
4370 MutableArrayRef<ResultCandidate> Candidates,
4371 unsigned CurrentArg,
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004372 bool CompleteExpressionWithCurrentArg = true) {
4373 QualType ParamType;
4374 if (CompleteExpressionWithCurrentArg)
4375 ParamType = getParamType(SemaRef, Candidates, CurrentArg);
4376
4377 if (ParamType.isNull())
4378 SemaRef.CodeCompleteOrdinaryName(S, Sema::PCC_Expression);
4379 else
4380 SemaRef.CodeCompleteExpression(S, ParamType);
4381
4382 if (!Candidates.empty())
4383 SemaRef.CodeCompleter->ProcessOverloadCandidates(SemaRef, CurrentArg,
4384 Candidates.data(),
4385 Candidates.size());
4386}
4387
4388void Sema::CodeCompleteCall(Scope *S, Expr *Fn, ArrayRef<Expr *> Args) {
Douglas Gregorcabea402009-09-22 15:41:20 +00004389 if (!CodeCompleter)
4390 return;
Douglas Gregor3ef59522009-12-11 19:06:04 +00004391
4392 // When we're code-completing for a call, we fall back to ordinary
4393 // name code-completion whenever we can't produce specific
4394 // results. We may want to revisit this strategy in the future,
4395 // e.g., by merging the two kinds of results.
4396
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004397 // FIXME: Provide support for variadic template functions.
Douglas Gregor3ef59522009-12-11 19:06:04 +00004398
Douglas Gregorcabea402009-09-22 15:41:20 +00004399 // Ignore type-dependent call expressions entirely.
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00004400 if (!Fn || Fn->isTypeDependent() || anyNullArguments(Args) ||
4401 Expr::hasAnyTypeDependentArguments(Args)) {
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004402 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregorcabea402009-09-22 15:41:20 +00004403 return;
Douglas Gregor3ef59522009-12-11 19:06:04 +00004404 }
Douglas Gregorcabea402009-09-22 15:41:20 +00004405
John McCall57500772009-12-16 12:17:52 +00004406 // Build an overload candidate set based on the functions we find.
John McCallbc077cf2010-02-08 23:07:23 +00004407 SourceLocation Loc = Fn->getExprLoc();
Richard Smith100b24a2014-04-17 01:52:14 +00004408 OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal);
John McCall57500772009-12-16 12:17:52 +00004409
Chris Lattner0e62c1c2011-07-23 10:55:15 +00004410 SmallVector<ResultCandidate, 8> Results;
Douglas Gregorff59f672010-01-21 15:46:19 +00004411
John McCall57500772009-12-16 12:17:52 +00004412 Expr *NakedFn = Fn->IgnoreParenCasts();
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004413 if (auto ULE = dyn_cast<UnresolvedLookupExpr>(NakedFn))
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00004414 AddOverloadedCallCandidates(ULE, Args, CandidateSet,
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004415 /*PartialOverloading=*/true);
4416 else if (auto UME = dyn_cast<UnresolvedMemberExpr>(NakedFn)) {
4417 TemplateArgumentListInfo TemplateArgsBuffer, *TemplateArgs = nullptr;
4418 if (UME->hasExplicitTemplateArgs()) {
4419 UME->copyTemplateArgumentsInto(TemplateArgsBuffer);
4420 TemplateArgs = &TemplateArgsBuffer;
Douglas Gregorff59f672010-01-21 15:46:19 +00004421 }
Erik Verbruggenf1898cf2017-03-28 07:22:21 +00004422
4423 // Add the base as first argument (use a nullptr if the base is implicit).
4424 SmallVector<Expr *, 12> ArgExprs(
4425 1, UME->isImplicitAccess() ? nullptr : UME->getBase());
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004426 ArgExprs.append(Args.begin(), Args.end());
4427 UnresolvedSet<8> Decls;
4428 Decls.append(UME->decls_begin(), UME->decls_end());
Benjamin Kramere3962ae2017-10-26 08:41:28 +00004429 const bool FirstArgumentIsBase = !UME->isImplicitAccess() && UME->getBase();
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004430 AddFunctionCandidates(Decls, ArgExprs, CandidateSet, TemplateArgs,
4431 /*SuppressUsedConversions=*/false,
Benjamin Kramere3962ae2017-10-26 08:41:28 +00004432 /*PartialOverloading=*/true,
4433 FirstArgumentIsBase);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004434 } else {
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004435 FunctionDecl *FD = nullptr;
4436 if (auto MCE = dyn_cast<MemberExpr>(NakedFn))
4437 FD = dyn_cast<FunctionDecl>(MCE->getMemberDecl());
4438 else if (auto DRE = dyn_cast<DeclRefExpr>(NakedFn))
4439 FD = dyn_cast<FunctionDecl>(DRE->getDecl());
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00004440 if (FD) { // We check whether it's a resolved function declaration.
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00004441 if (!getLangOpts().CPlusPlus ||
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004442 !FD->getType()->getAs<FunctionProtoType>())
4443 Results.push_back(ResultCandidate(FD));
4444 else
4445 AddOverloadCandidate(FD, DeclAccessPair::make(FD, FD->getAccess()),
4446 Args, CandidateSet,
4447 /*SuppressUsedConversions=*/false,
4448 /*PartialOverloading=*/true);
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00004449
4450 } else if (auto DC = NakedFn->getType()->getAsCXXRecordDecl()) {
4451 // If expression's type is CXXRecordDecl, it may overload the function
4452 // call operator, so we check if it does and add them as candidates.
Francisco Lopes da Silvaa349a8a2015-01-25 08:47:59 +00004453 // A complete type is needed to lookup for member function call operators.
Richard Smithdb0ac552015-12-18 22:40:25 +00004454 if (isCompleteType(Loc, NakedFn->getType())) {
Francisco Lopes da Silvaa349a8a2015-01-25 08:47:59 +00004455 DeclarationName OpName = Context.DeclarationNames
4456 .getCXXOperatorName(OO_Call);
4457 LookupResult R(*this, OpName, Loc, LookupOrdinaryName);
4458 LookupQualifiedName(R, DC);
4459 R.suppressDiagnostics();
4460 SmallVector<Expr *, 12> ArgExprs(1, NakedFn);
4461 ArgExprs.append(Args.begin(), Args.end());
4462 AddFunctionCandidates(R.asUnresolvedSet(), ArgExprs, CandidateSet,
4463 /*ExplicitArgs=*/nullptr,
4464 /*SuppressUsedConversions=*/false,
4465 /*PartialOverloading=*/true);
4466 }
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00004467 } else {
4468 // Lastly we check whether expression's type is function pointer or
4469 // function.
4470 QualType T = NakedFn->getType();
4471 if (!T->getPointeeType().isNull())
4472 T = T->getPointeeType();
4473
4474 if (auto FP = T->getAs<FunctionProtoType>()) {
4475 if (!TooManyArguments(FP->getNumParams(), Args.size(),
Francisco Lopes da Silva62a9a4f2015-01-23 13:17:51 +00004476 /*PartialOverloading=*/true) ||
4477 FP->isVariadic())
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00004478 Results.push_back(ResultCandidate(FP));
4479 } else if (auto FT = T->getAs<FunctionType>())
Francisco Lopes da Silva62a9a4f2015-01-23 13:17:51 +00004480 // No prototype and declaration, it may be a K & R style function.
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00004481 Results.push_back(ResultCandidate(FT));
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004482 }
Douglas Gregorcabea402009-09-22 15:41:20 +00004483 }
Douglas Gregor3ef59522009-12-11 19:06:04 +00004484
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004485 mergeCandidatesWithResults(*this, Results, CandidateSet, Loc);
4486 CodeCompleteOverloadResults(*this, S, Results, Args.size(),
4487 !CandidateSet.empty());
4488}
4489
4490void Sema::CodeCompleteConstructor(Scope *S, QualType Type, SourceLocation Loc,
4491 ArrayRef<Expr *> Args) {
4492 if (!CodeCompleter)
4493 return;
4494
4495 // A complete type is needed to lookup for constructors.
Ilya Biryukovfb9dde72018-05-14 13:50:36 +00004496 CXXRecordDecl *RD =
4497 isCompleteType(Loc, Type) ? Type->getAsCXXRecordDecl() : nullptr;
Argyrios Kyrtzidisee1d76f2015-03-13 07:39:30 +00004498 if (!RD) {
4499 CodeCompleteExpression(S, Type);
4500 return;
4501 }
4502
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004503 // FIXME: Provide support for member initializers.
4504 // FIXME: Provide support for variadic template constructors.
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004505
4506 OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal);
4507
Argyrios Kyrtzidisee1d76f2015-03-13 07:39:30 +00004508 for (auto C : LookupConstructors(RD)) {
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004509 if (auto FD = dyn_cast<FunctionDecl>(C)) {
4510 AddOverloadCandidate(FD, DeclAccessPair::make(FD, C->getAccess()),
4511 Args, CandidateSet,
4512 /*SuppressUsedConversions=*/false,
4513 /*PartialOverloading=*/true);
4514 } else if (auto FTD = dyn_cast<FunctionTemplateDecl>(C)) {
4515 AddTemplateOverloadCandidate(FTD,
4516 DeclAccessPair::make(FTD, C->getAccess()),
4517 /*ExplicitTemplateArgs=*/nullptr,
4518 Args, CandidateSet,
4519 /*SuppressUsedConversions=*/false,
4520 /*PartialOverloading=*/true);
4521 }
4522 }
4523
4524 SmallVector<ResultCandidate, 8> Results;
4525 mergeCandidatesWithResults(*this, Results, CandidateSet, Loc);
4526 CodeCompleteOverloadResults(*this, S, Results, Args.size());
Douglas Gregorcabea402009-09-22 15:41:20 +00004527}
4528
John McCall48871652010-08-21 09:40:31 +00004529void Sema::CodeCompleteInitializer(Scope *S, Decl *D) {
4530 ValueDecl *VD = dyn_cast_or_null<ValueDecl>(D);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004531 if (!VD) {
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004532 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004533 return;
4534 }
4535
4536 CodeCompleteExpression(S, VD->getType());
4537}
4538
4539void Sema::CodeCompleteReturn(Scope *S) {
4540 QualType ResultType;
4541 if (isa<BlockDecl>(CurContext)) {
4542 if (BlockScopeInfo *BSI = getCurBlock())
4543 ResultType = BSI->ReturnType;
4544 } else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(CurContext))
Alp Toker314cc812014-01-25 16:55:45 +00004545 ResultType = Function->getReturnType();
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004546 else if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(CurContext))
Alp Toker314cc812014-01-25 16:55:45 +00004547 ResultType = Method->getReturnType();
4548
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004549 if (ResultType.isNull())
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004550 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004551 else
4552 CodeCompleteExpression(S, ResultType);
4553}
4554
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004555void Sema::CodeCompleteAfterIf(Scope *S) {
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004556 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004557 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004558 mapCodeCompletionContext(*this, PCC_Statement));
4559 Results.setFilter(&ResultBuilder::IsOrdinaryName);
4560 Results.EnterNewScope();
4561
4562 CodeCompletionDeclConsumer Consumer(Results, CurContext);
4563 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00004564 CodeCompleter->includeGlobals(),
4565 CodeCompleter->loadExternal());
4566
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004567 AddOrdinaryNameResults(PCC_Statement, S, *this, Results);
4568
4569 // "else" block
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004570 CodeCompletionBuilder Builder(Results.getAllocator(),
4571 Results.getCodeCompletionTUInfo());
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004572 Builder.AddTypedTextChunk("else");
Douglas Gregor3a5d6c22012-02-16 17:49:04 +00004573 if (Results.includeCodePatterns()) {
4574 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4575 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4576 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
4577 Builder.AddPlaceholderChunk("statements");
4578 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
4579 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4580 }
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004581 Results.AddResult(Builder.TakeString());
4582
4583 // "else if" block
4584 Builder.AddTypedTextChunk("else");
4585 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4586 Builder.AddTextChunk("if");
4587 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4588 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00004589 if (getLangOpts().CPlusPlus)
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004590 Builder.AddPlaceholderChunk("condition");
4591 else
4592 Builder.AddPlaceholderChunk("expression");
4593 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor3a5d6c22012-02-16 17:49:04 +00004594 if (Results.includeCodePatterns()) {
4595 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4596 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4597 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
4598 Builder.AddPlaceholderChunk("statements");
4599 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
4600 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4601 }
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004602 Results.AddResult(Builder.TakeString());
4603
4604 Results.ExitScope();
4605
4606 if (S->getFnParent())
Craig Topper12126262015-11-15 17:27:57 +00004607 AddPrettyFunctionResults(getLangOpts(), Results);
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004608
4609 if (CodeCompleter->includeMacros())
Douglas Gregor8cb17462012-10-09 16:01:50 +00004610 AddMacroResults(PP, Results, false);
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004611
4612 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4613 Results.data(),Results.size());
4614}
4615
Richard Trieu2bd04012011-09-09 02:00:50 +00004616void Sema::CodeCompleteAssignmentRHS(Scope *S, Expr *LHS) {
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004617 if (LHS)
4618 CodeCompleteExpression(S, static_cast<Expr *>(LHS)->getType());
4619 else
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004620 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004621}
4622
Jeffrey Yasskinc76498d2010-04-08 16:38:48 +00004623void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS,
Douglas Gregor2436e712009-09-17 21:32:03 +00004624 bool EnteringContext) {
Eric Liu06d34022017-12-12 11:35:46 +00004625 if (SS.isEmpty() || !CodeCompleter)
Douglas Gregor2436e712009-09-17 21:32:03 +00004626 return;
Alex Lorenz8a7a4cf2017-06-15 21:40:54 +00004627
Eric Liu06d34022017-12-12 11:35:46 +00004628 // We want to keep the scope specifier even if it's invalid (e.g. the scope
4629 // "a::b::" is not corresponding to any context/namespace in the AST), since
4630 // it can be useful for global code completion which have information about
4631 // contexts/symbols that are not in the AST.
4632 if (SS.isInvalid()) {
4633 CodeCompletionContext CC(CodeCompletionContext::CCC_Name);
4634 CC.setCXXScopeSpecifier(SS);
4635 HandleCodeCompleteResults(this, CodeCompleter, CC, nullptr, 0);
4636 return;
4637 }
Alex Lorenz8a7a4cf2017-06-15 21:40:54 +00004638 // Always pretend to enter a context to ensure that a dependent type
4639 // resolves to a dependent record.
4640 DeclContext *Ctx = computeDeclContext(SS, /*EnteringContext=*/true);
Douglas Gregor3545ff42009-09-21 16:56:56 +00004641 if (!Ctx)
4642 return;
Douglas Gregor800f2f02009-12-11 18:28:39 +00004643
4644 // Try to instantiate any non-dependent declaration contexts before
4645 // we look in them.
John McCall0b66eb32010-05-01 00:40:08 +00004646 if (!isDependentScopeSpecifier(SS) && RequireCompleteDeclContext(SS, Ctx))
Douglas Gregor800f2f02009-12-11 18:28:39 +00004647 return;
4648
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004649 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004650 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004651 CodeCompletionContext::CCC_Name);
Douglas Gregorac322ec2010-08-27 21:18:54 +00004652 Results.EnterNewScope();
Eric Liu06d34022017-12-12 11:35:46 +00004653
Douglas Gregor3545ff42009-09-21 16:56:56 +00004654 // The "template" keyword can follow "::" in the grammar, but only
4655 // put it into the grammar if the nested-name-specifier is dependent.
Aaron Ballman4a979672014-01-03 13:56:08 +00004656 NestedNameSpecifier *NNS = SS.getScopeRep();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004657 if (!Results.empty() && NNS->isDependent())
Douglas Gregor78a21012010-01-14 16:01:26 +00004658 Results.AddResult("template");
Douglas Gregorac322ec2010-08-27 21:18:54 +00004659
4660 // Add calls to overridden virtual functions, if there are any.
4661 //
4662 // FIXME: This isn't wonderful, because we don't know whether we're actually
4663 // in a context that permits expressions. This is a general issue with
4664 // qualified-id completions.
4665 if (!EnteringContext)
4666 MaybeAddOverrideCalls(*this, Ctx, Results);
Eric Liu06d34022017-12-12 11:35:46 +00004667 Results.ExitScope();
4668
Eric Liufead6ae2017-12-13 10:26:49 +00004669 if (CodeCompleter->includeNamespaceLevelDecls() ||
4670 (!Ctx->isNamespace() && !Ctx->isTranslationUnit())) {
4671 CodeCompletionDeclConsumer Consumer(Results, CurContext);
4672 LookupVisibleDecls(Ctx, LookupOrdinaryName, Consumer,
4673 /*IncludeGlobalScope=*/true,
Sam McCallbb2cf632018-01-12 14:51:47 +00004674 /*IncludeDependentBases=*/true,
4675 CodeCompleter->loadExternal());
Eric Liufead6ae2017-12-13 10:26:49 +00004676 }
Douglas Gregorac322ec2010-08-27 21:18:54 +00004677
Eric Liu06d34022017-12-12 11:35:46 +00004678 auto CC = Results.getCompletionContext();
4679 CC.setCXXScopeSpecifier(SS);
4680
4681 HandleCodeCompleteResults(this, CodeCompleter, CC, Results.data(),
4682 Results.size());
Douglas Gregor2436e712009-09-17 21:32:03 +00004683}
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00004684
4685void Sema::CodeCompleteUsing(Scope *S) {
4686 if (!CodeCompleter)
4687 return;
4688
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004689 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004690 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00004691 CodeCompletionContext::CCC_PotentiallyQualifiedName,
4692 &ResultBuilder::IsNestedNameSpecifier);
Douglas Gregor64b12b52009-09-22 23:31:26 +00004693 Results.EnterNewScope();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004694
4695 // If we aren't in class scope, we could see the "namespace" keyword.
4696 if (!S->isClassScope())
John McCall276321a2010-08-25 06:19:51 +00004697 Results.AddResult(CodeCompletionResult("namespace"));
Douglas Gregor3545ff42009-09-21 16:56:56 +00004698
4699 // After "using", we can see anything that would start a
4700 // nested-name-specifier.
Douglas Gregora6e2edc2010-01-14 03:27:13 +00004701 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00004702 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00004703 CodeCompleter->includeGlobals(),
4704 CodeCompleter->loadExternal());
Douglas Gregor64b12b52009-09-22 23:31:26 +00004705 Results.ExitScope();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004706
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004707 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004708 CodeCompletionContext::CCC_PotentiallyQualifiedName,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004709 Results.data(),Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00004710}
4711
4712void Sema::CodeCompleteUsingDirective(Scope *S) {
4713 if (!CodeCompleter)
4714 return;
4715
Douglas Gregor3545ff42009-09-21 16:56:56 +00004716 // After "using namespace", we expect to see a namespace name or namespace
4717 // alias.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004718 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004719 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004720 CodeCompletionContext::CCC_Namespace,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004721 &ResultBuilder::IsNamespaceOrAlias);
Douglas Gregor64b12b52009-09-22 23:31:26 +00004722 Results.EnterNewScope();
Douglas Gregora6e2edc2010-01-14 03:27:13 +00004723 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00004724 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00004725 CodeCompleter->includeGlobals(),
4726 CodeCompleter->loadExternal());
Douglas Gregor64b12b52009-09-22 23:31:26 +00004727 Results.ExitScope();
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004728 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor39982192010-08-15 06:18:01 +00004729 CodeCompletionContext::CCC_Namespace,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004730 Results.data(),Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00004731}
4732
4733void Sema::CodeCompleteNamespaceDecl(Scope *S) {
4734 if (!CodeCompleter)
4735 return;
4736
Ted Kremenekc37877d2013-10-08 17:08:03 +00004737 DeclContext *Ctx = S->getEntity();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004738 if (!S->getParent())
4739 Ctx = Context.getTranslationUnitDecl();
4740
Douglas Gregor0ac41382010-09-23 23:01:17 +00004741 bool SuppressedGlobalResults
4742 = Ctx && !CodeCompleter->includeGlobals() && isa<TranslationUnitDecl>(Ctx);
4743
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004744 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004745 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00004746 SuppressedGlobalResults
4747 ? CodeCompletionContext::CCC_Namespace
4748 : CodeCompletionContext::CCC_Other,
4749 &ResultBuilder::IsNamespace);
4750
4751 if (Ctx && Ctx->isFileContext() && !SuppressedGlobalResults) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00004752 // We only want to see those namespaces that have already been defined
4753 // within this scope, because its likely that the user is creating an
4754 // extended namespace declaration. Keep track of the most recent
4755 // definition of each namespace.
4756 std::map<NamespaceDecl *, NamespaceDecl *> OrigToLatest;
4757 for (DeclContext::specific_decl_iterator<NamespaceDecl>
4758 NS(Ctx->decls_begin()), NSEnd(Ctx->decls_end());
4759 NS != NSEnd; ++NS)
David Blaikie40ed2972012-06-06 20:45:41 +00004760 OrigToLatest[NS->getOriginalNamespace()] = *NS;
Douglas Gregor3545ff42009-09-21 16:56:56 +00004761
4762 // Add the most recent definition (or extended definition) of each
4763 // namespace to the list of results.
Douglas Gregor64b12b52009-09-22 23:31:26 +00004764 Results.EnterNewScope();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004765 for (std::map<NamespaceDecl *, NamespaceDecl *>::iterator
Douglas Gregor78254c82012-03-27 23:34:16 +00004766 NS = OrigToLatest.begin(),
4767 NSEnd = OrigToLatest.end();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004768 NS != NSEnd; ++NS)
Douglas Gregor0a0e2b32013-01-31 04:52:16 +00004769 Results.AddResult(CodeCompletionResult(
Craig Topperc3ec1492014-05-26 06:22:03 +00004770 NS->second, Results.getBasePriority(NS->second),
4771 nullptr),
4772 CurContext, nullptr, false);
Douglas Gregor64b12b52009-09-22 23:31:26 +00004773 Results.ExitScope();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004774 }
4775
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004776 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004777 Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004778 Results.data(),Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00004779}
4780
4781void Sema::CodeCompleteNamespaceAliasDecl(Scope *S) {
4782 if (!CodeCompleter)
4783 return;
4784
Douglas Gregor3545ff42009-09-21 16:56:56 +00004785 // After "namespace", we expect to see a namespace or alias.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004786 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004787 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004788 CodeCompletionContext::CCC_Namespace,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004789 &ResultBuilder::IsNamespaceOrAlias);
Douglas Gregora6e2edc2010-01-14 03:27:13 +00004790 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00004791 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00004792 CodeCompleter->includeGlobals(),
4793 CodeCompleter->loadExternal());
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004794 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004795 Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004796 Results.data(),Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00004797}
4798
Douglas Gregorc811ede2009-09-18 20:05:18 +00004799void Sema::CodeCompleteOperatorName(Scope *S) {
4800 if (!CodeCompleter)
4801 return;
Douglas Gregor3545ff42009-09-21 16:56:56 +00004802
John McCall276321a2010-08-25 06:19:51 +00004803 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004804 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004805 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004806 CodeCompletionContext::CCC_Type,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004807 &ResultBuilder::IsType);
Douglas Gregor64b12b52009-09-22 23:31:26 +00004808 Results.EnterNewScope();
Douglas Gregorc811ede2009-09-18 20:05:18 +00004809
Douglas Gregor3545ff42009-09-21 16:56:56 +00004810 // Add the names of overloadable operators.
4811#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
4812 if (std::strcmp(Spelling, "?")) \
Douglas Gregor78a21012010-01-14 16:01:26 +00004813 Results.AddResult(Result(Spelling));
Douglas Gregor3545ff42009-09-21 16:56:56 +00004814#include "clang/Basic/OperatorKinds.def"
4815
4816 // Add any type names visible from the current scope
Douglas Gregor6ae4c522010-01-14 03:21:49 +00004817 Results.allowNestedNameSpecifiers();
Douglas Gregora6e2edc2010-01-14 03:27:13 +00004818 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00004819 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00004820 CodeCompleter->includeGlobals(),
4821 CodeCompleter->loadExternal());
4822
Douglas Gregor3545ff42009-09-21 16:56:56 +00004823 // Add any type specifiers
David Blaikiebbafb8a2012-03-11 07:00:24 +00004824 AddTypeSpecifierResults(getLangOpts(), Results);
Douglas Gregor64b12b52009-09-22 23:31:26 +00004825 Results.ExitScope();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004826
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004827 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor39982192010-08-15 06:18:01 +00004828 CodeCompletionContext::CCC_Type,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004829 Results.data(),Results.size());
Douglas Gregorc811ede2009-09-18 20:05:18 +00004830}
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00004831
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00004832void Sema::CodeCompleteConstructorInitializer(
4833 Decl *ConstructorD,
4834 ArrayRef <CXXCtorInitializer *> Initializers) {
Benjamin Kramera4f8df02015-07-09 15:31:10 +00004835 if (!ConstructorD)
4836 return;
4837
4838 AdjustDeclIfTemplate(ConstructorD);
4839
4840 CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(ConstructorD);
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004841 if (!Constructor)
4842 return;
4843
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004844 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004845 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00004846 CodeCompletionContext::CCC_PotentiallyQualifiedName);
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004847 Results.EnterNewScope();
4848
4849 // Fill in any already-initialized fields or base classes.
4850 llvm::SmallPtrSet<FieldDecl *, 4> InitializedFields;
4851 llvm::SmallPtrSet<CanQualType, 4> InitializedBases;
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00004852 for (unsigned I = 0, E = Initializers.size(); I != E; ++I) {
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004853 if (Initializers[I]->isBaseInitializer())
4854 InitializedBases.insert(
4855 Context.getCanonicalType(QualType(Initializers[I]->getBaseClass(), 0)));
4856 else
Francois Pichetd583da02010-12-04 09:14:42 +00004857 InitializedFields.insert(cast<FieldDecl>(
4858 Initializers[I]->getAnyMember()));
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004859 }
4860
4861 // Add completions for base classes.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004862 CodeCompletionBuilder Builder(Results.getAllocator(),
4863 Results.getCodeCompletionTUInfo());
Benjamin Kramera4f8df02015-07-09 15:31:10 +00004864 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00004865 bool SawLastInitializer = Initializers.empty();
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004866 CXXRecordDecl *ClassDecl = Constructor->getParent();
Aaron Ballman574705e2014-03-13 15:41:46 +00004867 for (const auto &Base : ClassDecl->bases()) {
David Blaikie82e95a32014-11-19 07:49:47 +00004868 if (!InitializedBases.insert(Context.getCanonicalType(Base.getType()))
4869 .second) {
Douglas Gregor99129ef2010-08-29 19:27:27 +00004870 SawLastInitializer
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00004871 = !Initializers.empty() &&
4872 Initializers.back()->isBaseInitializer() &&
Aaron Ballman574705e2014-03-13 15:41:46 +00004873 Context.hasSameUnqualifiedType(Base.getType(),
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00004874 QualType(Initializers.back()->getBaseClass(), 0));
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004875 continue;
Douglas Gregor99129ef2010-08-29 19:27:27 +00004876 }
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004877
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004878 Builder.AddTypedTextChunk(
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00004879 Results.getAllocator().CopyString(
Aaron Ballman574705e2014-03-13 15:41:46 +00004880 Base.getType().getAsString(Policy)));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004881 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4882 Builder.AddPlaceholderChunk("args");
4883 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4884 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor99129ef2010-08-29 19:27:27 +00004885 SawLastInitializer? CCP_NextInitializer
4886 : CCP_MemberDeclaration));
4887 SawLastInitializer = false;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004888 }
4889
4890 // Add completions for virtual base classes.
Aaron Ballman445a9392014-03-13 16:15:17 +00004891 for (const auto &Base : ClassDecl->vbases()) {
David Blaikie82e95a32014-11-19 07:49:47 +00004892 if (!InitializedBases.insert(Context.getCanonicalType(Base.getType()))
4893 .second) {
Douglas Gregor99129ef2010-08-29 19:27:27 +00004894 SawLastInitializer
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00004895 = !Initializers.empty() &&
4896 Initializers.back()->isBaseInitializer() &&
Aaron Ballman445a9392014-03-13 16:15:17 +00004897 Context.hasSameUnqualifiedType(Base.getType(),
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00004898 QualType(Initializers.back()->getBaseClass(), 0));
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004899 continue;
Douglas Gregor99129ef2010-08-29 19:27:27 +00004900 }
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004901
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004902 Builder.AddTypedTextChunk(
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00004903 Builder.getAllocator().CopyString(
Aaron Ballman445a9392014-03-13 16:15:17 +00004904 Base.getType().getAsString(Policy)));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004905 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4906 Builder.AddPlaceholderChunk("args");
4907 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4908 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor99129ef2010-08-29 19:27:27 +00004909 SawLastInitializer? CCP_NextInitializer
4910 : CCP_MemberDeclaration));
4911 SawLastInitializer = false;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004912 }
4913
4914 // Add completions for members.
Aaron Ballmane8a8bae2014-03-08 20:12:42 +00004915 for (auto *Field : ClassDecl->fields()) {
David Blaikie82e95a32014-11-19 07:49:47 +00004916 if (!InitializedFields.insert(cast<FieldDecl>(Field->getCanonicalDecl()))
4917 .second) {
Douglas Gregor99129ef2010-08-29 19:27:27 +00004918 SawLastInitializer
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00004919 = !Initializers.empty() &&
4920 Initializers.back()->isAnyMemberInitializer() &&
Aaron Ballmane8a8bae2014-03-08 20:12:42 +00004921 Initializers.back()->getAnyMember() == Field;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004922 continue;
Douglas Gregor99129ef2010-08-29 19:27:27 +00004923 }
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004924
4925 if (!Field->getDeclName())
4926 continue;
4927
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00004928 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004929 Field->getIdentifier()->getName()));
4930 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4931 Builder.AddPlaceholderChunk("args");
4932 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4933 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor99129ef2010-08-29 19:27:27 +00004934 SawLastInitializer? CCP_NextInitializer
Douglas Gregorf3af3112010-09-09 21:42:20 +00004935 : CCP_MemberDeclaration,
Douglas Gregor78254c82012-03-27 23:34:16 +00004936 CXCursor_MemberRef,
4937 CXAvailability_Available,
Aaron Ballmane8a8bae2014-03-08 20:12:42 +00004938 Field));
Douglas Gregor99129ef2010-08-29 19:27:27 +00004939 SawLastInitializer = false;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004940 }
4941 Results.ExitScope();
4942
Douglas Gregor0ac41382010-09-23 23:01:17 +00004943 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004944 Results.data(), Results.size());
4945}
4946
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00004947/// Determine whether this scope denotes a namespace.
Douglas Gregord8c61782012-02-15 15:34:24 +00004948static bool isNamespaceScope(Scope *S) {
Ted Kremenekc37877d2013-10-08 17:08:03 +00004949 DeclContext *DC = S->getEntity();
Douglas Gregord8c61782012-02-15 15:34:24 +00004950 if (!DC)
4951 return false;
4952
4953 return DC->isFileContext();
4954}
4955
4956void Sema::CodeCompleteLambdaIntroducer(Scope *S, LambdaIntroducer &Intro,
4957 bool AfterAmpersand) {
4958 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004959 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregord8c61782012-02-15 15:34:24 +00004960 CodeCompletionContext::CCC_Other);
4961 Results.EnterNewScope();
4962
4963 // Note what has already been captured.
4964 llvm::SmallPtrSet<IdentifierInfo *, 4> Known;
4965 bool IncludedThis = false;
Benjamin Kramerf3ca26982014-05-10 16:31:55 +00004966 for (const auto &C : Intro.Captures) {
4967 if (C.Kind == LCK_This) {
Douglas Gregord8c61782012-02-15 15:34:24 +00004968 IncludedThis = true;
4969 continue;
4970 }
4971
Benjamin Kramerf3ca26982014-05-10 16:31:55 +00004972 Known.insert(C.Id);
Douglas Gregord8c61782012-02-15 15:34:24 +00004973 }
4974
4975 // Look for other capturable variables.
4976 for (; S && !isNamespaceScope(S); S = S->getParent()) {
Aaron Ballman35c54952014-03-17 16:55:25 +00004977 for (const auto *D : S->decls()) {
4978 const auto *Var = dyn_cast<VarDecl>(D);
Douglas Gregord8c61782012-02-15 15:34:24 +00004979 if (!Var ||
4980 !Var->hasLocalStorage() ||
4981 Var->hasAttr<BlocksAttr>())
4982 continue;
4983
David Blaikie82e95a32014-11-19 07:49:47 +00004984 if (Known.insert(Var->getIdentifier()).second)
Douglas Gregor0a0e2b32013-01-31 04:52:16 +00004985 Results.AddResult(CodeCompletionResult(Var, CCP_LocalDeclaration),
Craig Topperc3ec1492014-05-26 06:22:03 +00004986 CurContext, nullptr, false);
Douglas Gregord8c61782012-02-15 15:34:24 +00004987 }
4988 }
4989
4990 // Add 'this', if it would be valid.
4991 if (!IncludedThis && !AfterAmpersand && Intro.Default != LCD_ByCopy)
4992 addThisCompletion(*this, Results);
4993
4994 Results.ExitScope();
4995
4996 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4997 Results.data(), Results.size());
4998}
4999
James Dennett596e4752012-06-14 03:11:41 +00005000/// Macro that optionally prepends an "@" to the string literal passed in via
5001/// Keyword, depending on whether NeedAt is true or false.
5002#define OBJC_AT_KEYWORD_NAME(NeedAt,Keyword) ((NeedAt)? "@" Keyword : Keyword)
5003
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005004static void AddObjCImplementationResults(const LangOptions &LangOpts,
Douglas Gregorf1934162010-01-13 21:24:21 +00005005 ResultBuilder &Results,
5006 bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005007 typedef CodeCompletionResult Result;
Douglas Gregorf1934162010-01-13 21:24:21 +00005008 // Since we have an implementation, we can end it.
James Dennett596e4752012-06-14 03:11:41 +00005009 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"end")));
Douglas Gregorf1934162010-01-13 21:24:21 +00005010
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005011 CodeCompletionBuilder Builder(Results.getAllocator(),
5012 Results.getCodeCompletionTUInfo());
Douglas Gregorf1934162010-01-13 21:24:21 +00005013 if (LangOpts.ObjC2) {
5014 // @dynamic
James Dennett596e4752012-06-14 03:11:41 +00005015 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"dynamic"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005016 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5017 Builder.AddPlaceholderChunk("property");
5018 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf1934162010-01-13 21:24:21 +00005019
5020 // @synthesize
James Dennett596e4752012-06-14 03:11:41 +00005021 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"synthesize"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005022 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5023 Builder.AddPlaceholderChunk("property");
5024 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf1934162010-01-13 21:24:21 +00005025 }
5026}
5027
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005028static void AddObjCInterfaceResults(const LangOptions &LangOpts,
Douglas Gregorf1934162010-01-13 21:24:21 +00005029 ResultBuilder &Results,
5030 bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005031 typedef CodeCompletionResult Result;
Douglas Gregorf1934162010-01-13 21:24:21 +00005032
5033 // Since we have an interface or protocol, we can end it.
James Dennett596e4752012-06-14 03:11:41 +00005034 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"end")));
Douglas Gregorf1934162010-01-13 21:24:21 +00005035
5036 if (LangOpts.ObjC2) {
5037 // @property
James Dennett596e4752012-06-14 03:11:41 +00005038 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"property")));
Douglas Gregorf1934162010-01-13 21:24:21 +00005039
5040 // @required
James Dennett596e4752012-06-14 03:11:41 +00005041 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"required")));
Douglas Gregorf1934162010-01-13 21:24:21 +00005042
5043 // @optional
James Dennett596e4752012-06-14 03:11:41 +00005044 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"optional")));
Douglas Gregorf1934162010-01-13 21:24:21 +00005045 }
5046}
5047
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005048static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005049 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005050 CodeCompletionBuilder Builder(Results.getAllocator(),
5051 Results.getCodeCompletionTUInfo());
Douglas Gregorf1934162010-01-13 21:24:21 +00005052
5053 // @class name ;
James Dennett596e4752012-06-14 03:11:41 +00005054 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"class"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005055 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5056 Builder.AddPlaceholderChunk("name");
5057 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf1934162010-01-13 21:24:21 +00005058
Douglas Gregorf4c33342010-05-28 00:22:41 +00005059 if (Results.includeCodePatterns()) {
5060 // @interface name
5061 // FIXME: Could introduce the whole pattern, including superclasses and
5062 // such.
James Dennett596e4752012-06-14 03:11:41 +00005063 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"interface"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005064 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5065 Builder.AddPlaceholderChunk("class");
5066 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf1934162010-01-13 21:24:21 +00005067
Douglas Gregorf4c33342010-05-28 00:22:41 +00005068 // @protocol name
James Dennett596e4752012-06-14 03:11:41 +00005069 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"protocol"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005070 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5071 Builder.AddPlaceholderChunk("protocol");
5072 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00005073
5074 // @implementation name
James Dennett596e4752012-06-14 03:11:41 +00005075 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"implementation"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005076 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5077 Builder.AddPlaceholderChunk("class");
5078 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00005079 }
Douglas Gregorf1934162010-01-13 21:24:21 +00005080
5081 // @compatibility_alias name
James Dennett596e4752012-06-14 03:11:41 +00005082 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"compatibility_alias"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005083 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5084 Builder.AddPlaceholderChunk("alias");
5085 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5086 Builder.AddPlaceholderChunk("class");
5087 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor61e36812013-03-07 23:26:24 +00005088
5089 if (Results.getSema().getLangOpts().Modules) {
5090 // @import name
5091 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "import"));
5092 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5093 Builder.AddPlaceholderChunk("module");
5094 Results.AddResult(Result(Builder.TakeString()));
5095 }
Douglas Gregorf1934162010-01-13 21:24:21 +00005096}
5097
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005098void Sema::CodeCompleteObjCAtDirective(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005099 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005100 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005101 CodeCompletionContext::CCC_Other);
Douglas Gregorf48706c2009-12-07 09:27:33 +00005102 Results.EnterNewScope();
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005103 if (isa<ObjCImplDecl>(CurContext))
David Blaikiebbafb8a2012-03-11 07:00:24 +00005104 AddObjCImplementationResults(getLangOpts(), Results, false);
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005105 else if (CurContext->isObjCContainer())
David Blaikiebbafb8a2012-03-11 07:00:24 +00005106 AddObjCInterfaceResults(getLangOpts(), Results, false);
Douglas Gregorf1934162010-01-13 21:24:21 +00005107 else
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005108 AddObjCTopLevelResults(Results, false);
Douglas Gregorf48706c2009-12-07 09:27:33 +00005109 Results.ExitScope();
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005110 HandleCodeCompleteResults(this, CodeCompleter,
5111 CodeCompletionContext::CCC_Other,
5112 Results.data(),Results.size());
Douglas Gregorf48706c2009-12-07 09:27:33 +00005113}
5114
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005115static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005116 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005117 CodeCompletionBuilder Builder(Results.getAllocator(),
5118 Results.getCodeCompletionTUInfo());
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005119
5120 // @encode ( type-name )
Douglas Gregore5c79d52011-10-18 21:20:17 +00005121 const char *EncodeType = "char[]";
David Blaikiebbafb8a2012-03-11 07:00:24 +00005122 if (Results.getSema().getLangOpts().CPlusPlus ||
5123 Results.getSema().getLangOpts().ConstStrings)
Jordan Rose9da05852012-06-15 18:19:56 +00005124 EncodeType = "const char[]";
Douglas Gregore5c79d52011-10-18 21:20:17 +00005125 Builder.AddResultTypeChunk(EncodeType);
James Dennett596e4752012-06-14 03:11:41 +00005126 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"encode"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005127 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5128 Builder.AddPlaceholderChunk("type-name");
5129 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5130 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005131
5132 // @protocol ( protocol-name )
Douglas Gregore5c79d52011-10-18 21:20:17 +00005133 Builder.AddResultTypeChunk("Protocol *");
James Dennett596e4752012-06-14 03:11:41 +00005134 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"protocol"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005135 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5136 Builder.AddPlaceholderChunk("protocol-name");
5137 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5138 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005139
5140 // @selector ( selector )
Douglas Gregore5c79d52011-10-18 21:20:17 +00005141 Builder.AddResultTypeChunk("SEL");
James Dennett596e4752012-06-14 03:11:41 +00005142 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"selector"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005143 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5144 Builder.AddPlaceholderChunk("selector");
5145 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5146 Results.AddResult(Result(Builder.TakeString()));
Jordan Rose9da05852012-06-15 18:19:56 +00005147
5148 // @"string"
5149 Builder.AddResultTypeChunk("NSString *");
5150 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"\""));
5151 Builder.AddPlaceholderChunk("string");
5152 Builder.AddTextChunk("\"");
5153 Results.AddResult(Result(Builder.TakeString()));
5154
Douglas Gregor951de302012-07-17 23:24:47 +00005155 // @[objects, ...]
Jordan Rose9da05852012-06-15 18:19:56 +00005156 Builder.AddResultTypeChunk("NSArray *");
James Dennett596e4752012-06-14 03:11:41 +00005157 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"["));
Ted Kremeneke65b0862012-03-06 20:05:56 +00005158 Builder.AddPlaceholderChunk("objects, ...");
Ted Kremeneke65b0862012-03-06 20:05:56 +00005159 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
5160 Results.AddResult(Result(Builder.TakeString()));
5161
Douglas Gregor951de302012-07-17 23:24:47 +00005162 // @{key : object, ...}
Jordan Rose9da05852012-06-15 18:19:56 +00005163 Builder.AddResultTypeChunk("NSDictionary *");
James Dennett596e4752012-06-14 03:11:41 +00005164 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"{"));
Ted Kremeneke65b0862012-03-06 20:05:56 +00005165 Builder.AddPlaceholderChunk("key");
Ted Kremeneke65b0862012-03-06 20:05:56 +00005166 Builder.AddChunk(CodeCompletionString::CK_Colon);
5167 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5168 Builder.AddPlaceholderChunk("object, ...");
Ted Kremeneke65b0862012-03-06 20:05:56 +00005169 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5170 Results.AddResult(Result(Builder.TakeString()));
Jordan Rose9da05852012-06-15 18:19:56 +00005171
Douglas Gregor951de302012-07-17 23:24:47 +00005172 // @(expression)
Jordan Rose9da05852012-06-15 18:19:56 +00005173 Builder.AddResultTypeChunk("id");
5174 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "("));
Jordan Rose9da05852012-06-15 18:19:56 +00005175 Builder.AddPlaceholderChunk("expression");
Jordan Rose9da05852012-06-15 18:19:56 +00005176 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5177 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005178}
5179
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005180static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005181 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005182 CodeCompletionBuilder Builder(Results.getAllocator(),
5183 Results.getCodeCompletionTUInfo());
Douglas Gregorf1934162010-01-13 21:24:21 +00005184
Douglas Gregorf4c33342010-05-28 00:22:41 +00005185 if (Results.includeCodePatterns()) {
5186 // @try { statements } @catch ( declaration ) { statements } @finally
5187 // { statements }
James Dennett596e4752012-06-14 03:11:41 +00005188 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"try"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005189 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5190 Builder.AddPlaceholderChunk("statements");
5191 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5192 Builder.AddTextChunk("@catch");
5193 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5194 Builder.AddPlaceholderChunk("parameter");
5195 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5196 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5197 Builder.AddPlaceholderChunk("statements");
5198 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5199 Builder.AddTextChunk("@finally");
5200 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5201 Builder.AddPlaceholderChunk("statements");
5202 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5203 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00005204 }
Douglas Gregorf1934162010-01-13 21:24:21 +00005205
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005206 // @throw
James Dennett596e4752012-06-14 03:11:41 +00005207 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"throw"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005208 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5209 Builder.AddPlaceholderChunk("expression");
5210 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf1934162010-01-13 21:24:21 +00005211
Douglas Gregorf4c33342010-05-28 00:22:41 +00005212 if (Results.includeCodePatterns()) {
5213 // @synchronized ( expression ) { statements }
James Dennett596e4752012-06-14 03:11:41 +00005214 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"synchronized"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005215 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5216 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5217 Builder.AddPlaceholderChunk("expression");
5218 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5219 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5220 Builder.AddPlaceholderChunk("statements");
5221 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5222 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00005223 }
Douglas Gregorf1934162010-01-13 21:24:21 +00005224}
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005225
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005226static void AddObjCVisibilityResults(const LangOptions &LangOpts,
Douglas Gregor48d46252010-01-13 21:54:15 +00005227 ResultBuilder &Results,
5228 bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005229 typedef CodeCompletionResult Result;
James Dennett596e4752012-06-14 03:11:41 +00005230 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"private")));
5231 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"protected")));
5232 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"public")));
Douglas Gregor48d46252010-01-13 21:54:15 +00005233 if (LangOpts.ObjC2)
James Dennett596e4752012-06-14 03:11:41 +00005234 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"package")));
Douglas Gregor48d46252010-01-13 21:54:15 +00005235}
5236
5237void Sema::CodeCompleteObjCAtVisibility(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005238 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005239 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005240 CodeCompletionContext::CCC_Other);
Douglas Gregor48d46252010-01-13 21:54:15 +00005241 Results.EnterNewScope();
David Blaikiebbafb8a2012-03-11 07:00:24 +00005242 AddObjCVisibilityResults(getLangOpts(), Results, false);
Douglas Gregor48d46252010-01-13 21:54:15 +00005243 Results.ExitScope();
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005244 HandleCodeCompleteResults(this, CodeCompleter,
5245 CodeCompletionContext::CCC_Other,
5246 Results.data(),Results.size());
Douglas Gregor48d46252010-01-13 21:54:15 +00005247}
5248
5249void Sema::CodeCompleteObjCAtStatement(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005250 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005251 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005252 CodeCompletionContext::CCC_Other);
Douglas Gregorf1934162010-01-13 21:24:21 +00005253 Results.EnterNewScope();
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005254 AddObjCStatementResults(Results, false);
5255 AddObjCExpressionResults(Results, false);
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005256 Results.ExitScope();
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005257 HandleCodeCompleteResults(this, CodeCompleter,
5258 CodeCompletionContext::CCC_Other,
5259 Results.data(),Results.size());
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005260}
5261
5262void Sema::CodeCompleteObjCAtExpression(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005263 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005264 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005265 CodeCompletionContext::CCC_Other);
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005266 Results.EnterNewScope();
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005267 AddObjCExpressionResults(Results, false);
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005268 Results.ExitScope();
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005269 HandleCodeCompleteResults(this, CodeCompleter,
5270 CodeCompletionContext::CCC_Other,
5271 Results.data(),Results.size());
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005272}
5273
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00005274/// Determine whether the addition of the given flag to an Objective-C
Douglas Gregore6078da2009-11-19 00:14:45 +00005275/// property's attributes will cause a conflict.
Bill Wendling44426052012-12-20 19:22:21 +00005276static bool ObjCPropertyFlagConflicts(unsigned Attributes, unsigned NewFlag) {
Douglas Gregore6078da2009-11-19 00:14:45 +00005277 // Check if we've already added this flag.
Bill Wendling44426052012-12-20 19:22:21 +00005278 if (Attributes & NewFlag)
Douglas Gregore6078da2009-11-19 00:14:45 +00005279 return true;
5280
Bill Wendling44426052012-12-20 19:22:21 +00005281 Attributes |= NewFlag;
Douglas Gregore6078da2009-11-19 00:14:45 +00005282
5283 // Check for collisions with "readonly".
Bill Wendling44426052012-12-20 19:22:21 +00005284 if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) &&
5285 (Attributes & ObjCDeclSpec::DQ_PR_readwrite))
Douglas Gregore6078da2009-11-19 00:14:45 +00005286 return true;
5287
Jordan Rose53cb2f32012-08-20 20:01:13 +00005288 // Check for more than one of { assign, copy, retain, strong, weak }.
Bill Wendling44426052012-12-20 19:22:21 +00005289 unsigned AssignCopyRetMask = Attributes & (ObjCDeclSpec::DQ_PR_assign |
John McCall31168b02011-06-15 23:02:42 +00005290 ObjCDeclSpec::DQ_PR_unsafe_unretained |
Douglas Gregore6078da2009-11-19 00:14:45 +00005291 ObjCDeclSpec::DQ_PR_copy |
Jordan Rose53cb2f32012-08-20 20:01:13 +00005292 ObjCDeclSpec::DQ_PR_retain |
5293 ObjCDeclSpec::DQ_PR_strong |
5294 ObjCDeclSpec::DQ_PR_weak);
Douglas Gregore6078da2009-11-19 00:14:45 +00005295 if (AssignCopyRetMask &&
5296 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_assign &&
John McCall31168b02011-06-15 23:02:42 +00005297 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_unsafe_unretained &&
Douglas Gregore6078da2009-11-19 00:14:45 +00005298 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_copy &&
John McCall31168b02011-06-15 23:02:42 +00005299 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_retain &&
Jordan Rose53cb2f32012-08-20 20:01:13 +00005300 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_strong &&
5301 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_weak)
Douglas Gregore6078da2009-11-19 00:14:45 +00005302 return true;
5303
5304 return false;
5305}
5306
Douglas Gregor36029f42009-11-18 23:08:07 +00005307void Sema::CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS) {
Steve Naroff936354c2009-10-08 21:55:05 +00005308 if (!CodeCompleter)
5309 return;
Douglas Gregor1b605f72009-11-19 01:08:35 +00005310
Bill Wendling44426052012-12-20 19:22:21 +00005311 unsigned Attributes = ODS.getPropertyAttributes();
Steve Naroff936354c2009-10-08 21:55:05 +00005312
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005313 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005314 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005315 CodeCompletionContext::CCC_Other);
Steve Naroff936354c2009-10-08 21:55:05 +00005316 Results.EnterNewScope();
Bill Wendling44426052012-12-20 19:22:21 +00005317 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readonly))
John McCall276321a2010-08-25 06:19:51 +00005318 Results.AddResult(CodeCompletionResult("readonly"));
Bill Wendling44426052012-12-20 19:22:21 +00005319 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_assign))
John McCall276321a2010-08-25 06:19:51 +00005320 Results.AddResult(CodeCompletionResult("assign"));
Bill Wendling44426052012-12-20 19:22:21 +00005321 if (!ObjCPropertyFlagConflicts(Attributes,
John McCall31168b02011-06-15 23:02:42 +00005322 ObjCDeclSpec::DQ_PR_unsafe_unretained))
5323 Results.AddResult(CodeCompletionResult("unsafe_unretained"));
Bill Wendling44426052012-12-20 19:22:21 +00005324 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readwrite))
John McCall276321a2010-08-25 06:19:51 +00005325 Results.AddResult(CodeCompletionResult("readwrite"));
Bill Wendling44426052012-12-20 19:22:21 +00005326 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_retain))
John McCall276321a2010-08-25 06:19:51 +00005327 Results.AddResult(CodeCompletionResult("retain"));
Bill Wendling44426052012-12-20 19:22:21 +00005328 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_strong))
John McCall31168b02011-06-15 23:02:42 +00005329 Results.AddResult(CodeCompletionResult("strong"));
Bill Wendling44426052012-12-20 19:22:21 +00005330 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_copy))
John McCall276321a2010-08-25 06:19:51 +00005331 Results.AddResult(CodeCompletionResult("copy"));
Bill Wendling44426052012-12-20 19:22:21 +00005332 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_nonatomic))
John McCall276321a2010-08-25 06:19:51 +00005333 Results.AddResult(CodeCompletionResult("nonatomic"));
Bill Wendling44426052012-12-20 19:22:21 +00005334 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_atomic))
Fariborz Jahanian1c2d29e2011-06-11 17:14:27 +00005335 Results.AddResult(CodeCompletionResult("atomic"));
Jordan Rose53cb2f32012-08-20 20:01:13 +00005336
5337 // Only suggest "weak" if we're compiling for ARC-with-weak-references or GC.
John McCall460ce582015-10-22 18:38:17 +00005338 if (getLangOpts().ObjCWeak || getLangOpts().getGC() != LangOptions::NonGC)
Bill Wendling44426052012-12-20 19:22:21 +00005339 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_weak))
Jordan Rose53cb2f32012-08-20 20:01:13 +00005340 Results.AddResult(CodeCompletionResult("weak"));
5341
Bill Wendling44426052012-12-20 19:22:21 +00005342 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_setter)) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005343 CodeCompletionBuilder Setter(Results.getAllocator(),
5344 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005345 Setter.AddTypedTextChunk("setter");
Argyrios Kyrtzidis7bbb8812014-02-20 07:55:15 +00005346 Setter.AddTextChunk("=");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005347 Setter.AddPlaceholderChunk("method");
5348 Results.AddResult(CodeCompletionResult(Setter.TakeString()));
Douglas Gregor45f83ee2009-11-19 00:01:57 +00005349 }
Bill Wendling44426052012-12-20 19:22:21 +00005350 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_getter)) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005351 CodeCompletionBuilder Getter(Results.getAllocator(),
5352 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005353 Getter.AddTypedTextChunk("getter");
Argyrios Kyrtzidis7bbb8812014-02-20 07:55:15 +00005354 Getter.AddTextChunk("=");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005355 Getter.AddPlaceholderChunk("method");
5356 Results.AddResult(CodeCompletionResult(Getter.TakeString()));
Douglas Gregor45f83ee2009-11-19 00:01:57 +00005357 }
Douglas Gregor86b42682015-06-19 18:27:52 +00005358 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_nullability)) {
5359 Results.AddResult(CodeCompletionResult("nonnull"));
5360 Results.AddResult(CodeCompletionResult("nullable"));
5361 Results.AddResult(CodeCompletionResult("null_unspecified"));
5362 Results.AddResult(CodeCompletionResult("null_resettable"));
5363 }
Steve Naroff936354c2009-10-08 21:55:05 +00005364 Results.ExitScope();
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005365 HandleCodeCompleteResults(this, CodeCompleter,
5366 CodeCompletionContext::CCC_Other,
5367 Results.data(),Results.size());
Steve Naroff936354c2009-10-08 21:55:05 +00005368}
Steve Naroffeae65032009-11-07 02:08:14 +00005369
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00005370/// Describes the kind of Objective-C method that we want to find
Douglas Gregorc8537c52009-11-19 07:41:15 +00005371/// via code completion.
5372enum ObjCMethodKind {
Dmitri Gribenko4280e5c2012-06-08 23:13:42 +00005373 MK_Any, ///< Any kind of method, provided it means other specified criteria.
5374 MK_ZeroArgSelector, ///< Zero-argument (unary) selector.
5375 MK_OneArgSelector ///< One-argument selector.
Douglas Gregorc8537c52009-11-19 07:41:15 +00005376};
5377
Douglas Gregor67c692c2010-08-26 15:07:07 +00005378static bool isAcceptableObjCSelector(Selector Sel,
5379 ObjCMethodKind WantKind,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005380 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005381 bool AllowSameLength = true) {
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005382 unsigned NumSelIdents = SelIdents.size();
Douglas Gregor67c692c2010-08-26 15:07:07 +00005383 if (NumSelIdents > Sel.getNumArgs())
5384 return false;
5385
5386 switch (WantKind) {
5387 case MK_Any: break;
5388 case MK_ZeroArgSelector: return Sel.isUnarySelector();
5389 case MK_OneArgSelector: return Sel.getNumArgs() == 1;
5390 }
5391
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005392 if (!AllowSameLength && NumSelIdents && NumSelIdents == Sel.getNumArgs())
5393 return false;
5394
Douglas Gregor67c692c2010-08-26 15:07:07 +00005395 for (unsigned I = 0; I != NumSelIdents; ++I)
5396 if (SelIdents[I] != Sel.getIdentifierInfoForSlot(I))
5397 return false;
5398
5399 return true;
5400}
5401
Douglas Gregorc8537c52009-11-19 07:41:15 +00005402static bool isAcceptableObjCMethod(ObjCMethodDecl *Method,
5403 ObjCMethodKind WantKind,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005404 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005405 bool AllowSameLength = true) {
Douglas Gregor67c692c2010-08-26 15:07:07 +00005406 return isAcceptableObjCSelector(Method->getSelector(), WantKind, SelIdents,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005407 AllowSameLength);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005408}
Douglas Gregor1154e272010-09-16 16:06:31 +00005409
5410namespace {
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00005411 /// A set of selectors, which is used to avoid introducing multiple
Douglas Gregor1154e272010-09-16 16:06:31 +00005412 /// completions with the same selector into the result set.
5413 typedef llvm::SmallPtrSet<Selector, 16> VisitedSelectorSet;
5414}
5415
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00005416/// Add all of the Objective-C methods in the given Objective-C
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005417/// container to the set of results.
5418///
5419/// The container will be a class, protocol, category, or implementation of
5420/// any of the above. This mether will recurse to include methods from
5421/// the superclasses of classes along with their categories, protocols, and
5422/// implementations.
5423///
5424/// \param Container the container in which we'll look to find methods.
5425///
James Dennett596e4752012-06-14 03:11:41 +00005426/// \param WantInstanceMethods Whether to add instance methods (only); if
5427/// false, this routine will add factory methods (only).
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005428///
5429/// \param CurContext the context in which we're performing the lookup that
5430/// finds methods.
5431///
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005432/// \param AllowSameLength Whether we allow a method to be added to the list
5433/// when it has the same number of parameters as we have selector identifiers.
5434///
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005435/// \param Results the structure into which we'll add results.
Alex Lorenz638dbc32017-01-24 14:15:08 +00005436static void AddObjCMethods(ObjCContainerDecl *Container,
5437 bool WantInstanceMethods, ObjCMethodKind WantKind,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005438 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005439 DeclContext *CurContext,
Alex Lorenz638dbc32017-01-24 14:15:08 +00005440 VisitedSelectorSet &Selectors, bool AllowSameLength,
5441 ResultBuilder &Results, bool InOriginalClass = true,
5442 bool IsRootClass = false) {
John McCall276321a2010-08-25 06:19:51 +00005443 typedef CodeCompletionResult Result;
Douglas Gregor9b4f3702012-06-12 13:44:08 +00005444 Container = getContainerDef(Container);
Douglas Gregor41778c32013-01-30 06:58:39 +00005445 ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container);
Alex Lorenz638dbc32017-01-24 14:15:08 +00005446 IsRootClass = IsRootClass || (IFace && !IFace->getSuperClass());
Aaron Ballmanaff18c02014-03-13 19:03:34 +00005447 for (auto *M : Container->methods()) {
Douglas Gregor41778c32013-01-30 06:58:39 +00005448 // The instance methods on the root class can be messaged via the
5449 // metaclass.
5450 if (M->isInstanceMethod() == WantInstanceMethods ||
Alex Lorenz638dbc32017-01-24 14:15:08 +00005451 (IsRootClass && !WantInstanceMethods)) {
Douglas Gregor1b605f72009-11-19 01:08:35 +00005452 // Check whether the selector identifiers we've been given are a
5453 // subset of the identifiers for this particular method.
Aaron Ballmanaff18c02014-03-13 19:03:34 +00005454 if (!isAcceptableObjCMethod(M, WantKind, SelIdents, AllowSameLength))
Douglas Gregor1b605f72009-11-19 01:08:35 +00005455 continue;
Douglas Gregorc8537c52009-11-19 07:41:15 +00005456
David Blaikie82e95a32014-11-19 07:49:47 +00005457 if (!Selectors.insert(M->getSelector()).second)
Douglas Gregor1154e272010-09-16 16:06:31 +00005458 continue;
Craig Topperc3ec1492014-05-26 06:22:03 +00005459
5460 Result R = Result(M, Results.getBasePriority(M), nullptr);
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005461 R.StartParameter = SelIdents.size();
Douglas Gregorc8537c52009-11-19 07:41:15 +00005462 R.AllParametersAreInformative = (WantKind != MK_Any);
Douglas Gregor416b5752010-08-25 01:08:01 +00005463 if (!InOriginalClass)
5464 R.Priority += CCD_InBaseClass;
Douglas Gregor1b605f72009-11-19 01:08:35 +00005465 Results.MaybeAddResult(R, CurContext);
5466 }
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005467 }
5468
Douglas Gregorf37c9492010-09-16 15:34:59 +00005469 // Visit the protocols of protocols.
5470 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Douglas Gregore6e48b12012-01-01 19:29:29 +00005471 if (Protocol->hasDefinition()) {
5472 const ObjCList<ObjCProtocolDecl> &Protocols
5473 = Protocol->getReferencedProtocols();
5474 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
5475 E = Protocols.end();
5476 I != E; ++I)
Alex Lorenz638dbc32017-01-24 14:15:08 +00005477 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, CurContext,
5478 Selectors, AllowSameLength, Results, false, IsRootClass);
Douglas Gregore6e48b12012-01-01 19:29:29 +00005479 }
Douglas Gregorf37c9492010-09-16 15:34:59 +00005480 }
5481
Douglas Gregorc0ac7d62011-12-15 05:27:12 +00005482 if (!IFace || !IFace->hasDefinition())
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005483 return;
5484
5485 // Add methods in protocols.
Aaron Ballmana49c5062014-03-13 20:29:09 +00005486 for (auto *I : IFace->protocols())
Alex Lorenz638dbc32017-01-24 14:15:08 +00005487 AddObjCMethods(I, WantInstanceMethods, WantKind, SelIdents, CurContext,
5488 Selectors, AllowSameLength, Results, false, IsRootClass);
5489
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005490 // Add methods in categories.
Aaron Ballman15063e12014-03-13 21:35:02 +00005491 for (auto *CatDecl : IFace->known_categories()) {
Douglas Gregor048fbfa2013-01-16 23:00:23 +00005492 AddObjCMethods(CatDecl, WantInstanceMethods, WantKind, SelIdents,
Alex Lorenz638dbc32017-01-24 14:15:08 +00005493 CurContext, Selectors, AllowSameLength, Results,
5494 InOriginalClass, IsRootClass);
5495
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005496 // Add a categories protocol methods.
5497 const ObjCList<ObjCProtocolDecl> &Protocols
5498 = CatDecl->getReferencedProtocols();
5499 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
5500 E = Protocols.end();
5501 I != E; ++I)
Alex Lorenz638dbc32017-01-24 14:15:08 +00005502 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, CurContext,
5503 Selectors, AllowSameLength, Results, false, IsRootClass);
5504
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005505 // Add methods in category implementations.
5506 if (ObjCCategoryImplDecl *Impl = CatDecl->getImplementation())
Alex Lorenz638dbc32017-01-24 14:15:08 +00005507 AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents, CurContext,
5508 Selectors, AllowSameLength, Results, InOriginalClass,
5509 IsRootClass);
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005510 }
5511
5512 // Add methods in superclass.
Alex Lorenz638dbc32017-01-24 14:15:08 +00005513 // Avoid passing in IsRootClass since root classes won't have super classes.
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005514 if (IFace->getSuperClass())
Alex Lorenz638dbc32017-01-24 14:15:08 +00005515 AddObjCMethods(IFace->getSuperClass(), WantInstanceMethods, WantKind,
5516 SelIdents, CurContext, Selectors, AllowSameLength, Results,
5517 /*IsRootClass=*/false);
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005518
5519 // Add methods in our implementation, if any.
5520 if (ObjCImplementationDecl *Impl = IFace->getImplementation())
Alex Lorenz638dbc32017-01-24 14:15:08 +00005521 AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents, CurContext,
5522 Selectors, AllowSameLength, Results, InOriginalClass,
5523 IsRootClass);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005524}
5525
5526
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005527void Sema::CodeCompleteObjCPropertyGetter(Scope *S) {
Douglas Gregorc8537c52009-11-19 07:41:15 +00005528 // Try to find the interface where getters might live.
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005529 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005530 if (!Class) {
5531 if (ObjCCategoryDecl *Category
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005532 = dyn_cast_or_null<ObjCCategoryDecl>(CurContext))
Douglas Gregorc8537c52009-11-19 07:41:15 +00005533 Class = Category->getClassInterface();
5534
5535 if (!Class)
5536 return;
5537 }
5538
5539 // Find all of the potential getters.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005540 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005541 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005542 CodeCompletionContext::CCC_Other);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005543 Results.EnterNewScope();
5544
Douglas Gregor1154e272010-09-16 16:06:31 +00005545 VisitedSelectorSet Selectors;
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005546 AddObjCMethods(Class, true, MK_ZeroArgSelector, None, CurContext, Selectors,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005547 /*AllowSameLength=*/true, Results);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005548 Results.ExitScope();
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005549 HandleCodeCompleteResults(this, CodeCompleter,
5550 CodeCompletionContext::CCC_Other,
5551 Results.data(),Results.size());
Douglas Gregorc8537c52009-11-19 07:41:15 +00005552}
5553
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005554void Sema::CodeCompleteObjCPropertySetter(Scope *S) {
Douglas Gregorc8537c52009-11-19 07:41:15 +00005555 // Try to find the interface where setters might live.
5556 ObjCInterfaceDecl *Class
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005557 = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005558 if (!Class) {
5559 if (ObjCCategoryDecl *Category
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005560 = dyn_cast_or_null<ObjCCategoryDecl>(CurContext))
Douglas Gregorc8537c52009-11-19 07:41:15 +00005561 Class = Category->getClassInterface();
5562
5563 if (!Class)
5564 return;
5565 }
5566
5567 // Find all of the potential getters.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005568 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005569 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005570 CodeCompletionContext::CCC_Other);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005571 Results.EnterNewScope();
5572
Douglas Gregor1154e272010-09-16 16:06:31 +00005573 VisitedSelectorSet Selectors;
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005574 AddObjCMethods(Class, true, MK_OneArgSelector, None, CurContext,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005575 Selectors, /*AllowSameLength=*/true, Results);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005576
5577 Results.ExitScope();
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005578 HandleCodeCompleteResults(this, CodeCompleter,
5579 CodeCompletionContext::CCC_Other,
5580 Results.data(),Results.size());
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005581}
5582
Douglas Gregorf34a6f02011-02-15 22:19:42 +00005583void Sema::CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS,
5584 bool IsParameter) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005585 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005586 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005587 CodeCompletionContext::CCC_Type);
Douglas Gregor99fa2642010-08-24 01:06:58 +00005588 Results.EnterNewScope();
5589
5590 // Add context-sensitive, Objective-C parameter-passing keywords.
5591 bool AddedInOut = false;
5592 if ((DS.getObjCDeclQualifier() &
5593 (ObjCDeclSpec::DQ_In | ObjCDeclSpec::DQ_Inout)) == 0) {
5594 Results.AddResult("in");
5595 Results.AddResult("inout");
5596 AddedInOut = true;
5597 }
5598 if ((DS.getObjCDeclQualifier() &
5599 (ObjCDeclSpec::DQ_Out | ObjCDeclSpec::DQ_Inout)) == 0) {
5600 Results.AddResult("out");
5601 if (!AddedInOut)
5602 Results.AddResult("inout");
5603 }
5604 if ((DS.getObjCDeclQualifier() &
5605 (ObjCDeclSpec::DQ_Bycopy | ObjCDeclSpec::DQ_Byref |
5606 ObjCDeclSpec::DQ_Oneway)) == 0) {
5607 Results.AddResult("bycopy");
5608 Results.AddResult("byref");
5609 Results.AddResult("oneway");
5610 }
Douglas Gregor86b42682015-06-19 18:27:52 +00005611 if ((DS.getObjCDeclQualifier() & ObjCDeclSpec::DQ_CSNullability) == 0) {
5612 Results.AddResult("nonnull");
5613 Results.AddResult("nullable");
5614 Results.AddResult("null_unspecified");
5615 }
Douglas Gregor99fa2642010-08-24 01:06:58 +00005616
Douglas Gregorf34a6f02011-02-15 22:19:42 +00005617 // If we're completing the return type of an Objective-C method and the
5618 // identifier IBAction refers to a macro, provide a completion item for
5619 // an action, e.g.,
5620 // IBAction)<#selector#>:(id)sender
5621 if (DS.getObjCDeclQualifier() == 0 && !IsParameter &&
Richard Smith20e883e2015-04-29 23:20:19 +00005622 PP.isMacroDefined("IBAction")) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005623 CodeCompletionBuilder Builder(Results.getAllocator(),
5624 Results.getCodeCompletionTUInfo(),
5625 CCP_CodePattern, CXAvailability_Available);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00005626 Builder.AddTypedTextChunk("IBAction");
Benjamin Kramerdb534a42012-03-26 16:57:36 +00005627 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00005628 Builder.AddPlaceholderChunk("selector");
Benjamin Kramerdb534a42012-03-26 16:57:36 +00005629 Builder.AddChunk(CodeCompletionString::CK_Colon);
5630 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00005631 Builder.AddTextChunk("id");
Benjamin Kramerdb534a42012-03-26 16:57:36 +00005632 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00005633 Builder.AddTextChunk("sender");
5634 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
5635 }
Douglas Gregored1f5972013-01-30 07:11:43 +00005636
5637 // If we're completing the return type, provide 'instancetype'.
5638 if (!IsParameter) {
5639 Results.AddResult(CodeCompletionResult("instancetype"));
5640 }
Douglas Gregorf34a6f02011-02-15 22:19:42 +00005641
Douglas Gregor99fa2642010-08-24 01:06:58 +00005642 // Add various builtin type names and specifiers.
5643 AddOrdinaryNameResults(PCC_Type, S, *this, Results);
5644 Results.ExitScope();
5645
5646 // Add the various type names
5647 Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
5648 CodeCompletionDeclConsumer Consumer(Results, CurContext);
5649 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00005650 CodeCompleter->includeGlobals(),
5651 CodeCompleter->loadExternal());
5652
Douglas Gregor99fa2642010-08-24 01:06:58 +00005653 if (CodeCompleter->includeMacros())
Douglas Gregor8cb17462012-10-09 16:01:50 +00005654 AddMacroResults(PP, Results, false);
Douglas Gregor99fa2642010-08-24 01:06:58 +00005655
5656 HandleCodeCompleteResults(this, CodeCompleter,
5657 CodeCompletionContext::CCC_Type,
5658 Results.data(), Results.size());
5659}
5660
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00005661/// When we have an expression with type "id", we may assume
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005662/// that it has some more-specific class type based on knowledge of
5663/// common uses of Objective-C. This routine returns that class type,
5664/// or NULL if no better result could be determined.
5665static ObjCInterfaceDecl *GetAssumedMessageSendExprType(Expr *E) {
Douglas Gregored0b69d2010-09-15 16:23:04 +00005666 ObjCMessageExpr *Msg = dyn_cast_or_null<ObjCMessageExpr>(E);
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005667 if (!Msg)
Craig Topperc3ec1492014-05-26 06:22:03 +00005668 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005669
5670 Selector Sel = Msg->getSelector();
5671 if (Sel.isNull())
Craig Topperc3ec1492014-05-26 06:22:03 +00005672 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005673
5674 IdentifierInfo *Id = Sel.getIdentifierInfoForSlot(0);
5675 if (!Id)
Craig Topperc3ec1492014-05-26 06:22:03 +00005676 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005677
5678 ObjCMethodDecl *Method = Msg->getMethodDecl();
5679 if (!Method)
Craig Topperc3ec1492014-05-26 06:22:03 +00005680 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005681
5682 // Determine the class that we're sending the message to.
Craig Topperc3ec1492014-05-26 06:22:03 +00005683 ObjCInterfaceDecl *IFace = nullptr;
Douglas Gregor9a129192010-04-21 00:45:42 +00005684 switch (Msg->getReceiverKind()) {
5685 case ObjCMessageExpr::Class:
John McCall8b07ec22010-05-15 11:32:37 +00005686 if (const ObjCObjectType *ObjType
5687 = Msg->getClassReceiver()->getAs<ObjCObjectType>())
5688 IFace = ObjType->getInterface();
Douglas Gregor9a129192010-04-21 00:45:42 +00005689 break;
5690
5691 case ObjCMessageExpr::Instance: {
5692 QualType T = Msg->getInstanceReceiver()->getType();
5693 if (const ObjCObjectPointerType *Ptr = T->getAs<ObjCObjectPointerType>())
5694 IFace = Ptr->getInterfaceDecl();
5695 break;
5696 }
5697
5698 case ObjCMessageExpr::SuperInstance:
5699 case ObjCMessageExpr::SuperClass:
5700 break;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005701 }
5702
5703 if (!IFace)
Craig Topperc3ec1492014-05-26 06:22:03 +00005704 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005705
5706 ObjCInterfaceDecl *Super = IFace->getSuperClass();
5707 if (Method->isInstanceMethod())
5708 return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
5709 .Case("retain", IFace)
John McCall31168b02011-06-15 23:02:42 +00005710 .Case("strong", IFace)
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005711 .Case("autorelease", IFace)
5712 .Case("copy", IFace)
5713 .Case("copyWithZone", IFace)
5714 .Case("mutableCopy", IFace)
5715 .Case("mutableCopyWithZone", IFace)
5716 .Case("awakeFromCoder", IFace)
5717 .Case("replacementObjectFromCoder", IFace)
5718 .Case("class", IFace)
5719 .Case("classForCoder", IFace)
5720 .Case("superclass", Super)
Craig Topperc3ec1492014-05-26 06:22:03 +00005721 .Default(nullptr);
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005722
5723 return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
5724 .Case("new", IFace)
5725 .Case("alloc", IFace)
5726 .Case("allocWithZone", IFace)
5727 .Case("class", IFace)
5728 .Case("superclass", Super)
Craig Topperc3ec1492014-05-26 06:22:03 +00005729 .Default(nullptr);
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005730}
5731
Douglas Gregor6fc04132010-08-27 15:10:57 +00005732// Add a special completion for a message send to "super", which fills in the
5733// most likely case of forwarding all of our arguments to the superclass
5734// function.
5735///
5736/// \param S The semantic analysis object.
5737///
Dmitri Gribenkoadba9be2012-08-23 17:58:28 +00005738/// \param NeedSuperKeyword Whether we need to prefix this completion with
Douglas Gregor6fc04132010-08-27 15:10:57 +00005739/// the "super" keyword. Otherwise, we just need to provide the arguments.
5740///
5741/// \param SelIdents The identifiers in the selector that have already been
5742/// provided as arguments for a send to "super".
5743///
Douglas Gregor6fc04132010-08-27 15:10:57 +00005744/// \param Results The set of results to augment.
5745///
5746/// \returns the Objective-C method declaration that would be invoked by
5747/// this "super" completion. If NULL, no completion was added.
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005748static ObjCMethodDecl *AddSuperSendCompletion(
5749 Sema &S, bool NeedSuperKeyword,
5750 ArrayRef<IdentifierInfo *> SelIdents,
5751 ResultBuilder &Results) {
Douglas Gregor6fc04132010-08-27 15:10:57 +00005752 ObjCMethodDecl *CurMethod = S.getCurMethodDecl();
5753 if (!CurMethod)
Craig Topperc3ec1492014-05-26 06:22:03 +00005754 return nullptr;
5755
Douglas Gregor6fc04132010-08-27 15:10:57 +00005756 ObjCInterfaceDecl *Class = CurMethod->getClassInterface();
5757 if (!Class)
Craig Topperc3ec1492014-05-26 06:22:03 +00005758 return nullptr;
5759
Douglas Gregor6fc04132010-08-27 15:10:57 +00005760 // Try to find a superclass method with the same selector.
Craig Topperc3ec1492014-05-26 06:22:03 +00005761 ObjCMethodDecl *SuperMethod = nullptr;
Douglas Gregorb5f1e462011-02-16 00:51:18 +00005762 while ((Class = Class->getSuperClass()) && !SuperMethod) {
5763 // Check in the class
Douglas Gregor6fc04132010-08-27 15:10:57 +00005764 SuperMethod = Class->getMethod(CurMethod->getSelector(),
5765 CurMethod->isInstanceMethod());
5766
Douglas Gregorb5f1e462011-02-16 00:51:18 +00005767 // Check in categories or class extensions.
5768 if (!SuperMethod) {
Aaron Ballman15063e12014-03-13 21:35:02 +00005769 for (const auto *Cat : Class->known_categories()) {
Douglas Gregor048fbfa2013-01-16 23:00:23 +00005770 if ((SuperMethod = Cat->getMethod(CurMethod->getSelector(),
Douglas Gregorb5f1e462011-02-16 00:51:18 +00005771 CurMethod->isInstanceMethod())))
5772 break;
Douglas Gregor048fbfa2013-01-16 23:00:23 +00005773 }
Douglas Gregorb5f1e462011-02-16 00:51:18 +00005774 }
5775 }
5776
Douglas Gregor6fc04132010-08-27 15:10:57 +00005777 if (!SuperMethod)
Craig Topperc3ec1492014-05-26 06:22:03 +00005778 return nullptr;
5779
Douglas Gregor6fc04132010-08-27 15:10:57 +00005780 // Check whether the superclass method has the same signature.
5781 if (CurMethod->param_size() != SuperMethod->param_size() ||
5782 CurMethod->isVariadic() != SuperMethod->isVariadic())
Craig Topperc3ec1492014-05-26 06:22:03 +00005783 return nullptr;
5784
Douglas Gregor6fc04132010-08-27 15:10:57 +00005785 for (ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin(),
5786 CurPEnd = CurMethod->param_end(),
5787 SuperP = SuperMethod->param_begin();
5788 CurP != CurPEnd; ++CurP, ++SuperP) {
5789 // Make sure the parameter types are compatible.
5790 if (!S.Context.hasSameUnqualifiedType((*CurP)->getType(),
5791 (*SuperP)->getType()))
Craig Topperc3ec1492014-05-26 06:22:03 +00005792 return nullptr;
5793
Douglas Gregor6fc04132010-08-27 15:10:57 +00005794 // Make sure we have a parameter name to forward!
5795 if (!(*CurP)->getIdentifier())
Craig Topperc3ec1492014-05-26 06:22:03 +00005796 return nullptr;
Douglas Gregor6fc04132010-08-27 15:10:57 +00005797 }
5798
5799 // We have a superclass method. Now, form the send-to-super completion.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005800 CodeCompletionBuilder Builder(Results.getAllocator(),
5801 Results.getCodeCompletionTUInfo());
Douglas Gregor6fc04132010-08-27 15:10:57 +00005802
5803 // Give this completion a return type.
Douglas Gregorc3425b12015-07-07 06:20:19 +00005804 AddResultTypeChunk(S.Context, getCompletionPrintingPolicy(S), SuperMethod,
5805 Results.getCompletionContext().getBaseType(),
Douglas Gregor75acd922011-09-27 23:30:47 +00005806 Builder);
Douglas Gregor6fc04132010-08-27 15:10:57 +00005807
5808 // If we need the "super" keyword, add it (plus some spacing).
5809 if (NeedSuperKeyword) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005810 Builder.AddTypedTextChunk("super");
5811 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregor6fc04132010-08-27 15:10:57 +00005812 }
5813
5814 Selector Sel = CurMethod->getSelector();
5815 if (Sel.isUnarySelector()) {
5816 if (NeedSuperKeyword)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005817 Builder.AddTextChunk(Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00005818 Sel.getNameForSlot(0)));
Douglas Gregor6fc04132010-08-27 15:10:57 +00005819 else
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005820 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00005821 Sel.getNameForSlot(0)));
Douglas Gregor6fc04132010-08-27 15:10:57 +00005822 } else {
5823 ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin();
5824 for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I, ++CurP) {
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005825 if (I > SelIdents.size())
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005826 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregor6fc04132010-08-27 15:10:57 +00005827
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005828 if (I < SelIdents.size())
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005829 Builder.AddInformativeChunk(
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005830 Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00005831 Sel.getNameForSlot(I) + ":"));
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005832 else if (NeedSuperKeyword || I > SelIdents.size()) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005833 Builder.AddTextChunk(
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005834 Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00005835 Sel.getNameForSlot(I) + ":"));
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005836 Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005837 (*CurP)->getIdentifier()->getName()));
Douglas Gregor6fc04132010-08-27 15:10:57 +00005838 } else {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005839 Builder.AddTypedTextChunk(
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005840 Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00005841 Sel.getNameForSlot(I) + ":"));
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005842 Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005843 (*CurP)->getIdentifier()->getName()));
Douglas Gregor6fc04132010-08-27 15:10:57 +00005844 }
5845 }
5846 }
5847
Douglas Gregor78254c82012-03-27 23:34:16 +00005848 Results.AddResult(CodeCompletionResult(Builder.TakeString(), SuperMethod,
5849 CCP_SuperCompletion));
Douglas Gregor6fc04132010-08-27 15:10:57 +00005850 return SuperMethod;
5851}
5852
Douglas Gregora817a192010-05-27 23:06:34 +00005853void Sema::CodeCompleteObjCMessageReceiver(Scope *S) {
John McCall276321a2010-08-25 06:19:51 +00005854 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005855 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005856 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005857 CodeCompletionContext::CCC_ObjCMessageReceiver,
Richard Smith2bf7fdb2013-01-02 11:42:31 +00005858 getLangOpts().CPlusPlus11
Douglas Gregord8c61782012-02-15 15:34:24 +00005859 ? &ResultBuilder::IsObjCMessageReceiverOrLambdaCapture
5860 : &ResultBuilder::IsObjCMessageReceiver);
Douglas Gregora817a192010-05-27 23:06:34 +00005861
Douglas Gregora817a192010-05-27 23:06:34 +00005862 CodeCompletionDeclConsumer Consumer(Results, CurContext);
5863 Results.EnterNewScope();
Douglas Gregor39982192010-08-15 06:18:01 +00005864 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00005865 CodeCompleter->includeGlobals(),
5866 CodeCompleter->loadExternal());
5867
Douglas Gregora817a192010-05-27 23:06:34 +00005868 // If we are in an Objective-C method inside a class that has a superclass,
5869 // add "super" as an option.
5870 if (ObjCMethodDecl *Method = getCurMethodDecl())
5871 if (ObjCInterfaceDecl *Iface = Method->getClassInterface())
Douglas Gregor6fc04132010-08-27 15:10:57 +00005872 if (Iface->getSuperClass()) {
Douglas Gregora817a192010-05-27 23:06:34 +00005873 Results.AddResult(Result("super"));
Douglas Gregor6fc04132010-08-27 15:10:57 +00005874
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005875 AddSuperSendCompletion(*this, /*NeedSuperKeyword=*/true, None, Results);
Douglas Gregor6fc04132010-08-27 15:10:57 +00005876 }
Douglas Gregora817a192010-05-27 23:06:34 +00005877
Richard Smith2bf7fdb2013-01-02 11:42:31 +00005878 if (getLangOpts().CPlusPlus11)
Douglas Gregord8c61782012-02-15 15:34:24 +00005879 addThisCompletion(*this, Results);
5880
Douglas Gregora817a192010-05-27 23:06:34 +00005881 Results.ExitScope();
5882
5883 if (CodeCompleter->includeMacros())
Douglas Gregor8cb17462012-10-09 16:01:50 +00005884 AddMacroResults(PP, Results, false);
Douglas Gregor50832e02010-09-20 22:39:41 +00005885 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005886 Results.data(), Results.size());
Douglas Gregora817a192010-05-27 23:06:34 +00005887
5888}
5889
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005890void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005891 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00005892 bool AtArgumentExpression) {
Craig Topperc3ec1492014-05-26 06:22:03 +00005893 ObjCInterfaceDecl *CDecl = nullptr;
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005894 if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
5895 // Figure out which interface we're in.
5896 CDecl = CurMethod->getClassInterface();
5897 if (!CDecl)
5898 return;
5899
5900 // Find the superclass of this class.
5901 CDecl = CDecl->getSuperClass();
5902 if (!CDecl)
5903 return;
5904
5905 if (CurMethod->isInstanceMethod()) {
5906 // We are inside an instance method, which means that the message
5907 // send [super ...] is actually calling an instance method on the
Douglas Gregor392a84b2010-10-13 21:24:53 +00005908 // current object.
Craig Topperc3ec1492014-05-26 06:22:03 +00005909 return CodeCompleteObjCInstanceMessage(S, nullptr, SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00005910 AtArgumentExpression,
Douglas Gregor392a84b2010-10-13 21:24:53 +00005911 CDecl);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005912 }
5913
5914 // Fall through to send to the superclass in CDecl.
5915 } else {
5916 // "super" may be the name of a type or variable. Figure out which
5917 // it is.
Argyrios Kyrtzidis3e56dd42013-03-14 22:56:43 +00005918 IdentifierInfo *Super = getSuperIdentifier();
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005919 NamedDecl *ND = LookupSingleName(S, Super, SuperLoc,
5920 LookupOrdinaryName);
5921 if ((CDecl = dyn_cast_or_null<ObjCInterfaceDecl>(ND))) {
5922 // "super" names an interface. Use it.
5923 } else if (TypeDecl *TD = dyn_cast_or_null<TypeDecl>(ND)) {
John McCall8b07ec22010-05-15 11:32:37 +00005924 if (const ObjCObjectType *Iface
5925 = Context.getTypeDeclType(TD)->getAs<ObjCObjectType>())
5926 CDecl = Iface->getInterface();
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005927 } else if (ND && isa<UnresolvedUsingTypenameDecl>(ND)) {
5928 // "super" names an unresolved type; we can't be more specific.
5929 } else {
5930 // Assume that "super" names some kind of value and parse that way.
5931 CXXScopeSpec SS;
Abramo Bagnara7945c982012-01-27 09:46:47 +00005932 SourceLocation TemplateKWLoc;
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005933 UnqualifiedId id;
5934 id.setIdentifier(Super, SuperLoc);
Abramo Bagnara7945c982012-01-27 09:46:47 +00005935 ExprResult SuperExpr = ActOnIdExpression(S, SS, TemplateKWLoc, id,
5936 false, false);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005937 return CodeCompleteObjCInstanceMessage(S, (Expr *)SuperExpr.get(),
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005938 SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00005939 AtArgumentExpression);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005940 }
5941
5942 // Fall through
5943 }
5944
John McCallba7bf592010-08-24 05:47:05 +00005945 ParsedType Receiver;
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005946 if (CDecl)
John McCallba7bf592010-08-24 05:47:05 +00005947 Receiver = ParsedType::make(Context.getObjCInterfaceType(CDecl));
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005948 return CodeCompleteObjCClassMessage(S, Receiver, SelIdents,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005949 AtArgumentExpression,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00005950 /*IsSuper=*/true);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005951}
5952
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00005953/// Given a set of code-completion results for the argument of a message
Douglas Gregor74661272010-09-21 00:03:25 +00005954/// send, determine the preferred type (if any) for that argument expression.
5955static QualType getPreferredArgumentTypeForMessageSend(ResultBuilder &Results,
5956 unsigned NumSelIdents) {
5957 typedef CodeCompletionResult Result;
5958 ASTContext &Context = Results.getSema().Context;
5959
5960 QualType PreferredType;
5961 unsigned BestPriority = CCP_Unlikely * 2;
5962 Result *ResultsData = Results.data();
5963 for (unsigned I = 0, N = Results.size(); I != N; ++I) {
5964 Result &R = ResultsData[I];
5965 if (R.Kind == Result::RK_Declaration &&
5966 isa<ObjCMethodDecl>(R.Declaration)) {
5967 if (R.Priority <= BestPriority) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00005968 const ObjCMethodDecl *Method = cast<ObjCMethodDecl>(R.Declaration);
Douglas Gregor74661272010-09-21 00:03:25 +00005969 if (NumSelIdents <= Method->param_size()) {
Alp Toker03376dc2014-07-07 09:02:20 +00005970 QualType MyPreferredType = Method->parameters()[NumSelIdents - 1]
Douglas Gregor74661272010-09-21 00:03:25 +00005971 ->getType();
5972 if (R.Priority < BestPriority || PreferredType.isNull()) {
5973 BestPriority = R.Priority;
5974 PreferredType = MyPreferredType;
5975 } else if (!Context.hasSameUnqualifiedType(PreferredType,
5976 MyPreferredType)) {
5977 PreferredType = QualType();
5978 }
5979 }
5980 }
5981 }
5982 }
5983
5984 return PreferredType;
5985}
5986
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005987static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
5988 ParsedType Receiver,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005989 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00005990 bool AtArgumentExpression,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005991 bool IsSuper,
5992 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00005993 typedef CodeCompletionResult Result;
Craig Topperc3ec1492014-05-26 06:22:03 +00005994 ObjCInterfaceDecl *CDecl = nullptr;
5995
Douglas Gregor8ce33212009-11-17 17:59:40 +00005996 // If the given name refers to an interface type, retrieve the
5997 // corresponding declaration.
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005998 if (Receiver) {
Craig Topperc3ec1492014-05-26 06:22:03 +00005999 QualType T = SemaRef.GetTypeFromParser(Receiver, nullptr);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006000 if (!T.isNull())
John McCall8b07ec22010-05-15 11:32:37 +00006001 if (const ObjCObjectType *Interface = T->getAs<ObjCObjectType>())
6002 CDecl = Interface->getInterface();
Douglas Gregor8ce33212009-11-17 17:59:40 +00006003 }
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006004
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006005 // Add all of the factory methods in this Objective-C class, its protocols,
6006 // superclasses, categories, implementation, etc.
Steve Naroffeae65032009-11-07 02:08:14 +00006007 Results.EnterNewScope();
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006008
Douglas Gregor6fc04132010-08-27 15:10:57 +00006009 // If this is a send-to-super, try to add the special "super" send
6010 // completion.
6011 if (IsSuper) {
6012 if (ObjCMethodDecl *SuperMethod
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006013 = AddSuperSendCompletion(SemaRef, false, SelIdents, Results))
Douglas Gregor6fc04132010-08-27 15:10:57 +00006014 Results.Ignore(SuperMethod);
6015 }
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006016
Douglas Gregorc2cb2e22010-08-27 15:29:55 +00006017 // If we're inside an Objective-C method definition, prefer its selector to
6018 // others.
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006019 if (ObjCMethodDecl *CurMethod = SemaRef.getCurMethodDecl())
Douglas Gregorc2cb2e22010-08-27 15:29:55 +00006020 Results.setPreferredSelector(CurMethod->getSelector());
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006021
Douglas Gregor1154e272010-09-16 16:06:31 +00006022 VisitedSelectorSet Selectors;
Douglas Gregor6285f752010-04-06 16:40:00 +00006023 if (CDecl)
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006024 AddObjCMethods(CDecl, false, MK_Any, SelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00006025 SemaRef.CurContext, Selectors, AtArgumentExpression,
6026 Results);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006027 else {
Douglas Gregor6285f752010-04-06 16:40:00 +00006028 // We're messaging "id" as a type; provide all class/factory methods.
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006029
Douglas Gregord720daf2010-04-06 17:30:22 +00006030 // If we have an external source, load the entire class method
Sebastian Redld44cd6a2010-08-18 23:57:06 +00006031 // pool from the AST file.
Axel Naumanndd433f02012-10-18 19:05:02 +00006032 if (SemaRef.getExternalSource()) {
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006033 for (uint32_t I = 0,
Axel Naumanndd433f02012-10-18 19:05:02 +00006034 N = SemaRef.getExternalSource()->GetNumExternalSelectors();
John McCall75b960e2010-06-01 09:23:16 +00006035 I != N; ++I) {
Axel Naumanndd433f02012-10-18 19:05:02 +00006036 Selector Sel = SemaRef.getExternalSource()->GetExternalSelector(I);
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006037 if (Sel.isNull() || SemaRef.MethodPool.count(Sel))
Douglas Gregord720daf2010-04-06 17:30:22 +00006038 continue;
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006039
6040 SemaRef.ReadMethodPool(Sel);
Douglas Gregord720daf2010-04-06 17:30:22 +00006041 }
6042 }
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006043
6044 for (Sema::GlobalMethodPool::iterator M = SemaRef.MethodPool.begin(),
6045 MEnd = SemaRef.MethodPool.end();
Sebastian Redl75d8a322010-08-02 23:18:59 +00006046 M != MEnd; ++M) {
6047 for (ObjCMethodList *MethList = &M->second.second;
Nico Weber2e0c8f72014-12-27 03:58:08 +00006048 MethList && MethList->getMethod();
Argyrios Kyrtzidisd3da6e02013-04-17 00:08:58 +00006049 MethList = MethList->getNext()) {
Nico Weber2e0c8f72014-12-27 03:58:08 +00006050 if (!isAcceptableObjCMethod(MethList->getMethod(), MK_Any, SelIdents))
Douglas Gregor6285f752010-04-06 16:40:00 +00006051 continue;
Craig Topperc3ec1492014-05-26 06:22:03 +00006052
Nico Weber2e0c8f72014-12-27 03:58:08 +00006053 Result R(MethList->getMethod(),
6054 Results.getBasePriority(MethList->getMethod()), nullptr);
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006055 R.StartParameter = SelIdents.size();
Douglas Gregor6285f752010-04-06 16:40:00 +00006056 R.AllParametersAreInformative = false;
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006057 Results.MaybeAddResult(R, SemaRef.CurContext);
Douglas Gregor6285f752010-04-06 16:40:00 +00006058 }
6059 }
6060 }
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006061
6062 Results.ExitScope();
6063}
Douglas Gregor6285f752010-04-06 16:40:00 +00006064
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006065void Sema::CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006066 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006067 bool AtArgumentExpression,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006068 bool IsSuper) {
Douglas Gregor63745d52011-07-21 01:05:26 +00006069
6070 QualType T = this->GetTypeFromParser(Receiver);
6071
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006072 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006073 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor63745d52011-07-21 01:05:26 +00006074 CodeCompletionContext(CodeCompletionContext::CCC_ObjCClassMessage,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006075 T, SelIdents));
Douglas Gregor63745d52011-07-21 01:05:26 +00006076
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006077 AddClassMessageCompletions(*this, S, Receiver, SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006078 AtArgumentExpression, IsSuper, Results);
Douglas Gregor74661272010-09-21 00:03:25 +00006079
6080 // If we're actually at the argument expression (rather than prior to the
6081 // selector), we're actually performing code completion for an expression.
6082 // Determine whether we have a single, best method. If so, we can
6083 // code-complete the expression using the corresponding parameter type as
6084 // our preferred type, improving completion results.
6085 if (AtArgumentExpression) {
6086 QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006087 SelIdents.size());
Douglas Gregor74661272010-09-21 00:03:25 +00006088 if (PreferredType.isNull())
6089 CodeCompleteOrdinaryName(S, PCC_Expression);
6090 else
6091 CodeCompleteExpression(S, PreferredType);
6092 return;
6093 }
6094
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006095 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor63745d52011-07-21 01:05:26 +00006096 Results.getCompletionContext(),
Douglas Gregor6fc04132010-08-27 15:10:57 +00006097 Results.data(), Results.size());
Steve Naroffeae65032009-11-07 02:08:14 +00006098}
6099
Richard Trieu2bd04012011-09-09 02:00:50 +00006100void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006101 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006102 bool AtArgumentExpression,
Douglas Gregor392a84b2010-10-13 21:24:53 +00006103 ObjCInterfaceDecl *Super) {
John McCall276321a2010-08-25 06:19:51 +00006104 typedef CodeCompletionResult Result;
Steve Naroffeae65032009-11-07 02:08:14 +00006105
6106 Expr *RecExpr = static_cast<Expr *>(Receiver);
Steve Naroffeae65032009-11-07 02:08:14 +00006107
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006108 // If necessary, apply function/array conversion to the receiver.
6109 // C99 6.7.5.3p[7,8].
John Wiegley01296292011-04-08 18:41:53 +00006110 if (RecExpr) {
6111 ExprResult Conv = DefaultFunctionArrayLvalueConversion(RecExpr);
6112 if (Conv.isInvalid()) // conversion failed. bail.
6113 return;
Nikola Smiljanic01a75982014-05-29 10:55:11 +00006114 RecExpr = Conv.get();
John Wiegley01296292011-04-08 18:41:53 +00006115 }
Douglas Gregor392a84b2010-10-13 21:24:53 +00006116 QualType ReceiverType = RecExpr? RecExpr->getType()
6117 : Super? Context.getObjCObjectPointerType(
6118 Context.getObjCInterfaceType(Super))
6119 : Context.getObjCIdType();
Steve Naroffeae65032009-11-07 02:08:14 +00006120
Douglas Gregordc520b02010-11-08 21:12:30 +00006121 // If we're messaging an expression with type "id" or "Class", check
6122 // whether we know something special about the receiver that allows
6123 // us to assume a more-specific receiver type.
Anders Carlsson382ba412014-02-28 19:07:22 +00006124 if (ReceiverType->isObjCIdType() || ReceiverType->isObjCClassType()) {
Douglas Gregordc520b02010-11-08 21:12:30 +00006125 if (ObjCInterfaceDecl *IFace = GetAssumedMessageSendExprType(RecExpr)) {
6126 if (ReceiverType->isObjCClassType())
6127 return CodeCompleteObjCClassMessage(S,
6128 ParsedType::make(Context.getObjCInterfaceType(IFace)),
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006129 SelIdents,
Douglas Gregordc520b02010-11-08 21:12:30 +00006130 AtArgumentExpression, Super);
6131
6132 ReceiverType = Context.getObjCObjectPointerType(
6133 Context.getObjCInterfaceType(IFace));
6134 }
Anders Carlsson382ba412014-02-28 19:07:22 +00006135 } else if (RecExpr && getLangOpts().CPlusPlus) {
6136 ExprResult Conv = PerformContextuallyConvertToObjCPointer(RecExpr);
6137 if (Conv.isUsable()) {
Nikola Smiljanic01a75982014-05-29 10:55:11 +00006138 RecExpr = Conv.get();
Anders Carlsson382ba412014-02-28 19:07:22 +00006139 ReceiverType = RecExpr->getType();
6140 }
6141 }
Douglas Gregordc520b02010-11-08 21:12:30 +00006142
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006143 // Build the set of methods we can see.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006144 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006145 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor63745d52011-07-21 01:05:26 +00006146 CodeCompletionContext(CodeCompletionContext::CCC_ObjCInstanceMessage,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006147 ReceiverType, SelIdents));
Douglas Gregor63745d52011-07-21 01:05:26 +00006148
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006149 Results.EnterNewScope();
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006150
Douglas Gregor6fc04132010-08-27 15:10:57 +00006151 // If this is a send-to-super, try to add the special "super" send
6152 // completion.
Douglas Gregor392a84b2010-10-13 21:24:53 +00006153 if (Super) {
Douglas Gregor6fc04132010-08-27 15:10:57 +00006154 if (ObjCMethodDecl *SuperMethod
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006155 = AddSuperSendCompletion(*this, false, SelIdents, Results))
Douglas Gregor6fc04132010-08-27 15:10:57 +00006156 Results.Ignore(SuperMethod);
6157 }
6158
Douglas Gregorc2cb2e22010-08-27 15:29:55 +00006159 // If we're inside an Objective-C method definition, prefer its selector to
6160 // others.
6161 if (ObjCMethodDecl *CurMethod = getCurMethodDecl())
6162 Results.setPreferredSelector(CurMethod->getSelector());
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006163
Douglas Gregor1154e272010-09-16 16:06:31 +00006164 // Keep track of the selectors we've already added.
6165 VisitedSelectorSet Selectors;
6166
Douglas Gregora3329fa2009-11-18 00:06:18 +00006167 // Handle messages to Class. This really isn't a message to an instance
6168 // method, so we treat it the same way we would treat a message send to a
6169 // class method.
6170 if (ReceiverType->isObjCClassType() ||
6171 ReceiverType->isObjCQualifiedClassType()) {
6172 if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
6173 if (ObjCInterfaceDecl *ClassDecl = CurMethod->getClassInterface())
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006174 AddObjCMethods(ClassDecl, false, MK_Any, SelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00006175 CurContext, Selectors, AtArgumentExpression, Results);
Douglas Gregora3329fa2009-11-18 00:06:18 +00006176 }
6177 }
6178 // Handle messages to a qualified ID ("id<foo>").
6179 else if (const ObjCObjectPointerType *QualID
6180 = ReceiverType->getAsObjCQualifiedIdType()) {
6181 // Search protocols for instance methods.
Aaron Ballman83731462014-03-17 16:14:00 +00006182 for (auto *I : QualID->quals())
6183 AddObjCMethods(I, true, MK_Any, SelIdents, CurContext,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00006184 Selectors, AtArgumentExpression, Results);
Douglas Gregora3329fa2009-11-18 00:06:18 +00006185 }
6186 // Handle messages to a pointer to interface type.
6187 else if (const ObjCObjectPointerType *IFacePtr
6188 = ReceiverType->getAsObjCInterfacePointerType()) {
6189 // Search the class, its superclasses, etc., for instance methods.
Douglas Gregorc8537c52009-11-19 07:41:15 +00006190 AddObjCMethods(IFacePtr->getInterfaceDecl(), true, MK_Any, SelIdents,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006191 CurContext, Selectors, AtArgumentExpression,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00006192 Results);
Douglas Gregora3329fa2009-11-18 00:06:18 +00006193
6194 // Search protocols for instance methods.
Aaron Ballman83731462014-03-17 16:14:00 +00006195 for (auto *I : IFacePtr->quals())
6196 AddObjCMethods(I, true, MK_Any, SelIdents, CurContext,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00006197 Selectors, AtArgumentExpression, Results);
Douglas Gregora3329fa2009-11-18 00:06:18 +00006198 }
Douglas Gregor6285f752010-04-06 16:40:00 +00006199 // Handle messages to "id".
6200 else if (ReceiverType->isObjCIdType()) {
Douglas Gregord720daf2010-04-06 17:30:22 +00006201 // We're messaging "id", so provide all instance methods we know
6202 // about as code-completion results.
6203
6204 // If we have an external source, load the entire class method
Sebastian Redld44cd6a2010-08-18 23:57:06 +00006205 // pool from the AST file.
Douglas Gregord720daf2010-04-06 17:30:22 +00006206 if (ExternalSource) {
John McCall75b960e2010-06-01 09:23:16 +00006207 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
6208 I != N; ++I) {
6209 Selector Sel = ExternalSource->GetExternalSelector(I);
Sebastian Redl75d8a322010-08-02 23:18:59 +00006210 if (Sel.isNull() || MethodPool.count(Sel))
Douglas Gregord720daf2010-04-06 17:30:22 +00006211 continue;
6212
Sebastian Redl75d8a322010-08-02 23:18:59 +00006213 ReadMethodPool(Sel);
Douglas Gregord720daf2010-04-06 17:30:22 +00006214 }
6215 }
6216
Sebastian Redl75d8a322010-08-02 23:18:59 +00006217 for (GlobalMethodPool::iterator M = MethodPool.begin(),
6218 MEnd = MethodPool.end();
6219 M != MEnd; ++M) {
6220 for (ObjCMethodList *MethList = &M->second.first;
Nico Weber2e0c8f72014-12-27 03:58:08 +00006221 MethList && MethList->getMethod();
Argyrios Kyrtzidisd3da6e02013-04-17 00:08:58 +00006222 MethList = MethList->getNext()) {
Nico Weber2e0c8f72014-12-27 03:58:08 +00006223 if (!isAcceptableObjCMethod(MethList->getMethod(), MK_Any, SelIdents))
Douglas Gregor6285f752010-04-06 16:40:00 +00006224 continue;
Douglas Gregor1154e272010-09-16 16:06:31 +00006225
Nico Weber2e0c8f72014-12-27 03:58:08 +00006226 if (!Selectors.insert(MethList->getMethod()->getSelector()).second)
Douglas Gregor1154e272010-09-16 16:06:31 +00006227 continue;
Craig Topperc3ec1492014-05-26 06:22:03 +00006228
Nico Weber2e0c8f72014-12-27 03:58:08 +00006229 Result R(MethList->getMethod(),
6230 Results.getBasePriority(MethList->getMethod()), nullptr);
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006231 R.StartParameter = SelIdents.size();
Douglas Gregor6285f752010-04-06 16:40:00 +00006232 R.AllParametersAreInformative = false;
6233 Results.MaybeAddResult(R, CurContext);
6234 }
6235 }
6236 }
Steve Naroffeae65032009-11-07 02:08:14 +00006237 Results.ExitScope();
Douglas Gregor74661272010-09-21 00:03:25 +00006238
6239
6240 // If we're actually at the argument expression (rather than prior to the
6241 // selector), we're actually performing code completion for an expression.
6242 // Determine whether we have a single, best method. If so, we can
6243 // code-complete the expression using the corresponding parameter type as
6244 // our preferred type, improving completion results.
6245 if (AtArgumentExpression) {
6246 QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006247 SelIdents.size());
Douglas Gregor74661272010-09-21 00:03:25 +00006248 if (PreferredType.isNull())
6249 CodeCompleteOrdinaryName(S, PCC_Expression);
6250 else
6251 CodeCompleteExpression(S, PreferredType);
6252 return;
6253 }
6254
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006255 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor63745d52011-07-21 01:05:26 +00006256 Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006257 Results.data(),Results.size());
Steve Naroffeae65032009-11-07 02:08:14 +00006258}
Douglas Gregorbaf69612009-11-18 04:19:12 +00006259
Douglas Gregor68762e72010-08-23 21:17:50 +00006260void Sema::CodeCompleteObjCForCollection(Scope *S,
6261 DeclGroupPtrTy IterationVar) {
6262 CodeCompleteExpressionData Data;
6263 Data.ObjCCollection = true;
6264
6265 if (IterationVar.getAsOpaquePtr()) {
Serge Pavlov9ddb76e2013-08-27 13:15:56 +00006266 DeclGroupRef DG = IterationVar.get();
Douglas Gregor68762e72010-08-23 21:17:50 +00006267 for (DeclGroupRef::iterator I = DG.begin(), End = DG.end(); I != End; ++I) {
6268 if (*I)
6269 Data.IgnoreDecls.push_back(*I);
6270 }
6271 }
6272
6273 CodeCompleteExpression(S, Data);
6274}
6275
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006276void Sema::CodeCompleteObjCSelector(Scope *S,
6277 ArrayRef<IdentifierInfo *> SelIdents) {
Douglas Gregor67c692c2010-08-26 15:07:07 +00006278 // If we have an external source, load the entire class method
6279 // pool from the AST file.
6280 if (ExternalSource) {
6281 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
6282 I != N; ++I) {
6283 Selector Sel = ExternalSource->GetExternalSelector(I);
6284 if (Sel.isNull() || MethodPool.count(Sel))
6285 continue;
6286
6287 ReadMethodPool(Sel);
6288 }
6289 }
6290
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006291 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006292 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006293 CodeCompletionContext::CCC_SelectorName);
Douglas Gregor67c692c2010-08-26 15:07:07 +00006294 Results.EnterNewScope();
6295 for (GlobalMethodPool::iterator M = MethodPool.begin(),
6296 MEnd = MethodPool.end();
6297 M != MEnd; ++M) {
6298
6299 Selector Sel = M->first;
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006300 if (!isAcceptableObjCSelector(Sel, MK_Any, SelIdents))
Douglas Gregor67c692c2010-08-26 15:07:07 +00006301 continue;
6302
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006303 CodeCompletionBuilder Builder(Results.getAllocator(),
6304 Results.getCodeCompletionTUInfo());
Douglas Gregor67c692c2010-08-26 15:07:07 +00006305 if (Sel.isUnarySelector()) {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00006306 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00006307 Sel.getNameForSlot(0)));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006308 Results.AddResult(Builder.TakeString());
Douglas Gregor67c692c2010-08-26 15:07:07 +00006309 continue;
6310 }
6311
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00006312 std::string Accumulator;
Douglas Gregor67c692c2010-08-26 15:07:07 +00006313 for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I) {
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006314 if (I == SelIdents.size()) {
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00006315 if (!Accumulator.empty()) {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00006316 Builder.AddInformativeChunk(Builder.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006317 Accumulator));
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00006318 Accumulator.clear();
6319 }
6320 }
6321
Benjamin Kramer632500c2011-07-26 16:59:25 +00006322 Accumulator += Sel.getNameForSlot(I);
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00006323 Accumulator += ':';
Douglas Gregor67c692c2010-08-26 15:07:07 +00006324 }
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00006325 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString( Accumulator));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006326 Results.AddResult(Builder.TakeString());
Douglas Gregor67c692c2010-08-26 15:07:07 +00006327 }
6328 Results.ExitScope();
6329
6330 HandleCodeCompleteResults(this, CodeCompleter,
6331 CodeCompletionContext::CCC_SelectorName,
6332 Results.data(), Results.size());
6333}
6334
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006335/// Add all of the protocol declarations that we find in the given
Douglas Gregorbaf69612009-11-18 04:19:12 +00006336/// (translation unit) context.
6337static void AddProtocolResults(DeclContext *Ctx, DeclContext *CurContext,
Douglas Gregor5b4671c2009-11-18 04:49:41 +00006338 bool OnlyForwardDeclarations,
Douglas Gregorbaf69612009-11-18 04:19:12 +00006339 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00006340 typedef CodeCompletionResult Result;
Douglas Gregorbaf69612009-11-18 04:19:12 +00006341
Aaron Ballman629afae2014-03-07 19:56:05 +00006342 for (const auto *D : Ctx->decls()) {
Douglas Gregorbaf69612009-11-18 04:19:12 +00006343 // Record any protocols we find.
Aaron Ballman629afae2014-03-07 19:56:05 +00006344 if (const auto *Proto = dyn_cast<ObjCProtocolDecl>(D))
Douglas Gregore6e48b12012-01-01 19:29:29 +00006345 if (!OnlyForwardDeclarations || !Proto->hasDefinition())
Craig Topperc3ec1492014-05-26 06:22:03 +00006346 Results.AddResult(Result(Proto, Results.getBasePriority(Proto),nullptr),
6347 CurContext, nullptr, false);
Douglas Gregorbaf69612009-11-18 04:19:12 +00006348 }
6349}
6350
Craig Topper883dd332015-12-24 23:58:11 +00006351void Sema::CodeCompleteObjCProtocolReferences(
6352 ArrayRef<IdentifierLocPair> Protocols) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006353 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006354 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006355 CodeCompletionContext::CCC_ObjCProtocolName);
Douglas Gregorbaf69612009-11-18 04:19:12 +00006356
Chandler Carruthede11632016-11-04 06:06:50 +00006357 if (CodeCompleter->includeGlobals()) {
Douglas Gregora3b23b02010-12-09 21:44:02 +00006358 Results.EnterNewScope();
6359
6360 // Tell the result set to ignore all of the protocols we have
6361 // already seen.
6362 // FIXME: This doesn't work when caching code-completion results.
Craig Topper883dd332015-12-24 23:58:11 +00006363 for (const IdentifierLocPair &Pair : Protocols)
6364 if (ObjCProtocolDecl *Protocol = LookupProtocol(Pair.first,
6365 Pair.second))
Douglas Gregora3b23b02010-12-09 21:44:02 +00006366 Results.Ignore(Protocol);
Douglas Gregorbaf69612009-11-18 04:19:12 +00006367
Douglas Gregora3b23b02010-12-09 21:44:02 +00006368 // Add all protocols.
6369 AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, false,
6370 Results);
Douglas Gregor5b4671c2009-11-18 04:49:41 +00006371
Douglas Gregora3b23b02010-12-09 21:44:02 +00006372 Results.ExitScope();
6373 }
6374
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006375 HandleCodeCompleteResults(this, CodeCompleter,
6376 CodeCompletionContext::CCC_ObjCProtocolName,
6377 Results.data(),Results.size());
Douglas Gregor5b4671c2009-11-18 04:49:41 +00006378}
6379
6380void Sema::CodeCompleteObjCProtocolDecl(Scope *) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006381 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006382 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006383 CodeCompletionContext::CCC_ObjCProtocolName);
Douglas Gregor5b4671c2009-11-18 04:49:41 +00006384
Chandler Carruthede11632016-11-04 06:06:50 +00006385 if (CodeCompleter->includeGlobals()) {
Douglas Gregora3b23b02010-12-09 21:44:02 +00006386 Results.EnterNewScope();
6387
6388 // Add all protocols.
6389 AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, true,
6390 Results);
Douglas Gregorbaf69612009-11-18 04:19:12 +00006391
Douglas Gregora3b23b02010-12-09 21:44:02 +00006392 Results.ExitScope();
6393 }
6394
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006395 HandleCodeCompleteResults(this, CodeCompleter,
6396 CodeCompletionContext::CCC_ObjCProtocolName,
6397 Results.data(),Results.size());
Douglas Gregorbaf69612009-11-18 04:19:12 +00006398}
Douglas Gregor49c22a72009-11-18 16:26:39 +00006399
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006400/// Add all of the Objective-C interface declarations that we find in
Douglas Gregor49c22a72009-11-18 16:26:39 +00006401/// the given (translation unit) context.
6402static void AddInterfaceResults(DeclContext *Ctx, DeclContext *CurContext,
6403 bool OnlyForwardDeclarations,
6404 bool OnlyUnimplemented,
6405 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00006406 typedef CodeCompletionResult Result;
Douglas Gregor49c22a72009-11-18 16:26:39 +00006407
Aaron Ballman629afae2014-03-07 19:56:05 +00006408 for (const auto *D : Ctx->decls()) {
Douglas Gregor1c283312010-08-11 12:19:30 +00006409 // Record any interfaces we find.
Aaron Ballman629afae2014-03-07 19:56:05 +00006410 if (const auto *Class = dyn_cast<ObjCInterfaceDecl>(D))
Douglas Gregordc9166c2011-12-15 20:29:51 +00006411 if ((!OnlyForwardDeclarations || !Class->hasDefinition()) &&
Douglas Gregor1c283312010-08-11 12:19:30 +00006412 (!OnlyUnimplemented || !Class->getImplementation()))
Craig Topperc3ec1492014-05-26 06:22:03 +00006413 Results.AddResult(Result(Class, Results.getBasePriority(Class),nullptr),
6414 CurContext, nullptr, false);
Douglas Gregor49c22a72009-11-18 16:26:39 +00006415 }
6416}
6417
6418void Sema::CodeCompleteObjCInterfaceDecl(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006419 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006420 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006421 CodeCompletionContext::CCC_Other);
Douglas Gregor49c22a72009-11-18 16:26:39 +00006422 Results.EnterNewScope();
6423
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006424 if (CodeCompleter->includeGlobals()) {
6425 // Add all classes.
6426 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
6427 false, Results);
6428 }
6429
Douglas Gregor49c22a72009-11-18 16:26:39 +00006430 Results.ExitScope();
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006431
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006432 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006433 CodeCompletionContext::CCC_ObjCInterfaceName,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006434 Results.data(),Results.size());
Douglas Gregor49c22a72009-11-18 16:26:39 +00006435}
6436
Douglas Gregorb2ccf012010-04-15 22:33:43 +00006437void Sema::CodeCompleteObjCSuperclass(Scope *S, IdentifierInfo *ClassName,
6438 SourceLocation ClassNameLoc) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006439 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006440 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006441 CodeCompletionContext::CCC_ObjCInterfaceName);
Douglas Gregor49c22a72009-11-18 16:26:39 +00006442 Results.EnterNewScope();
6443
6444 // Make sure that we ignore the class we're currently defining.
6445 NamedDecl *CurClass
Douglas Gregorb2ccf012010-04-15 22:33:43 +00006446 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006447 if (CurClass && isa<ObjCInterfaceDecl>(CurClass))
Douglas Gregor49c22a72009-11-18 16:26:39 +00006448 Results.Ignore(CurClass);
6449
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006450 if (CodeCompleter->includeGlobals()) {
6451 // Add all classes.
6452 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
6453 false, Results);
6454 }
6455
Douglas Gregor49c22a72009-11-18 16:26:39 +00006456 Results.ExitScope();
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006457
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006458 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006459 CodeCompletionContext::CCC_ObjCInterfaceName,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006460 Results.data(),Results.size());
Douglas Gregor49c22a72009-11-18 16:26:39 +00006461}
6462
6463void Sema::CodeCompleteObjCImplementationDecl(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006464 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006465 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006466 CodeCompletionContext::CCC_Other);
Douglas Gregor49c22a72009-11-18 16:26:39 +00006467 Results.EnterNewScope();
6468
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006469 if (CodeCompleter->includeGlobals()) {
6470 // Add all unimplemented classes.
6471 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
6472 true, Results);
6473 }
6474
Douglas Gregor49c22a72009-11-18 16:26:39 +00006475 Results.ExitScope();
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006476
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006477 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006478 CodeCompletionContext::CCC_ObjCInterfaceName,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006479 Results.data(),Results.size());
Douglas Gregor49c22a72009-11-18 16:26:39 +00006480}
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006481
6482void Sema::CodeCompleteObjCInterfaceCategory(Scope *S,
Douglas Gregorb2ccf012010-04-15 22:33:43 +00006483 IdentifierInfo *ClassName,
6484 SourceLocation ClassNameLoc) {
John McCall276321a2010-08-25 06:19:51 +00006485 typedef CodeCompletionResult Result;
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006486
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006487 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006488 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor21325842011-07-07 16:03:39 +00006489 CodeCompletionContext::CCC_ObjCCategoryName);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006490
6491 // Ignore any categories we find that have already been implemented by this
6492 // interface.
6493 llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
6494 NamedDecl *CurClass
Douglas Gregorb2ccf012010-04-15 22:33:43 +00006495 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006496 if (ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass)){
Aaron Ballman3fe486a2014-03-13 21:23:55 +00006497 for (const auto *Cat : Class->visible_categories())
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006498 CategoryNames.insert(Cat->getIdentifier());
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006499 }
6500
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006501 // Add all of the categories we know about.
6502 Results.EnterNewScope();
6503 TranslationUnitDecl *TU = Context.getTranslationUnitDecl();
Aaron Ballman629afae2014-03-07 19:56:05 +00006504 for (const auto *D : TU->decls())
6505 if (const auto *Category = dyn_cast<ObjCCategoryDecl>(D))
David Blaikie82e95a32014-11-19 07:49:47 +00006506 if (CategoryNames.insert(Category->getIdentifier()).second)
Craig Topperc3ec1492014-05-26 06:22:03 +00006507 Results.AddResult(Result(Category, Results.getBasePriority(Category),
6508 nullptr),
6509 CurContext, nullptr, false);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006510 Results.ExitScope();
6511
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006512 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor21325842011-07-07 16:03:39 +00006513 CodeCompletionContext::CCC_ObjCCategoryName,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006514 Results.data(),Results.size());
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006515}
6516
6517void Sema::CodeCompleteObjCImplementationCategory(Scope *S,
Douglas Gregorb2ccf012010-04-15 22:33:43 +00006518 IdentifierInfo *ClassName,
6519 SourceLocation ClassNameLoc) {
John McCall276321a2010-08-25 06:19:51 +00006520 typedef CodeCompletionResult Result;
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006521
6522 // Find the corresponding interface. If we couldn't find the interface, the
6523 // program itself is ill-formed. However, we'll try to be helpful still by
6524 // providing the list of all of the categories we know about.
6525 NamedDecl *CurClass
Douglas Gregorb2ccf012010-04-15 22:33:43 +00006526 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006527 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass);
6528 if (!Class)
Douglas Gregorb2ccf012010-04-15 22:33:43 +00006529 return CodeCompleteObjCInterfaceCategory(S, ClassName, ClassNameLoc);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006530
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006531 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006532 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor21325842011-07-07 16:03:39 +00006533 CodeCompletionContext::CCC_ObjCCategoryName);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006534
6535 // Add all of the categories that have have corresponding interface
6536 // declarations in this class and any of its superclasses, except for
6537 // already-implemented categories in the class itself.
6538 llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
6539 Results.EnterNewScope();
6540 bool IgnoreImplemented = true;
6541 while (Class) {
Aaron Ballman3fe486a2014-03-13 21:23:55 +00006542 for (const auto *Cat : Class->visible_categories()) {
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006543 if ((!IgnoreImplemented || !Cat->getImplementation()) &&
David Blaikie82e95a32014-11-19 07:49:47 +00006544 CategoryNames.insert(Cat->getIdentifier()).second)
Craig Topperc3ec1492014-05-26 06:22:03 +00006545 Results.AddResult(Result(Cat, Results.getBasePriority(Cat), nullptr),
6546 CurContext, nullptr, false);
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006547 }
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006548
6549 Class = Class->getSuperClass();
6550 IgnoreImplemented = false;
6551 }
6552 Results.ExitScope();
6553
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006554 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor21325842011-07-07 16:03:39 +00006555 CodeCompletionContext::CCC_ObjCCategoryName,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006556 Results.data(),Results.size());
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006557}
Douglas Gregor5d649882009-11-18 22:32:06 +00006558
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00006559void Sema::CodeCompleteObjCPropertyDefinition(Scope *S) {
Douglas Gregorc3425b12015-07-07 06:20:19 +00006560 CodeCompletionContext CCContext(CodeCompletionContext::CCC_Other);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006561 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006562 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorc3425b12015-07-07 06:20:19 +00006563 CCContext);
Douglas Gregor5d649882009-11-18 22:32:06 +00006564
6565 // Figure out where this @synthesize lives.
6566 ObjCContainerDecl *Container
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00006567 = dyn_cast_or_null<ObjCContainerDecl>(CurContext);
Douglas Gregor5d649882009-11-18 22:32:06 +00006568 if (!Container ||
6569 (!isa<ObjCImplementationDecl>(Container) &&
6570 !isa<ObjCCategoryImplDecl>(Container)))
6571 return;
6572
6573 // Ignore any properties that have already been implemented.
Douglas Gregor9b4f3702012-06-12 13:44:08 +00006574 Container = getContainerDef(Container);
Aaron Ballman629afae2014-03-07 19:56:05 +00006575 for (const auto *D : Container->decls())
6576 if (const auto *PropertyImpl = dyn_cast<ObjCPropertyImplDecl>(D))
Douglas Gregor5d649882009-11-18 22:32:06 +00006577 Results.Ignore(PropertyImpl->getPropertyDecl());
6578
6579 // Add any properties that we find.
Douglas Gregorb888acf2010-12-09 23:01:55 +00006580 AddedPropertiesSet AddedProperties;
Douglas Gregor5d649882009-11-18 22:32:06 +00006581 Results.EnterNewScope();
6582 if (ObjCImplementationDecl *ClassImpl
6583 = dyn_cast<ObjCImplementationDecl>(Container))
Douglas Gregorc3425b12015-07-07 06:20:19 +00006584 AddObjCProperties(CCContext, ClassImpl->getClassInterface(), false,
Douglas Gregor95147142011-05-05 15:50:42 +00006585 /*AllowNullaryMethods=*/false, CurContext,
Douglas Gregorb888acf2010-12-09 23:01:55 +00006586 AddedProperties, Results);
Douglas Gregor5d649882009-11-18 22:32:06 +00006587 else
Douglas Gregorc3425b12015-07-07 06:20:19 +00006588 AddObjCProperties(CCContext,
6589 cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl(),
Douglas Gregor95147142011-05-05 15:50:42 +00006590 false, /*AllowNullaryMethods=*/false, CurContext,
6591 AddedProperties, Results);
Douglas Gregor5d649882009-11-18 22:32:06 +00006592 Results.ExitScope();
6593
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006594 HandleCodeCompleteResults(this, CodeCompleter,
6595 CodeCompletionContext::CCC_Other,
6596 Results.data(),Results.size());
Douglas Gregor5d649882009-11-18 22:32:06 +00006597}
6598
6599void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S,
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00006600 IdentifierInfo *PropertyName) {
John McCall276321a2010-08-25 06:19:51 +00006601 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006602 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006603 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006604 CodeCompletionContext::CCC_Other);
Douglas Gregor5d649882009-11-18 22:32:06 +00006605
6606 // Figure out where this @synthesize lives.
6607 ObjCContainerDecl *Container
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00006608 = dyn_cast_or_null<ObjCContainerDecl>(CurContext);
Douglas Gregor5d649882009-11-18 22:32:06 +00006609 if (!Container ||
6610 (!isa<ObjCImplementationDecl>(Container) &&
6611 !isa<ObjCCategoryImplDecl>(Container)))
6612 return;
6613
6614 // Figure out which interface we're looking into.
Craig Topperc3ec1492014-05-26 06:22:03 +00006615 ObjCInterfaceDecl *Class = nullptr;
Douglas Gregor5d649882009-11-18 22:32:06 +00006616 if (ObjCImplementationDecl *ClassImpl
Manman Ren5b786402016-01-28 18:49:28 +00006617 = dyn_cast<ObjCImplementationDecl>(Container))
Douglas Gregor5d649882009-11-18 22:32:06 +00006618 Class = ClassImpl->getClassInterface();
6619 else
6620 Class = cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl()
6621 ->getClassInterface();
6622
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006623 // Determine the type of the property we're synthesizing.
6624 QualType PropertyType = Context.getObjCIdType();
6625 if (Class) {
Manman Ren5b786402016-01-28 18:49:28 +00006626 if (ObjCPropertyDecl *Property = Class->FindPropertyDeclaration(
6627 PropertyName, ObjCPropertyQueryKind::OBJC_PR_query_instance)) {
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006628 PropertyType
6629 = Property->getType().getNonReferenceType().getUnqualifiedType();
6630
6631 // Give preference to ivars
6632 Results.setPreferredType(PropertyType);
6633 }
6634 }
6635
Douglas Gregor5d649882009-11-18 22:32:06 +00006636 // Add all of the instance variables in this class and its superclasses.
6637 Results.EnterNewScope();
Douglas Gregor331faa02011-04-18 14:13:53 +00006638 bool SawSimilarlyNamedIvar = false;
6639 std::string NameWithPrefix;
6640 NameWithPrefix += '_';
Benjamin Kramer632500c2011-07-26 16:59:25 +00006641 NameWithPrefix += PropertyName->getName();
Douglas Gregor331faa02011-04-18 14:13:53 +00006642 std::string NameWithSuffix = PropertyName->getName().str();
6643 NameWithSuffix += '_';
Douglas Gregor5d649882009-11-18 22:32:06 +00006644 for(; Class; Class = Class->getSuperClass()) {
Douglas Gregor331faa02011-04-18 14:13:53 +00006645 for (ObjCIvarDecl *Ivar = Class->all_declared_ivar_begin(); Ivar;
6646 Ivar = Ivar->getNextIvar()) {
Craig Topperc3ec1492014-05-26 06:22:03 +00006647 Results.AddResult(Result(Ivar, Results.getBasePriority(Ivar), nullptr),
6648 CurContext, nullptr, false);
6649
Douglas Gregor331faa02011-04-18 14:13:53 +00006650 // Determine whether we've seen an ivar with a name similar to the
6651 // property.
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006652 if ((PropertyName == Ivar->getIdentifier() ||
Douglas Gregor331faa02011-04-18 14:13:53 +00006653 NameWithPrefix == Ivar->getName() ||
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006654 NameWithSuffix == Ivar->getName())) {
Douglas Gregor331faa02011-04-18 14:13:53 +00006655 SawSimilarlyNamedIvar = true;
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006656
6657 // Reduce the priority of this result by one, to give it a slight
6658 // advantage over other results whose names don't match so closely.
6659 if (Results.size() &&
6660 Results.data()[Results.size() - 1].Kind
6661 == CodeCompletionResult::RK_Declaration &&
6662 Results.data()[Results.size() - 1].Declaration == Ivar)
6663 Results.data()[Results.size() - 1].Priority--;
6664 }
Douglas Gregor331faa02011-04-18 14:13:53 +00006665 }
Douglas Gregor5d649882009-11-18 22:32:06 +00006666 }
Douglas Gregor331faa02011-04-18 14:13:53 +00006667
6668 if (!SawSimilarlyNamedIvar) {
6669 // Create ivar result _propName, that the user can use to synthesize
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006670 // an ivar of the appropriate type.
6671 unsigned Priority = CCP_MemberDeclaration + 1;
Douglas Gregor331faa02011-04-18 14:13:53 +00006672 typedef CodeCompletionResult Result;
6673 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006674 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo(),
6675 Priority,CXAvailability_Available);
Douglas Gregor331faa02011-04-18 14:13:53 +00006676
Douglas Gregor75acd922011-09-27 23:30:47 +00006677 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006678 Builder.AddResultTypeChunk(GetCompletionTypeString(PropertyType, Context,
Douglas Gregor75acd922011-09-27 23:30:47 +00006679 Policy, Allocator));
Douglas Gregor331faa02011-04-18 14:13:53 +00006680 Builder.AddTypedTextChunk(Allocator.CopyString(NameWithPrefix));
6681 Results.AddResult(Result(Builder.TakeString(), Priority,
6682 CXCursor_ObjCIvarDecl));
6683 }
6684
Douglas Gregor5d649882009-11-18 22:32:06 +00006685 Results.ExitScope();
6686
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006687 HandleCodeCompleteResults(this, CodeCompleter,
6688 CodeCompletionContext::CCC_Other,
6689 Results.data(),Results.size());
Douglas Gregor5d649882009-11-18 22:32:06 +00006690}
Douglas Gregor636a61e2010-04-07 00:21:17 +00006691
Douglas Gregor416b5752010-08-25 01:08:01 +00006692// Mapping from selectors to the methods that implement that selector, along
6693// with the "in original class" flag.
Benjamin Kramereb8c4462013-06-29 17:52:13 +00006694typedef llvm::DenseMap<
6695 Selector, llvm::PointerIntPair<ObjCMethodDecl *, 1, bool> > KnownMethodsMap;
Douglas Gregor636a61e2010-04-07 00:21:17 +00006696
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006697/// Find all of the methods that reside in the given container
Douglas Gregor636a61e2010-04-07 00:21:17 +00006698/// (and its superclasses, protocols, etc.) that meet the given
6699/// criteria. Insert those methods into the map of known methods,
6700/// indexed by selector so they can be easily found.
6701static void FindImplementableMethods(ASTContext &Context,
6702 ObjCContainerDecl *Container,
Alex Lorenzb8740422017-10-24 16:39:37 +00006703 Optional<bool> WantInstanceMethods,
Douglas Gregor636a61e2010-04-07 00:21:17 +00006704 QualType ReturnType,
Douglas Gregor416b5752010-08-25 01:08:01 +00006705 KnownMethodsMap &KnownMethods,
6706 bool InOriginalClass = true) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00006707 if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)) {
Douglas Gregor9b4f3702012-06-12 13:44:08 +00006708 // Make sure we have a definition; that's what we'll walk.
Douglas Gregorc0ac7d62011-12-15 05:27:12 +00006709 if (!IFace->hasDefinition())
6710 return;
Douglas Gregor9b4f3702012-06-12 13:44:08 +00006711
6712 IFace = IFace->getDefinition();
6713 Container = IFace;
Douglas Gregorc0ac7d62011-12-15 05:27:12 +00006714
Douglas Gregor636a61e2010-04-07 00:21:17 +00006715 const ObjCList<ObjCProtocolDecl> &Protocols
6716 = IFace->getReferencedProtocols();
6717 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006718 E = Protocols.end();
Douglas Gregor636a61e2010-04-07 00:21:17 +00006719 I != E; ++I)
6720 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006721 KnownMethods, InOriginalClass);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006722
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006723 // Add methods from any class extensions and categories.
Aaron Ballman3fe486a2014-03-13 21:23:55 +00006724 for (auto *Cat : IFace->visible_categories()) {
6725 FindImplementableMethods(Context, Cat, WantInstanceMethods, ReturnType,
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006726 KnownMethods, false);
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006727 }
6728
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006729 // Visit the superclass.
6730 if (IFace->getSuperClass())
6731 FindImplementableMethods(Context, IFace->getSuperClass(),
6732 WantInstanceMethods, ReturnType,
6733 KnownMethods, false);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006734 }
6735
6736 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(Container)) {
6737 // Recurse into protocols.
6738 const ObjCList<ObjCProtocolDecl> &Protocols
6739 = Category->getReferencedProtocols();
6740 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006741 E = Protocols.end();
Douglas Gregor636a61e2010-04-07 00:21:17 +00006742 I != E; ++I)
6743 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006744 KnownMethods, InOriginalClass);
6745
6746 // If this category is the original class, jump to the interface.
6747 if (InOriginalClass && Category->getClassInterface())
6748 FindImplementableMethods(Context, Category->getClassInterface(),
6749 WantInstanceMethods, ReturnType, KnownMethods,
6750 false);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006751 }
6752
6753 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Douglas Gregor9b4f3702012-06-12 13:44:08 +00006754 // Make sure we have a definition; that's what we'll walk.
6755 if (!Protocol->hasDefinition())
6756 return;
6757 Protocol = Protocol->getDefinition();
6758 Container = Protocol;
6759
6760 // Recurse into protocols.
6761 const ObjCList<ObjCProtocolDecl> &Protocols
6762 = Protocol->getReferencedProtocols();
6763 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
6764 E = Protocols.end();
6765 I != E; ++I)
6766 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
6767 KnownMethods, false);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006768 }
6769
6770 // Add methods in this container. This operation occurs last because
6771 // we want the methods from this container to override any methods
6772 // we've previously seen with the same selector.
Aaron Ballmanaff18c02014-03-13 19:03:34 +00006773 for (auto *M : Container->methods()) {
Alex Lorenzb8740422017-10-24 16:39:37 +00006774 if (!WantInstanceMethods || M->isInstanceMethod() == *WantInstanceMethods) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00006775 if (!ReturnType.isNull() &&
Alp Toker314cc812014-01-25 16:55:45 +00006776 !Context.hasSameUnqualifiedType(ReturnType, M->getReturnType()))
Douglas Gregor636a61e2010-04-07 00:21:17 +00006777 continue;
6778
Benjamin Kramereb8c4462013-06-29 17:52:13 +00006779 KnownMethods[M->getSelector()] =
Aaron Ballmanaff18c02014-03-13 19:03:34 +00006780 KnownMethodsMap::mapped_type(M, InOriginalClass);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006781 }
6782 }
6783}
6784
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006785/// Add the parenthesized return or parameter type chunk to a code
Douglas Gregor669a25a2011-02-17 00:22:45 +00006786/// completion string.
6787static void AddObjCPassingTypeChunk(QualType Type,
Douglas Gregor29979142012-04-10 18:35:07 +00006788 unsigned ObjCDeclQuals,
Douglas Gregor669a25a2011-02-17 00:22:45 +00006789 ASTContext &Context,
Douglas Gregor75acd922011-09-27 23:30:47 +00006790 const PrintingPolicy &Policy,
Douglas Gregor669a25a2011-02-17 00:22:45 +00006791 CodeCompletionBuilder &Builder) {
6792 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregor86b42682015-06-19 18:27:52 +00006793 std::string Quals = formatObjCParamQualifiers(ObjCDeclQuals, Type);
Douglas Gregor29979142012-04-10 18:35:07 +00006794 if (!Quals.empty())
6795 Builder.AddTextChunk(Builder.getAllocator().CopyString(Quals));
Douglas Gregor75acd922011-09-27 23:30:47 +00006796 Builder.AddTextChunk(GetCompletionTypeString(Type, Context, Policy,
Douglas Gregor669a25a2011-02-17 00:22:45 +00006797 Builder.getAllocator()));
6798 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6799}
6800
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006801/// Determine whether the given class is or inherits from a class by
Douglas Gregor669a25a2011-02-17 00:22:45 +00006802/// the given name.
6803static bool InheritsFromClassNamed(ObjCInterfaceDecl *Class,
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006804 StringRef Name) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006805 if (!Class)
6806 return false;
6807
6808 if (Class->getIdentifier() && Class->getIdentifier()->getName() == Name)
6809 return true;
6810
6811 return InheritsFromClassNamed(Class->getSuperClass(), Name);
6812}
6813
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006814/// Add code completions for Objective-C Key-Value Coding (KVC) and
Douglas Gregor669a25a2011-02-17 00:22:45 +00006815/// Key-Value Observing (KVO).
6816static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
6817 bool IsInstanceMethod,
6818 QualType ReturnType,
6819 ASTContext &Context,
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006820 VisitedSelectorSet &KnownSelectors,
Douglas Gregor669a25a2011-02-17 00:22:45 +00006821 ResultBuilder &Results) {
6822 IdentifierInfo *PropName = Property->getIdentifier();
6823 if (!PropName || PropName->getLength() == 0)
6824 return;
6825
Douglas Gregor75acd922011-09-27 23:30:47 +00006826 PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema());
6827
Douglas Gregor669a25a2011-02-17 00:22:45 +00006828 // Builder that will create each code completion.
6829 typedef CodeCompletionResult Result;
6830 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006831 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Douglas Gregor669a25a2011-02-17 00:22:45 +00006832
6833 // The selector table.
6834 SelectorTable &Selectors = Context.Selectors;
6835
6836 // The property name, copied into the code completion allocation region
6837 // on demand.
6838 struct KeyHolder {
6839 CodeCompletionAllocator &Allocator;
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006840 StringRef Key;
Douglas Gregor669a25a2011-02-17 00:22:45 +00006841 const char *CopiedKey;
Craig Topperc3ec1492014-05-26 06:22:03 +00006842
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006843 KeyHolder(CodeCompletionAllocator &Allocator, StringRef Key)
Craig Topperc3ec1492014-05-26 06:22:03 +00006844 : Allocator(Allocator), Key(Key), CopiedKey(nullptr) {}
6845
Douglas Gregor669a25a2011-02-17 00:22:45 +00006846 operator const char *() {
6847 if (CopiedKey)
6848 return CopiedKey;
6849
6850 return CopiedKey = Allocator.CopyString(Key);
6851 }
6852 } Key(Allocator, PropName->getName());
6853
6854 // The uppercased name of the property name.
6855 std::string UpperKey = PropName->getName();
6856 if (!UpperKey.empty())
Jordan Rose4938f272013-02-09 10:09:43 +00006857 UpperKey[0] = toUppercase(UpperKey[0]);
Douglas Gregor669a25a2011-02-17 00:22:45 +00006858
6859 bool ReturnTypeMatchesProperty = ReturnType.isNull() ||
6860 Context.hasSameUnqualifiedType(ReturnType.getNonReferenceType(),
6861 Property->getType());
6862 bool ReturnTypeMatchesVoid
6863 = ReturnType.isNull() || ReturnType->isVoidType();
6864
6865 // Add the normal accessor -(type)key.
6866 if (IsInstanceMethod &&
David Blaikie82e95a32014-11-19 07:49:47 +00006867 KnownSelectors.insert(Selectors.getNullarySelector(PropName)).second &&
Douglas Gregor669a25a2011-02-17 00:22:45 +00006868 ReturnTypeMatchesProperty && !Property->getGetterMethodDecl()) {
6869 if (ReturnType.isNull())
Douglas Gregor29979142012-04-10 18:35:07 +00006870 AddObjCPassingTypeChunk(Property->getType(), /*Quals=*/0,
6871 Context, Policy, Builder);
Douglas Gregor669a25a2011-02-17 00:22:45 +00006872
6873 Builder.AddTypedTextChunk(Key);
6874 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
6875 CXCursor_ObjCInstanceMethodDecl));
6876 }
6877
6878 // If we have an integral or boolean property (or the user has provided
6879 // an integral or boolean return type), add the accessor -(type)isKey.
6880 if (IsInstanceMethod &&
6881 ((!ReturnType.isNull() &&
6882 (ReturnType->isIntegerType() || ReturnType->isBooleanType())) ||
6883 (ReturnType.isNull() &&
6884 (Property->getType()->isIntegerType() ||
6885 Property->getType()->isBooleanType())))) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006886 std::string SelectorName = (Twine("is") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006887 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00006888 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
6889 .second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006890 if (ReturnType.isNull()) {
6891 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6892 Builder.AddTextChunk("BOOL");
6893 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6894 }
6895
6896 Builder.AddTypedTextChunk(
6897 Allocator.CopyString(SelectorId->getName()));
6898 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
6899 CXCursor_ObjCInstanceMethodDecl));
6900 }
6901 }
6902
6903 // Add the normal mutator.
6904 if (IsInstanceMethod && ReturnTypeMatchesVoid &&
6905 !Property->getSetterMethodDecl()) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006906 std::string SelectorName = (Twine("set") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006907 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00006908 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006909 if (ReturnType.isNull()) {
6910 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6911 Builder.AddTextChunk("void");
6912 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6913 }
6914
6915 Builder.AddTypedTextChunk(
6916 Allocator.CopyString(SelectorId->getName()));
6917 Builder.AddTypedTextChunk(":");
Douglas Gregor29979142012-04-10 18:35:07 +00006918 AddObjCPassingTypeChunk(Property->getType(), /*Quals=*/0,
6919 Context, Policy, Builder);
Douglas Gregor669a25a2011-02-17 00:22:45 +00006920 Builder.AddTextChunk(Key);
6921 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
6922 CXCursor_ObjCInstanceMethodDecl));
6923 }
6924 }
6925
6926 // Indexed and unordered accessors
6927 unsigned IndexedGetterPriority = CCP_CodePattern;
6928 unsigned IndexedSetterPriority = CCP_CodePattern;
6929 unsigned UnorderedGetterPriority = CCP_CodePattern;
6930 unsigned UnorderedSetterPriority = CCP_CodePattern;
6931 if (const ObjCObjectPointerType *ObjCPointer
6932 = Property->getType()->getAs<ObjCObjectPointerType>()) {
6933 if (ObjCInterfaceDecl *IFace = ObjCPointer->getInterfaceDecl()) {
6934 // If this interface type is not provably derived from a known
6935 // collection, penalize the corresponding completions.
6936 if (!InheritsFromClassNamed(IFace, "NSMutableArray")) {
6937 IndexedSetterPriority += CCD_ProbablyNotObjCCollection;
6938 if (!InheritsFromClassNamed(IFace, "NSArray"))
6939 IndexedGetterPriority += CCD_ProbablyNotObjCCollection;
6940 }
6941
6942 if (!InheritsFromClassNamed(IFace, "NSMutableSet")) {
6943 UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;
6944 if (!InheritsFromClassNamed(IFace, "NSSet"))
6945 UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;
6946 }
6947 }
6948 } else {
6949 IndexedGetterPriority += CCD_ProbablyNotObjCCollection;
6950 IndexedSetterPriority += CCD_ProbablyNotObjCCollection;
6951 UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;
6952 UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;
6953 }
6954
6955 // Add -(NSUInteger)countOf<key>
6956 if (IsInstanceMethod &&
6957 (ReturnType.isNull() || ReturnType->isIntegerType())) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006958 std::string SelectorName = (Twine("countOf") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006959 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00006960 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
6961 .second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006962 if (ReturnType.isNull()) {
6963 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6964 Builder.AddTextChunk("NSUInteger");
6965 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6966 }
6967
6968 Builder.AddTypedTextChunk(
6969 Allocator.CopyString(SelectorId->getName()));
6970 Results.AddResult(Result(Builder.TakeString(),
6971 std::min(IndexedGetterPriority,
6972 UnorderedGetterPriority),
6973 CXCursor_ObjCInstanceMethodDecl));
6974 }
6975 }
6976
6977 // Indexed getters
6978 // Add -(id)objectInKeyAtIndex:(NSUInteger)index
6979 if (IsInstanceMethod &&
6980 (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006981 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006982 = (Twine("objectIn") + UpperKey + "AtIndex").str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006983 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00006984 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006985 if (ReturnType.isNull()) {
6986 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6987 Builder.AddTextChunk("id");
6988 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6989 }
6990
6991 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6992 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6993 Builder.AddTextChunk("NSUInteger");
6994 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6995 Builder.AddTextChunk("index");
6996 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
6997 CXCursor_ObjCInstanceMethodDecl));
6998 }
6999 }
7000
7001 // Add -(NSArray *)keyAtIndexes:(NSIndexSet *)indexes
7002 if (IsInstanceMethod &&
7003 (ReturnType.isNull() ||
7004 (ReturnType->isObjCObjectPointerType() &&
7005 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
7006 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
7007 ->getName() == "NSArray"))) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007008 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007009 = (Twine(Property->getName()) + "AtIndexes").str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007010 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007011 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007012 if (ReturnType.isNull()) {
7013 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7014 Builder.AddTextChunk("NSArray *");
7015 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7016 }
7017
7018 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7019 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7020 Builder.AddTextChunk("NSIndexSet *");
7021 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7022 Builder.AddTextChunk("indexes");
7023 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
7024 CXCursor_ObjCInstanceMethodDecl));
7025 }
7026 }
7027
7028 // Add -(void)getKey:(type **)buffer range:(NSRange)inRange
7029 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007030 std::string SelectorName = (Twine("get") + UpperKey).str();
Douglas Gregor669a25a2011-02-17 00:22:45 +00007031 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007032 &Context.Idents.get(SelectorName),
Douglas Gregor669a25a2011-02-17 00:22:45 +00007033 &Context.Idents.get("range")
7034 };
7035
David Blaikie82e95a32014-11-19 07:49:47 +00007036 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007037 if (ReturnType.isNull()) {
7038 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7039 Builder.AddTextChunk("void");
7040 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7041 }
7042
7043 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7044 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7045 Builder.AddPlaceholderChunk("object-type");
7046 Builder.AddTextChunk(" **");
7047 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7048 Builder.AddTextChunk("buffer");
7049 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7050 Builder.AddTypedTextChunk("range:");
7051 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7052 Builder.AddTextChunk("NSRange");
7053 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7054 Builder.AddTextChunk("inRange");
7055 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
7056 CXCursor_ObjCInstanceMethodDecl));
7057 }
7058 }
7059
7060 // Mutable indexed accessors
7061
7062 // - (void)insertObject:(type *)object inKeyAtIndex:(NSUInteger)index
7063 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007064 std::string SelectorName = (Twine("in") + UpperKey + "AtIndex").str();
Douglas Gregor669a25a2011-02-17 00:22:45 +00007065 IdentifierInfo *SelectorIds[2] = {
7066 &Context.Idents.get("insertObject"),
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007067 &Context.Idents.get(SelectorName)
Douglas Gregor669a25a2011-02-17 00:22:45 +00007068 };
7069
David Blaikie82e95a32014-11-19 07:49:47 +00007070 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007071 if (ReturnType.isNull()) {
7072 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7073 Builder.AddTextChunk("void");
7074 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7075 }
7076
7077 Builder.AddTypedTextChunk("insertObject:");
7078 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7079 Builder.AddPlaceholderChunk("object-type");
7080 Builder.AddTextChunk(" *");
7081 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7082 Builder.AddTextChunk("object");
7083 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7084 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7085 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7086 Builder.AddPlaceholderChunk("NSUInteger");
7087 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7088 Builder.AddTextChunk("index");
7089 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
7090 CXCursor_ObjCInstanceMethodDecl));
7091 }
7092 }
7093
7094 // - (void)insertKey:(NSArray *)array atIndexes:(NSIndexSet *)indexes
7095 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007096 std::string SelectorName = (Twine("insert") + UpperKey).str();
Douglas Gregor669a25a2011-02-17 00:22:45 +00007097 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007098 &Context.Idents.get(SelectorName),
Douglas Gregor669a25a2011-02-17 00:22:45 +00007099 &Context.Idents.get("atIndexes")
7100 };
7101
David Blaikie82e95a32014-11-19 07:49:47 +00007102 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007103 if (ReturnType.isNull()) {
7104 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7105 Builder.AddTextChunk("void");
7106 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7107 }
7108
7109 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7110 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7111 Builder.AddTextChunk("NSArray *");
7112 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7113 Builder.AddTextChunk("array");
7114 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7115 Builder.AddTypedTextChunk("atIndexes:");
7116 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7117 Builder.AddPlaceholderChunk("NSIndexSet *");
7118 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7119 Builder.AddTextChunk("indexes");
7120 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
7121 CXCursor_ObjCInstanceMethodDecl));
7122 }
7123 }
7124
7125 // -(void)removeObjectFromKeyAtIndex:(NSUInteger)index
7126 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007127 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007128 = (Twine("removeObjectFrom") + UpperKey + "AtIndex").str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007129 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007130 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007131 if (ReturnType.isNull()) {
7132 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7133 Builder.AddTextChunk("void");
7134 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7135 }
7136
7137 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7138 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7139 Builder.AddTextChunk("NSUInteger");
7140 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7141 Builder.AddTextChunk("index");
7142 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
7143 CXCursor_ObjCInstanceMethodDecl));
7144 }
7145 }
7146
7147 // -(void)removeKeyAtIndexes:(NSIndexSet *)indexes
7148 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007149 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007150 = (Twine("remove") + UpperKey + "AtIndexes").str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007151 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007152 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007153 if (ReturnType.isNull()) {
7154 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7155 Builder.AddTextChunk("void");
7156 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7157 }
7158
7159 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7160 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7161 Builder.AddTextChunk("NSIndexSet *");
7162 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7163 Builder.AddTextChunk("indexes");
7164 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
7165 CXCursor_ObjCInstanceMethodDecl));
7166 }
7167 }
7168
7169 // - (void)replaceObjectInKeyAtIndex:(NSUInteger)index withObject:(id)object
7170 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007171 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007172 = (Twine("replaceObjectIn") + UpperKey + "AtIndex").str();
Douglas Gregor669a25a2011-02-17 00:22:45 +00007173 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007174 &Context.Idents.get(SelectorName),
Douglas Gregor669a25a2011-02-17 00:22:45 +00007175 &Context.Idents.get("withObject")
7176 };
7177
David Blaikie82e95a32014-11-19 07:49:47 +00007178 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007179 if (ReturnType.isNull()) {
7180 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7181 Builder.AddTextChunk("void");
7182 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7183 }
7184
7185 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7186 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7187 Builder.AddPlaceholderChunk("NSUInteger");
7188 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7189 Builder.AddTextChunk("index");
7190 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7191 Builder.AddTypedTextChunk("withObject:");
7192 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7193 Builder.AddTextChunk("id");
7194 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7195 Builder.AddTextChunk("object");
7196 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
7197 CXCursor_ObjCInstanceMethodDecl));
7198 }
7199 }
7200
7201 // - (void)replaceKeyAtIndexes:(NSIndexSet *)indexes withKey:(NSArray *)array
7202 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007203 std::string SelectorName1
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007204 = (Twine("replace") + UpperKey + "AtIndexes").str();
7205 std::string SelectorName2 = (Twine("with") + UpperKey).str();
Douglas Gregor669a25a2011-02-17 00:22:45 +00007206 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007207 &Context.Idents.get(SelectorName1),
7208 &Context.Idents.get(SelectorName2)
Douglas Gregor669a25a2011-02-17 00:22:45 +00007209 };
7210
David Blaikie82e95a32014-11-19 07:49:47 +00007211 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007212 if (ReturnType.isNull()) {
7213 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7214 Builder.AddTextChunk("void");
7215 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7216 }
7217
7218 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName1 + ":"));
7219 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7220 Builder.AddPlaceholderChunk("NSIndexSet *");
7221 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7222 Builder.AddTextChunk("indexes");
7223 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7224 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName2 + ":"));
7225 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7226 Builder.AddTextChunk("NSArray *");
7227 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7228 Builder.AddTextChunk("array");
7229 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
7230 CXCursor_ObjCInstanceMethodDecl));
7231 }
7232 }
7233
7234 // Unordered getters
7235 // - (NSEnumerator *)enumeratorOfKey
7236 if (IsInstanceMethod &&
7237 (ReturnType.isNull() ||
7238 (ReturnType->isObjCObjectPointerType() &&
7239 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
7240 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
7241 ->getName() == "NSEnumerator"))) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007242 std::string SelectorName = (Twine("enumeratorOf") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007243 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007244 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
7245 .second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007246 if (ReturnType.isNull()) {
7247 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7248 Builder.AddTextChunk("NSEnumerator *");
7249 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7250 }
7251
7252 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
7253 Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
7254 CXCursor_ObjCInstanceMethodDecl));
7255 }
7256 }
7257
7258 // - (type *)memberOfKey:(type *)object
7259 if (IsInstanceMethod &&
7260 (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007261 std::string SelectorName = (Twine("memberOf") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007262 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007263 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007264 if (ReturnType.isNull()) {
7265 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7266 Builder.AddPlaceholderChunk("object-type");
7267 Builder.AddTextChunk(" *");
7268 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7269 }
7270
7271 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7272 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7273 if (ReturnType.isNull()) {
7274 Builder.AddPlaceholderChunk("object-type");
7275 Builder.AddTextChunk(" *");
7276 } else {
7277 Builder.AddTextChunk(GetCompletionTypeString(ReturnType, Context,
Douglas Gregor75acd922011-09-27 23:30:47 +00007278 Policy,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007279 Builder.getAllocator()));
7280 }
7281 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7282 Builder.AddTextChunk("object");
7283 Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
7284 CXCursor_ObjCInstanceMethodDecl));
7285 }
7286 }
7287
7288 // Mutable unordered accessors
7289 // - (void)addKeyObject:(type *)object
7290 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007291 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007292 = (Twine("add") + UpperKey + Twine("Object")).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007293 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007294 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007295 if (ReturnType.isNull()) {
7296 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7297 Builder.AddTextChunk("void");
7298 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7299 }
7300
7301 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7302 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7303 Builder.AddPlaceholderChunk("object-type");
7304 Builder.AddTextChunk(" *");
7305 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7306 Builder.AddTextChunk("object");
7307 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
7308 CXCursor_ObjCInstanceMethodDecl));
7309 }
7310 }
7311
7312 // - (void)addKey:(NSSet *)objects
7313 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007314 std::string SelectorName = (Twine("add") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007315 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007316 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007317 if (ReturnType.isNull()) {
7318 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7319 Builder.AddTextChunk("void");
7320 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7321 }
7322
7323 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7324 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7325 Builder.AddTextChunk("NSSet *");
7326 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7327 Builder.AddTextChunk("objects");
7328 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
7329 CXCursor_ObjCInstanceMethodDecl));
7330 }
7331 }
7332
7333 // - (void)removeKeyObject:(type *)object
7334 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007335 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007336 = (Twine("remove") + UpperKey + Twine("Object")).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007337 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007338 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007339 if (ReturnType.isNull()) {
7340 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7341 Builder.AddTextChunk("void");
7342 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7343 }
7344
7345 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7346 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7347 Builder.AddPlaceholderChunk("object-type");
7348 Builder.AddTextChunk(" *");
7349 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7350 Builder.AddTextChunk("object");
7351 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
7352 CXCursor_ObjCInstanceMethodDecl));
7353 }
7354 }
7355
7356 // - (void)removeKey:(NSSet *)objects
7357 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007358 std::string SelectorName = (Twine("remove") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007359 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007360 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007361 if (ReturnType.isNull()) {
7362 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7363 Builder.AddTextChunk("void");
7364 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7365 }
7366
7367 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7368 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7369 Builder.AddTextChunk("NSSet *");
7370 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7371 Builder.AddTextChunk("objects");
7372 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
7373 CXCursor_ObjCInstanceMethodDecl));
7374 }
7375 }
7376
7377 // - (void)intersectKey:(NSSet *)objects
7378 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007379 std::string SelectorName = (Twine("intersect") + UpperKey).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.AddTextChunk("NSSet *");
7391 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7392 Builder.AddTextChunk("objects");
7393 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
7394 CXCursor_ObjCInstanceMethodDecl));
7395 }
7396 }
7397
7398 // Key-Value Observing
7399 // + (NSSet *)keyPathsForValuesAffectingKey
7400 if (!IsInstanceMethod &&
7401 (ReturnType.isNull() ||
7402 (ReturnType->isObjCObjectPointerType() &&
7403 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
7404 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
7405 ->getName() == "NSSet"))) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007406 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007407 = (Twine("keyPathsForValuesAffecting") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007408 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007409 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
7410 .second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007411 if (ReturnType.isNull()) {
7412 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Alex Lorenz71ecb072016-12-08 16:49:05 +00007413 Builder.AddTextChunk("NSSet<NSString *> *");
Douglas Gregor669a25a2011-02-17 00:22:45 +00007414 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7415 }
7416
7417 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
7418 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Douglas Gregor857bcda2011-06-02 04:02:27 +00007419 CXCursor_ObjCClassMethodDecl));
7420 }
7421 }
7422
7423 // + (BOOL)automaticallyNotifiesObserversForKey
7424 if (!IsInstanceMethod &&
7425 (ReturnType.isNull() ||
7426 ReturnType->isIntegerType() ||
7427 ReturnType->isBooleanType())) {
7428 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007429 = (Twine("automaticallyNotifiesObserversOf") + UpperKey).str();
Douglas Gregor857bcda2011-06-02 04:02:27 +00007430 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007431 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
7432 .second) {
Douglas Gregor857bcda2011-06-02 04:02:27 +00007433 if (ReturnType.isNull()) {
7434 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7435 Builder.AddTextChunk("BOOL");
7436 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7437 }
7438
7439 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
7440 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
7441 CXCursor_ObjCClassMethodDecl));
Douglas Gregor669a25a2011-02-17 00:22:45 +00007442 }
7443 }
7444}
7445
Alex Lorenzb8740422017-10-24 16:39:37 +00007446void Sema::CodeCompleteObjCMethodDecl(Scope *S, Optional<bool> IsInstanceMethod,
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00007447 ParsedType ReturnTy) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00007448 // Determine the return type of the method we're declaring, if
7449 // provided.
7450 QualType ReturnType = GetTypeFromParser(ReturnTy);
Craig Topperc3ec1492014-05-26 06:22:03 +00007451 Decl *IDecl = nullptr;
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00007452 if (CurContext->isObjCContainer()) {
7453 ObjCContainerDecl *OCD = dyn_cast<ObjCContainerDecl>(CurContext);
George Burgess IV00f70bd2018-03-01 05:43:23 +00007454 IDecl = OCD;
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00007455 }
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007456 // Determine where we should start searching for methods.
Craig Topperc3ec1492014-05-26 06:22:03 +00007457 ObjCContainerDecl *SearchDecl = nullptr;
Douglas Gregor636a61e2010-04-07 00:21:17 +00007458 bool IsInImplementation = false;
John McCall48871652010-08-21 09:40:31 +00007459 if (Decl *D = IDecl) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00007460 if (ObjCImplementationDecl *Impl = dyn_cast<ObjCImplementationDecl>(D)) {
7461 SearchDecl = Impl->getClassInterface();
Douglas Gregor636a61e2010-04-07 00:21:17 +00007462 IsInImplementation = true;
7463 } else if (ObjCCategoryImplDecl *CatImpl
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007464 = dyn_cast<ObjCCategoryImplDecl>(D)) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00007465 SearchDecl = CatImpl->getCategoryDecl();
Douglas Gregor636a61e2010-04-07 00:21:17 +00007466 IsInImplementation = true;
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007467 } else
Douglas Gregor636a61e2010-04-07 00:21:17 +00007468 SearchDecl = dyn_cast<ObjCContainerDecl>(D);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007469 }
7470
7471 if (!SearchDecl && S) {
Ted Kremenekc37877d2013-10-08 17:08:03 +00007472 if (DeclContext *DC = S->getEntity())
Douglas Gregor636a61e2010-04-07 00:21:17 +00007473 SearchDecl = dyn_cast<ObjCContainerDecl>(DC);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007474 }
7475
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007476 if (!SearchDecl) {
Douglas Gregor00c37ef2010-08-11 21:23:17 +00007477 HandleCodeCompleteResults(this, CodeCompleter,
7478 CodeCompletionContext::CCC_Other,
Craig Topperc3ec1492014-05-26 06:22:03 +00007479 nullptr, 0);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007480 return;
7481 }
7482
7483 // Find all of the methods that we could declare/implement here.
7484 KnownMethodsMap KnownMethods;
7485 FindImplementableMethods(Context, SearchDecl, IsInstanceMethod,
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007486 ReturnType, KnownMethods);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007487
Douglas Gregor636a61e2010-04-07 00:21:17 +00007488 // Add declarations or definitions for each of the known methods.
John McCall276321a2010-08-25 06:19:51 +00007489 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007490 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007491 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007492 CodeCompletionContext::CCC_Other);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007493 Results.EnterNewScope();
Douglas Gregor75acd922011-09-27 23:30:47 +00007494 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007495 for (KnownMethodsMap::iterator M = KnownMethods.begin(),
7496 MEnd = KnownMethods.end();
7497 M != MEnd; ++M) {
Benjamin Kramereb8c4462013-06-29 17:52:13 +00007498 ObjCMethodDecl *Method = M->second.getPointer();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007499 CodeCompletionBuilder Builder(Results.getAllocator(),
7500 Results.getCodeCompletionTUInfo());
Alex Lorenzb8740422017-10-24 16:39:37 +00007501
7502 // Add the '-'/'+' prefix if it wasn't provided yet.
7503 if (!IsInstanceMethod) {
7504 Builder.AddTextChunk(Method->isInstanceMethod() ? "-" : "+");
7505 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7506 }
7507
Douglas Gregor636a61e2010-04-07 00:21:17 +00007508 // If the result type was not already provided, add it to the
7509 // pattern as (type).
Argyrios Kyrtzidisf0917ab2015-07-24 17:00:19 +00007510 if (ReturnType.isNull()) {
7511 QualType ResTy = Method->getSendResultType().stripObjCKindOfType(Context);
7512 AttributedType::stripOuterNullability(ResTy);
7513 AddObjCPassingTypeChunk(ResTy,
Alp Toker314cc812014-01-25 16:55:45 +00007514 Method->getObjCDeclQualifier(), Context, Policy,
7515 Builder);
Argyrios Kyrtzidisf0917ab2015-07-24 17:00:19 +00007516 }
Douglas Gregor636a61e2010-04-07 00:21:17 +00007517
7518 Selector Sel = Method->getSelector();
7519
7520 // Add the first part of the selector to the pattern.
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00007521 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00007522 Sel.getNameForSlot(0)));
Douglas Gregor636a61e2010-04-07 00:21:17 +00007523
7524 // Add parameters to the pattern.
7525 unsigned I = 0;
7526 for (ObjCMethodDecl::param_iterator P = Method->param_begin(),
7527 PEnd = Method->param_end();
7528 P != PEnd; (void)++P, ++I) {
7529 // Add the part of the selector name.
7530 if (I == 0)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007531 Builder.AddTypedTextChunk(":");
Douglas Gregor636a61e2010-04-07 00:21:17 +00007532 else if (I < Sel.getNumArgs()) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007533 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7534 Builder.AddTypedTextChunk(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00007535 Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":"));
Douglas Gregor636a61e2010-04-07 00:21:17 +00007536 } else
7537 break;
7538
7539 // Add the parameter type.
Douglas Gregor86b42682015-06-19 18:27:52 +00007540 QualType ParamType;
7541 if ((*P)->getObjCDeclQualifier() & Decl::OBJC_TQ_CSNullability)
7542 ParamType = (*P)->getType();
7543 else
7544 ParamType = (*P)->getOriginalType();
Douglas Gregor9b7b3e92015-07-07 06:20:27 +00007545 ParamType = ParamType.substObjCTypeArgs(Context, {},
7546 ObjCSubstitutionContext::Parameter);
Argyrios Kyrtzidisf0917ab2015-07-24 17:00:19 +00007547 AttributedType::stripOuterNullability(ParamType);
Douglas Gregor86b42682015-06-19 18:27:52 +00007548 AddObjCPassingTypeChunk(ParamType,
Douglas Gregor29979142012-04-10 18:35:07 +00007549 (*P)->getObjCDeclQualifier(),
7550 Context, Policy,
Douglas Gregor75acd922011-09-27 23:30:47 +00007551 Builder);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007552
7553 if (IdentifierInfo *Id = (*P)->getIdentifier())
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00007554 Builder.AddTextChunk(Builder.getAllocator().CopyString( Id->getName()));
Douglas Gregor636a61e2010-04-07 00:21:17 +00007555 }
7556
7557 if (Method->isVariadic()) {
7558 if (Method->param_size() > 0)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007559 Builder.AddChunk(CodeCompletionString::CK_Comma);
7560 Builder.AddTextChunk("...");
Douglas Gregor400f5972010-08-31 05:13:43 +00007561 }
Douglas Gregor636a61e2010-04-07 00:21:17 +00007562
Douglas Gregord37c59d2010-05-28 00:57:46 +00007563 if (IsInImplementation && Results.includeCodePatterns()) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00007564 // We will be defining the method here, so add a compound statement.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007565 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7566 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
7567 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
Alp Toker314cc812014-01-25 16:55:45 +00007568 if (!Method->getReturnType()->isVoidType()) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00007569 // If the result type is not void, add a return clause.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007570 Builder.AddTextChunk("return");
7571 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7572 Builder.AddPlaceholderChunk("expression");
7573 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007574 } else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007575 Builder.AddPlaceholderChunk("statements");
Douglas Gregor636a61e2010-04-07 00:21:17 +00007576
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007577 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
7578 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007579 }
7580
Douglas Gregor416b5752010-08-25 01:08:01 +00007581 unsigned Priority = CCP_CodePattern;
Benjamin Kramereb8c4462013-06-29 17:52:13 +00007582 if (!M->second.getInt())
Douglas Gregor416b5752010-08-25 01:08:01 +00007583 Priority += CCD_InBaseClass;
7584
Douglas Gregor78254c82012-03-27 23:34:16 +00007585 Results.AddResult(Result(Builder.TakeString(), Method, Priority));
Douglas Gregor636a61e2010-04-07 00:21:17 +00007586 }
7587
Douglas Gregor669a25a2011-02-17 00:22:45 +00007588 // Add Key-Value-Coding and Key-Value-Observing accessor methods for all of
7589 // the properties in this class and its categories.
David Blaikiebbafb8a2012-03-11 07:00:24 +00007590 if (Context.getLangOpts().ObjC2) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007591 SmallVector<ObjCContainerDecl *, 4> Containers;
Douglas Gregor669a25a2011-02-17 00:22:45 +00007592 Containers.push_back(SearchDecl);
7593
Douglas Gregord4a8ced2011-05-04 23:50:46 +00007594 VisitedSelectorSet KnownSelectors;
7595 for (KnownMethodsMap::iterator M = KnownMethods.begin(),
7596 MEnd = KnownMethods.end();
7597 M != MEnd; ++M)
7598 KnownSelectors.insert(M->first);
7599
7600
Douglas Gregor669a25a2011-02-17 00:22:45 +00007601 ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(SearchDecl);
7602 if (!IFace)
7603 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(SearchDecl))
7604 IFace = Category->getClassInterface();
7605
Aaron Ballman3fe486a2014-03-13 21:23:55 +00007606 if (IFace)
7607 for (auto *Cat : IFace->visible_categories())
7608 Containers.push_back(Cat);
Alex Lorenzb8740422017-10-24 16:39:37 +00007609
7610 if (IsInstanceMethod) {
7611 for (unsigned I = 0, N = Containers.size(); I != N; ++I)
7612 for (auto *P : Containers[I]->instance_properties())
7613 AddObjCKeyValueCompletions(P, *IsInstanceMethod, ReturnType, Context,
7614 KnownSelectors, Results);
7615 }
Douglas Gregor669a25a2011-02-17 00:22:45 +00007616 }
7617
Douglas Gregor636a61e2010-04-07 00:21:17 +00007618 Results.ExitScope();
7619
Douglas Gregor00c37ef2010-08-11 21:23:17 +00007620 HandleCodeCompleteResults(this, CodeCompleter,
7621 CodeCompletionContext::CCC_Other,
7622 Results.data(),Results.size());
Douglas Gregor636a61e2010-04-07 00:21:17 +00007623}
Douglas Gregor95887f92010-07-08 23:20:03 +00007624
7625void Sema::CodeCompleteObjCMethodDeclSelector(Scope *S,
7626 bool IsInstanceMethod,
Douglas Gregor45879692010-07-08 23:37:41 +00007627 bool AtParameterName,
John McCallba7bf592010-08-24 05:47:05 +00007628 ParsedType ReturnTy,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00007629 ArrayRef<IdentifierInfo *> SelIdents) {
Douglas Gregor95887f92010-07-08 23:20:03 +00007630 // If we have an external source, load the entire class method
Sebastian Redld44cd6a2010-08-18 23:57:06 +00007631 // pool from the AST file.
Douglas Gregor95887f92010-07-08 23:20:03 +00007632 if (ExternalSource) {
7633 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
7634 I != N; ++I) {
7635 Selector Sel = ExternalSource->GetExternalSelector(I);
Sebastian Redl75d8a322010-08-02 23:18:59 +00007636 if (Sel.isNull() || MethodPool.count(Sel))
Douglas Gregor95887f92010-07-08 23:20:03 +00007637 continue;
Sebastian Redl75d8a322010-08-02 23:18:59 +00007638
7639 ReadMethodPool(Sel);
Douglas Gregor95887f92010-07-08 23:20:03 +00007640 }
7641 }
7642
7643 // Build the set of methods we can see.
John McCall276321a2010-08-25 06:19:51 +00007644 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007645 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007646 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007647 CodeCompletionContext::CCC_Other);
Douglas Gregor95887f92010-07-08 23:20:03 +00007648
7649 if (ReturnTy)
7650 Results.setPreferredType(GetTypeFromParser(ReturnTy).getNonReferenceType());
Sebastian Redl75d8a322010-08-02 23:18:59 +00007651
Douglas Gregor95887f92010-07-08 23:20:03 +00007652 Results.EnterNewScope();
Sebastian Redl75d8a322010-08-02 23:18:59 +00007653 for (GlobalMethodPool::iterator M = MethodPool.begin(),
7654 MEnd = MethodPool.end();
7655 M != MEnd; ++M) {
7656 for (ObjCMethodList *MethList = IsInstanceMethod ? &M->second.first :
7657 &M->second.second;
Nico Weber2e0c8f72014-12-27 03:58:08 +00007658 MethList && MethList->getMethod();
Argyrios Kyrtzidisd3da6e02013-04-17 00:08:58 +00007659 MethList = MethList->getNext()) {
Nico Weber2e0c8f72014-12-27 03:58:08 +00007660 if (!isAcceptableObjCMethod(MethList->getMethod(), MK_Any, SelIdents))
Douglas Gregor95887f92010-07-08 23:20:03 +00007661 continue;
7662
Douglas Gregor45879692010-07-08 23:37:41 +00007663 if (AtParameterName) {
7664 // Suggest parameter names we've seen before.
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00007665 unsigned NumSelIdents = SelIdents.size();
Nico Weber2e0c8f72014-12-27 03:58:08 +00007666 if (NumSelIdents &&
7667 NumSelIdents <= MethList->getMethod()->param_size()) {
7668 ParmVarDecl *Param =
7669 MethList->getMethod()->parameters()[NumSelIdents - 1];
Douglas Gregor45879692010-07-08 23:37:41 +00007670 if (Param->getIdentifier()) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007671 CodeCompletionBuilder Builder(Results.getAllocator(),
7672 Results.getCodeCompletionTUInfo());
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00007673 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007674 Param->getIdentifier()->getName()));
7675 Results.AddResult(Builder.TakeString());
Douglas Gregor45879692010-07-08 23:37:41 +00007676 }
7677 }
7678
7679 continue;
7680 }
Craig Topperc3ec1492014-05-26 06:22:03 +00007681
Nico Weber2e0c8f72014-12-27 03:58:08 +00007682 Result R(MethList->getMethod(),
7683 Results.getBasePriority(MethList->getMethod()), nullptr);
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00007684 R.StartParameter = SelIdents.size();
Douglas Gregor95887f92010-07-08 23:20:03 +00007685 R.AllParametersAreInformative = false;
7686 R.DeclaringEntity = true;
7687 Results.MaybeAddResult(R, CurContext);
7688 }
7689 }
7690
7691 Results.ExitScope();
Alex Lorenz847fda12017-01-03 11:56:40 +00007692
7693 if (!AtParameterName && !SelIdents.empty() &&
7694 SelIdents.front()->getName().startswith("init")) {
7695 for (const auto &M : PP.macros()) {
7696 if (M.first->getName() != "NS_DESIGNATED_INITIALIZER")
7697 continue;
7698 Results.EnterNewScope();
7699 CodeCompletionBuilder Builder(Results.getAllocator(),
7700 Results.getCodeCompletionTUInfo());
7701 Builder.AddTypedTextChunk(
7702 Builder.getAllocator().CopyString(M.first->getName()));
7703 Results.AddResult(CodeCompletionResult(Builder.TakeString(), CCP_Macro,
7704 CXCursor_MacroDefinition));
7705 Results.ExitScope();
7706 }
7707 }
7708
Douglas Gregor00c37ef2010-08-11 21:23:17 +00007709 HandleCodeCompleteResults(this, CodeCompleter,
7710 CodeCompletionContext::CCC_Other,
7711 Results.data(),Results.size());
Douglas Gregor95887f92010-07-08 23:20:03 +00007712}
Douglas Gregorb14904c2010-08-13 22:48:40 +00007713
Douglas Gregorec00a262010-08-24 22:20:20 +00007714void Sema::CodeCompletePreprocessorDirective(bool InConditional) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007715 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007716 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00007717 CodeCompletionContext::CCC_PreprocessorDirective);
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007718 Results.EnterNewScope();
7719
7720 // #if <condition>
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007721 CodeCompletionBuilder Builder(Results.getAllocator(),
7722 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007723 Builder.AddTypedTextChunk("if");
7724 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7725 Builder.AddPlaceholderChunk("condition");
7726 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007727
7728 // #ifdef <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007729 Builder.AddTypedTextChunk("ifdef");
7730 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7731 Builder.AddPlaceholderChunk("macro");
7732 Results.AddResult(Builder.TakeString());
7733
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007734 // #ifndef <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007735 Builder.AddTypedTextChunk("ifndef");
7736 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7737 Builder.AddPlaceholderChunk("macro");
7738 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007739
7740 if (InConditional) {
7741 // #elif <condition>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007742 Builder.AddTypedTextChunk("elif");
7743 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7744 Builder.AddPlaceholderChunk("condition");
7745 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007746
7747 // #else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007748 Builder.AddTypedTextChunk("else");
7749 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007750
7751 // #endif
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007752 Builder.AddTypedTextChunk("endif");
7753 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007754 }
7755
7756 // #include "header"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007757 Builder.AddTypedTextChunk("include");
7758 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7759 Builder.AddTextChunk("\"");
7760 Builder.AddPlaceholderChunk("header");
7761 Builder.AddTextChunk("\"");
7762 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007763
7764 // #include <header>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007765 Builder.AddTypedTextChunk("include");
7766 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7767 Builder.AddTextChunk("<");
7768 Builder.AddPlaceholderChunk("header");
7769 Builder.AddTextChunk(">");
7770 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007771
7772 // #define <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007773 Builder.AddTypedTextChunk("define");
7774 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7775 Builder.AddPlaceholderChunk("macro");
7776 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007777
7778 // #define <macro>(<args>)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007779 Builder.AddTypedTextChunk("define");
7780 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7781 Builder.AddPlaceholderChunk("macro");
7782 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7783 Builder.AddPlaceholderChunk("args");
7784 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7785 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007786
7787 // #undef <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007788 Builder.AddTypedTextChunk("undef");
7789 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7790 Builder.AddPlaceholderChunk("macro");
7791 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007792
7793 // #line <number>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007794 Builder.AddTypedTextChunk("line");
7795 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7796 Builder.AddPlaceholderChunk("number");
7797 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007798
7799 // #line <number> "filename"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007800 Builder.AddTypedTextChunk("line");
7801 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7802 Builder.AddPlaceholderChunk("number");
7803 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7804 Builder.AddTextChunk("\"");
7805 Builder.AddPlaceholderChunk("filename");
7806 Builder.AddTextChunk("\"");
7807 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007808
7809 // #error <message>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007810 Builder.AddTypedTextChunk("error");
7811 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7812 Builder.AddPlaceholderChunk("message");
7813 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007814
7815 // #pragma <arguments>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007816 Builder.AddTypedTextChunk("pragma");
7817 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7818 Builder.AddPlaceholderChunk("arguments");
7819 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007820
David Blaikiebbafb8a2012-03-11 07:00:24 +00007821 if (getLangOpts().ObjC1) {
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007822 // #import "header"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007823 Builder.AddTypedTextChunk("import");
7824 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7825 Builder.AddTextChunk("\"");
7826 Builder.AddPlaceholderChunk("header");
7827 Builder.AddTextChunk("\"");
7828 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007829
7830 // #import <header>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007831 Builder.AddTypedTextChunk("import");
7832 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7833 Builder.AddTextChunk("<");
7834 Builder.AddPlaceholderChunk("header");
7835 Builder.AddTextChunk(">");
7836 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007837 }
7838
7839 // #include_next "header"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007840 Builder.AddTypedTextChunk("include_next");
7841 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7842 Builder.AddTextChunk("\"");
7843 Builder.AddPlaceholderChunk("header");
7844 Builder.AddTextChunk("\"");
7845 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007846
7847 // #include_next <header>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007848 Builder.AddTypedTextChunk("include_next");
7849 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7850 Builder.AddTextChunk("<");
7851 Builder.AddPlaceholderChunk("header");
7852 Builder.AddTextChunk(">");
7853 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007854
7855 // #warning <message>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007856 Builder.AddTypedTextChunk("warning");
7857 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7858 Builder.AddPlaceholderChunk("message");
7859 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007860
7861 // Note: #ident and #sccs are such crazy anachronisms that we don't provide
7862 // completions for them. And __include_macros is a Clang-internal extension
7863 // that we don't want to encourage anyone to use.
7864
7865 // FIXME: we don't support #assert or #unassert, so don't suggest them.
7866 Results.ExitScope();
7867
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007868 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0de55ce2010-08-25 18:41:16 +00007869 CodeCompletionContext::CCC_PreprocessorDirective,
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007870 Results.data(), Results.size());
7871}
7872
7873void Sema::CodeCompleteInPreprocessorConditionalExclusion(Scope *S) {
Douglas Gregorec00a262010-08-24 22:20:20 +00007874 CodeCompleteOrdinaryName(S,
John McCallfaf5fb42010-08-26 23:41:50 +00007875 S->getFnParent()? Sema::PCC_RecoveryInFunction
7876 : Sema::PCC_Namespace);
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007877}
7878
Douglas Gregorec00a262010-08-24 22:20:20 +00007879void Sema::CodeCompletePreprocessorMacroName(bool IsDefinition) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007880 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007881 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00007882 IsDefinition? CodeCompletionContext::CCC_MacroName
7883 : CodeCompletionContext::CCC_MacroNameUse);
Douglas Gregor12785102010-08-24 20:21:13 +00007884 if (!IsDefinition && (!CodeCompleter || CodeCompleter->includeMacros())) {
7885 // Add just the names of macros, not their arguments.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007886 CodeCompletionBuilder Builder(Results.getAllocator(),
7887 Results.getCodeCompletionTUInfo());
Douglas Gregor12785102010-08-24 20:21:13 +00007888 Results.EnterNewScope();
7889 for (Preprocessor::macro_iterator M = PP.macro_begin(),
7890 MEnd = PP.macro_end();
7891 M != MEnd; ++M) {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00007892 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007893 M->first->getName()));
Argyrios Kyrtzidis5c8b1cd2012-09-27 00:24:09 +00007894 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
7895 CCP_CodePattern,
7896 CXCursor_MacroDefinition));
Douglas Gregor12785102010-08-24 20:21:13 +00007897 }
7898 Results.ExitScope();
7899 } else if (IsDefinition) {
7900 // FIXME: Can we detect when the user just wrote an include guard above?
7901 }
7902
Douglas Gregor0ac41382010-09-23 23:01:17 +00007903 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor12785102010-08-24 20:21:13 +00007904 Results.data(), Results.size());
7905}
7906
Douglas Gregorec00a262010-08-24 22:20:20 +00007907void Sema::CodeCompletePreprocessorExpression() {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007908 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007909 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00007910 CodeCompletionContext::CCC_PreprocessorExpression);
Douglas Gregorec00a262010-08-24 22:20:20 +00007911
7912 if (!CodeCompleter || CodeCompleter->includeMacros())
Douglas Gregor8cb17462012-10-09 16:01:50 +00007913 AddMacroResults(PP, Results, true);
Douglas Gregorec00a262010-08-24 22:20:20 +00007914
7915 // defined (<macro>)
7916 Results.EnterNewScope();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007917 CodeCompletionBuilder Builder(Results.getAllocator(),
7918 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007919 Builder.AddTypedTextChunk("defined");
7920 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7921 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7922 Builder.AddPlaceholderChunk("macro");
7923 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7924 Results.AddResult(Builder.TakeString());
Douglas Gregorec00a262010-08-24 22:20:20 +00007925 Results.ExitScope();
7926
7927 HandleCodeCompleteResults(this, CodeCompleter,
7928 CodeCompletionContext::CCC_PreprocessorExpression,
7929 Results.data(), Results.size());
7930}
7931
7932void Sema::CodeCompletePreprocessorMacroArgument(Scope *S,
7933 IdentifierInfo *Macro,
7934 MacroInfo *MacroInfo,
7935 unsigned Argument) {
7936 // FIXME: In the future, we could provide "overload" results, much like we
7937 // do for function calls.
7938
Argyrios Kyrtzidis75f6cd22011-08-18 19:41:28 +00007939 // Now just ignore this. There will be another code-completion callback
7940 // for the expanded tokens.
Douglas Gregorec00a262010-08-24 22:20:20 +00007941}
7942
Douglas Gregor11583702010-08-25 17:04:25 +00007943void Sema::CodeCompleteNaturalLanguage() {
Douglas Gregor11583702010-08-25 17:04:25 +00007944 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregorea736372010-08-25 17:10:00 +00007945 CodeCompletionContext::CCC_NaturalLanguage,
Craig Topperc3ec1492014-05-26 06:22:03 +00007946 nullptr, 0);
Douglas Gregor11583702010-08-25 17:04:25 +00007947}
7948
Alex Lorenzf7f6f822017-05-09 16:05:04 +00007949void Sema::CodeCompleteAvailabilityPlatformName() {
7950 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
7951 CodeCompleter->getCodeCompletionTUInfo(),
7952 CodeCompletionContext::CCC_Other);
7953 Results.EnterNewScope();
7954 static const char *Platforms[] = {"macOS", "iOS", "watchOS", "tvOS"};
7955 for (const char *Platform : llvm::makeArrayRef(Platforms)) {
7956 Results.AddResult(CodeCompletionResult(Platform));
7957 Results.AddResult(CodeCompletionResult(Results.getAllocator().CopyString(
7958 Twine(Platform) + "ApplicationExtension")));
7959 }
7960 Results.ExitScope();
7961 HandleCodeCompleteResults(this, CodeCompleter,
7962 CodeCompletionContext::CCC_Other, Results.data(),
7963 Results.size());
7964}
7965
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00007966void Sema::GatherGlobalCodeCompletions(CodeCompletionAllocator &Allocator,
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007967 CodeCompletionTUInfo &CCTUInfo,
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007968 SmallVectorImpl<CodeCompletionResult> &Results) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007969 ResultBuilder Builder(*this, Allocator, CCTUInfo,
7970 CodeCompletionContext::CCC_Recovery);
Douglas Gregor39982192010-08-15 06:18:01 +00007971 if (!CodeCompleter || CodeCompleter->includeGlobals()) {
7972 CodeCompletionDeclConsumer Consumer(Builder,
7973 Context.getTranslationUnitDecl());
Sam McCallbb2cf632018-01-12 14:51:47 +00007974 LookupVisibleDecls(Context.getTranslationUnitDecl(), LookupAnyName,
7975 Consumer,
7976 !CodeCompleter || CodeCompleter->loadExternal());
Douglas Gregor39982192010-08-15 06:18:01 +00007977 }
Douglas Gregorb14904c2010-08-13 22:48:40 +00007978
7979 if (!CodeCompleter || CodeCompleter->includeMacros())
Douglas Gregor8cb17462012-10-09 16:01:50 +00007980 AddMacroResults(PP, Builder, true);
Douglas Gregorb14904c2010-08-13 22:48:40 +00007981
7982 Results.clear();
7983 Results.insert(Results.end(),
7984 Builder.data(), Builder.data() + Builder.size());
7985}