blob: bdf538b9dcdd47f169226ca5e5c784ab612c3138 [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//===----------------------------------------------------------------------===//
Eric Liub91e0812018-10-02 10:29:00 +000013#include "clang/AST/Decl.h"
Ilya Biryukov4e7a6fe2017-09-22 19:07:37 +000014#include "clang/AST/DeclCXX.h"
John McCallde6836a2010-08-24 07:21:54 +000015#include "clang/AST/DeclObjC.h"
Douglas Gregorf2510672009-09-21 19:57:38 +000016#include "clang/AST/ExprCXX.h"
Douglas Gregor8ce33212009-11-17 17:59:40 +000017#include "clang/AST/ExprObjC.h"
Ilya Biryukovb5da91c2017-11-08 10:39:09 +000018#include "clang/AST/QualTypeNames.h"
Jordan Rose4938f272013-02-09 10:09:43 +000019#include "clang/Basic/CharInfo.h"
Douglas Gregor07f43572012-01-29 18:15:03 +000020#include "clang/Lex/HeaderSearch.h"
Douglas Gregorf329c7c2009-10-30 16:50:04 +000021#include "clang/Lex/MacroInfo.h"
22#include "clang/Lex/Preprocessor.h"
Chandler Carruth3a022472012-12-04 09:13:33 +000023#include "clang/Sema/CodeCompleteConsumer.h"
Chandler Carruth3a022472012-12-04 09:13:33 +000024#include "clang/Sema/Lookup.h"
25#include "clang/Sema/Overload.h"
26#include "clang/Sema/Scope.h"
27#include "clang/Sema/ScopeInfo.h"
Ilya Biryukov4e7a6fe2017-09-22 19:07:37 +000028#include "clang/Sema/SemaInternal.h"
Douglas Gregor1154e272010-09-16 16:06:31 +000029#include "llvm/ADT/DenseSet.h"
Benjamin Kramere0513cb2012-01-30 16:17:39 +000030#include "llvm/ADT/SmallBitVector.h"
Douglas Gregor3545ff42009-09-21 16:56:56 +000031#include "llvm/ADT/SmallPtrSet.h"
Benjamin Kramer49038022012-02-04 13:45:25 +000032#include "llvm/ADT/SmallString.h"
Douglas Gregore6688e62009-09-28 03:51:44 +000033#include "llvm/ADT/StringExtras.h"
Douglas Gregor9d2ddb22010-04-06 19:22:33 +000034#include "llvm/ADT/StringSwitch.h"
Douglas Gregor67c692c2010-08-26 15:07:07 +000035#include "llvm/ADT/Twine.h"
Sam McCall3d8051a2018-09-18 08:40:41 +000036#include "llvm/ADT/iterator_range.h"
37#include "llvm/Support/Path.h"
Douglas Gregor3545ff42009-09-21 16:56:56 +000038#include <list>
39#include <map>
40#include <vector>
Douglas Gregor2436e712009-09-17 21:32:03 +000041
42using namespace clang;
John McCallaab3e412010-08-25 08:40:02 +000043using namespace sema;
Douglas Gregor2436e712009-09-17 21:32:03 +000044
Douglas Gregor3545ff42009-09-21 16:56:56 +000045namespace {
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000046 /// A container of code-completion results.
Douglas Gregor3545ff42009-09-21 16:56:56 +000047 class ResultBuilder {
48 public:
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000049 /// The type of a name-lookup filter, which can be provided to the
Douglas Gregor3545ff42009-09-21 16:56:56 +000050 /// name-lookup routines to specify which declarations should be included in
51 /// the result set (when it returns true) and which declarations should be
52 /// filtered out (returns false).
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +000053 typedef bool (ResultBuilder::*LookupFilter)(const NamedDecl *) const;
Ivan Donchevskii13d90542017-10-27 11:05:40 +000054
John McCall276321a2010-08-25 06:19:51 +000055 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +000056
Douglas Gregor3545ff42009-09-21 16:56:56 +000057 private:
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000058 /// The actual results we have found.
Douglas Gregor3545ff42009-09-21 16:56:56 +000059 std::vector<Result> Results;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +000060
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000061 /// A record of all of the declarations we have found and placed
Douglas Gregor3545ff42009-09-21 16:56:56 +000062 /// into the result set, used to ensure that no declaration ever gets into
63 /// the result set twice.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +000064 llvm::SmallPtrSet<const Decl*, 16> AllDeclsFound;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +000065
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +000066 typedef std::pair<const NamedDecl *, unsigned> DeclIndexPair;
Douglas Gregor05e7ca32009-12-06 20:23:50 +000067
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000068 /// An entry in the shadow map, which is optimized to store
Douglas Gregor05e7ca32009-12-06 20:23:50 +000069 /// a single (declaration, index) mapping (the common case) but
70 /// can also store a list of (declaration, index) mappings.
71 class ShadowMapEntry {
Chris Lattner0e62c1c2011-07-23 10:55:15 +000072 typedef SmallVector<DeclIndexPair, 4> DeclIndexPairVector;
Douglas Gregor05e7ca32009-12-06 20:23:50 +000073
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000074 /// Contains either the solitary NamedDecl * or a vector
Douglas Gregor05e7ca32009-12-06 20:23:50 +000075 /// of (declaration, index) pairs.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +000076 llvm::PointerUnion<const NamedDecl *, DeclIndexPairVector*> DeclOrVector;
Douglas Gregor05e7ca32009-12-06 20:23:50 +000077
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000078 /// When the entry contains a single declaration, this is
Douglas Gregor05e7ca32009-12-06 20:23:50 +000079 /// the index associated with that entry.
80 unsigned SingleDeclIndex;
81
82 public:
83 ShadowMapEntry() : DeclOrVector(), SingleDeclIndex(0) { }
84
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +000085 void Add(const NamedDecl *ND, unsigned Index) {
Douglas Gregor05e7ca32009-12-06 20:23:50 +000086 if (DeclOrVector.isNull()) {
87 // 0 - > 1 elements: just set the single element information.
88 DeclOrVector = ND;
89 SingleDeclIndex = Index;
90 return;
91 }
92
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +000093 if (const NamedDecl *PrevND =
94 DeclOrVector.dyn_cast<const NamedDecl *>()) {
Douglas Gregor05e7ca32009-12-06 20:23:50 +000095 // 1 -> 2 elements: create the vector of results and push in the
96 // existing declaration.
97 DeclIndexPairVector *Vec = new DeclIndexPairVector;
98 Vec->push_back(DeclIndexPair(PrevND, SingleDeclIndex));
99 DeclOrVector = Vec;
100 }
101
102 // Add the new element to the end of the vector.
103 DeclOrVector.get<DeclIndexPairVector*>()->push_back(
104 DeclIndexPair(ND, Index));
105 }
106
107 void Destroy() {
108 if (DeclIndexPairVector *Vec
109 = DeclOrVector.dyn_cast<DeclIndexPairVector *>()) {
110 delete Vec;
Craig Topperc3ec1492014-05-26 06:22:03 +0000111 DeclOrVector = ((NamedDecl *)nullptr);
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000112 }
113 }
114
115 // Iteration.
116 class iterator;
117 iterator begin() const;
118 iterator end() const;
119 };
120
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000121 /// A mapping from declaration names to the declarations that have
Douglas Gregor3545ff42009-09-21 16:56:56 +0000122 /// this name within a particular scope and their index within the list of
123 /// results.
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000124 typedef llvm::DenseMap<DeclarationName, ShadowMapEntry> ShadowMap;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000125
126 /// The semantic analysis object for which results are being
Douglas Gregor3545ff42009-09-21 16:56:56 +0000127 /// produced.
128 Sema &SemaRef;
Douglas Gregorb278aaf2011-02-01 19:23:04 +0000129
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000130 /// The allocator used to allocate new code-completion strings.
Douglas Gregorbcbf46c2011-02-01 22:57:45 +0000131 CodeCompletionAllocator &Allocator;
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +0000132
133 CodeCompletionTUInfo &CCTUInfo;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000134
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000135 /// If non-NULL, a filter function used to remove any code-completion
Douglas Gregor3545ff42009-09-21 16:56:56 +0000136 /// results that are not desirable.
137 LookupFilter Filter;
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000138
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000139 /// Whether we should allow declarations as
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000140 /// nested-name-specifiers that would otherwise be filtered out.
141 bool AllowNestedNameSpecifiers;
142
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000143 /// If set, the type that we would prefer our resulting value
Douglas Gregor7aa6b222010-05-30 01:49:25 +0000144 /// declarations to have.
145 ///
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000146 /// Closely matching the preferred type gives a boost to a result's
Douglas Gregor7aa6b222010-05-30 01:49:25 +0000147 /// priority.
148 CanQualType PreferredType;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000149
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000150 /// A list of shadow maps, which is used to model name hiding at
Douglas Gregor3545ff42009-09-21 16:56:56 +0000151 /// different levels of, e.g., the inheritance hierarchy.
152 std::list<ShadowMap> ShadowMaps;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000153
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000154 /// If we're potentially referring to a C++ member function, the set
Douglas Gregor9be0ed42010-08-26 16:36:48 +0000155 /// of qualifiers applied to the object type.
156 Qualifiers ObjectTypeQualifiers;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000157
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000158 /// Whether the \p ObjectTypeQualifiers field is active.
Douglas Gregor9be0ed42010-08-26 16:36:48 +0000159 bool HasObjectTypeQualifiers;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000160
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000161 /// The selector that we prefer.
Douglas Gregorc2cb2e22010-08-27 15:29:55 +0000162 Selector PreferredSelector;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000163
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000164 /// The completion context in which we are gathering results.
Douglas Gregor50832e02010-09-20 22:39:41 +0000165 CodeCompletionContext CompletionContext;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000166
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000167 /// If we are in an instance method definition, the \@implementation
Douglas Gregor05fcf842010-11-02 20:36:02 +0000168 /// object.
169 ObjCImplementationDecl *ObjCImplementation;
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000170
Douglas Gregor50832e02010-09-20 22:39:41 +0000171 void AdjustResultPriorityForDecl(Result &R);
Douglas Gregor95887f92010-07-08 23:20:03 +0000172
Douglas Gregor0212fd72010-09-21 16:06:22 +0000173 void MaybeAddConstructorResults(Result R);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000174
Douglas Gregor3545ff42009-09-21 16:56:56 +0000175 public:
Douglas Gregorbcbf46c2011-02-01 22:57:45 +0000176 explicit ResultBuilder(Sema &SemaRef, CodeCompletionAllocator &Allocator,
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +0000177 CodeCompletionTUInfo &CCTUInfo,
Douglas Gregor0ac41382010-09-23 23:01:17 +0000178 const CodeCompletionContext &CompletionContext,
Craig Topperc3ec1492014-05-26 06:22:03 +0000179 LookupFilter Filter = nullptr)
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +0000180 : SemaRef(SemaRef), Allocator(Allocator), CCTUInfo(CCTUInfo),
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000181 Filter(Filter),
182 AllowNestedNameSpecifiers(false), HasObjectTypeQualifiers(false),
Douglas Gregor05fcf842010-11-02 20:36:02 +0000183 CompletionContext(CompletionContext),
Craig Topperc3ec1492014-05-26 06:22:03 +0000184 ObjCImplementation(nullptr)
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000185 {
186 // If this is an Objective-C instance method definition, dig out the
Douglas Gregor05fcf842010-11-02 20:36:02 +0000187 // corresponding implementation.
188 switch (CompletionContext.getKind()) {
189 case CodeCompletionContext::CCC_Expression:
190 case CodeCompletionContext::CCC_ObjCMessageReceiver:
191 case CodeCompletionContext::CCC_ParenthesizedExpression:
192 case CodeCompletionContext::CCC_Statement:
193 case CodeCompletionContext::CCC_Recovery:
194 if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl())
195 if (Method->isInstanceMethod())
196 if (ObjCInterfaceDecl *Interface = Method->getClassInterface())
197 ObjCImplementation = Interface->getImplementation();
198 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000199
Douglas Gregor05fcf842010-11-02 20:36:02 +0000200 default:
201 break;
202 }
203 }
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000204
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000205 /// Determine the priority for a reference to the given declaration.
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000206 unsigned getBasePriority(const NamedDecl *D);
207
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000208 /// Whether we should include code patterns in the completion
Douglas Gregorf64acca2010-05-25 21:41:55 +0000209 /// results.
210 bool includeCodePatterns() const {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000211 return SemaRef.CodeCompleter &&
Douglas Gregorac322ec2010-08-27 21:18:54 +0000212 SemaRef.CodeCompleter->includeCodePatterns();
Douglas Gregorf64acca2010-05-25 21:41:55 +0000213 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000214
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000215 /// Set the filter used for code-completion results.
Douglas Gregor3545ff42009-09-21 16:56:56 +0000216 void setFilter(LookupFilter Filter) {
217 this->Filter = Filter;
218 }
Craig Topperc3ec1492014-05-26 06:22:03 +0000219
220 Result *data() { return Results.empty()? nullptr : &Results.front(); }
Douglas Gregor3545ff42009-09-21 16:56:56 +0000221 unsigned size() const { return Results.size(); }
222 bool empty() const { return Results.empty(); }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000223
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000224 /// Specify the preferred type.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000225 void setPreferredType(QualType T) {
226 PreferredType = SemaRef.Context.getCanonicalType(T);
Douglas Gregor7aa6b222010-05-30 01:49:25 +0000227 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000228
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000229 /// Set the cv-qualifiers on the object type, for us in filtering
Douglas Gregor9be0ed42010-08-26 16:36:48 +0000230 /// calls to member functions.
231 ///
232 /// When there are qualifiers in this set, they will be used to filter
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000233 /// out member functions that aren't available (because there will be a
Douglas Gregor9be0ed42010-08-26 16:36:48 +0000234 /// cv-qualifier mismatch) or prefer functions with an exact qualifier
235 /// match.
236 void setObjectTypeQualifiers(Qualifiers Quals) {
237 ObjectTypeQualifiers = Quals;
238 HasObjectTypeQualifiers = true;
239 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000240
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000241 /// Set the preferred selector.
Douglas Gregorc2cb2e22010-08-27 15:29:55 +0000242 ///
243 /// When an Objective-C method declaration result is added, and that
244 /// method's selector matches this preferred selector, we give that method
245 /// a slight priority boost.
246 void setPreferredSelector(Selector Sel) {
247 PreferredSelector = Sel;
248 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000249
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000250 /// Retrieve the code-completion context for which results are
Douglas Gregor50832e02010-09-20 22:39:41 +0000251 /// being collected.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000252 const CodeCompletionContext &getCompletionContext() const {
253 return CompletionContext;
Douglas Gregor50832e02010-09-20 22:39:41 +0000254 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000255
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000256 /// Specify whether nested-name-specifiers are allowed.
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000257 void allowNestedNameSpecifiers(bool Allow = true) {
258 AllowNestedNameSpecifiers = Allow;
259 }
260
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000261 /// Return the semantic analysis object for which we are collecting
Douglas Gregor74661272010-09-21 00:03:25 +0000262 /// code completion results.
263 Sema &getSema() const { return SemaRef; }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000264
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000265 /// Retrieve the allocator used to allocate code completion strings.
Douglas Gregorbcbf46c2011-02-01 22:57:45 +0000266 CodeCompletionAllocator &getAllocator() const { return Allocator; }
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +0000267
268 CodeCompletionTUInfo &getCodeCompletionTUInfo() const { return CCTUInfo; }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000269
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000270 /// Determine whether the given declaration is at all interesting
Douglas Gregor7c208612010-01-14 00:20:49 +0000271 /// as a code-completion result.
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000272 ///
273 /// \param ND the declaration that we are inspecting.
274 ///
275 /// \param AsNestedNameSpecifier will be set true if this declaration is
276 /// only interesting when it is a nested-name-specifier.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000277 bool isInterestingDecl(const NamedDecl *ND,
278 bool &AsNestedNameSpecifier) const;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000279
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000280 /// Check whether the result is hidden by the Hiding declaration.
Douglas Gregore0717ab2010-01-14 00:41:07 +0000281 ///
282 /// \returns true if the result is hidden and cannot be found, false if
283 /// the hidden result could still be found. When false, \p R may be
284 /// modified to describe how the result can be found (e.g., via extra
285 /// qualification).
286 bool CheckHiddenResult(Result &R, DeclContext *CurContext,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000287 const NamedDecl *Hiding);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000288
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000289 /// Add a new result to this result set (if it isn't already in one
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000290 /// of the shadow maps), or replace an existing result (for, e.g., a
Douglas Gregor3545ff42009-09-21 16:56:56 +0000291 /// redeclaration).
Douglas Gregor2af2f672009-09-21 20:12:40 +0000292 ///
Douglas Gregord8c61782012-02-15 15:34:24 +0000293 /// \param R the result to add (if it is unique).
Douglas Gregor2af2f672009-09-21 20:12:40 +0000294 ///
Douglas Gregord8c61782012-02-15 15:34:24 +0000295 /// \param CurContext the context in which this result will be named.
Craig Topperc3ec1492014-05-26 06:22:03 +0000296 void MaybeAddResult(Result R, DeclContext *CurContext = nullptr);
297
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000298 /// Add a new result to this result set, where we already know
Yaron Keren8fbe43982014-11-14 18:33:42 +0000299 /// the hiding declaration (if any).
Douglas Gregorc580c522010-01-14 01:09:38 +0000300 ///
301 /// \param R the result to add (if it is unique).
302 ///
303 /// \param CurContext the context in which this result will be named.
304 ///
305 /// \param Hiding the declaration that hides the result.
Douglas Gregor09bbc652010-01-14 15:47:35 +0000306 ///
307 /// \param InBaseClass whether the result was found in a base
308 /// class of the searched context.
309 void AddResult(Result R, DeclContext *CurContext, NamedDecl *Hiding,
310 bool InBaseClass);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000311
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000312 /// Add a new non-declaration result to this result set.
Douglas Gregor78a21012010-01-14 16:01:26 +0000313 void AddResult(Result R);
314
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000315 /// Enter into a new scope.
Douglas Gregor3545ff42009-09-21 16:56:56 +0000316 void EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000317
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000318 /// Exit from the current scope.
Douglas Gregor3545ff42009-09-21 16:56:56 +0000319 void ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000320
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000321 /// Ignore this declaration, if it is seen again.
Dmitri Gribenko6cfb1532013-02-14 13:53:30 +0000322 void Ignore(const Decl *D) { AllDeclsFound.insert(D->getCanonicalDecl()); }
Douglas Gregorbaf69612009-11-18 04:19:12 +0000323
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000324 /// Add a visited context.
Haojian Wu10d95c52018-01-17 14:29:25 +0000325 void addVisitedContext(DeclContext *Ctx) {
326 CompletionContext.addVisitedContext(Ctx);
327 }
328
Douglas Gregor3545ff42009-09-21 16:56:56 +0000329 /// \name Name lookup predicates
330 ///
331 /// These predicates can be passed to the name lookup functions to filter the
332 /// results of name lookup. All of the predicates have the same type, so that
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000333 ///
Douglas Gregor3545ff42009-09-21 16:56:56 +0000334 //@{
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000335 bool IsOrdinaryName(const NamedDecl *ND) const;
336 bool IsOrdinaryNonTypeName(const NamedDecl *ND) const;
337 bool IsIntegralConstantValue(const NamedDecl *ND) const;
338 bool IsOrdinaryNonValueName(const NamedDecl *ND) const;
339 bool IsNestedNameSpecifier(const NamedDecl *ND) const;
340 bool IsEnum(const NamedDecl *ND) const;
341 bool IsClassOrStruct(const NamedDecl *ND) const;
342 bool IsUnion(const NamedDecl *ND) const;
343 bool IsNamespace(const NamedDecl *ND) const;
344 bool IsNamespaceOrAlias(const NamedDecl *ND) const;
345 bool IsType(const NamedDecl *ND) const;
346 bool IsMember(const NamedDecl *ND) const;
347 bool IsObjCIvar(const NamedDecl *ND) const;
348 bool IsObjCMessageReceiver(const NamedDecl *ND) const;
349 bool IsObjCMessageReceiverOrLambdaCapture(const NamedDecl *ND) const;
350 bool IsObjCCollection(const NamedDecl *ND) const;
351 bool IsImpossibleToSatisfy(const NamedDecl *ND) const;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000352 //@}
353 };
Alexander Kornienkoab9db512015-06-22 23:07:51 +0000354}
Douglas Gregor3545ff42009-09-21 16:56:56 +0000355
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000356class ResultBuilder::ShadowMapEntry::iterator {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000357 llvm::PointerUnion<const NamedDecl *, const DeclIndexPair *> DeclOrIterator;
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000358 unsigned SingleDeclIndex;
359
360public:
361 typedef DeclIndexPair value_type;
362 typedef value_type reference;
363 typedef std::ptrdiff_t difference_type;
364 typedef std::input_iterator_tag iterator_category;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000365
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000366 class pointer {
367 DeclIndexPair Value;
368
369 public:
370 pointer(const DeclIndexPair &Value) : Value(Value) { }
371
372 const DeclIndexPair *operator->() const {
373 return &Value;
374 }
375 };
Craig Topperc3ec1492014-05-26 06:22:03 +0000376
377 iterator() : DeclOrIterator((NamedDecl *)nullptr), SingleDeclIndex(0) {}
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000378
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000379 iterator(const NamedDecl *SingleDecl, unsigned Index)
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000380 : DeclOrIterator(SingleDecl), SingleDeclIndex(Index) { }
381
382 iterator(const DeclIndexPair *Iterator)
383 : DeclOrIterator(Iterator), SingleDeclIndex(0) { }
384
385 iterator &operator++() {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000386 if (DeclOrIterator.is<const NamedDecl *>()) {
Craig Topperc3ec1492014-05-26 06:22:03 +0000387 DeclOrIterator = (NamedDecl *)nullptr;
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000388 SingleDeclIndex = 0;
389 return *this;
390 }
391
392 const DeclIndexPair *I = DeclOrIterator.get<const DeclIndexPair*>();
393 ++I;
394 DeclOrIterator = I;
395 return *this;
396 }
397
Chris Lattner9795b392010-09-04 18:12:20 +0000398 /*iterator operator++(int) {
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000399 iterator tmp(*this);
400 ++(*this);
401 return tmp;
Chris Lattner9795b392010-09-04 18:12:20 +0000402 }*/
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000403
404 reference operator*() const {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000405 if (const NamedDecl *ND = DeclOrIterator.dyn_cast<const NamedDecl *>())
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000406 return reference(ND, SingleDeclIndex);
407
Douglas Gregor94bb5e82009-12-06 21:27:58 +0000408 return *DeclOrIterator.get<const DeclIndexPair*>();
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000409 }
410
411 pointer operator->() const {
412 return pointer(**this);
413 }
414
415 friend bool operator==(const iterator &X, const iterator &Y) {
Douglas Gregor94bb5e82009-12-06 21:27:58 +0000416 return X.DeclOrIterator.getOpaqueValue()
417 == Y.DeclOrIterator.getOpaqueValue() &&
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000418 X.SingleDeclIndex == Y.SingleDeclIndex;
419 }
420
421 friend bool operator!=(const iterator &X, const iterator &Y) {
Douglas Gregor94bb5e82009-12-06 21:27:58 +0000422 return !(X == Y);
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000423 }
424};
425
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000426ResultBuilder::ShadowMapEntry::iterator
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000427ResultBuilder::ShadowMapEntry::begin() const {
428 if (DeclOrVector.isNull())
429 return iterator();
430
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000431 if (const NamedDecl *ND = DeclOrVector.dyn_cast<const NamedDecl *>())
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000432 return iterator(ND, SingleDeclIndex);
433
434 return iterator(DeclOrVector.get<DeclIndexPairVector *>()->begin());
435}
436
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000437ResultBuilder::ShadowMapEntry::iterator
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000438ResultBuilder::ShadowMapEntry::end() const {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000439 if (DeclOrVector.is<const NamedDecl *>() || DeclOrVector.isNull())
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000440 return iterator();
441
442 return iterator(DeclOrVector.get<DeclIndexPairVector *>()->end());
443}
444
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000445/// Compute the qualification required to get from the current context
Douglas Gregor2af2f672009-09-21 20:12:40 +0000446/// (\p CurContext) to the target context (\p TargetContext).
447///
448/// \param Context the AST context in which the qualification will be used.
449///
450/// \param CurContext the context where an entity is being named, which is
451/// typically based on the current scope.
452///
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000453/// \param TargetContext the context in which the named entity actually
Douglas Gregor2af2f672009-09-21 20:12:40 +0000454/// resides.
455///
456/// \returns a nested name specifier that refers into the target context, or
457/// NULL if no qualification is needed.
458static NestedNameSpecifier *
459getRequiredQualification(ASTContext &Context,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000460 const DeclContext *CurContext,
461 const DeclContext *TargetContext) {
462 SmallVector<const DeclContext *, 4> TargetParents;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000463
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000464 for (const DeclContext *CommonAncestor = TargetContext;
Douglas Gregor2af2f672009-09-21 20:12:40 +0000465 CommonAncestor && !CommonAncestor->Encloses(CurContext);
466 CommonAncestor = CommonAncestor->getLookupParent()) {
467 if (CommonAncestor->isTransparentContext() ||
468 CommonAncestor->isFunctionOrMethod())
469 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000470
Douglas Gregor2af2f672009-09-21 20:12:40 +0000471 TargetParents.push_back(CommonAncestor);
472 }
Craig Topperc3ec1492014-05-26 06:22:03 +0000473
474 NestedNameSpecifier *Result = nullptr;
Douglas Gregor2af2f672009-09-21 20:12:40 +0000475 while (!TargetParents.empty()) {
Robert Wilhelm25284cc2013-08-23 16:11:15 +0000476 const DeclContext *Parent = TargetParents.pop_back_val();
477
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000478 if (const NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Parent)) {
Douglas Gregor68762e72010-08-23 21:17:50 +0000479 if (!Namespace->getIdentifier())
480 continue;
481
Douglas Gregor2af2f672009-09-21 20:12:40 +0000482 Result = NestedNameSpecifier::Create(Context, Result, Namespace);
Douglas Gregor68762e72010-08-23 21:17:50 +0000483 }
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000484 else if (const TagDecl *TD = dyn_cast<TagDecl>(Parent))
Douglas Gregor2af2f672009-09-21 20:12:40 +0000485 Result = NestedNameSpecifier::Create(Context, Result,
486 false,
487 Context.getTypeDeclType(TD).getTypePtr());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000488 }
Douglas Gregor2af2f672009-09-21 20:12:40 +0000489 return Result;
490}
491
Alp Toker034bbd52014-06-30 01:33:53 +0000492/// Determine whether \p Id is a name reserved for the implementation (C99
493/// 7.1.3, C++ [lib.global.names]).
Argyrios Kyrtzidis5d8006d2016-07-01 01:17:02 +0000494static bool isReservedName(const IdentifierInfo *Id,
495 bool doubleUnderscoreOnly = false) {
Alp Toker034bbd52014-06-30 01:33:53 +0000496 if (Id->getLength() < 2)
497 return false;
498 const char *Name = Id->getNameStart();
499 return Name[0] == '_' &&
Argyrios Kyrtzidis5d8006d2016-07-01 01:17:02 +0000500 (Name[1] == '_' || (Name[1] >= 'A' && Name[1] <= 'Z' &&
501 !doubleUnderscoreOnly));
502}
503
504// Some declarations have reserved names that we don't want to ever show.
505// Filter out names reserved for the implementation if they come from a
506// system header.
507static bool shouldIgnoreDueToReservedName(const NamedDecl *ND, Sema &SemaRef) {
508 const IdentifierInfo *Id = ND->getIdentifier();
509 if (!Id)
510 return false;
511
512 // Ignore reserved names for compiler provided decls.
513 if (isReservedName(Id) && ND->getLocation().isInvalid())
514 return true;
515
516 // For system headers ignore only double-underscore names.
517 // This allows for system headers providing private symbols with a single
518 // underscore.
519 if (isReservedName(Id, /*doubleUnderscoreOnly=*/true) &&
520 SemaRef.SourceMgr.isInSystemHeader(
521 SemaRef.SourceMgr.getSpellingLoc(ND->getLocation())))
522 return true;
523
524 return false;
Alp Toker034bbd52014-06-30 01:33:53 +0000525}
526
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000527bool ResultBuilder::isInterestingDecl(const NamedDecl *ND,
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000528 bool &AsNestedNameSpecifier) const {
529 AsNestedNameSpecifier = false;
530
Richard Smithf2005d32015-12-29 23:34:32 +0000531 auto *Named = ND;
Douglas Gregor7c208612010-01-14 00:20:49 +0000532 ND = ND->getUnderlyingDecl();
Douglas Gregor58acf322009-10-09 22:16:47 +0000533
534 // Skip unnamed entities.
Douglas Gregor7c208612010-01-14 00:20:49 +0000535 if (!ND->getDeclName())
536 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000537
Douglas Gregor3545ff42009-09-21 16:56:56 +0000538 // Friend declarations and declarations introduced due to friends are never
539 // added as results.
Richard Smith6eece292015-01-15 02:27:20 +0000540 if (ND->getFriendObjectKind() == Decl::FOK_Undeclared)
Douglas Gregor7c208612010-01-14 00:20:49 +0000541 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000542
Douglas Gregor99fe2ad2009-12-11 17:31:05 +0000543 // Class template (partial) specializations are never added as results.
Douglas Gregor7c208612010-01-14 00:20:49 +0000544 if (isa<ClassTemplateSpecializationDecl>(ND) ||
545 isa<ClassTemplatePartialSpecializationDecl>(ND))
546 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000547
Douglas Gregor99fe2ad2009-12-11 17:31:05 +0000548 // Using declarations themselves are never added as results.
Douglas Gregor7c208612010-01-14 00:20:49 +0000549 if (isa<UsingDecl>(ND))
550 return false;
Argyrios Kyrtzidis5d8006d2016-07-01 01:17:02 +0000551
552 if (shouldIgnoreDueToReservedName(ND, SemaRef))
553 return false;
Douglas Gregor2927c0c2010-11-09 03:59:40 +0000554
Douglas Gregor59cab552010-08-16 23:05:20 +0000555 if (Filter == &ResultBuilder::IsNestedNameSpecifier ||
Richard Smithf2005d32015-12-29 23:34:32 +0000556 (isa<NamespaceDecl>(ND) &&
Douglas Gregor59cab552010-08-16 23:05:20 +0000557 Filter != &ResultBuilder::IsNamespace &&
Douglas Gregor0ac41382010-09-23 23:01:17 +0000558 Filter != &ResultBuilder::IsNamespaceOrAlias &&
Craig Topperc3ec1492014-05-26 06:22:03 +0000559 Filter != nullptr))
Douglas Gregor59cab552010-08-16 23:05:20 +0000560 AsNestedNameSpecifier = true;
561
Douglas Gregor3545ff42009-09-21 16:56:56 +0000562 // Filter out any unwanted results.
Richard Smithf2005d32015-12-29 23:34:32 +0000563 if (Filter && !(this->*Filter)(Named)) {
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000564 // Check whether it is interesting as a nested-name-specifier.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000565 if (AllowNestedNameSpecifiers && SemaRef.getLangOpts().CPlusPlus &&
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000566 IsNestedNameSpecifier(ND) &&
567 (Filter != &ResultBuilder::IsMember ||
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000568 (isa<CXXRecordDecl>(ND) &&
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000569 cast<CXXRecordDecl>(ND)->isInjectedClassName()))) {
570 AsNestedNameSpecifier = true;
571 return true;
572 }
573
Douglas Gregor7c208612010-01-14 00:20:49 +0000574 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000575 }
Douglas Gregor7c208612010-01-14 00:20:49 +0000576 // ... then it must be interesting!
577 return true;
578}
579
Douglas Gregore0717ab2010-01-14 00:41:07 +0000580bool ResultBuilder::CheckHiddenResult(Result &R, DeclContext *CurContext,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000581 const NamedDecl *Hiding) {
Douglas Gregore0717ab2010-01-14 00:41:07 +0000582 // In C, there is no way to refer to a hidden name.
583 // FIXME: This isn't true; we can find a tag name hidden by an ordinary
584 // name if we introduce the tag type.
David Blaikiebbafb8a2012-03-11 07:00:24 +0000585 if (!SemaRef.getLangOpts().CPlusPlus)
Douglas Gregore0717ab2010-01-14 00:41:07 +0000586 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000587
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000588 const DeclContext *HiddenCtx =
589 R.Declaration->getDeclContext()->getRedeclContext();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000590
Douglas Gregore0717ab2010-01-14 00:41:07 +0000591 // There is no way to qualify a name declared in a function or method.
592 if (HiddenCtx->isFunctionOrMethod())
593 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000594
Sebastian Redl50c68252010-08-31 00:36:30 +0000595 if (HiddenCtx == Hiding->getDeclContext()->getRedeclContext())
Douglas Gregore0717ab2010-01-14 00:41:07 +0000596 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000597
Douglas Gregore0717ab2010-01-14 00:41:07 +0000598 // We can refer to the result with the appropriate qualification. Do it.
599 R.Hidden = true;
600 R.QualifierIsInformative = false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000601
Douglas Gregore0717ab2010-01-14 00:41:07 +0000602 if (!R.Qualifier)
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000603 R.Qualifier = getRequiredQualification(SemaRef.Context,
604 CurContext,
Douglas Gregore0717ab2010-01-14 00:41:07 +0000605 R.Declaration->getDeclContext());
606 return false;
607}
608
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000609/// A simplified classification of types used to determine whether two
Douglas Gregor95887f92010-07-08 23:20:03 +0000610/// types are "similar enough" when adjusting priorities.
Douglas Gregor6e240332010-08-16 16:18:59 +0000611SimplifiedTypeClass clang::getSimplifiedTypeClass(CanQualType T) {
Douglas Gregor95887f92010-07-08 23:20:03 +0000612 switch (T->getTypeClass()) {
613 case Type::Builtin:
614 switch (cast<BuiltinType>(T)->getKind()) {
615 case BuiltinType::Void:
616 return STC_Void;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000617
Douglas Gregor95887f92010-07-08 23:20:03 +0000618 case BuiltinType::NullPtr:
619 return STC_Pointer;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000620
Douglas Gregor95887f92010-07-08 23:20:03 +0000621 case BuiltinType::Overload:
622 case BuiltinType::Dependent:
Douglas Gregor95887f92010-07-08 23:20:03 +0000623 return STC_Other;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000624
Douglas Gregor95887f92010-07-08 23:20:03 +0000625 case BuiltinType::ObjCId:
626 case BuiltinType::ObjCClass:
627 case BuiltinType::ObjCSel:
628 return STC_ObjectiveC;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000629
Douglas Gregor95887f92010-07-08 23:20:03 +0000630 default:
631 return STC_Arithmetic;
632 }
David Blaikie8a40f702012-01-17 06:56:22 +0000633
Douglas Gregor95887f92010-07-08 23:20:03 +0000634 case Type::Complex:
635 return STC_Arithmetic;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000636
Douglas Gregor95887f92010-07-08 23:20:03 +0000637 case Type::Pointer:
638 return STC_Pointer;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000639
Douglas Gregor95887f92010-07-08 23:20:03 +0000640 case Type::BlockPointer:
641 return STC_Block;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000642
Douglas Gregor95887f92010-07-08 23:20:03 +0000643 case Type::LValueReference:
644 case Type::RValueReference:
645 return getSimplifiedTypeClass(T->getAs<ReferenceType>()->getPointeeType());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000646
Douglas Gregor95887f92010-07-08 23:20:03 +0000647 case Type::ConstantArray:
648 case Type::IncompleteArray:
649 case Type::VariableArray:
650 case Type::DependentSizedArray:
651 return STC_Array;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000652
Douglas Gregor95887f92010-07-08 23:20:03 +0000653 case Type::DependentSizedExtVector:
654 case Type::Vector:
655 case Type::ExtVector:
656 return STC_Arithmetic;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000657
Douglas Gregor95887f92010-07-08 23:20:03 +0000658 case Type::FunctionProto:
659 case Type::FunctionNoProto:
660 return STC_Function;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000661
Douglas Gregor95887f92010-07-08 23:20:03 +0000662 case Type::Record:
663 return STC_Record;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000664
Douglas Gregor95887f92010-07-08 23:20:03 +0000665 case Type::Enum:
666 return STC_Arithmetic;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000667
Douglas Gregor95887f92010-07-08 23:20:03 +0000668 case Type::ObjCObject:
669 case Type::ObjCInterface:
670 case Type::ObjCObjectPointer:
671 return STC_ObjectiveC;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000672
Douglas Gregor95887f92010-07-08 23:20:03 +0000673 default:
674 return STC_Other;
675 }
676}
677
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000678/// Get the type that a given expression will have if this declaration
Douglas Gregor95887f92010-07-08 23:20:03 +0000679/// is used as an expression in its "typical" code-completion form.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000680QualType clang::getDeclUsageType(ASTContext &C, const NamedDecl *ND) {
George Burgess IV00f70bd2018-03-01 05:43:23 +0000681 ND = ND->getUnderlyingDecl();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000682
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000683 if (const TypeDecl *Type = dyn_cast<TypeDecl>(ND))
Douglas Gregor95887f92010-07-08 23:20:03 +0000684 return C.getTypeDeclType(Type);
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000685 if (const ObjCInterfaceDecl *Iface = dyn_cast<ObjCInterfaceDecl>(ND))
Douglas Gregor95887f92010-07-08 23:20:03 +0000686 return C.getObjCInterfaceType(Iface);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000687
Douglas Gregor95887f92010-07-08 23:20:03 +0000688 QualType T;
Alp Tokera2794f92014-01-22 07:29:52 +0000689 if (const FunctionDecl *Function = ND->getAsFunction())
Douglas Gregor603d81b2010-07-13 08:18:22 +0000690 T = Function->getCallResultType();
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000691 else if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND))
Douglas Gregor603d81b2010-07-13 08:18:22 +0000692 T = Method->getSendResultType();
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000693 else if (const EnumConstantDecl *Enumerator = dyn_cast<EnumConstantDecl>(ND))
Douglas Gregor95887f92010-07-08 23:20:03 +0000694 T = C.getTypeDeclType(cast<EnumDecl>(Enumerator->getDeclContext()));
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000695 else if (const ObjCPropertyDecl *Property = dyn_cast<ObjCPropertyDecl>(ND))
Douglas Gregor95887f92010-07-08 23:20:03 +0000696 T = Property->getType();
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000697 else if (const ValueDecl *Value = dyn_cast<ValueDecl>(ND))
Douglas Gregor95887f92010-07-08 23:20:03 +0000698 T = Value->getType();
699 else
700 return QualType();
Douglas Gregoraf670a82011-04-14 20:33:34 +0000701
702 // Dig through references, function pointers, and block pointers to
703 // get down to the likely type of an expression when the entity is
704 // used.
705 do {
706 if (const ReferenceType *Ref = T->getAs<ReferenceType>()) {
707 T = Ref->getPointeeType();
708 continue;
709 }
710
711 if (const PointerType *Pointer = T->getAs<PointerType>()) {
712 if (Pointer->getPointeeType()->isFunctionType()) {
713 T = Pointer->getPointeeType();
714 continue;
715 }
716
717 break;
718 }
719
720 if (const BlockPointerType *Block = T->getAs<BlockPointerType>()) {
721 T = Block->getPointeeType();
722 continue;
723 }
724
725 if (const FunctionType *Function = T->getAs<FunctionType>()) {
Alp Toker314cc812014-01-25 16:55:45 +0000726 T = Function->getReturnType();
Douglas Gregoraf670a82011-04-14 20:33:34 +0000727 continue;
728 }
729
730 break;
731 } while (true);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000732
Douglas Gregoraf670a82011-04-14 20:33:34 +0000733 return T;
Douglas Gregor95887f92010-07-08 23:20:03 +0000734}
735
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000736unsigned ResultBuilder::getBasePriority(const NamedDecl *ND) {
737 if (!ND)
738 return CCP_Unlikely;
739
740 // Context-based decisions.
Richard Smith541b38b2013-09-20 01:15:31 +0000741 const DeclContext *LexicalDC = ND->getLexicalDeclContext();
742 if (LexicalDC->isFunctionOrMethod()) {
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000743 // _cmd is relatively rare
744 if (const ImplicitParamDecl *ImplicitParam =
745 dyn_cast<ImplicitParamDecl>(ND))
746 if (ImplicitParam->getIdentifier() &&
747 ImplicitParam->getIdentifier()->isStr("_cmd"))
748 return CCP_ObjC_cmd;
749
750 return CCP_LocalDeclaration;
751 }
Richard Smith541b38b2013-09-20 01:15:31 +0000752
753 const DeclContext *DC = ND->getDeclContext()->getRedeclContext();
Ilya Biryukov4e7a6fe2017-09-22 19:07:37 +0000754 if (DC->isRecord() || isa<ObjCContainerDecl>(DC)) {
755 // Explicit destructor calls are very rare.
756 if (isa<CXXDestructorDecl>(ND))
757 return CCP_Unlikely;
758 // Explicit operator and conversion function calls are also very rare.
759 auto DeclNameKind = ND->getDeclName().getNameKind();
760 if (DeclNameKind == DeclarationName::CXXOperatorName ||
761 DeclNameKind == DeclarationName::CXXLiteralOperatorName ||
762 DeclNameKind == DeclarationName::CXXConversionFunctionName)
763 return CCP_Unlikely;
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000764 return CCP_MemberDeclaration;
Ilya Biryukov4e7a6fe2017-09-22 19:07:37 +0000765 }
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000766
767 // Content-based decisions.
768 if (isa<EnumConstantDecl>(ND))
769 return CCP_Constant;
770
Douglas Gregor52e0de42013-01-31 05:03:46 +0000771 // Use CCP_Type for type declarations unless we're in a statement, Objective-C
772 // message receiver, or parenthesized expression context. There, it's as
773 // likely that the user will want to write a type as other declarations.
774 if ((isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND)) &&
775 !(CompletionContext.getKind() == CodeCompletionContext::CCC_Statement ||
776 CompletionContext.getKind()
777 == CodeCompletionContext::CCC_ObjCMessageReceiver ||
778 CompletionContext.getKind()
779 == CodeCompletionContext::CCC_ParenthesizedExpression))
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000780 return CCP_Type;
781
782 return CCP_Declaration;
783}
784
Douglas Gregor50832e02010-09-20 22:39:41 +0000785void ResultBuilder::AdjustResultPriorityForDecl(Result &R) {
786 // If this is an Objective-C method declaration whose selector matches our
787 // preferred selector, give it a priority boost.
788 if (!PreferredSelector.isNull())
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000789 if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(R.Declaration))
Douglas Gregor50832e02010-09-20 22:39:41 +0000790 if (PreferredSelector == Method->getSelector())
791 R.Priority += CCD_SelectorMatch;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000792
Douglas Gregor50832e02010-09-20 22:39:41 +0000793 // If we have a preferred type, adjust the priority for results with exactly-
794 // matching or nearly-matching types.
795 if (!PreferredType.isNull()) {
796 QualType T = getDeclUsageType(SemaRef.Context, R.Declaration);
797 if (!T.isNull()) {
798 CanQualType TC = SemaRef.Context.getCanonicalType(T);
799 // Check for exactly-matching types (modulo qualifiers).
800 if (SemaRef.Context.hasSameUnqualifiedType(PreferredType, TC))
801 R.Priority /= CCF_ExactTypeMatch;
802 // Check for nearly-matching types, based on classification of each.
803 else if ((getSimplifiedTypeClass(PreferredType)
Douglas Gregor95887f92010-07-08 23:20:03 +0000804 == getSimplifiedTypeClass(TC)) &&
Douglas Gregor50832e02010-09-20 22:39:41 +0000805 !(PreferredType->isEnumeralType() && TC->isEnumeralType()))
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000806 R.Priority /= CCF_SimilarTypeMatch;
Douglas Gregor50832e02010-09-20 22:39:41 +0000807 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000808 }
Douglas Gregor95887f92010-07-08 23:20:03 +0000809}
810
Douglas Gregor0212fd72010-09-21 16:06:22 +0000811void ResultBuilder::MaybeAddConstructorResults(Result R) {
David Blaikiebbafb8a2012-03-11 07:00:24 +0000812 if (!SemaRef.getLangOpts().CPlusPlus || !R.Declaration ||
Douglas Gregor0212fd72010-09-21 16:06:22 +0000813 !CompletionContext.wantConstructorResults())
814 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000815
Douglas Gregor0212fd72010-09-21 16:06:22 +0000816 ASTContext &Context = SemaRef.Context;
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000817 const NamedDecl *D = R.Declaration;
Craig Topperc3ec1492014-05-26 06:22:03 +0000818 const CXXRecordDecl *Record = nullptr;
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000819 if (const ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(D))
Douglas Gregor0212fd72010-09-21 16:06:22 +0000820 Record = ClassTemplate->getTemplatedDecl();
821 else if ((Record = dyn_cast<CXXRecordDecl>(D))) {
822 // Skip specializations and partial specializations.
823 if (isa<ClassTemplateSpecializationDecl>(Record))
824 return;
825 } else {
826 // There are no constructors here.
827 return;
828 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000829
Douglas Gregor0212fd72010-09-21 16:06:22 +0000830 Record = Record->getDefinition();
831 if (!Record)
832 return;
833
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000834
Douglas Gregor0212fd72010-09-21 16:06:22 +0000835 QualType RecordTy = Context.getTypeDeclType(Record);
836 DeclarationName ConstructorName
837 = Context.DeclarationNames.getCXXConstructorName(
838 Context.getCanonicalType(RecordTy));
Richard Smithcf4bdde2015-02-21 02:45:19 +0000839 DeclContext::lookup_result Ctors = Record->lookup(ConstructorName);
840 for (DeclContext::lookup_iterator I = Ctors.begin(),
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000841 E = Ctors.end();
842 I != E; ++I) {
David Blaikieff7d47a2012-12-19 00:45:41 +0000843 R.Declaration = *I;
Douglas Gregor0212fd72010-09-21 16:06:22 +0000844 R.CursorKind = getCursorKindForDecl(R.Declaration);
845 Results.push_back(R);
846 }
847}
848
Sam McCall63c59722018-01-22 20:44:47 +0000849static bool isConstructor(const Decl *ND) {
850 if (const auto *Tmpl = dyn_cast<FunctionTemplateDecl>(ND))
851 ND = Tmpl->getTemplatedDecl();
852 return isa<CXXConstructorDecl>(ND);
853}
854
Douglas Gregor7c208612010-01-14 00:20:49 +0000855void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) {
856 assert(!ShadowMaps.empty() && "Must enter into a results scope");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000857
Douglas Gregor7c208612010-01-14 00:20:49 +0000858 if (R.Kind != Result::RK_Declaration) {
859 // For non-declaration results, just add the result.
860 Results.push_back(R);
861 return;
862 }
863
864 // Look through using declarations.
Kirill Bobyrev47d7f522018-07-11 14:49:49 +0000865 if (const UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(R.Declaration)) {
866 CodeCompletionResult Result(Using->getTargetDecl(),
867 getBasePriority(Using->getTargetDecl()),
868 R.Qualifier);
869 Result.ShadowDecl = Using;
870 MaybeAddResult(Result, CurContext);
Douglas Gregor7c208612010-01-14 00:20:49 +0000871 return;
872 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000873
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000874 const Decl *CanonDecl = R.Declaration->getCanonicalDecl();
Douglas Gregor7c208612010-01-14 00:20:49 +0000875 unsigned IDNS = CanonDecl->getIdentifierNamespace();
876
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000877 bool AsNestedNameSpecifier = false;
878 if (!isInterestingDecl(R.Declaration, AsNestedNameSpecifier))
Douglas Gregor7c208612010-01-14 00:20:49 +0000879 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000880
Douglas Gregor0212fd72010-09-21 16:06:22 +0000881 // C++ constructors are never found by name lookup.
Sam McCall63c59722018-01-22 20:44:47 +0000882 if (isConstructor(R.Declaration))
Douglas Gregor0212fd72010-09-21 16:06:22 +0000883 return;
884
Douglas Gregor3545ff42009-09-21 16:56:56 +0000885 ShadowMap &SMap = ShadowMaps.back();
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000886 ShadowMapEntry::iterator I, IEnd;
887 ShadowMap::iterator NamePos = SMap.find(R.Declaration->getDeclName());
888 if (NamePos != SMap.end()) {
889 I = NamePos->second.begin();
890 IEnd = NamePos->second.end();
891 }
892
893 for (; I != IEnd; ++I) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000894 const NamedDecl *ND = I->first;
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000895 unsigned Index = I->second;
Douglas Gregor3545ff42009-09-21 16:56:56 +0000896 if (ND->getCanonicalDecl() == CanonDecl) {
897 // This is a redeclaration. Always pick the newer declaration.
Douglas Gregor3545ff42009-09-21 16:56:56 +0000898 Results[Index].Declaration = R.Declaration;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000899
Douglas Gregor3545ff42009-09-21 16:56:56 +0000900 // We're done.
901 return;
902 }
903 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000904
Douglas Gregor3545ff42009-09-21 16:56:56 +0000905 // This is a new declaration in this scope. However, check whether this
906 // declaration name is hidden by a similarly-named declaration in an outer
907 // scope.
908 std::list<ShadowMap>::iterator SM, SMEnd = ShadowMaps.end();
909 --SMEnd;
910 for (SM = ShadowMaps.begin(); SM != SMEnd; ++SM) {
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000911 ShadowMapEntry::iterator I, IEnd;
912 ShadowMap::iterator NamePos = SM->find(R.Declaration->getDeclName());
913 if (NamePos != SM->end()) {
914 I = NamePos->second.begin();
915 IEnd = NamePos->second.end();
916 }
917 for (; I != IEnd; ++I) {
Douglas Gregor3545ff42009-09-21 16:56:56 +0000918 // A tag declaration does not hide a non-tag declaration.
John McCalle87beb22010-04-23 18:46:30 +0000919 if (I->first->hasTagIdentifierNamespace() &&
Richard Smith541b38b2013-09-20 01:15:31 +0000920 (IDNS & (Decl::IDNS_Member | Decl::IDNS_Ordinary |
921 Decl::IDNS_LocalExtern | Decl::IDNS_ObjCProtocol)))
Douglas Gregor3545ff42009-09-21 16:56:56 +0000922 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000923
Douglas Gregor3545ff42009-09-21 16:56:56 +0000924 // Protocols are in distinct namespaces from everything else.
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000925 if (((I->first->getIdentifierNamespace() & Decl::IDNS_ObjCProtocol)
Douglas Gregor3545ff42009-09-21 16:56:56 +0000926 || (IDNS & Decl::IDNS_ObjCProtocol)) &&
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000927 I->first->getIdentifierNamespace() != IDNS)
Douglas Gregor3545ff42009-09-21 16:56:56 +0000928 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000929
Douglas Gregor3545ff42009-09-21 16:56:56 +0000930 // The newly-added result is hidden by an entry in the shadow map.
Douglas Gregore0717ab2010-01-14 00:41:07 +0000931 if (CheckHiddenResult(R, CurContext, I->first))
Douglas Gregor3545ff42009-09-21 16:56:56 +0000932 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000933
Douglas Gregor3545ff42009-09-21 16:56:56 +0000934 break;
935 }
936 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000937
Douglas Gregor3545ff42009-09-21 16:56:56 +0000938 // Make sure that any given declaration only shows up in the result set once.
David Blaikie82e95a32014-11-19 07:49:47 +0000939 if (!AllDeclsFound.insert(CanonDecl).second)
Douglas Gregor3545ff42009-09-21 16:56:56 +0000940 return;
Douglas Gregorc2cb2e22010-08-27 15:29:55 +0000941
Douglas Gregore412a5a2009-09-23 22:26:46 +0000942 // If the filter is for nested-name-specifiers, then this result starts a
943 // nested-name-specifier.
Douglas Gregora2db7932010-05-26 22:00:08 +0000944 if (AsNestedNameSpecifier) {
Douglas Gregore412a5a2009-09-23 22:26:46 +0000945 R.StartsNestedNameSpecifier = true;
Douglas Gregora2db7932010-05-26 22:00:08 +0000946 R.Priority = CCP_NestedNameSpecifier;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000947 } else
Douglas Gregor50832e02010-09-20 22:39:41 +0000948 AdjustResultPriorityForDecl(R);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000949
Douglas Gregor5bf52692009-09-22 23:15:58 +0000950 // If this result is supposed to have an informative qualifier, add one.
Douglas Gregore412a5a2009-09-23 22:26:46 +0000951 if (R.QualifierIsInformative && !R.Qualifier &&
952 !R.StartsNestedNameSpecifier) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000953 const DeclContext *Ctx = R.Declaration->getDeclContext();
954 if (const NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Ctx))
Craig Topperc3ec1492014-05-26 06:22:03 +0000955 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, nullptr,
956 Namespace);
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000957 else if (const TagDecl *Tag = dyn_cast<TagDecl>(Ctx))
Craig Topperc3ec1492014-05-26 06:22:03 +0000958 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, nullptr,
959 false, SemaRef.Context.getTypeDeclType(Tag).getTypePtr());
Douglas Gregor5bf52692009-09-22 23:15:58 +0000960 else
961 R.QualifierIsInformative = false;
962 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000963
Douglas Gregor3545ff42009-09-21 16:56:56 +0000964 // Insert this result into the set of results and into the current shadow
965 // map.
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000966 SMap[R.Declaration->getDeclName()].Add(R.Declaration, Results.size());
Douglas Gregor3545ff42009-09-21 16:56:56 +0000967 Results.push_back(R);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000968
Douglas Gregor0212fd72010-09-21 16:06:22 +0000969 if (!AsNestedNameSpecifier)
970 MaybeAddConstructorResults(R);
Douglas Gregor3545ff42009-09-21 16:56:56 +0000971}
972
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000973void ResultBuilder::AddResult(Result R, DeclContext *CurContext,
Douglas Gregor09bbc652010-01-14 15:47:35 +0000974 NamedDecl *Hiding, bool InBaseClass = false) {
Douglas Gregor78a21012010-01-14 16:01:26 +0000975 if (R.Kind != Result::RK_Declaration) {
976 // For non-declaration results, just add the result.
977 Results.push_back(R);
978 return;
979 }
980
Douglas Gregorc580c522010-01-14 01:09:38 +0000981 // Look through using declarations.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000982 if (const UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(R.Declaration)) {
Kirill Bobyrev47d7f522018-07-11 14:49:49 +0000983 CodeCompletionResult Result(Using->getTargetDecl(),
984 getBasePriority(Using->getTargetDecl()),
985 R.Qualifier);
986 Result.ShadowDecl = Using;
987 AddResult(Result, CurContext, Hiding);
Douglas Gregorc580c522010-01-14 01:09:38 +0000988 return;
989 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000990
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000991 bool AsNestedNameSpecifier = false;
992 if (!isInterestingDecl(R.Declaration, AsNestedNameSpecifier))
Douglas Gregorc580c522010-01-14 01:09:38 +0000993 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000994
Douglas Gregor0212fd72010-09-21 16:06:22 +0000995 // C++ constructors are never found by name lookup.
Sam McCall63c59722018-01-22 20:44:47 +0000996 if (isConstructor(R.Declaration))
Douglas Gregor0212fd72010-09-21 16:06:22 +0000997 return;
998
Douglas Gregorc580c522010-01-14 01:09:38 +0000999 if (Hiding && CheckHiddenResult(R, CurContext, Hiding))
1000 return;
Nick Lewyckyc3921482012-04-03 21:44:08 +00001001
Douglas Gregorc580c522010-01-14 01:09:38 +00001002 // Make sure that any given declaration only shows up in the result set once.
David Blaikie82e95a32014-11-19 07:49:47 +00001003 if (!AllDeclsFound.insert(R.Declaration->getCanonicalDecl()).second)
Douglas Gregorc580c522010-01-14 01:09:38 +00001004 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001005
Douglas Gregorc580c522010-01-14 01:09:38 +00001006 // If the filter is for nested-name-specifiers, then this result starts a
1007 // nested-name-specifier.
Douglas Gregora2db7932010-05-26 22:00:08 +00001008 if (AsNestedNameSpecifier) {
Douglas Gregorc580c522010-01-14 01:09:38 +00001009 R.StartsNestedNameSpecifier = true;
Douglas Gregora2db7932010-05-26 22:00:08 +00001010 R.Priority = CCP_NestedNameSpecifier;
Kirill Bobyrev47d7f522018-07-11 14:49:49 +00001011 } else if (Filter == &ResultBuilder::IsMember && !R.Qualifier &&
1012 InBaseClass &&
1013 isa<CXXRecordDecl>(
1014 R.Declaration->getDeclContext()->getRedeclContext()))
Douglas Gregor09bbc652010-01-14 15:47:35 +00001015 R.QualifierIsInformative = true;
1016
Douglas Gregorc580c522010-01-14 01:09:38 +00001017 // If this result is supposed to have an informative qualifier, add one.
1018 if (R.QualifierIsInformative && !R.Qualifier &&
1019 !R.StartsNestedNameSpecifier) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001020 const DeclContext *Ctx = R.Declaration->getDeclContext();
1021 if (const NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Ctx))
Craig Topperc3ec1492014-05-26 06:22:03 +00001022 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, nullptr,
1023 Namespace);
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001024 else if (const TagDecl *Tag = dyn_cast<TagDecl>(Ctx))
Craig Topperc3ec1492014-05-26 06:22:03 +00001025 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, nullptr, false,
Douglas Gregor6ae4c522010-01-14 03:21:49 +00001026 SemaRef.Context.getTypeDeclType(Tag).getTypePtr());
Douglas Gregorc580c522010-01-14 01:09:38 +00001027 else
1028 R.QualifierIsInformative = false;
1029 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001030
Douglas Gregora2db7932010-05-26 22:00:08 +00001031 // Adjust the priority if this result comes from a base class.
1032 if (InBaseClass)
1033 R.Priority += CCD_InBaseClass;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001034
Douglas Gregor50832e02010-09-20 22:39:41 +00001035 AdjustResultPriorityForDecl(R);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001036
Douglas Gregor9be0ed42010-08-26 16:36:48 +00001037 if (HasObjectTypeQualifiers)
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001038 if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(R.Declaration))
Douglas Gregor9be0ed42010-08-26 16:36:48 +00001039 if (Method->isInstance()) {
1040 Qualifiers MethodQuals
1041 = Qualifiers::fromCVRMask(Method->getTypeQualifiers());
1042 if (ObjectTypeQualifiers == MethodQuals)
1043 R.Priority += CCD_ObjectQualifierMatch;
1044 else if (ObjectTypeQualifiers - MethodQuals) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001045 // The method cannot be invoked, because doing so would drop
Douglas Gregor9be0ed42010-08-26 16:36:48 +00001046 // qualifiers.
1047 return;
1048 }
1049 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001050
Douglas Gregorc580c522010-01-14 01:09:38 +00001051 // Insert this result into the set of results.
1052 Results.push_back(R);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001053
Douglas Gregor0212fd72010-09-21 16:06:22 +00001054 if (!AsNestedNameSpecifier)
1055 MaybeAddConstructorResults(R);
Douglas Gregorc580c522010-01-14 01:09:38 +00001056}
1057
Douglas Gregor78a21012010-01-14 16:01:26 +00001058void ResultBuilder::AddResult(Result R) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001059 assert(R.Kind != Result::RK_Declaration &&
Douglas Gregor78a21012010-01-14 16:01:26 +00001060 "Declaration results need more context");
1061 Results.push_back(R);
1062}
1063
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001064/// Enter into a new scope.
Benjamin Kramer3204b152015-05-29 19:42:19 +00001065void ResultBuilder::EnterNewScope() { ShadowMaps.emplace_back(); }
Douglas Gregor3545ff42009-09-21 16:56:56 +00001066
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001067/// Exit from the current scope.
Douglas Gregor3545ff42009-09-21 16:56:56 +00001068void ResultBuilder::ExitScope() {
Douglas Gregor05e7ca32009-12-06 20:23:50 +00001069 for (ShadowMap::iterator E = ShadowMaps.back().begin(),
1070 EEnd = ShadowMaps.back().end();
1071 E != EEnd;
1072 ++E)
1073 E->second.Destroy();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001074
Douglas Gregor3545ff42009-09-21 16:56:56 +00001075 ShadowMaps.pop_back();
1076}
1077
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001078/// Determines whether this given declaration will be found by
Douglas Gregor9d64c5e2009-09-21 20:51:25 +00001079/// ordinary name lookup.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001080bool ResultBuilder::IsOrdinaryName(const NamedDecl *ND) const {
George Burgess IV00f70bd2018-03-01 05:43:23 +00001081 ND = ND->getUnderlyingDecl();
Douglas Gregor70febae2010-05-28 00:49:12 +00001082
Richard Smith541b38b2013-09-20 01:15:31 +00001083 // If name lookup finds a local extern declaration, then we are in a
1084 // context where it behaves like an ordinary name.
1085 unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_LocalExtern;
David Blaikiebbafb8a2012-03-11 07:00:24 +00001086 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregor9858ed52010-06-15 20:26:51 +00001087 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member;
David Blaikiebbafb8a2012-03-11 07:00:24 +00001088 else if (SemaRef.getLangOpts().ObjC1) {
Douglas Gregor05fcf842010-11-02 20:36:02 +00001089 if (isa<ObjCIvarDecl>(ND))
1090 return true;
Douglas Gregor05fcf842010-11-02 20:36:02 +00001091 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001092
Douglas Gregor9d64c5e2009-09-21 20:51:25 +00001093 return ND->getIdentifierNamespace() & IDNS;
1094}
1095
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001096/// Determines whether this given declaration will be found by
Douglas Gregor70febae2010-05-28 00:49:12 +00001097/// ordinary name lookup but is not a type name.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001098bool ResultBuilder::IsOrdinaryNonTypeName(const NamedDecl *ND) const {
George Burgess IV00f70bd2018-03-01 05:43:23 +00001099 ND = ND->getUnderlyingDecl();
Alex Lorenzf3df1f72017-11-14 01:46:24 +00001100 if (isa<TypeDecl>(ND))
Douglas Gregor70febae2010-05-28 00:49:12 +00001101 return false;
Alex Lorenzf3df1f72017-11-14 01:46:24 +00001102 // Objective-C interfaces names are not filtered by this method because they
1103 // can be used in a class property expression. We can still filter out
1104 // @class declarations though.
1105 if (const auto *ID = dyn_cast<ObjCInterfaceDecl>(ND)) {
1106 if (!ID->getDefinition())
1107 return false;
1108 }
1109
Richard Smith541b38b2013-09-20 01:15:31 +00001110 unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_LocalExtern;
David Blaikiebbafb8a2012-03-11 07:00:24 +00001111 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregor9858ed52010-06-15 20:26:51 +00001112 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member;
David Blaikiebbafb8a2012-03-11 07:00:24 +00001113 else if (SemaRef.getLangOpts().ObjC1) {
Douglas Gregor05fcf842010-11-02 20:36:02 +00001114 if (isa<ObjCIvarDecl>(ND))
1115 return true;
Douglas Gregor05fcf842010-11-02 20:36:02 +00001116 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001117
Douglas Gregor70febae2010-05-28 00:49:12 +00001118 return ND->getIdentifierNamespace() & IDNS;
1119}
1120
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001121bool ResultBuilder::IsIntegralConstantValue(const NamedDecl *ND) const {
Douglas Gregor85b50632010-07-28 21:50:18 +00001122 if (!IsOrdinaryNonTypeName(ND))
1123 return 0;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001124
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001125 if (const ValueDecl *VD = dyn_cast<ValueDecl>(ND->getUnderlyingDecl()))
Douglas Gregor85b50632010-07-28 21:50:18 +00001126 if (VD->getType()->isIntegralOrEnumerationType())
1127 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001128
Douglas Gregor85b50632010-07-28 21:50:18 +00001129 return false;
1130}
1131
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001132/// Determines whether this given declaration will be found by
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001133/// ordinary name lookup.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001134bool ResultBuilder::IsOrdinaryNonValueName(const NamedDecl *ND) const {
George Burgess IV00f70bd2018-03-01 05:43:23 +00001135 ND = ND->getUnderlyingDecl();
Douglas Gregor70febae2010-05-28 00:49:12 +00001136
Richard Smith541b38b2013-09-20 01:15:31 +00001137 unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_LocalExtern;
David Blaikiebbafb8a2012-03-11 07:00:24 +00001138 if (SemaRef.getLangOpts().CPlusPlus)
John McCalle87beb22010-04-23 18:46:30 +00001139 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001140
1141 return (ND->getIdentifierNamespace() & IDNS) &&
1142 !isa<ValueDecl>(ND) && !isa<FunctionTemplateDecl>(ND) &&
Douglas Gregor70febae2010-05-28 00:49:12 +00001143 !isa<ObjCPropertyDecl>(ND);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001144}
1145
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001146/// Determines whether the given declaration is suitable as the
Douglas Gregor3545ff42009-09-21 16:56:56 +00001147/// start of a C++ nested-name-specifier, e.g., a class or namespace.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001148bool ResultBuilder::IsNestedNameSpecifier(const NamedDecl *ND) const {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001149 // Allow us to find class templates, too.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001150 if (const ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
Douglas Gregor3545ff42009-09-21 16:56:56 +00001151 ND = ClassTemplate->getTemplatedDecl();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001152
Douglas Gregor3545ff42009-09-21 16:56:56 +00001153 return SemaRef.isAcceptableNestedNameSpecifier(ND);
1154}
1155
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001156/// Determines whether the given declaration is an enumeration.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001157bool ResultBuilder::IsEnum(const NamedDecl *ND) const {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001158 return isa<EnumDecl>(ND);
1159}
1160
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001161/// Determines whether the given declaration is a class or struct.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001162bool ResultBuilder::IsClassOrStruct(const NamedDecl *ND) const {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001163 // Allow us to find class templates, too.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001164 if (const ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
Douglas Gregor3545ff42009-09-21 16:56:56 +00001165 ND = ClassTemplate->getTemplatedDecl();
Joao Matosdc86f942012-08-31 18:45:21 +00001166
1167 // For purposes of this check, interfaces match too.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001168 if (const RecordDecl *RD = dyn_cast<RecordDecl>(ND))
Abramo Bagnara6150c882010-05-11 21:36:43 +00001169 return RD->getTagKind() == TTK_Class ||
Joao Matosdc86f942012-08-31 18:45:21 +00001170 RD->getTagKind() == TTK_Struct ||
1171 RD->getTagKind() == TTK_Interface;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001172
Douglas Gregor3545ff42009-09-21 16:56:56 +00001173 return false;
1174}
1175
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001176/// Determines whether the given declaration is a union.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001177bool ResultBuilder::IsUnion(const NamedDecl *ND) const {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001178 // Allow us to find class templates, too.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001179 if (const ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
Douglas Gregor3545ff42009-09-21 16:56:56 +00001180 ND = ClassTemplate->getTemplatedDecl();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001181
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001182 if (const RecordDecl *RD = dyn_cast<RecordDecl>(ND))
Abramo Bagnara6150c882010-05-11 21:36:43 +00001183 return RD->getTagKind() == TTK_Union;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001184
Douglas Gregor3545ff42009-09-21 16:56:56 +00001185 return false;
1186}
1187
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001188/// Determines whether the given declaration is a namespace.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001189bool ResultBuilder::IsNamespace(const NamedDecl *ND) const {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001190 return isa<NamespaceDecl>(ND);
1191}
1192
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001193/// Determines whether the given declaration is a namespace or
Douglas Gregor3545ff42009-09-21 16:56:56 +00001194/// namespace alias.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001195bool ResultBuilder::IsNamespaceOrAlias(const NamedDecl *ND) const {
Richard Smithf2005d32015-12-29 23:34:32 +00001196 return isa<NamespaceDecl>(ND->getUnderlyingDecl());
Douglas Gregor3545ff42009-09-21 16:56:56 +00001197}
1198
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001199/// Determines whether the given declaration is a type.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001200bool ResultBuilder::IsType(const NamedDecl *ND) const {
Richard Smithf2005d32015-12-29 23:34:32 +00001201 ND = ND->getUnderlyingDecl();
Douglas Gregor99fa2642010-08-24 01:06:58 +00001202 return isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND);
Douglas Gregor3545ff42009-09-21 16:56:56 +00001203}
1204
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001205/// Determines which members of a class should be visible via
Douglas Gregor99fe2ad2009-12-11 17:31:05 +00001206/// "." or "->". Only value declarations, nested name specifiers, and
1207/// using declarations thereof should show up.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001208bool ResultBuilder::IsMember(const NamedDecl *ND) const {
Richard Smithf2005d32015-12-29 23:34:32 +00001209 ND = ND->getUnderlyingDecl();
Douglas Gregor70788392009-12-11 18:14:22 +00001210 return isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND) ||
Richard Smithf2005d32015-12-29 23:34:32 +00001211 isa<ObjCPropertyDecl>(ND);
Douglas Gregore412a5a2009-09-23 22:26:46 +00001212}
1213
Douglas Gregora817a192010-05-27 23:06:34 +00001214static bool isObjCReceiverType(ASTContext &C, QualType T) {
1215 T = C.getCanonicalType(T);
1216 switch (T->getTypeClass()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001217 case Type::ObjCObject:
Douglas Gregora817a192010-05-27 23:06:34 +00001218 case Type::ObjCInterface:
1219 case Type::ObjCObjectPointer:
1220 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001221
Douglas Gregora817a192010-05-27 23:06:34 +00001222 case Type::Builtin:
1223 switch (cast<BuiltinType>(T)->getKind()) {
1224 case BuiltinType::ObjCId:
1225 case BuiltinType::ObjCClass:
1226 case BuiltinType::ObjCSel:
1227 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001228
Douglas Gregora817a192010-05-27 23:06:34 +00001229 default:
1230 break;
1231 }
1232 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001233
Douglas Gregora817a192010-05-27 23:06:34 +00001234 default:
1235 break;
1236 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001237
David Blaikiebbafb8a2012-03-11 07:00:24 +00001238 if (!C.getLangOpts().CPlusPlus)
Douglas Gregora817a192010-05-27 23:06:34 +00001239 return false;
1240
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001241 // FIXME: We could perform more analysis here to determine whether a
Douglas Gregora817a192010-05-27 23:06:34 +00001242 // particular class type has any conversions to Objective-C types. For now,
1243 // just accept all class types.
1244 return T->isDependentType() || T->isRecordType();
1245}
1246
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001247bool ResultBuilder::IsObjCMessageReceiver(const NamedDecl *ND) const {
Douglas Gregora817a192010-05-27 23:06:34 +00001248 QualType T = getDeclUsageType(SemaRef.Context, ND);
1249 if (T.isNull())
1250 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001251
Douglas Gregora817a192010-05-27 23:06:34 +00001252 T = SemaRef.Context.getBaseElementType(T);
1253 return isObjCReceiverType(SemaRef.Context, T);
1254}
1255
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001256bool ResultBuilder::IsObjCMessageReceiverOrLambdaCapture(const NamedDecl *ND) const {
Douglas Gregord8c61782012-02-15 15:34:24 +00001257 if (IsObjCMessageReceiver(ND))
1258 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001259
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001260 const VarDecl *Var = dyn_cast<VarDecl>(ND);
Douglas Gregord8c61782012-02-15 15:34:24 +00001261 if (!Var)
1262 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001263
Douglas Gregord8c61782012-02-15 15:34:24 +00001264 return Var->hasLocalStorage() && !Var->hasAttr<BlocksAttr>();
1265}
1266
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001267bool ResultBuilder::IsObjCCollection(const NamedDecl *ND) const {
David Blaikiebbafb8a2012-03-11 07:00:24 +00001268 if ((SemaRef.getLangOpts().CPlusPlus && !IsOrdinaryName(ND)) ||
1269 (!SemaRef.getLangOpts().CPlusPlus && !IsOrdinaryNonTypeName(ND)))
Douglas Gregor68762e72010-08-23 21:17:50 +00001270 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001271
Douglas Gregor68762e72010-08-23 21:17:50 +00001272 QualType T = getDeclUsageType(SemaRef.Context, ND);
1273 if (T.isNull())
1274 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001275
Douglas Gregor68762e72010-08-23 21:17:50 +00001276 T = SemaRef.Context.getBaseElementType(T);
1277 return T->isObjCObjectType() || T->isObjCObjectPointerType() ||
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001278 T->isObjCIdType() ||
David Blaikiebbafb8a2012-03-11 07:00:24 +00001279 (SemaRef.getLangOpts().CPlusPlus && T->isRecordType());
Douglas Gregor68762e72010-08-23 21:17:50 +00001280}
Douglas Gregora817a192010-05-27 23:06:34 +00001281
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001282bool ResultBuilder::IsImpossibleToSatisfy(const NamedDecl *ND) const {
Douglas Gregor0ac41382010-09-23 23:01:17 +00001283 return false;
1284}
1285
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001286/// Determines whether the given declaration is an Objective-C
Douglas Gregor2b8162b2010-01-14 16:08:12 +00001287/// instance variable.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001288bool ResultBuilder::IsObjCIvar(const NamedDecl *ND) const {
Douglas Gregor2b8162b2010-01-14 16:08:12 +00001289 return isa<ObjCIvarDecl>(ND);
1290}
1291
Douglas Gregorc580c522010-01-14 01:09:38 +00001292namespace {
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001293 /// Visible declaration consumer that adds a code-completion result
Douglas Gregorc580c522010-01-14 01:09:38 +00001294 /// for each visible declaration.
1295 class CodeCompletionDeclConsumer : public VisibleDeclConsumer {
1296 ResultBuilder &Results;
1297 DeclContext *CurContext;
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00001298 std::vector<FixItHint> FixIts;
Eric Liub91e0812018-10-02 10:29:00 +00001299 // This is set to the record where the search starts, if this is a record
1300 // member completion.
1301 RecordDecl *MemberCompletionRecord = nullptr;
Haojian Wu10d95c52018-01-17 14:29:25 +00001302
Douglas Gregorc580c522010-01-14 01:09:38 +00001303 public:
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00001304 CodeCompletionDeclConsumer(
1305 ResultBuilder &Results, DeclContext *CurContext,
Eric Liub91e0812018-10-02 10:29:00 +00001306 std::vector<FixItHint> FixIts = std::vector<FixItHint>(),
1307 RecordDecl *MemberCompletionRecord = nullptr)
1308 : Results(Results), CurContext(CurContext), FixIts(std::move(FixIts)),
1309 MemberCompletionRecord(MemberCompletionRecord) {}
Craig Toppere14c0f82014-03-12 04:55:44 +00001310
1311 void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx,
1312 bool InBaseClass) override {
Erik Verbruggen2e657ff2011-10-06 07:27:49 +00001313 bool Accessible = true;
Eric Liub91e0812018-10-02 10:29:00 +00001314 if (Ctx) {
1315 // Set the actual accessing context (i.e. naming class) to the record
1316 // context where the search starts. When `InBaseClass` is true, `Ctx`
1317 // will be the base class, which is not the actual naming class.
1318 DeclContext *AccessingCtx =
1319 MemberCompletionRecord ? MemberCompletionRecord : Ctx;
1320 Accessible = Results.getSema().IsSimplyAccessible(ND, AccessingCtx);
1321 }
Craig Topperc3ec1492014-05-26 06:22:03 +00001322 ResultBuilder::Result Result(ND, Results.getBasePriority(ND), nullptr,
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00001323 false, Accessible, FixIts);
Erik Verbruggen2e657ff2011-10-06 07:27:49 +00001324 Results.AddResult(Result, CurContext, Hiding, InBaseClass);
Douglas Gregorc580c522010-01-14 01:09:38 +00001325 }
Haojian Wu10d95c52018-01-17 14:29:25 +00001326
1327 void EnteredContext(DeclContext* Ctx) override {
1328 Results.addVisitedContext(Ctx);
1329 }
Douglas Gregorc580c522010-01-14 01:09:38 +00001330 };
Alexander Kornienkoab9db512015-06-22 23:07:51 +00001331}
Douglas Gregorc580c522010-01-14 01:09:38 +00001332
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001333/// Add type specifiers for the current language as keyword results.
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001334static void AddTypeSpecifierResults(const LangOptions &LangOpts,
Douglas Gregor3545ff42009-09-21 16:56:56 +00001335 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00001336 typedef CodeCompletionResult Result;
Douglas Gregora2db7932010-05-26 22:00:08 +00001337 Results.AddResult(Result("short", CCP_Type));
1338 Results.AddResult(Result("long", CCP_Type));
1339 Results.AddResult(Result("signed", CCP_Type));
1340 Results.AddResult(Result("unsigned", CCP_Type));
1341 Results.AddResult(Result("void", CCP_Type));
1342 Results.AddResult(Result("char", CCP_Type));
1343 Results.AddResult(Result("int", CCP_Type));
1344 Results.AddResult(Result("float", CCP_Type));
1345 Results.AddResult(Result("double", CCP_Type));
1346 Results.AddResult(Result("enum", CCP_Type));
1347 Results.AddResult(Result("struct", CCP_Type));
1348 Results.AddResult(Result("union", CCP_Type));
1349 Results.AddResult(Result("const", CCP_Type));
1350 Results.AddResult(Result("volatile", CCP_Type));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001351
Douglas Gregor3545ff42009-09-21 16:56:56 +00001352 if (LangOpts.C99) {
1353 // C99-specific
Douglas Gregora2db7932010-05-26 22:00:08 +00001354 Results.AddResult(Result("_Complex", CCP_Type));
1355 Results.AddResult(Result("_Imaginary", CCP_Type));
1356 Results.AddResult(Result("_Bool", CCP_Type));
1357 Results.AddResult(Result("restrict", CCP_Type));
Douglas Gregor3545ff42009-09-21 16:56:56 +00001358 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001359
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00001360 CodeCompletionBuilder Builder(Results.getAllocator(),
1361 Results.getCodeCompletionTUInfo());
Douglas Gregor3545ff42009-09-21 16:56:56 +00001362 if (LangOpts.CPlusPlus) {
1363 // C++-specific
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001364 Results.AddResult(Result("bool", CCP_Type +
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00001365 (LangOpts.ObjC1? CCD_bool_in_ObjC : 0)));
Douglas Gregora2db7932010-05-26 22:00:08 +00001366 Results.AddResult(Result("class", CCP_Type));
1367 Results.AddResult(Result("wchar_t", CCP_Type));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001368
Douglas Gregorf4c33342010-05-28 00:22:41 +00001369 // typename qualified-id
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001370 Builder.AddTypedTextChunk("typename");
1371 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1372 Builder.AddPlaceholderChunk("qualifier");
1373 Builder.AddTextChunk("::");
1374 Builder.AddPlaceholderChunk("name");
1375 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001376
Richard Smith2bf7fdb2013-01-02 11:42:31 +00001377 if (LangOpts.CPlusPlus11) {
Douglas Gregora2db7932010-05-26 22:00:08 +00001378 Results.AddResult(Result("auto", CCP_Type));
1379 Results.AddResult(Result("char16_t", CCP_Type));
1380 Results.AddResult(Result("char32_t", CCP_Type));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001381
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001382 Builder.AddTypedTextChunk("decltype");
1383 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1384 Builder.AddPlaceholderChunk("expression");
1385 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1386 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor3545ff42009-09-21 16:56:56 +00001387 }
Alex Lorenz46eed9d2017-02-13 23:35:59 +00001388 } else
1389 Results.AddResult(Result("__auto_type", CCP_Type));
1390
Richard Smith7b301e22018-05-24 21:51:52 +00001391 // GNU keywords
1392 if (LangOpts.GNUKeywords) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001393 // FIXME: Enable when we actually support decimal floating point.
Douglas Gregor78a21012010-01-14 16:01:26 +00001394 // Results.AddResult(Result("_Decimal32"));
1395 // Results.AddResult(Result("_Decimal64"));
1396 // Results.AddResult(Result("_Decimal128"));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001397
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001398 Builder.AddTypedTextChunk("typeof");
1399 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1400 Builder.AddPlaceholderChunk("expression");
1401 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00001402
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001403 Builder.AddTypedTextChunk("typeof");
1404 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1405 Builder.AddPlaceholderChunk("type");
1406 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1407 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor3545ff42009-09-21 16:56:56 +00001408 }
Douglas Gregor86b42682015-06-19 18:27:52 +00001409
1410 // Nullability
Douglas Gregoraea7afd2015-06-24 22:02:08 +00001411 Results.AddResult(Result("_Nonnull", CCP_Type));
1412 Results.AddResult(Result("_Null_unspecified", CCP_Type));
1413 Results.AddResult(Result("_Nullable", CCP_Type));
Douglas Gregor3545ff42009-09-21 16:56:56 +00001414}
1415
John McCallfaf5fb42010-08-26 23:41:50 +00001416static void AddStorageSpecifiers(Sema::ParserCompletionContext CCC,
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001417 const LangOptions &LangOpts,
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001418 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00001419 typedef CodeCompletionResult Result;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001420 // Note: we don't suggest either "auto" or "register", because both
1421 // are pointless as storage specifiers. Elsewhere, we suggest "auto"
1422 // in C++0x as a type specifier.
Douglas Gregor78a21012010-01-14 16:01:26 +00001423 Results.AddResult(Result("extern"));
1424 Results.AddResult(Result("static"));
Alex Lorenz8f4d3992017-02-13 23:19:40 +00001425
1426 if (LangOpts.CPlusPlus11) {
1427 CodeCompletionAllocator &Allocator = Results.getAllocator();
1428 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
1429
1430 // alignas
1431 Builder.AddTypedTextChunk("alignas");
1432 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1433 Builder.AddPlaceholderChunk("expression");
1434 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1435 Results.AddResult(Result(Builder.TakeString()));
1436
1437 Results.AddResult(Result("constexpr"));
1438 Results.AddResult(Result("thread_local"));
1439 }
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001440}
1441
John McCallfaf5fb42010-08-26 23:41:50 +00001442static void AddFunctionSpecifiers(Sema::ParserCompletionContext CCC,
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001443 const LangOptions &LangOpts,
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001444 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00001445 typedef CodeCompletionResult Result;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001446 switch (CCC) {
John McCallfaf5fb42010-08-26 23:41:50 +00001447 case Sema::PCC_Class:
1448 case Sema::PCC_MemberTemplate:
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001449 if (LangOpts.CPlusPlus) {
Douglas Gregor78a21012010-01-14 16:01:26 +00001450 Results.AddResult(Result("explicit"));
1451 Results.AddResult(Result("friend"));
1452 Results.AddResult(Result("mutable"));
1453 Results.AddResult(Result("virtual"));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001454 }
Adrian Prantlf3b3ccd2017-12-19 22:06:11 +00001455 LLVM_FALLTHROUGH;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001456
John McCallfaf5fb42010-08-26 23:41:50 +00001457 case Sema::PCC_ObjCInterface:
1458 case Sema::PCC_ObjCImplementation:
1459 case Sema::PCC_Namespace:
1460 case Sema::PCC_Template:
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001461 if (LangOpts.CPlusPlus || LangOpts.C99)
Douglas Gregor78a21012010-01-14 16:01:26 +00001462 Results.AddResult(Result("inline"));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001463 break;
1464
John McCallfaf5fb42010-08-26 23:41:50 +00001465 case Sema::PCC_ObjCInstanceVariableList:
1466 case Sema::PCC_Expression:
1467 case Sema::PCC_Statement:
1468 case Sema::PCC_ForInit:
1469 case Sema::PCC_Condition:
1470 case Sema::PCC_RecoveryInFunction:
1471 case Sema::PCC_Type:
Douglas Gregor5e35d592010-09-14 23:59:36 +00001472 case Sema::PCC_ParenthesizedExpression:
Douglas Gregor80039242011-02-15 20:33:25 +00001473 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001474 break;
1475 }
1476}
1477
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001478static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt);
1479static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt);
1480static void AddObjCVisibilityResults(const LangOptions &LangOpts,
Douglas Gregor48d46252010-01-13 21:54:15 +00001481 ResultBuilder &Results,
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001482 bool NeedAt);
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001483static void AddObjCImplementationResults(const LangOptions &LangOpts,
Douglas Gregorf1934162010-01-13 21:24:21 +00001484 ResultBuilder &Results,
1485 bool NeedAt);
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001486static void AddObjCInterfaceResults(const LangOptions &LangOpts,
Douglas Gregorf1934162010-01-13 21:24:21 +00001487 ResultBuilder &Results,
1488 bool NeedAt);
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001489static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt);
Douglas Gregorf1934162010-01-13 21:24:21 +00001490
Douglas Gregorf4c33342010-05-28 00:22:41 +00001491static void AddTypedefResult(ResultBuilder &Results) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00001492 CodeCompletionBuilder Builder(Results.getAllocator(),
1493 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001494 Builder.AddTypedTextChunk("typedef");
1495 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1496 Builder.AddPlaceholderChunk("type");
1497 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1498 Builder.AddPlaceholderChunk("name");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001499 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00001500}
1501
John McCallfaf5fb42010-08-26 23:41:50 +00001502static bool WantTypesInContext(Sema::ParserCompletionContext CCC,
Douglas Gregor70febae2010-05-28 00:49:12 +00001503 const LangOptions &LangOpts) {
Douglas Gregor70febae2010-05-28 00:49:12 +00001504 switch (CCC) {
John McCallfaf5fb42010-08-26 23:41:50 +00001505 case Sema::PCC_Namespace:
1506 case Sema::PCC_Class:
1507 case Sema::PCC_ObjCInstanceVariableList:
1508 case Sema::PCC_Template:
1509 case Sema::PCC_MemberTemplate:
1510 case Sema::PCC_Statement:
1511 case Sema::PCC_RecoveryInFunction:
1512 case Sema::PCC_Type:
Douglas Gregor5e35d592010-09-14 23:59:36 +00001513 case Sema::PCC_ParenthesizedExpression:
Douglas Gregor80039242011-02-15 20:33:25 +00001514 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregor70febae2010-05-28 00:49:12 +00001515 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001516
John McCallfaf5fb42010-08-26 23:41:50 +00001517 case Sema::PCC_Expression:
1518 case Sema::PCC_Condition:
Douglas Gregor5e35d592010-09-14 23:59:36 +00001519 return LangOpts.CPlusPlus;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001520
Douglas Gregor5e35d592010-09-14 23:59:36 +00001521 case Sema::PCC_ObjCInterface:
1522 case Sema::PCC_ObjCImplementation:
Douglas Gregor70febae2010-05-28 00:49:12 +00001523 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001524
John McCallfaf5fb42010-08-26 23:41:50 +00001525 case Sema::PCC_ForInit:
Douglas Gregor5e35d592010-09-14 23:59:36 +00001526 return LangOpts.CPlusPlus || LangOpts.ObjC1 || LangOpts.C99;
Douglas Gregor70febae2010-05-28 00:49:12 +00001527 }
David Blaikie8a40f702012-01-17 06:56:22 +00001528
1529 llvm_unreachable("Invalid ParserCompletionContext!");
Douglas Gregor70febae2010-05-28 00:49:12 +00001530}
1531
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00001532static PrintingPolicy getCompletionPrintingPolicy(const ASTContext &Context,
1533 const Preprocessor &PP) {
1534 PrintingPolicy Policy = Sema::getPrintingPolicy(Context, PP);
Douglas Gregore5c79d52011-10-18 21:20:17 +00001535 Policy.AnonymousTagLocations = false;
1536 Policy.SuppressStrongLifetime = true;
Douglas Gregor2e10cf92011-11-03 00:16:13 +00001537 Policy.SuppressUnwrittenScope = true;
Ilya Biryukovb5da91c2017-11-08 10:39:09 +00001538 Policy.SuppressScope = true;
Douglas Gregore5c79d52011-10-18 21:20:17 +00001539 return Policy;
1540}
1541
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001542/// Retrieve a printing policy suitable for code completion.
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00001543static PrintingPolicy getCompletionPrintingPolicy(Sema &S) {
1544 return getCompletionPrintingPolicy(S.Context, S.PP);
1545}
1546
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001547/// Retrieve the string representation of the given type as a string
Douglas Gregore5c79d52011-10-18 21:20:17 +00001548/// that has the appropriate lifetime for code completion.
1549///
1550/// This routine provides a fast path where we provide constant strings for
1551/// common type names.
1552static const char *GetCompletionTypeString(QualType T,
1553 ASTContext &Context,
1554 const PrintingPolicy &Policy,
1555 CodeCompletionAllocator &Allocator) {
1556 if (!T.getLocalQualifiers()) {
1557 // Built-in type names are constant strings.
1558 if (const BuiltinType *BT = dyn_cast<BuiltinType>(T))
Argyrios Kyrtzidisbbff3da2012-05-05 04:20:28 +00001559 return BT->getNameAsCString(Policy);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001560
Douglas Gregore5c79d52011-10-18 21:20:17 +00001561 // Anonymous tag types are constant strings.
1562 if (const TagType *TagT = dyn_cast<TagType>(T))
1563 if (TagDecl *Tag = TagT->getDecl())
John McCall5ea95772013-03-09 00:54:27 +00001564 if (!Tag->hasNameForLinkage()) {
Douglas Gregore5c79d52011-10-18 21:20:17 +00001565 switch (Tag->getTagKind()) {
1566 case TTK_Struct: return "struct <anonymous>";
Joao Matosdc86f942012-08-31 18:45:21 +00001567 case TTK_Interface: return "__interface <anonymous>";
1568 case TTK_Class: return "class <anonymous>";
Douglas Gregore5c79d52011-10-18 21:20:17 +00001569 case TTK_Union: return "union <anonymous>";
1570 case TTK_Enum: return "enum <anonymous>";
1571 }
1572 }
1573 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001574
Douglas Gregore5c79d52011-10-18 21:20:17 +00001575 // Slow path: format the type as a string.
1576 std::string Result;
1577 T.getAsStringInternal(Result, Policy);
1578 return Allocator.CopyString(Result);
1579}
1580
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001581/// Add a completion for "this", if we're in a member function.
Douglas Gregord8c61782012-02-15 15:34:24 +00001582static void addThisCompletion(Sema &S, ResultBuilder &Results) {
1583 QualType ThisTy = S.getCurrentThisType();
1584 if (ThisTy.isNull())
1585 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001586
Douglas Gregord8c61782012-02-15 15:34:24 +00001587 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00001588 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Douglas Gregord8c61782012-02-15 15:34:24 +00001589 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001590 Builder.AddResultTypeChunk(GetCompletionTypeString(ThisTy,
1591 S.Context,
Douglas Gregord8c61782012-02-15 15:34:24 +00001592 Policy,
1593 Allocator));
1594 Builder.AddTypedTextChunk("this");
Joao Matosdc86f942012-08-31 18:45:21 +00001595 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
Douglas Gregord8c61782012-02-15 15:34:24 +00001596}
1597
Alex Lorenz8f4d3992017-02-13 23:19:40 +00001598static void AddStaticAssertResult(CodeCompletionBuilder &Builder,
1599 ResultBuilder &Results,
1600 const LangOptions &LangOpts) {
1601 if (!LangOpts.CPlusPlus11)
1602 return;
1603
1604 Builder.AddTypedTextChunk("static_assert");
1605 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1606 Builder.AddPlaceholderChunk("expression");
1607 Builder.AddChunk(CodeCompletionString::CK_Comma);
1608 Builder.AddPlaceholderChunk("message");
1609 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1610 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
1611}
1612
Kadir Cetinkayaae45d0a42018-10-02 09:42:31 +00001613namespace {
1614void printOverrideString(llvm::raw_ostream &OS, CodeCompletionString *CCS) {
1615 for (const auto &C : *CCS) {
1616 if (C.Kind == CodeCompletionString::CK_Optional)
1617 printOverrideString(OS, C.Optional);
1618 else
1619 OS << C.Text;
1620 // Add a space after return type.
1621 if (C.Kind == CodeCompletionString::CK_ResultType)
1622 OS << ' ';
1623 }
1624}
1625} // namespace
1626
1627static void AddOverrideResults(ResultBuilder &Results,
1628 const CodeCompletionContext &CCContext,
1629 CodeCompletionBuilder &Builder) {
1630 Sema &S = Results.getSema();
1631 const auto *CR = llvm::dyn_cast<CXXRecordDecl>(S.CurContext);
1632 // If not inside a class/struct/union return empty.
1633 if (!CR)
1634 return;
1635 // First store overrides within current class.
1636 // These are stored by name to make querying fast in the later step.
1637 llvm::StringMap<std::vector<FunctionDecl *>> Overrides;
1638 for (auto *Method : CR->methods()) {
1639 if (!Method->isVirtual() || !Method->getIdentifier())
1640 continue;
1641 Overrides[Method->getName()].push_back(Method);
1642 }
1643
1644 for (const auto &Base : CR->bases()) {
1645 const auto *BR = Base.getType().getTypePtr()->getAsCXXRecordDecl();
1646 if (!BR)
1647 continue;
1648 for (auto *Method : BR->methods()) {
1649 if (!Method->isVirtual() || !Method->getIdentifier())
1650 continue;
1651 const auto it = Overrides.find(Method->getName());
1652 bool IsOverriden = false;
1653 if (it != Overrides.end()) {
1654 for (auto *MD : it->second) {
1655 // If the method in current body is not an overload of this virtual
1656 // function, then it overrides this one.
1657 if (!S.IsOverload(MD, Method, false)) {
1658 IsOverriden = true;
1659 break;
1660 }
1661 }
1662 }
1663 if (!IsOverriden) {
1664 // Generates a new CodeCompletionResult by taking this function and
1665 // converting it into an override declaration with only one chunk in the
1666 // final CodeCompletionString as a TypedTextChunk.
1667 std::string OverrideSignature;
1668 llvm::raw_string_ostream OS(OverrideSignature);
1669 CodeCompletionResult CCR(Method, 0);
1670 PrintingPolicy Policy =
1671 getCompletionPrintingPolicy(S.getASTContext(), S.getPreprocessor());
1672 auto *CCS = CCR.createCodeCompletionStringForOverride(
1673 S.getPreprocessor(), S.getASTContext(), Builder,
1674 /*IncludeBriefComments=*/false, CCContext, Policy);
1675 Results.AddResult(CodeCompletionResult(CCS, Method, CCP_CodePattern));
1676 }
1677 }
1678 }
1679}
1680
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001681/// Add language constructs that show up for "ordinary" names.
John McCallfaf5fb42010-08-26 23:41:50 +00001682static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001683 Scope *S,
1684 Sema &SemaRef,
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001685 ResultBuilder &Results) {
Douglas Gregore5c79d52011-10-18 21:20:17 +00001686 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00001687 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001688
John McCall276321a2010-08-25 06:19:51 +00001689 typedef CodeCompletionResult Result;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001690 switch (CCC) {
John McCallfaf5fb42010-08-26 23:41:50 +00001691 case Sema::PCC_Namespace:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001692 if (SemaRef.getLangOpts().CPlusPlus) {
Douglas Gregorf4c33342010-05-28 00:22:41 +00001693 if (Results.includeCodePatterns()) {
1694 // namespace <identifier> { declarations }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001695 Builder.AddTypedTextChunk("namespace");
1696 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1697 Builder.AddPlaceholderChunk("identifier");
1698 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1699 Builder.AddPlaceholderChunk("declarations");
1700 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1701 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1702 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00001703 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001704
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001705 // namespace identifier = identifier ;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001706 Builder.AddTypedTextChunk("namespace");
1707 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1708 Builder.AddPlaceholderChunk("name");
1709 Builder.AddChunk(CodeCompletionString::CK_Equal);
1710 Builder.AddPlaceholderChunk("namespace");
1711 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001712
1713 // Using directives
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001714 Builder.AddTypedTextChunk("using");
1715 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1716 Builder.AddTextChunk("namespace");
1717 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1718 Builder.AddPlaceholderChunk("identifier");
1719 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001720
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001721 // asm(string-literal)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001722 Builder.AddTypedTextChunk("asm");
1723 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1724 Builder.AddPlaceholderChunk("string-literal");
1725 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1726 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001727
Douglas Gregorf4c33342010-05-28 00:22:41 +00001728 if (Results.includeCodePatterns()) {
1729 // Explicit template instantiation
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001730 Builder.AddTypedTextChunk("template");
1731 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1732 Builder.AddPlaceholderChunk("declaration");
1733 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00001734 }
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001735 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001736
David Blaikiebbafb8a2012-03-11 07:00:24 +00001737 if (SemaRef.getLangOpts().ObjC1)
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001738 AddObjCTopLevelResults(Results, true);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001739
Douglas Gregorf4c33342010-05-28 00:22:41 +00001740 AddTypedefResult(Results);
Adrian Prantlf3b3ccd2017-12-19 22:06:11 +00001741 LLVM_FALLTHROUGH;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001742
John McCallfaf5fb42010-08-26 23:41:50 +00001743 case Sema::PCC_Class:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001744 if (SemaRef.getLangOpts().CPlusPlus) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001745 // Using declaration
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001746 Builder.AddTypedTextChunk("using");
1747 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1748 Builder.AddPlaceholderChunk("qualifier");
1749 Builder.AddTextChunk("::");
1750 Builder.AddPlaceholderChunk("name");
1751 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001752
Douglas Gregorf4c33342010-05-28 00:22:41 +00001753 // using typename qualifier::name (only in a dependent context)
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001754 if (SemaRef.CurContext->isDependentContext()) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001755 Builder.AddTypedTextChunk("using");
1756 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1757 Builder.AddTextChunk("typename");
1758 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1759 Builder.AddPlaceholderChunk("qualifier");
1760 Builder.AddTextChunk("::");
1761 Builder.AddPlaceholderChunk("name");
1762 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001763 }
1764
Alex Lorenz8f4d3992017-02-13 23:19:40 +00001765 AddStaticAssertResult(Builder, Results, SemaRef.getLangOpts());
1766
John McCallfaf5fb42010-08-26 23:41:50 +00001767 if (CCC == Sema::PCC_Class) {
Douglas Gregorf4c33342010-05-28 00:22:41 +00001768 AddTypedefResult(Results);
1769
Erik Verbruggen6524c052017-10-24 13:46:58 +00001770 bool IsNotInheritanceScope =
1771 !(S->getFlags() & Scope::ClassInheritanceScope);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001772 // public:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001773 Builder.AddTypedTextChunk("public");
Erik Verbruggen6524c052017-10-24 13:46:58 +00001774 if (IsNotInheritanceScope && Results.includeCodePatterns())
Douglas Gregor9489cdf2012-04-10 17:56:28 +00001775 Builder.AddChunk(CodeCompletionString::CK_Colon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001776 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001777
1778 // protected:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001779 Builder.AddTypedTextChunk("protected");
Erik Verbruggen6524c052017-10-24 13:46:58 +00001780 if (IsNotInheritanceScope && Results.includeCodePatterns())
Douglas Gregor9489cdf2012-04-10 17:56:28 +00001781 Builder.AddChunk(CodeCompletionString::CK_Colon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001782 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001783
1784 // private:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001785 Builder.AddTypedTextChunk("private");
Erik Verbruggen6524c052017-10-24 13:46:58 +00001786 if (IsNotInheritanceScope && Results.includeCodePatterns())
Douglas Gregor9489cdf2012-04-10 17:56:28 +00001787 Builder.AddChunk(CodeCompletionString::CK_Colon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001788 Results.AddResult(Result(Builder.TakeString()));
Kadir Cetinkayaae45d0a42018-10-02 09:42:31 +00001789
1790 // FIXME: This adds override results only if we are at the first word of
1791 // the declaration/definition. Also call this from other sides to have
1792 // more use-cases.
1793 AddOverrideResults(Results, CodeCompletionContext::CCC_ClassStructUnion,
1794 Builder);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001795 }
1796 }
Adrian Prantlf3b3ccd2017-12-19 22:06:11 +00001797 LLVM_FALLTHROUGH;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001798
John McCallfaf5fb42010-08-26 23:41:50 +00001799 case Sema::PCC_Template:
1800 case Sema::PCC_MemberTemplate:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001801 if (SemaRef.getLangOpts().CPlusPlus && Results.includeCodePatterns()) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001802 // template < parameters >
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001803 Builder.AddTypedTextChunk("template");
1804 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1805 Builder.AddPlaceholderChunk("parameters");
1806 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1807 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001808 }
1809
David Blaikiebbafb8a2012-03-11 07:00:24 +00001810 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
1811 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001812 break;
1813
John McCallfaf5fb42010-08-26 23:41:50 +00001814 case Sema::PCC_ObjCInterface:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001815 AddObjCInterfaceResults(SemaRef.getLangOpts(), Results, true);
1816 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
1817 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregorf1934162010-01-13 21:24:21 +00001818 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001819
John McCallfaf5fb42010-08-26 23:41:50 +00001820 case Sema::PCC_ObjCImplementation:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001821 AddObjCImplementationResults(SemaRef.getLangOpts(), Results, true);
1822 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
1823 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregorf1934162010-01-13 21:24:21 +00001824 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001825
John McCallfaf5fb42010-08-26 23:41:50 +00001826 case Sema::PCC_ObjCInstanceVariableList:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001827 AddObjCVisibilityResults(SemaRef.getLangOpts(), Results, true);
Douglas Gregor48d46252010-01-13 21:54:15 +00001828 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001829
John McCallfaf5fb42010-08-26 23:41:50 +00001830 case Sema::PCC_RecoveryInFunction:
1831 case Sema::PCC_Statement: {
Douglas Gregorf4c33342010-05-28 00:22:41 +00001832 AddTypedefResult(Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001833
David Blaikiebbafb8a2012-03-11 07:00:24 +00001834 if (SemaRef.getLangOpts().CPlusPlus && Results.includeCodePatterns() &&
1835 SemaRef.getLangOpts().CXXExceptions) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001836 Builder.AddTypedTextChunk("try");
1837 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1838 Builder.AddPlaceholderChunk("statements");
1839 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1840 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1841 Builder.AddTextChunk("catch");
1842 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1843 Builder.AddPlaceholderChunk("declaration");
1844 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1845 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1846 Builder.AddPlaceholderChunk("statements");
1847 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1848 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1849 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001850 }
David Blaikiebbafb8a2012-03-11 07:00:24 +00001851 if (SemaRef.getLangOpts().ObjC1)
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001852 AddObjCStatementResults(Results, true);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001853
Douglas Gregorf64acca2010-05-25 21:41:55 +00001854 if (Results.includeCodePatterns()) {
1855 // if (condition) { statements }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001856 Builder.AddTypedTextChunk("if");
1857 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00001858 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001859 Builder.AddPlaceholderChunk("condition");
Douglas Gregorf64acca2010-05-25 21:41:55 +00001860 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001861 Builder.AddPlaceholderChunk("expression");
1862 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1863 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1864 Builder.AddPlaceholderChunk("statements");
1865 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1866 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1867 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001868
Douglas Gregorf64acca2010-05-25 21:41:55 +00001869 // switch (condition) { }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001870 Builder.AddTypedTextChunk("switch");
1871 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00001872 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001873 Builder.AddPlaceholderChunk("condition");
Douglas Gregorf64acca2010-05-25 21:41:55 +00001874 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001875 Builder.AddPlaceholderChunk("expression");
1876 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1877 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1878 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1879 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1880 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf64acca2010-05-25 21:41:55 +00001881 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001882
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001883 // Switch-specific statements.
Sam McCallaeb4b3e2018-10-10 10:51:48 +00001884 if (SemaRef.getCurFunction() &&
1885 !SemaRef.getCurFunction()->SwitchStack.empty()) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001886 // case expression:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001887 Builder.AddTypedTextChunk("case");
1888 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1889 Builder.AddPlaceholderChunk("expression");
1890 Builder.AddChunk(CodeCompletionString::CK_Colon);
1891 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001892
1893 // default:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001894 Builder.AddTypedTextChunk("default");
1895 Builder.AddChunk(CodeCompletionString::CK_Colon);
1896 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001897 }
1898
Douglas Gregorf64acca2010-05-25 21:41:55 +00001899 if (Results.includeCodePatterns()) {
1900 /// while (condition) { statements }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001901 Builder.AddTypedTextChunk("while");
1902 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00001903 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001904 Builder.AddPlaceholderChunk("condition");
Douglas Gregorf64acca2010-05-25 21:41:55 +00001905 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001906 Builder.AddPlaceholderChunk("expression");
1907 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1908 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1909 Builder.AddPlaceholderChunk("statements");
1910 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1911 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1912 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf64acca2010-05-25 21:41:55 +00001913
1914 // do { statements } while ( expression );
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001915 Builder.AddTypedTextChunk("do");
1916 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1917 Builder.AddPlaceholderChunk("statements");
1918 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1919 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1920 Builder.AddTextChunk("while");
1921 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1922 Builder.AddPlaceholderChunk("expression");
1923 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1924 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001925
Douglas Gregorf64acca2010-05-25 21:41:55 +00001926 // for ( for-init-statement ; condition ; expression ) { statements }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001927 Builder.AddTypedTextChunk("for");
1928 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00001929 if (SemaRef.getLangOpts().CPlusPlus || SemaRef.getLangOpts().C99)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001930 Builder.AddPlaceholderChunk("init-statement");
Douglas Gregorf64acca2010-05-25 21:41:55 +00001931 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001932 Builder.AddPlaceholderChunk("init-expression");
1933 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
1934 Builder.AddPlaceholderChunk("condition");
1935 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
1936 Builder.AddPlaceholderChunk("inc-expression");
1937 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1938 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1939 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1940 Builder.AddPlaceholderChunk("statements");
1941 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1942 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1943 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf64acca2010-05-25 21:41:55 +00001944 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001945
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001946 if (S->getContinueParent()) {
1947 // continue ;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001948 Builder.AddTypedTextChunk("continue");
1949 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001950 }
1951
1952 if (S->getBreakParent()) {
1953 // break ;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001954 Builder.AddTypedTextChunk("break");
1955 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001956 }
1957
1958 // "return expression ;" or "return ;", depending on whether we
1959 // know the function is void or not.
1960 bool isVoid = false;
1961 if (FunctionDecl *Function = dyn_cast<FunctionDecl>(SemaRef.CurContext))
Alp Toker314cc812014-01-25 16:55:45 +00001962 isVoid = Function->getReturnType()->isVoidType();
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001963 else if (ObjCMethodDecl *Method
1964 = dyn_cast<ObjCMethodDecl>(SemaRef.CurContext))
Alp Toker314cc812014-01-25 16:55:45 +00001965 isVoid = Method->getReturnType()->isVoidType();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001966 else if (SemaRef.getCurBlock() &&
Douglas Gregor9a28e842010-03-01 23:15:13 +00001967 !SemaRef.getCurBlock()->ReturnType.isNull())
1968 isVoid = SemaRef.getCurBlock()->ReturnType->isVoidType();
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001969 Builder.AddTypedTextChunk("return");
Douglas Gregor44272ca2010-02-18 04:06:48 +00001970 if (!isVoid) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001971 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1972 Builder.AddPlaceholderChunk("expression");
Douglas Gregor44272ca2010-02-18 04:06:48 +00001973 }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001974 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001975
Douglas Gregorf4c33342010-05-28 00:22:41 +00001976 // goto identifier ;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001977 Builder.AddTypedTextChunk("goto");
1978 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1979 Builder.AddPlaceholderChunk("label");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001980 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001981
Douglas Gregorf4c33342010-05-28 00:22:41 +00001982 // Using directives
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001983 Builder.AddTypedTextChunk("using");
1984 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1985 Builder.AddTextChunk("namespace");
1986 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1987 Builder.AddPlaceholderChunk("identifier");
1988 Results.AddResult(Result(Builder.TakeString()));
Alex Lorenz8f4d3992017-02-13 23:19:40 +00001989
1990 AddStaticAssertResult(Builder, Results, SemaRef.getLangOpts());
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001991 }
Galina Kistanovabe3ba9da2017-06-07 06:31:55 +00001992 LLVM_FALLTHROUGH;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001993
1994 // Fall through (for statement expressions).
John McCallfaf5fb42010-08-26 23:41:50 +00001995 case Sema::PCC_ForInit:
1996 case Sema::PCC_Condition:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001997 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001998 // Fall through: conditions and statements can have expressions.
Galina Kistanova33399112017-06-03 06:35:06 +00001999 LLVM_FALLTHROUGH;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002000
Douglas Gregor5e35d592010-09-14 23:59:36 +00002001 case Sema::PCC_ParenthesizedExpression:
David Blaikiebbafb8a2012-03-11 07:00:24 +00002002 if (SemaRef.getLangOpts().ObjCAutoRefCount &&
John McCall31168b02011-06-15 23:02:42 +00002003 CCC == Sema::PCC_ParenthesizedExpression) {
2004 // (__bridge <type>)<expression>
2005 Builder.AddTypedTextChunk("__bridge");
2006 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2007 Builder.AddPlaceholderChunk("type");
2008 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2009 Builder.AddPlaceholderChunk("expression");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002010 Results.AddResult(Result(Builder.TakeString()));
John McCall31168b02011-06-15 23:02:42 +00002011
2012 // (__bridge_transfer <Objective-C type>)<expression>
2013 Builder.AddTypedTextChunk("__bridge_transfer");
2014 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2015 Builder.AddPlaceholderChunk("Objective-C type");
2016 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2017 Builder.AddPlaceholderChunk("expression");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002018 Results.AddResult(Result(Builder.TakeString()));
John McCall31168b02011-06-15 23:02:42 +00002019
2020 // (__bridge_retained <CF type>)<expression>
2021 Builder.AddTypedTextChunk("__bridge_retained");
2022 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2023 Builder.AddPlaceholderChunk("CF type");
2024 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2025 Builder.AddPlaceholderChunk("expression");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002026 Results.AddResult(Result(Builder.TakeString()));
John McCall31168b02011-06-15 23:02:42 +00002027 }
2028 // Fall through
Galina Kistanova33399112017-06-03 06:35:06 +00002029 LLVM_FALLTHROUGH;
John McCall31168b02011-06-15 23:02:42 +00002030
John McCallfaf5fb42010-08-26 23:41:50 +00002031 case Sema::PCC_Expression: {
David Blaikiebbafb8a2012-03-11 07:00:24 +00002032 if (SemaRef.getLangOpts().CPlusPlus) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002033 // 'this', if we're in a non-static member function.
Douglas Gregord8c61782012-02-15 15:34:24 +00002034 addThisCompletion(SemaRef, Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002035
Douglas Gregore5c79d52011-10-18 21:20:17 +00002036 // true
2037 Builder.AddResultTypeChunk("bool");
2038 Builder.AddTypedTextChunk("true");
2039 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002040
Douglas Gregore5c79d52011-10-18 21:20:17 +00002041 // false
2042 Builder.AddResultTypeChunk("bool");
2043 Builder.AddTypedTextChunk("false");
2044 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002045
David Blaikiebbafb8a2012-03-11 07:00:24 +00002046 if (SemaRef.getLangOpts().RTTI) {
Douglas Gregorc05f6572011-04-12 02:47:21 +00002047 // dynamic_cast < type-id > ( expression )
2048 Builder.AddTypedTextChunk("dynamic_cast");
2049 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
2050 Builder.AddPlaceholderChunk("type");
2051 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
2052 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2053 Builder.AddPlaceholderChunk("expression");
2054 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002055 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc05f6572011-04-12 02:47:21 +00002056 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002057
Douglas Gregorf4c33342010-05-28 00:22:41 +00002058 // static_cast < type-id > ( expression )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002059 Builder.AddTypedTextChunk("static_cast");
2060 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
2061 Builder.AddPlaceholderChunk("type");
2062 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
2063 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2064 Builder.AddPlaceholderChunk("expression");
2065 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002066 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002067
Douglas Gregorf4c33342010-05-28 00:22:41 +00002068 // reinterpret_cast < type-id > ( expression )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002069 Builder.AddTypedTextChunk("reinterpret_cast");
2070 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
2071 Builder.AddPlaceholderChunk("type");
2072 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
2073 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2074 Builder.AddPlaceholderChunk("expression");
2075 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002076 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002077
Douglas Gregorf4c33342010-05-28 00:22:41 +00002078 // const_cast < type-id > ( expression )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002079 Builder.AddTypedTextChunk("const_cast");
2080 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
2081 Builder.AddPlaceholderChunk("type");
2082 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
2083 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2084 Builder.AddPlaceholderChunk("expression");
2085 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002086 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002087
David Blaikiebbafb8a2012-03-11 07:00:24 +00002088 if (SemaRef.getLangOpts().RTTI) {
Douglas Gregorc05f6572011-04-12 02:47:21 +00002089 // typeid ( expression-or-type )
Douglas Gregore5c79d52011-10-18 21:20:17 +00002090 Builder.AddResultTypeChunk("std::type_info");
Douglas Gregorc05f6572011-04-12 02:47:21 +00002091 Builder.AddTypedTextChunk("typeid");
2092 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2093 Builder.AddPlaceholderChunk("expression-or-type");
2094 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002095 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc05f6572011-04-12 02:47:21 +00002096 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002097
Douglas Gregorf4c33342010-05-28 00:22:41 +00002098 // new T ( ... )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002099 Builder.AddTypedTextChunk("new");
2100 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2101 Builder.AddPlaceholderChunk("type");
2102 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2103 Builder.AddPlaceholderChunk("expressions");
2104 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002105 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002106
Douglas Gregorf4c33342010-05-28 00:22:41 +00002107 // new T [ ] ( ... )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002108 Builder.AddTypedTextChunk("new");
2109 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2110 Builder.AddPlaceholderChunk("type");
2111 Builder.AddChunk(CodeCompletionString::CK_LeftBracket);
2112 Builder.AddPlaceholderChunk("size");
2113 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
2114 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2115 Builder.AddPlaceholderChunk("expressions");
2116 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002117 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002118
Douglas Gregorf4c33342010-05-28 00:22:41 +00002119 // delete expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00002120 Builder.AddResultTypeChunk("void");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002121 Builder.AddTypedTextChunk("delete");
2122 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2123 Builder.AddPlaceholderChunk("expression");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002124 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002125
Douglas Gregorf4c33342010-05-28 00:22:41 +00002126 // delete [] expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00002127 Builder.AddResultTypeChunk("void");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002128 Builder.AddTypedTextChunk("delete");
2129 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2130 Builder.AddChunk(CodeCompletionString::CK_LeftBracket);
2131 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
2132 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2133 Builder.AddPlaceholderChunk("expression");
2134 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002135
David Blaikiebbafb8a2012-03-11 07:00:24 +00002136 if (SemaRef.getLangOpts().CXXExceptions) {
Douglas Gregorc05f6572011-04-12 02:47:21 +00002137 // throw expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00002138 Builder.AddResultTypeChunk("void");
Douglas Gregorc05f6572011-04-12 02:47:21 +00002139 Builder.AddTypedTextChunk("throw");
2140 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2141 Builder.AddPlaceholderChunk("expression");
2142 Results.AddResult(Result(Builder.TakeString()));
2143 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002144
Douglas Gregora2db7932010-05-26 22:00:08 +00002145 // FIXME: Rethrow?
Douglas Gregor4205fef2011-10-18 16:29:03 +00002146
Richard Smith2bf7fdb2013-01-02 11:42:31 +00002147 if (SemaRef.getLangOpts().CPlusPlus11) {
Douglas Gregor4205fef2011-10-18 16:29:03 +00002148 // nullptr
Douglas Gregore5c79d52011-10-18 21:20:17 +00002149 Builder.AddResultTypeChunk("std::nullptr_t");
Douglas Gregor4205fef2011-10-18 16:29:03 +00002150 Builder.AddTypedTextChunk("nullptr");
2151 Results.AddResult(Result(Builder.TakeString()));
2152
2153 // alignof
Douglas Gregore5c79d52011-10-18 21:20:17 +00002154 Builder.AddResultTypeChunk("size_t");
Douglas Gregor4205fef2011-10-18 16:29:03 +00002155 Builder.AddTypedTextChunk("alignof");
2156 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2157 Builder.AddPlaceholderChunk("type");
2158 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2159 Results.AddResult(Result(Builder.TakeString()));
2160
2161 // noexcept
Douglas Gregore5c79d52011-10-18 21:20:17 +00002162 Builder.AddResultTypeChunk("bool");
Douglas Gregor4205fef2011-10-18 16:29:03 +00002163 Builder.AddTypedTextChunk("noexcept");
2164 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2165 Builder.AddPlaceholderChunk("expression");
2166 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2167 Results.AddResult(Result(Builder.TakeString()));
2168
2169 // sizeof... expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00002170 Builder.AddResultTypeChunk("size_t");
Douglas Gregor4205fef2011-10-18 16:29:03 +00002171 Builder.AddTypedTextChunk("sizeof...");
2172 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2173 Builder.AddPlaceholderChunk("parameter-pack");
2174 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2175 Results.AddResult(Result(Builder.TakeString()));
2176 }
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002177 }
2178
David Blaikiebbafb8a2012-03-11 07:00:24 +00002179 if (SemaRef.getLangOpts().ObjC1) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002180 // Add "super", if we're in an Objective-C class with a superclass.
Ted Kremenek305a0a72010-05-31 21:43:10 +00002181 if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl()) {
2182 // The interface can be NULL.
2183 if (ObjCInterfaceDecl *ID = Method->getClassInterface())
Douglas Gregore5c79d52011-10-18 21:20:17 +00002184 if (ID->getSuperClass()) {
2185 std::string SuperType;
2186 SuperType = ID->getSuperClass()->getNameAsString();
2187 if (Method->isInstanceMethod())
2188 SuperType += " *";
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002189
Douglas Gregore5c79d52011-10-18 21:20:17 +00002190 Builder.AddResultTypeChunk(Allocator.CopyString(SuperType));
2191 Builder.AddTypedTextChunk("super");
2192 Results.AddResult(Result(Builder.TakeString()));
2193 }
Ted Kremenek305a0a72010-05-31 21:43:10 +00002194 }
2195
Douglas Gregorf98e6a22010-01-13 23:51:12 +00002196 AddObjCExpressionResults(Results, true);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002197 }
2198
Jordan Rose58d54722012-06-30 21:33:57 +00002199 if (SemaRef.getLangOpts().C11) {
2200 // _Alignof
2201 Builder.AddResultTypeChunk("size_t");
Richard Smith20e883e2015-04-29 23:20:19 +00002202 if (SemaRef.PP.isMacroDefined("alignof"))
Jordan Rose58d54722012-06-30 21:33:57 +00002203 Builder.AddTypedTextChunk("alignof");
2204 else
2205 Builder.AddTypedTextChunk("_Alignof");
2206 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2207 Builder.AddPlaceholderChunk("type");
2208 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2209 Results.AddResult(Result(Builder.TakeString()));
2210 }
2211
Douglas Gregorf4c33342010-05-28 00:22:41 +00002212 // sizeof expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00002213 Builder.AddResultTypeChunk("size_t");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002214 Builder.AddTypedTextChunk("sizeof");
2215 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2216 Builder.AddPlaceholderChunk("expression-or-type");
2217 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2218 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002219 break;
2220 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002221
John McCallfaf5fb42010-08-26 23:41:50 +00002222 case Sema::PCC_Type:
Douglas Gregor80039242011-02-15 20:33:25 +00002223 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregor99fa2642010-08-24 01:06:58 +00002224 break;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002225 }
2226
David Blaikiebbafb8a2012-03-11 07:00:24 +00002227 if (WantTypesInContext(CCC, SemaRef.getLangOpts()))
2228 AddTypeSpecifierResults(SemaRef.getLangOpts(), Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002229
David Blaikiebbafb8a2012-03-11 07:00:24 +00002230 if (SemaRef.getLangOpts().CPlusPlus && CCC != Sema::PCC_Type)
Douglas Gregor78a21012010-01-14 16:01:26 +00002231 Results.AddResult(Result("operator"));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002232}
2233
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002234/// If the given declaration has an associated type, add it as a result
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002235/// type chunk.
2236static void AddResultTypeChunk(ASTContext &Context,
Douglas Gregor75acd922011-09-27 23:30:47 +00002237 const PrintingPolicy &Policy,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002238 const NamedDecl *ND,
Douglas Gregorc3425b12015-07-07 06:20:19 +00002239 QualType BaseType,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002240 CodeCompletionBuilder &Result) {
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002241 if (!ND)
2242 return;
Douglas Gregor0212fd72010-09-21 16:06:22 +00002243
2244 // Skip constructors and conversion functions, which have their return types
2245 // built into their names.
Sam McCall63c59722018-01-22 20:44:47 +00002246 if (isConstructor(ND) || isa<CXXConversionDecl>(ND))
Douglas Gregor0212fd72010-09-21 16:06:22 +00002247 return;
2248
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002249 // Determine the type of the declaration (if it has a type).
Alp Tokera2794f92014-01-22 07:29:52 +00002250 QualType T;
2251 if (const FunctionDecl *Function = ND->getAsFunction())
Alp Toker314cc812014-01-25 16:55:45 +00002252 T = Function->getReturnType();
Douglas Gregorc3425b12015-07-07 06:20:19 +00002253 else if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND)) {
2254 if (!BaseType.isNull())
2255 T = Method->getSendResultType(BaseType);
2256 else
2257 T = Method->getReturnType();
Ilya Biryukovb5da91c2017-11-08 10:39:09 +00002258 } else if (const EnumConstantDecl *Enumerator = dyn_cast<EnumConstantDecl>(ND)) {
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002259 T = Context.getTypeDeclType(cast<TypeDecl>(Enumerator->getDeclContext()));
Ilya Biryukovb5da91c2017-11-08 10:39:09 +00002260 T = clang::TypeName::getFullyQualifiedType(T, Context);
2261 } else if (isa<UnresolvedUsingValueDecl>(ND)) {
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002262 /* Do nothing: ignore unresolved using declarations*/
Douglas Gregorc3425b12015-07-07 06:20:19 +00002263 } else if (const ObjCIvarDecl *Ivar = dyn_cast<ObjCIvarDecl>(ND)) {
2264 if (!BaseType.isNull())
2265 T = Ivar->getUsageType(BaseType);
2266 else
2267 T = Ivar->getType();
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002268 } else if (const ValueDecl *Value = dyn_cast<ValueDecl>(ND)) {
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002269 T = Value->getType();
Douglas Gregorc3425b12015-07-07 06:20:19 +00002270 } else if (const ObjCPropertyDecl *Property = dyn_cast<ObjCPropertyDecl>(ND)) {
2271 if (!BaseType.isNull())
2272 T = Property->getUsageType(BaseType);
2273 else
2274 T = Property->getType();
2275 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002276
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002277 if (T.isNull() || Context.hasSameType(T, Context.DependentTy))
2278 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002279
Douglas Gregor75acd922011-09-27 23:30:47 +00002280 Result.AddResultTypeChunk(GetCompletionTypeString(T, Context, Policy,
Douglas Gregor304f9b02011-02-01 21:15:40 +00002281 Result.getAllocator()));
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002282}
2283
Richard Smith20e883e2015-04-29 23:20:19 +00002284static void MaybeAddSentinel(Preprocessor &PP,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002285 const NamedDecl *FunctionOrMethod,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002286 CodeCompletionBuilder &Result) {
Douglas Gregordbb71db2010-08-23 23:51:41 +00002287 if (SentinelAttr *Sentinel = FunctionOrMethod->getAttr<SentinelAttr>())
2288 if (Sentinel->getSentinel() == 0) {
Richard Smith20e883e2015-04-29 23:20:19 +00002289 if (PP.getLangOpts().ObjC1 && PP.isMacroDefined("nil"))
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002290 Result.AddTextChunk(", nil");
Richard Smith20e883e2015-04-29 23:20:19 +00002291 else if (PP.isMacroDefined("NULL"))
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002292 Result.AddTextChunk(", NULL");
Douglas Gregordbb71db2010-08-23 23:51:41 +00002293 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002294 Result.AddTextChunk(", (void*)0");
Douglas Gregordbb71db2010-08-23 23:51:41 +00002295 }
2296}
2297
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002298static std::string formatObjCParamQualifiers(unsigned ObjCQuals,
Douglas Gregor86b42682015-06-19 18:27:52 +00002299 QualType &Type) {
Douglas Gregor8f08d742011-07-30 07:55:26 +00002300 std::string Result;
2301 if (ObjCQuals & Decl::OBJC_TQ_In)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002302 Result += "in ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002303 else if (ObjCQuals & Decl::OBJC_TQ_Inout)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002304 Result += "inout ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002305 else if (ObjCQuals & Decl::OBJC_TQ_Out)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002306 Result += "out ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002307 if (ObjCQuals & Decl::OBJC_TQ_Bycopy)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002308 Result += "bycopy ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002309 else if (ObjCQuals & Decl::OBJC_TQ_Byref)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002310 Result += "byref ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002311 if (ObjCQuals & Decl::OBJC_TQ_Oneway)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002312 Result += "oneway ";
Douglas Gregor86b42682015-06-19 18:27:52 +00002313 if (ObjCQuals & Decl::OBJC_TQ_CSNullability) {
2314 if (auto nullability = AttributedType::stripOuterNullability(Type)) {
2315 switch (*nullability) {
2316 case NullabilityKind::NonNull:
2317 Result += "nonnull ";
2318 break;
2319
2320 case NullabilityKind::Nullable:
2321 Result += "nullable ";
2322 break;
2323
2324 case NullabilityKind::Unspecified:
2325 Result += "null_unspecified ";
2326 break;
2327 }
2328 }
2329 }
Douglas Gregor8f08d742011-07-30 07:55:26 +00002330 return Result;
2331}
2332
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002333/// Tries to find the most appropriate type location for an Objective-C
Alex Lorenza1951202016-10-18 10:35:27 +00002334/// block placeholder.
2335///
2336/// This function ignores things like typedefs and qualifiers in order to
2337/// present the most relevant and accurate block placeholders in code completion
2338/// results.
2339static void findTypeLocationForBlockDecl(const TypeSourceInfo *TSInfo,
2340 FunctionTypeLoc &Block,
2341 FunctionProtoTypeLoc &BlockProto,
2342 bool SuppressBlock = false) {
2343 if (!TSInfo)
2344 return;
2345 TypeLoc TL = TSInfo->getTypeLoc().getUnqualifiedLoc();
2346 while (true) {
2347 // Look through typedefs.
2348 if (!SuppressBlock) {
2349 if (TypedefTypeLoc TypedefTL = TL.getAs<TypedefTypeLoc>()) {
2350 if (TypeSourceInfo *InnerTSInfo =
2351 TypedefTL.getTypedefNameDecl()->getTypeSourceInfo()) {
2352 TL = InnerTSInfo->getTypeLoc().getUnqualifiedLoc();
2353 continue;
2354 }
2355 }
2356
2357 // Look through qualified types
2358 if (QualifiedTypeLoc QualifiedTL = TL.getAs<QualifiedTypeLoc>()) {
2359 TL = QualifiedTL.getUnqualifiedLoc();
2360 continue;
2361 }
2362
2363 if (AttributedTypeLoc AttrTL = TL.getAs<AttributedTypeLoc>()) {
2364 TL = AttrTL.getModifiedLoc();
2365 continue;
2366 }
2367 }
2368
2369 // Try to get the function prototype behind the block pointer type,
2370 // then we're done.
2371 if (BlockPointerTypeLoc BlockPtr = TL.getAs<BlockPointerTypeLoc>()) {
2372 TL = BlockPtr.getPointeeLoc().IgnoreParens();
2373 Block = TL.getAs<FunctionTypeLoc>();
2374 BlockProto = TL.getAs<FunctionProtoTypeLoc>();
2375 }
2376 break;
2377 }
2378}
2379
Alex Lorenz920ae142016-10-18 10:38:58 +00002380static std::string
2381formatBlockPlaceholder(const PrintingPolicy &Policy, const NamedDecl *BlockDecl,
2382 FunctionTypeLoc &Block, FunctionProtoTypeLoc &BlockProto,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002383 bool SuppressBlockName = false,
Alex Lorenz920ae142016-10-18 10:38:58 +00002384 bool SuppressBlock = false,
2385 Optional<ArrayRef<QualType>> ObjCSubsts = None);
2386
Richard Smith20e883e2015-04-29 23:20:19 +00002387static std::string FormatFunctionParameter(const PrintingPolicy &Policy,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002388 const ParmVarDecl *Param,
Douglas Gregord793e7c2011-10-18 04:23:19 +00002389 bool SuppressName = false,
Douglas Gregorc3425b12015-07-07 06:20:19 +00002390 bool SuppressBlock = false,
2391 Optional<ArrayRef<QualType>> ObjCSubsts = None) {
Douglas Gregore90dd002010-08-24 16:15:59 +00002392 bool ObjCMethodParam = isa<ObjCMethodDecl>(Param->getDeclContext());
2393 if (Param->getType()->isDependentType() ||
2394 !Param->getType()->isBlockPointerType()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002395 // The argument for a dependent or non-block parameter is a placeholder
Douglas Gregore90dd002010-08-24 16:15:59 +00002396 // containing that parameter's type.
2397 std::string Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002398
Douglas Gregor981a0c42010-08-29 19:47:46 +00002399 if (Param->getIdentifier() && !ObjCMethodParam && !SuppressName)
Douglas Gregore90dd002010-08-24 16:15:59 +00002400 Result = Param->getIdentifier()->getName();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002401
Douglas Gregor86b42682015-06-19 18:27:52 +00002402 QualType Type = Param->getType();
Douglas Gregorc3425b12015-07-07 06:20:19 +00002403 if (ObjCSubsts)
2404 Type = Type.substObjCTypeArgs(Param->getASTContext(), *ObjCSubsts,
2405 ObjCSubstitutionContext::Parameter);
Douglas Gregore90dd002010-08-24 16:15:59 +00002406 if (ObjCMethodParam) {
Douglas Gregor86b42682015-06-19 18:27:52 +00002407 Result = "(" + formatObjCParamQualifiers(Param->getObjCDeclQualifier(),
2408 Type);
2409 Result += Type.getAsString(Policy) + ")";
Douglas Gregor981a0c42010-08-29 19:47:46 +00002410 if (Param->getIdentifier() && !SuppressName)
Douglas Gregore90dd002010-08-24 16:15:59 +00002411 Result += Param->getIdentifier()->getName();
Douglas Gregor86b42682015-06-19 18:27:52 +00002412 } else {
2413 Type.getAsStringInternal(Result, Policy);
Douglas Gregore90dd002010-08-24 16:15:59 +00002414 }
2415 return Result;
2416 }
Alex Lorenza1951202016-10-18 10:35:27 +00002417
Douglas Gregore90dd002010-08-24 16:15:59 +00002418 // The argument for a block pointer parameter is a block literal with
2419 // the appropriate type.
David Blaikie6adc78e2013-02-18 22:06:02 +00002420 FunctionTypeLoc Block;
2421 FunctionProtoTypeLoc BlockProto;
Alex Lorenza1951202016-10-18 10:35:27 +00002422 findTypeLocationForBlockDecl(Param->getTypeSourceInfo(), Block, BlockProto,
2423 SuppressBlock);
Alex Lorenz6bf4a582017-03-13 15:43:42 +00002424 // Try to retrieve the block type information from the property if this is a
2425 // parameter in a setter.
2426 if (!Block && ObjCMethodParam &&
2427 cast<ObjCMethodDecl>(Param->getDeclContext())->isPropertyAccessor()) {
2428 if (const auto *PD = cast<ObjCMethodDecl>(Param->getDeclContext())
2429 ->findPropertyDecl(/*CheckOverrides=*/false))
2430 findTypeLocationForBlockDecl(PD->getTypeSourceInfo(), Block, BlockProto,
2431 SuppressBlock);
2432 }
Douglas Gregore90dd002010-08-24 16:15:59 +00002433
2434 if (!Block) {
2435 // We were unable to find a FunctionProtoTypeLoc with parameter names
2436 // for the block; just use the parameter type as a placeholder.
2437 std::string Result;
Douglas Gregord793e7c2011-10-18 04:23:19 +00002438 if (!ObjCMethodParam && Param->getIdentifier())
2439 Result = Param->getIdentifier()->getName();
2440
Douglas Gregor86b42682015-06-19 18:27:52 +00002441 QualType Type = Param->getType().getUnqualifiedType();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002442
Douglas Gregore90dd002010-08-24 16:15:59 +00002443 if (ObjCMethodParam) {
Alex Lorenz01bcfc12016-11-23 16:28:34 +00002444 Result = Type.getAsString(Policy);
2445 std::string Quals =
2446 formatObjCParamQualifiers(Param->getObjCDeclQualifier(), Type);
2447 if (!Quals.empty())
2448 Result = "(" + Quals + " " + Result + ")";
2449 if (Result.back() != ')')
2450 Result += " ";
Douglas Gregore90dd002010-08-24 16:15:59 +00002451 if (Param->getIdentifier())
2452 Result += Param->getIdentifier()->getName();
Douglas Gregor86b42682015-06-19 18:27:52 +00002453 } else {
2454 Type.getAsStringInternal(Result, Policy);
Douglas Gregore90dd002010-08-24 16:15:59 +00002455 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002456
Douglas Gregore90dd002010-08-24 16:15:59 +00002457 return Result;
2458 }
Alex Lorenz01bcfc12016-11-23 16:28:34 +00002459
Douglas Gregore90dd002010-08-24 16:15:59 +00002460 // We have the function prototype behind the block pointer type, as it was
2461 // written in the source.
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002462 return formatBlockPlaceholder(Policy, Param, Block, BlockProto,
2463 /*SuppressBlockName=*/false, SuppressBlock,
Alex Lorenz920ae142016-10-18 10:38:58 +00002464 ObjCSubsts);
2465}
2466
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002467/// Returns a placeholder string that corresponds to an Objective-C block
Alex Lorenz920ae142016-10-18 10:38:58 +00002468/// declaration.
2469///
2470/// \param BlockDecl A declaration with an Objective-C block type.
2471///
2472/// \param Block The most relevant type location for that block type.
2473///
Alexander Kornienko2a8c18d2018-04-06 15:14:32 +00002474/// \param SuppressBlockName Determines whether or not the name of the block
Alex Lorenz920ae142016-10-18 10:38:58 +00002475/// declaration is included in the resulting string.
2476static std::string
2477formatBlockPlaceholder(const PrintingPolicy &Policy, const NamedDecl *BlockDecl,
2478 FunctionTypeLoc &Block, FunctionProtoTypeLoc &BlockProto,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002479 bool SuppressBlockName, bool SuppressBlock,
Alex Lorenz920ae142016-10-18 10:38:58 +00002480 Optional<ArrayRef<QualType>> ObjCSubsts) {
Douglas Gregor67da50e2010-09-08 22:47:51 +00002481 std::string Result;
Alp Toker314cc812014-01-25 16:55:45 +00002482 QualType ResultType = Block.getTypePtr()->getReturnType();
Douglas Gregorc3425b12015-07-07 06:20:19 +00002483 if (ObjCSubsts)
Alex Lorenz920ae142016-10-18 10:38:58 +00002484 ResultType =
2485 ResultType.substObjCTypeArgs(BlockDecl->getASTContext(), *ObjCSubsts,
2486 ObjCSubstitutionContext::Result);
Douglas Gregord793e7c2011-10-18 04:23:19 +00002487 if (!ResultType->isVoidType() || SuppressBlock)
John McCall31168b02011-06-15 23:02:42 +00002488 ResultType.getAsStringInternal(Result, Policy);
Douglas Gregord793e7c2011-10-18 04:23:19 +00002489
2490 // Format the parameter list.
2491 std::string Params;
Alp Tokerb3fd5cf2014-01-21 00:32:38 +00002492 if (!BlockProto || Block.getNumParams() == 0) {
David Blaikie6adc78e2013-02-18 22:06:02 +00002493 if (BlockProto && BlockProto.getTypePtr()->isVariadic())
Douglas Gregord793e7c2011-10-18 04:23:19 +00002494 Params = "(...)";
Douglas Gregoraf25cfa2010-10-02 23:49:58 +00002495 else
Douglas Gregord793e7c2011-10-18 04:23:19 +00002496 Params = "(void)";
Douglas Gregor67da50e2010-09-08 22:47:51 +00002497 } else {
Douglas Gregord793e7c2011-10-18 04:23:19 +00002498 Params += "(";
Alp Tokerb3fd5cf2014-01-21 00:32:38 +00002499 for (unsigned I = 0, N = Block.getNumParams(); I != N; ++I) {
Douglas Gregor67da50e2010-09-08 22:47:51 +00002500 if (I)
Douglas Gregord793e7c2011-10-18 04:23:19 +00002501 Params += ", ";
Richard Smith20e883e2015-04-29 23:20:19 +00002502 Params += FormatFunctionParameter(Policy, Block.getParam(I),
Alp Tokerb3fd5cf2014-01-21 00:32:38 +00002503 /*SuppressName=*/false,
Alex Lorenz920ae142016-10-18 10:38:58 +00002504 /*SuppressBlock=*/true, ObjCSubsts);
Alp Tokerb3fd5cf2014-01-21 00:32:38 +00002505
David Blaikie6adc78e2013-02-18 22:06:02 +00002506 if (I == N - 1 && BlockProto.getTypePtr()->isVariadic())
Douglas Gregord793e7c2011-10-18 04:23:19 +00002507 Params += ", ...";
Douglas Gregor67da50e2010-09-08 22:47:51 +00002508 }
Douglas Gregord793e7c2011-10-18 04:23:19 +00002509 Params += ")";
Douglas Gregor400f5972010-08-31 05:13:43 +00002510 }
Alex Lorenz920ae142016-10-18 10:38:58 +00002511
Douglas Gregord793e7c2011-10-18 04:23:19 +00002512 if (SuppressBlock) {
2513 // Format as a parameter.
2514 Result = Result + " (^";
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002515 if (!SuppressBlockName && BlockDecl->getIdentifier())
Alex Lorenz920ae142016-10-18 10:38:58 +00002516 Result += BlockDecl->getIdentifier()->getName();
Douglas Gregord793e7c2011-10-18 04:23:19 +00002517 Result += ")";
2518 Result += Params;
2519 } else {
2520 // Format as a block literal argument.
2521 Result = '^' + Result;
2522 Result += Params;
Alex Lorenz920ae142016-10-18 10:38:58 +00002523
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002524 if (!SuppressBlockName && BlockDecl->getIdentifier())
Alex Lorenz920ae142016-10-18 10:38:58 +00002525 Result += BlockDecl->getIdentifier()->getName();
Douglas Gregord793e7c2011-10-18 04:23:19 +00002526 }
Alex Lorenz920ae142016-10-18 10:38:58 +00002527
Douglas Gregore90dd002010-08-24 16:15:59 +00002528 return Result;
2529}
2530
Erik Verbruggen11338c52017-07-19 10:45:40 +00002531static std::string GetDefaultValueString(const ParmVarDecl *Param,
2532 const SourceManager &SM,
2533 const LangOptions &LangOpts) {
Ilya Biryukovb6d1ec82017-07-21 09:24:00 +00002534 const SourceRange SrcRange = Param->getDefaultArgRange();
Erik Verbruggen11338c52017-07-19 10:45:40 +00002535 CharSourceRange CharSrcRange = CharSourceRange::getTokenRange(SrcRange);
2536 bool Invalid = CharSrcRange.isInvalid();
2537 if (Invalid)
2538 return "";
2539 StringRef srcText = Lexer::getSourceText(CharSrcRange, SM, LangOpts, &Invalid);
2540 if (Invalid)
2541 return "";
2542
2543 if (srcText.empty() || srcText == "=") {
2544 // Lexer can't determine the value.
2545 // This happens if the code is incorrect (for example class is forward declared).
2546 return "";
2547 }
Erik Verbruggen797980e2017-07-19 11:15:36 +00002548 std::string DefValue(srcText.str());
Erik Verbruggen11338c52017-07-19 10:45:40 +00002549 // FIXME: remove this check if the Lexer::getSourceText value is fixed and
2550 // this value always has (or always does not have) '=' in front of it
2551 if (DefValue.at(0) != '=') {
2552 // If we don't have '=' in front of value.
2553 // Lexer returns built-in types values without '=' and user-defined types values with it.
2554 return " = " + DefValue;
2555 }
2556 return " " + DefValue;
2557}
2558
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002559/// Add function parameter chunks to the given code completion string.
Richard Smith20e883e2015-04-29 23:20:19 +00002560static void AddFunctionParameterChunks(Preprocessor &PP,
Douglas Gregor75acd922011-09-27 23:30:47 +00002561 const PrintingPolicy &Policy,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002562 const FunctionDecl *Function,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002563 CodeCompletionBuilder &Result,
2564 unsigned Start = 0,
2565 bool InOptional = false) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002566 bool FirstParameter = true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002567
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002568 for (unsigned P = Start, N = Function->getNumParams(); P != N; ++P) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002569 const ParmVarDecl *Param = Function->getParamDecl(P);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002570
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002571 if (Param->hasDefaultArg() && !InOptional) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002572 // When we see an optional default argument, put that argument and
2573 // the remaining default arguments into a new, optional string.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00002574 CodeCompletionBuilder Opt(Result.getAllocator(),
2575 Result.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002576 if (!FirstParameter)
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002577 Opt.AddChunk(CodeCompletionString::CK_Comma);
Richard Smith20e883e2015-04-29 23:20:19 +00002578 AddFunctionParameterChunks(PP, Policy, Function, Opt, P, true);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002579 Result.AddOptionalChunk(Opt.TakeString());
2580 break;
Douglas Gregor3545ff42009-09-21 16:56:56 +00002581 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002582
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002583 if (FirstParameter)
2584 FirstParameter = false;
2585 else
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002586 Result.AddChunk(CodeCompletionString::CK_Comma);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002587
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002588 InOptional = false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002589
Douglas Gregor3545ff42009-09-21 16:56:56 +00002590 // Format the placeholder string.
Richard Smith20e883e2015-04-29 23:20:19 +00002591 std::string PlaceholderStr = FormatFunctionParameter(Policy, Param);
Erik Verbruggen11338c52017-07-19 10:45:40 +00002592 if (Param->hasDefaultArg())
2593 PlaceholderStr += GetDefaultValueString(Param, PP.getSourceManager(), PP.getLangOpts());
Richard Smith20e883e2015-04-29 23:20:19 +00002594
Douglas Gregor400f5972010-08-31 05:13:43 +00002595 if (Function->isVariadic() && P == N - 1)
2596 PlaceholderStr += ", ...";
2597
Douglas Gregor3545ff42009-09-21 16:56:56 +00002598 // Add the placeholder string.
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002599 Result.AddPlaceholderChunk(
2600 Result.getAllocator().CopyString(PlaceholderStr));
Douglas Gregor3545ff42009-09-21 16:56:56 +00002601 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002602
2603 if (const FunctionProtoType *Proto
Douglas Gregorba449032009-09-22 21:42:17 +00002604 = Function->getType()->getAs<FunctionProtoType>())
Douglas Gregordbb71db2010-08-23 23:51:41 +00002605 if (Proto->isVariadic()) {
Alp Toker9cacbab2014-01-20 20:26:09 +00002606 if (Proto->getNumParams() == 0)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002607 Result.AddPlaceholderChunk("...");
Douglas Gregordbb71db2010-08-23 23:51:41 +00002608
Richard Smith20e883e2015-04-29 23:20:19 +00002609 MaybeAddSentinel(PP, Function, Result);
Douglas Gregordbb71db2010-08-23 23:51:41 +00002610 }
Douglas Gregor3545ff42009-09-21 16:56:56 +00002611}
2612
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002613/// Add template parameter chunks to the given code completion string.
Douglas Gregor3545ff42009-09-21 16:56:56 +00002614static void AddTemplateParameterChunks(ASTContext &Context,
Douglas Gregor75acd922011-09-27 23:30:47 +00002615 const PrintingPolicy &Policy,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002616 const TemplateDecl *Template,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002617 CodeCompletionBuilder &Result,
2618 unsigned MaxParameters = 0,
2619 unsigned Start = 0,
2620 bool InDefaultArg = false) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002621 bool FirstParameter = true;
Richard Smith6eece292015-01-15 02:27:20 +00002622
2623 // Prefer to take the template parameter names from the first declaration of
2624 // the template.
2625 Template = cast<TemplateDecl>(Template->getCanonicalDecl());
2626
Douglas Gregor3545ff42009-09-21 16:56:56 +00002627 TemplateParameterList *Params = Template->getTemplateParameters();
2628 TemplateParameterList::iterator PEnd = Params->end();
2629 if (MaxParameters)
2630 PEnd = Params->begin() + MaxParameters;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002631 for (TemplateParameterList::iterator P = Params->begin() + Start;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002632 P != PEnd; ++P) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002633 bool HasDefaultArg = false;
2634 std::string PlaceholderStr;
2635 if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*P)) {
2636 if (TTP->wasDeclaredWithTypename())
2637 PlaceholderStr = "typename";
2638 else
2639 PlaceholderStr = "class";
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002640
Douglas Gregor3545ff42009-09-21 16:56:56 +00002641 if (TTP->getIdentifier()) {
2642 PlaceholderStr += ' ';
2643 PlaceholderStr += TTP->getIdentifier()->getName();
2644 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002645
Douglas Gregor3545ff42009-09-21 16:56:56 +00002646 HasDefaultArg = TTP->hasDefaultArgument();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002647 } else if (NonTypeTemplateParmDecl *NTTP
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002648 = dyn_cast<NonTypeTemplateParmDecl>(*P)) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002649 if (NTTP->getIdentifier())
2650 PlaceholderStr = NTTP->getIdentifier()->getName();
John McCall31168b02011-06-15 23:02:42 +00002651 NTTP->getType().getAsStringInternal(PlaceholderStr, Policy);
Douglas Gregor3545ff42009-09-21 16:56:56 +00002652 HasDefaultArg = NTTP->hasDefaultArgument();
2653 } else {
2654 assert(isa<TemplateTemplateParmDecl>(*P));
2655 TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*P);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002656
Douglas Gregor3545ff42009-09-21 16:56:56 +00002657 // Since putting the template argument list into the placeholder would
2658 // be very, very long, we just use an abbreviation.
2659 PlaceholderStr = "template<...> class";
2660 if (TTP->getIdentifier()) {
2661 PlaceholderStr += ' ';
2662 PlaceholderStr += TTP->getIdentifier()->getName();
2663 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002664
Douglas Gregor3545ff42009-09-21 16:56:56 +00002665 HasDefaultArg = TTP->hasDefaultArgument();
2666 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002667
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002668 if (HasDefaultArg && !InDefaultArg) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002669 // When we see an optional default argument, put that argument and
2670 // the remaining default arguments into a new, optional string.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00002671 CodeCompletionBuilder Opt(Result.getAllocator(),
2672 Result.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002673 if (!FirstParameter)
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002674 Opt.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor75acd922011-09-27 23:30:47 +00002675 AddTemplateParameterChunks(Context, Policy, Template, Opt, MaxParameters,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002676 P - Params->begin(), true);
2677 Result.AddOptionalChunk(Opt.TakeString());
2678 break;
Douglas Gregor3545ff42009-09-21 16:56:56 +00002679 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002680
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002681 InDefaultArg = false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002682
Douglas Gregor3545ff42009-09-21 16:56:56 +00002683 if (FirstParameter)
2684 FirstParameter = false;
2685 else
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002686 Result.AddChunk(CodeCompletionString::CK_Comma);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002687
Douglas Gregor3545ff42009-09-21 16:56:56 +00002688 // Add the placeholder string.
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002689 Result.AddPlaceholderChunk(
2690 Result.getAllocator().CopyString(PlaceholderStr));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002691 }
Douglas Gregor3545ff42009-09-21 16:56:56 +00002692}
2693
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002694/// Add a qualifier to the given code-completion string, if the
Douglas Gregorf2510672009-09-21 19:57:38 +00002695/// provided nested-name-specifier is non-NULL.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002696static void
2697AddQualifierToCompletionString(CodeCompletionBuilder &Result,
2698 NestedNameSpecifier *Qualifier,
Douglas Gregor0f622362009-12-11 18:44:16 +00002699 bool QualifierIsInformative,
Douglas Gregor75acd922011-09-27 23:30:47 +00002700 ASTContext &Context,
2701 const PrintingPolicy &Policy) {
Douglas Gregorf2510672009-09-21 19:57:38 +00002702 if (!Qualifier)
2703 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002704
Douglas Gregorf2510672009-09-21 19:57:38 +00002705 std::string PrintedNNS;
2706 {
2707 llvm::raw_string_ostream OS(PrintedNNS);
Douglas Gregor75acd922011-09-27 23:30:47 +00002708 Qualifier->print(OS, Policy);
Douglas Gregorf2510672009-09-21 19:57:38 +00002709 }
Douglas Gregor5bf52692009-09-22 23:15:58 +00002710 if (QualifierIsInformative)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002711 Result.AddInformativeChunk(Result.getAllocator().CopyString(PrintedNNS));
Douglas Gregor5bf52692009-09-22 23:15:58 +00002712 else
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002713 Result.AddTextChunk(Result.getAllocator().CopyString(PrintedNNS));
Douglas Gregorf2510672009-09-21 19:57:38 +00002714}
2715
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002716static void
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002717AddFunctionTypeQualsToCompletionString(CodeCompletionBuilder &Result,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002718 const FunctionDecl *Function) {
Douglas Gregor0f622362009-12-11 18:44:16 +00002719 const FunctionProtoType *Proto
2720 = Function->getType()->getAs<FunctionProtoType>();
2721 if (!Proto || !Proto->getTypeQuals())
2722 return;
2723
Douglas Gregor304f9b02011-02-01 21:15:40 +00002724 // FIXME: Add ref-qualifier!
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002725
Douglas Gregor304f9b02011-02-01 21:15:40 +00002726 // Handle single qualifiers without copying
2727 if (Proto->getTypeQuals() == Qualifiers::Const) {
2728 Result.AddInformativeChunk(" const");
2729 return;
2730 }
2731
2732 if (Proto->getTypeQuals() == Qualifiers::Volatile) {
2733 Result.AddInformativeChunk(" volatile");
2734 return;
2735 }
2736
2737 if (Proto->getTypeQuals() == Qualifiers::Restrict) {
2738 Result.AddInformativeChunk(" restrict");
2739 return;
2740 }
2741
2742 // Handle multiple qualifiers.
Douglas Gregor0f622362009-12-11 18:44:16 +00002743 std::string QualsStr;
David Blaikief5697e52012-08-10 00:55:35 +00002744 if (Proto->isConst())
Douglas Gregor0f622362009-12-11 18:44:16 +00002745 QualsStr += " const";
David Blaikief5697e52012-08-10 00:55:35 +00002746 if (Proto->isVolatile())
Douglas Gregor0f622362009-12-11 18:44:16 +00002747 QualsStr += " volatile";
David Blaikief5697e52012-08-10 00:55:35 +00002748 if (Proto->isRestrict())
Douglas Gregor0f622362009-12-11 18:44:16 +00002749 QualsStr += " restrict";
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002750 Result.AddInformativeChunk(Result.getAllocator().CopyString(QualsStr));
Douglas Gregor0f622362009-12-11 18:44:16 +00002751}
2752
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002753/// Add the name of the given declaration
Douglas Gregor75acd922011-09-27 23:30:47 +00002754static void AddTypedNameChunk(ASTContext &Context, const PrintingPolicy &Policy,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002755 const NamedDecl *ND,
2756 CodeCompletionBuilder &Result) {
Douglas Gregor0212fd72010-09-21 16:06:22 +00002757 DeclarationName Name = ND->getDeclName();
2758 if (!Name)
2759 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002760
Douglas Gregor0212fd72010-09-21 16:06:22 +00002761 switch (Name.getNameKind()) {
Douglas Gregor304f9b02011-02-01 21:15:40 +00002762 case DeclarationName::CXXOperatorName: {
Craig Topperc3ec1492014-05-26 06:22:03 +00002763 const char *OperatorName = nullptr;
Douglas Gregor304f9b02011-02-01 21:15:40 +00002764 switch (Name.getCXXOverloadedOperator()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002765 case OO_None:
Douglas Gregor304f9b02011-02-01 21:15:40 +00002766 case OO_Conditional:
2767 case NUM_OVERLOADED_OPERATORS:
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002768 OperatorName = "operator";
Douglas Gregor304f9b02011-02-01 21:15:40 +00002769 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002770
Douglas Gregor304f9b02011-02-01 21:15:40 +00002771#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
2772 case OO_##Name: OperatorName = "operator" Spelling; break;
2773#define OVERLOADED_OPERATOR_MULTI(Name,Spelling,Unary,Binary,MemberOnly)
2774#include "clang/Basic/OperatorKinds.def"
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002775
Douglas Gregor304f9b02011-02-01 21:15:40 +00002776 case OO_New: OperatorName = "operator new"; break;
2777 case OO_Delete: OperatorName = "operator delete"; break;
2778 case OO_Array_New: OperatorName = "operator new[]"; break;
2779 case OO_Array_Delete: OperatorName = "operator delete[]"; break;
2780 case OO_Call: OperatorName = "operator()"; break;
2781 case OO_Subscript: OperatorName = "operator[]"; break;
2782 }
2783 Result.AddTypedTextChunk(OperatorName);
2784 break;
2785 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002786
Douglas Gregor0212fd72010-09-21 16:06:22 +00002787 case DeclarationName::Identifier:
2788 case DeclarationName::CXXConversionFunctionName:
Douglas Gregor0212fd72010-09-21 16:06:22 +00002789 case DeclarationName::CXXDestructorName:
2790 case DeclarationName::CXXLiteralOperatorName:
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002791 Result.AddTypedTextChunk(
2792 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor0212fd72010-09-21 16:06:22 +00002793 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002794
Richard Smith35845152017-02-07 01:37:30 +00002795 case DeclarationName::CXXDeductionGuideName:
Douglas Gregor0212fd72010-09-21 16:06:22 +00002796 case DeclarationName::CXXUsingDirective:
2797 case DeclarationName::ObjCZeroArgSelector:
2798 case DeclarationName::ObjCOneArgSelector:
2799 case DeclarationName::ObjCMultiArgSelector:
2800 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002801
Douglas Gregor0212fd72010-09-21 16:06:22 +00002802 case DeclarationName::CXXConstructorName: {
Craig Topperc3ec1492014-05-26 06:22:03 +00002803 CXXRecordDecl *Record = nullptr;
Douglas Gregor0212fd72010-09-21 16:06:22 +00002804 QualType Ty = Name.getCXXNameType();
2805 if (const RecordType *RecordTy = Ty->getAs<RecordType>())
2806 Record = cast<CXXRecordDecl>(RecordTy->getDecl());
2807 else if (const InjectedClassNameType *InjectedTy
2808 = Ty->getAs<InjectedClassNameType>())
2809 Record = InjectedTy->getDecl();
2810 else {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002811 Result.AddTypedTextChunk(
2812 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor0212fd72010-09-21 16:06:22 +00002813 break;
2814 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002815
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002816 Result.AddTypedTextChunk(
2817 Result.getAllocator().CopyString(Record->getNameAsString()));
Douglas Gregor0212fd72010-09-21 16:06:22 +00002818 if (ClassTemplateDecl *Template = Record->getDescribedClassTemplate()) {
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002819 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Douglas Gregor75acd922011-09-27 23:30:47 +00002820 AddTemplateParameterChunks(Context, Policy, Template, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002821 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregor0212fd72010-09-21 16:06:22 +00002822 }
2823 break;
2824 }
2825 }
2826}
2827
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002828CodeCompletionString *CodeCompletionResult::CreateCodeCompletionString(Sema &S,
Douglas Gregorc3425b12015-07-07 06:20:19 +00002829 const CodeCompletionContext &CCContext,
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00002830 CodeCompletionAllocator &Allocator,
Dmitri Gribenko3292d062012-07-02 17:35:10 +00002831 CodeCompletionTUInfo &CCTUInfo,
2832 bool IncludeBriefComments) {
Douglas Gregorc3425b12015-07-07 06:20:19 +00002833 return CreateCodeCompletionString(S.Context, S.PP, CCContext, Allocator,
2834 CCTUInfo, IncludeBriefComments);
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002835}
2836
Eric Liu00f43c92018-07-06 09:43:57 +00002837CodeCompletionString *CodeCompletionResult::CreateCodeCompletionStringForMacro(
2838 Preprocessor &PP, CodeCompletionAllocator &Allocator,
2839 CodeCompletionTUInfo &CCTUInfo) {
2840 assert(Kind == RK_Macro);
2841 CodeCompletionBuilder Result(Allocator, CCTUInfo, Priority, Availability);
2842 const MacroInfo *MI = PP.getMacroInfo(Macro);
2843 Result.AddTypedTextChunk(Result.getAllocator().CopyString(Macro->getName()));
2844
2845 if (!MI || !MI->isFunctionLike())
2846 return Result.TakeString();
2847
2848 // Format a function-like macro with placeholders for the arguments.
2849 Result.AddChunk(CodeCompletionString::CK_LeftParen);
2850 MacroInfo::param_iterator A = MI->param_begin(), AEnd = MI->param_end();
2851
2852 // C99 variadic macros add __VA_ARGS__ at the end. Skip it.
2853 if (MI->isC99Varargs()) {
2854 --AEnd;
2855
2856 if (A == AEnd) {
2857 Result.AddPlaceholderChunk("...");
2858 }
2859 }
2860
2861 for (MacroInfo::param_iterator A = MI->param_begin(); A != AEnd; ++A) {
2862 if (A != MI->param_begin())
2863 Result.AddChunk(CodeCompletionString::CK_Comma);
2864
2865 if (MI->isVariadic() && (A + 1) == AEnd) {
2866 SmallString<32> Arg = (*A)->getName();
2867 if (MI->isC99Varargs())
2868 Arg += ", ...";
2869 else
2870 Arg += "...";
2871 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg));
2872 break;
2873 }
2874
2875 // Non-variadic macros are simple.
2876 Result.AddPlaceholderChunk(
2877 Result.getAllocator().CopyString((*A)->getName()));
2878 }
2879 Result.AddChunk(CodeCompletionString::CK_RightParen);
2880 return Result.TakeString();
2881}
2882
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002883/// If possible, create a new code completion string for the given
Douglas Gregor3545ff42009-09-21 16:56:56 +00002884/// result.
2885///
2886/// \returns Either a new, heap-allocated code completion string describing
2887/// how to use this result, or NULL to indicate that the string or name of the
2888/// result is all that is needed.
2889CodeCompletionString *
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002890CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx,
2891 Preprocessor &PP,
Douglas Gregorc3425b12015-07-07 06:20:19 +00002892 const CodeCompletionContext &CCContext,
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00002893 CodeCompletionAllocator &Allocator,
Dmitri Gribenko3292d062012-07-02 17:35:10 +00002894 CodeCompletionTUInfo &CCTUInfo,
2895 bool IncludeBriefComments) {
Eric Liu00f43c92018-07-06 09:43:57 +00002896 if (Kind == RK_Macro)
2897 return CreateCodeCompletionStringForMacro(PP, Allocator, CCTUInfo);
2898
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00002899 CodeCompletionBuilder Result(Allocator, CCTUInfo, Priority, Availability);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002900
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002901 PrintingPolicy Policy = getCompletionPrintingPolicy(Ctx, PP);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002902 if (Kind == RK_Pattern) {
2903 Pattern->Priority = Priority;
2904 Pattern->Availability = Availability;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002905
Douglas Gregor78254c82012-03-27 23:34:16 +00002906 if (Declaration) {
2907 Result.addParentContext(Declaration->getDeclContext());
Douglas Gregor78254c82012-03-27 23:34:16 +00002908 Pattern->ParentName = Result.getParentName();
Ilya Biryukova3f955b2018-05-16 12:30:01 +00002909 if (const RawComment *RC =
2910 getPatternCompletionComment(Ctx, Declaration)) {
2911 Result.addBriefComment(RC->getBriefText(Ctx));
2912 Pattern->BriefComment = Result.getBriefComment();
2913 }
Douglas Gregor78254c82012-03-27 23:34:16 +00002914 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002915
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002916 return Pattern;
2917 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002918
Douglas Gregorf09935f2009-12-01 05:55:20 +00002919 if (Kind == RK_Keyword) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002920 Result.AddTypedTextChunk(Keyword);
2921 return Result.TakeString();
Douglas Gregorf09935f2009-12-01 05:55:20 +00002922 }
Douglas Gregorf64acca2010-05-25 21:41:55 +00002923 assert(Kind == RK_Declaration && "Missed a result kind?");
Kadir Cetinkayaae45d0a42018-10-02 09:42:31 +00002924 return createCodeCompletionStringForDecl(PP, Ctx, Result, IncludeBriefComments,
2925 CCContext, Policy);
2926}
2927
2928CodeCompletionString *
2929CodeCompletionResult::createCodeCompletionStringForOverride(
2930 Preprocessor &PP, ASTContext &Ctx, CodeCompletionBuilder &Result,
2931 bool IncludeBriefComments, const CodeCompletionContext &CCContext,
2932 PrintingPolicy &Policy) {
2933 std::string OverrideSignature;
2934 llvm::raw_string_ostream OS(OverrideSignature);
2935 auto *CCS = createCodeCompletionStringForDecl(PP, Ctx, Result,
2936 /*IncludeBriefComments=*/false,
2937 CCContext, Policy);
2938 printOverrideString(OS, CCS);
2939 OS << " override";
2940 Result.AddTypedTextChunk(Result.getAllocator().CopyString(OS.str()));
2941 return Result.TakeString();
2942}
2943
2944CodeCompletionString *CodeCompletionResult::createCodeCompletionStringForDecl(
2945 Preprocessor &PP, ASTContext &Ctx, CodeCompletionBuilder &Result,
2946 bool IncludeBriefComments, const CodeCompletionContext &CCContext,
2947 PrintingPolicy &Policy) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002948 const NamedDecl *ND = Declaration;
Douglas Gregor78254c82012-03-27 23:34:16 +00002949 Result.addParentContext(ND->getDeclContext());
Dmitri Gribenko3292d062012-07-02 17:35:10 +00002950
2951 if (IncludeBriefComments) {
2952 // Add documentation comment, if it exists.
Ilya Biryukova3f955b2018-05-16 12:30:01 +00002953 if (const RawComment *RC = getCompletionComment(Ctx, Declaration)) {
Dmitri Gribenko3292d062012-07-02 17:35:10 +00002954 Result.addBriefComment(RC->getBriefText(Ctx));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002955 }
Dmitri Gribenko3292d062012-07-02 17:35:10 +00002956 }
2957
Douglas Gregor9eb77012009-11-07 00:00:49 +00002958 if (StartsNestedNameSpecifier) {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002959 Result.AddTypedTextChunk(
2960 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002961 Result.AddTextChunk("::");
2962 return Result.TakeString();
Douglas Gregor9eb77012009-11-07 00:00:49 +00002963 }
Erik Verbruggen98ea7f62011-10-14 15:31:08 +00002964
Aaron Ballmanbe22bcb2014-03-10 17:08:28 +00002965 for (const auto *I : ND->specific_attrs<AnnotateAttr>())
2966 Result.AddAnnotation(Result.getAllocator().CopyString(I->getAnnotation()));
Aaron Ballmanb97112e2014-03-08 22:19:01 +00002967
Douglas Gregorc3425b12015-07-07 06:20:19 +00002968 AddResultTypeChunk(Ctx, Policy, ND, CCContext.getBaseType(), Result);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002969
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002970 if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(ND)) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002971 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002972 Ctx, Policy);
2973 AddTypedNameChunk(Ctx, Policy, ND, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002974 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Richard Smith20e883e2015-04-29 23:20:19 +00002975 AddFunctionParameterChunks(PP, Policy, Function, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002976 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor0f622362009-12-11 18:44:16 +00002977 AddFunctionTypeQualsToCompletionString(Result, Function);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002978 return Result.TakeString();
Douglas Gregor3545ff42009-09-21 16:56:56 +00002979 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002980
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002981 if (const FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND)) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002982 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002983 Ctx, Policy);
Douglas Gregor3545ff42009-09-21 16:56:56 +00002984 FunctionDecl *Function = FunTmpl->getTemplatedDecl();
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002985 AddTypedNameChunk(Ctx, Policy, Function, Result);
Douglas Gregor0212fd72010-09-21 16:06:22 +00002986
Douglas Gregor3545ff42009-09-21 16:56:56 +00002987 // Figure out which template parameters are deduced (or have default
2988 // arguments).
Benjamin Kramere0513cb2012-01-30 16:17:39 +00002989 llvm::SmallBitVector Deduced;
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002990 Sema::MarkDeducedTemplateParameters(Ctx, FunTmpl, Deduced);
Douglas Gregor3545ff42009-09-21 16:56:56 +00002991 unsigned LastDeducibleArgument;
2992 for (LastDeducibleArgument = Deduced.size(); LastDeducibleArgument > 0;
2993 --LastDeducibleArgument) {
2994 if (!Deduced[LastDeducibleArgument - 1]) {
2995 // C++0x: Figure out if the template argument has a default. If so,
2996 // the user doesn't need to type this argument.
2997 // FIXME: We need to abstract template parameters better!
2998 bool HasDefaultArg = false;
2999 NamedDecl *Param = FunTmpl->getTemplateParameters()->getParam(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003000 LastDeducibleArgument - 1);
Douglas Gregor3545ff42009-09-21 16:56:56 +00003001 if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param))
3002 HasDefaultArg = TTP->hasDefaultArgument();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003003 else if (NonTypeTemplateParmDecl *NTTP
Douglas Gregor3545ff42009-09-21 16:56:56 +00003004 = dyn_cast<NonTypeTemplateParmDecl>(Param))
3005 HasDefaultArg = NTTP->hasDefaultArgument();
3006 else {
3007 assert(isa<TemplateTemplateParmDecl>(Param));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003008 HasDefaultArg
Douglas Gregor9eb77012009-11-07 00:00:49 +00003009 = cast<TemplateTemplateParmDecl>(Param)->hasDefaultArgument();
Douglas Gregor3545ff42009-09-21 16:56:56 +00003010 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003011
Douglas Gregor3545ff42009-09-21 16:56:56 +00003012 if (!HasDefaultArg)
3013 break;
3014 }
3015 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003016
Douglas Gregor3545ff42009-09-21 16:56:56 +00003017 if (LastDeducibleArgument) {
3018 // Some of the function template arguments cannot be deduced from a
3019 // function call, so we introduce an explicit template argument list
3020 // containing all of the arguments up to the first deducible argument.
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003021 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003022 AddTemplateParameterChunks(Ctx, Policy, FunTmpl, Result,
Douglas Gregor3545ff42009-09-21 16:56:56 +00003023 LastDeducibleArgument);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003024 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregor3545ff42009-09-21 16:56:56 +00003025 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003026
Douglas Gregor3545ff42009-09-21 16:56:56 +00003027 // Add the function parameters
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003028 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Richard Smith20e883e2015-04-29 23:20:19 +00003029 AddFunctionParameterChunks(PP, Policy, Function, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003030 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor0f622362009-12-11 18:44:16 +00003031 AddFunctionTypeQualsToCompletionString(Result, Function);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003032 return Result.TakeString();
Douglas Gregor3545ff42009-09-21 16:56:56 +00003033 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003034
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00003035 if (const TemplateDecl *Template = dyn_cast<TemplateDecl>(ND)) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003036 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003037 Ctx, Policy);
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003038 Result.AddTypedTextChunk(
3039 Result.getAllocator().CopyString(Template->getNameAsString()));
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003040 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003041 AddTemplateParameterChunks(Ctx, Policy, Template, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003042 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003043 return Result.TakeString();
Douglas Gregor3545ff42009-09-21 16:56:56 +00003044 }
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00003045 if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND)) {
Douglas Gregord3c5d792009-11-17 16:44:22 +00003046 Selector Sel = Method->getSelector();
3047 if (Sel.isUnarySelector()) {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003048 Result.AddTypedTextChunk(Result.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00003049 Sel.getNameForSlot(0)));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003050 return Result.TakeString();
Douglas Gregord3c5d792009-11-17 16:44:22 +00003051 }
3052
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00003053 std::string SelName = Sel.getNameForSlot(0).str();
Douglas Gregor1b605f72009-11-19 01:08:35 +00003054 SelName += ':';
3055 if (StartParameter == 0)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003056 Result.AddTypedTextChunk(Result.getAllocator().CopyString(SelName));
Douglas Gregor1b605f72009-11-19 01:08:35 +00003057 else {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003058 Result.AddInformativeChunk(Result.getAllocator().CopyString(SelName));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003059
Douglas Gregor1b605f72009-11-19 01:08:35 +00003060 // If there is only one parameter, and we're past it, add an empty
3061 // typed-text chunk since there is nothing to type.
3062 if (Method->param_size() == 1)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003063 Result.AddTypedTextChunk("");
Douglas Gregor1b605f72009-11-19 01:08:35 +00003064 }
Douglas Gregord3c5d792009-11-17 16:44:22 +00003065 unsigned Idx = 0;
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00003066 for (ObjCMethodDecl::param_const_iterator P = Method->param_begin(),
3067 PEnd = Method->param_end();
Douglas Gregord3c5d792009-11-17 16:44:22 +00003068 P != PEnd; (void)++P, ++Idx) {
3069 if (Idx > 0) {
Douglas Gregor1b605f72009-11-19 01:08:35 +00003070 std::string Keyword;
3071 if (Idx > StartParameter)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003072 Result.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregord3c5d792009-11-17 16:44:22 +00003073 if (IdentifierInfo *II = Sel.getIdentifierInfoForSlot(Idx))
Benjamin Kramer632500c2011-07-26 16:59:25 +00003074 Keyword += II->getName();
Douglas Gregord3c5d792009-11-17 16:44:22 +00003075 Keyword += ":";
Douglas Gregor95887f92010-07-08 23:20:03 +00003076 if (Idx < StartParameter || AllParametersAreInformative)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003077 Result.AddInformativeChunk(Result.getAllocator().CopyString(Keyword));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003078 else
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003079 Result.AddTypedTextChunk(Result.getAllocator().CopyString(Keyword));
Douglas Gregord3c5d792009-11-17 16:44:22 +00003080 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003081
Douglas Gregor1b605f72009-11-19 01:08:35 +00003082 // If we're before the starting parameter, skip the placeholder.
3083 if (Idx < StartParameter)
3084 continue;
Douglas Gregord3c5d792009-11-17 16:44:22 +00003085
3086 std::string Arg;
Douglas Gregorc3425b12015-07-07 06:20:19 +00003087 QualType ParamType = (*P)->getType();
3088 Optional<ArrayRef<QualType>> ObjCSubsts;
3089 if (!CCContext.getBaseType().isNull())
3090 ObjCSubsts = CCContext.getBaseType()->getObjCSubstitutions(Method);
3091
3092 if (ParamType->isBlockPointerType() && !DeclaringEntity)
3093 Arg = FormatFunctionParameter(Policy, *P, true,
3094 /*SuppressBlock=*/false,
3095 ObjCSubsts);
Douglas Gregore90dd002010-08-24 16:15:59 +00003096 else {
Douglas Gregorc3425b12015-07-07 06:20:19 +00003097 if (ObjCSubsts)
3098 ParamType = ParamType.substObjCTypeArgs(Ctx, *ObjCSubsts,
3099 ObjCSubstitutionContext::Parameter);
Douglas Gregor86b42682015-06-19 18:27:52 +00003100 Arg = "(" + formatObjCParamQualifiers((*P)->getObjCDeclQualifier(),
Douglas Gregorc3425b12015-07-07 06:20:19 +00003101 ParamType);
3102 Arg += ParamType.getAsString(Policy) + ")";
Douglas Gregore90dd002010-08-24 16:15:59 +00003103 if (IdentifierInfo *II = (*P)->getIdentifier())
Douglas Gregor981a0c42010-08-29 19:47:46 +00003104 if (DeclaringEntity || AllParametersAreInformative)
Benjamin Kramer632500c2011-07-26 16:59:25 +00003105 Arg += II->getName();
Douglas Gregore90dd002010-08-24 16:15:59 +00003106 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003107
Douglas Gregor400f5972010-08-31 05:13:43 +00003108 if (Method->isVariadic() && (P + 1) == PEnd)
3109 Arg += ", ...";
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003110
Douglas Gregor95887f92010-07-08 23:20:03 +00003111 if (DeclaringEntity)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003112 Result.AddTextChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregor95887f92010-07-08 23:20:03 +00003113 else if (AllParametersAreInformative)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003114 Result.AddInformativeChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregorc8537c52009-11-19 07:41:15 +00003115 else
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003116 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregord3c5d792009-11-17 16:44:22 +00003117 }
3118
Douglas Gregor04c5f972009-12-23 00:21:46 +00003119 if (Method->isVariadic()) {
Douglas Gregor400f5972010-08-31 05:13:43 +00003120 if (Method->param_size() == 0) {
3121 if (DeclaringEntity)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003122 Result.AddTextChunk(", ...");
Douglas Gregor400f5972010-08-31 05:13:43 +00003123 else if (AllParametersAreInformative)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003124 Result.AddInformativeChunk(", ...");
Douglas Gregor400f5972010-08-31 05:13:43 +00003125 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003126 Result.AddPlaceholderChunk(", ...");
Douglas Gregor400f5972010-08-31 05:13:43 +00003127 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003128
Richard Smith20e883e2015-04-29 23:20:19 +00003129 MaybeAddSentinel(PP, Method, Result);
Douglas Gregor04c5f972009-12-23 00:21:46 +00003130 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003131
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003132 return Result.TakeString();
Douglas Gregord3c5d792009-11-17 16:44:22 +00003133 }
3134
Douglas Gregorf09935f2009-12-01 05:55:20 +00003135 if (Qualifier)
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003136 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003137 Ctx, Policy);
Douglas Gregorf09935f2009-12-01 05:55:20 +00003138
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003139 Result.AddTypedTextChunk(
Kadir Cetinkayaae45d0a42018-10-02 09:42:31 +00003140 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003141 return Result.TakeString();
Douglas Gregor3545ff42009-09-21 16:56:56 +00003142}
3143
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003144const RawComment *clang::getCompletionComment(const ASTContext &Ctx,
3145 const NamedDecl *ND) {
3146 if (!ND)
3147 return nullptr;
3148 if (auto *RC = Ctx.getRawCommentForAnyRedecl(ND))
3149 return RC;
3150
3151 // Try to find comment from a property for ObjC methods.
3152 const ObjCMethodDecl *M = dyn_cast<ObjCMethodDecl>(ND);
3153 if (!M)
3154 return nullptr;
3155 const ObjCPropertyDecl *PDecl = M->findPropertyDecl();
3156 if (!PDecl)
3157 return nullptr;
3158
3159 return Ctx.getRawCommentForAnyRedecl(PDecl);
3160}
3161
3162const RawComment *clang::getPatternCompletionComment(const ASTContext &Ctx,
3163 const NamedDecl *ND) {
3164 const ObjCMethodDecl *M = dyn_cast_or_null<ObjCMethodDecl>(ND);
3165 if (!M || !M->isPropertyAccessor())
3166 return nullptr;
3167
3168 // Provide code completion comment for self.GetterName where
3169 // GetterName is the getter method for a property with name
3170 // different from the property name (declared via a property
3171 // getter attribute.
3172 const ObjCPropertyDecl *PDecl = M->findPropertyDecl();
3173 if (!PDecl)
3174 return nullptr;
3175 if (PDecl->getGetterName() == M->getSelector() &&
3176 PDecl->getIdentifier() != M->getIdentifier()) {
3177 if (auto *RC = Ctx.getRawCommentForAnyRedecl(M))
3178 return RC;
3179 if (auto *RC = Ctx.getRawCommentForAnyRedecl(PDecl))
3180 return RC;
3181 }
3182 return nullptr;
3183}
3184
3185const RawComment *clang::getParameterComment(
3186 const ASTContext &Ctx,
3187 const CodeCompleteConsumer::OverloadCandidate &Result,
3188 unsigned ArgIndex) {
3189 auto FDecl = Result.getFunction();
3190 if (!FDecl)
3191 return nullptr;
3192 if (ArgIndex < FDecl->getNumParams())
3193 return Ctx.getRawCommentForAnyRedecl(FDecl->getParamDecl(ArgIndex));
3194 return nullptr;
3195}
3196
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003197/// Add function overload parameter chunks to the given code completion
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003198/// string.
3199static void AddOverloadParameterChunks(ASTContext &Context,
3200 const PrintingPolicy &Policy,
3201 const FunctionDecl *Function,
3202 const FunctionProtoType *Prototype,
3203 CodeCompletionBuilder &Result,
3204 unsigned CurrentArg,
3205 unsigned Start = 0,
3206 bool InOptional = false) {
3207 bool FirstParameter = true;
3208 unsigned NumParams = Function ? Function->getNumParams()
3209 : Prototype->getNumParams();
3210
3211 for (unsigned P = Start; P != NumParams; ++P) {
3212 if (Function && Function->getParamDecl(P)->hasDefaultArg() && !InOptional) {
3213 // When we see an optional default argument, put that argument and
3214 // the remaining default arguments into a new, optional string.
3215 CodeCompletionBuilder Opt(Result.getAllocator(),
3216 Result.getCodeCompletionTUInfo());
3217 if (!FirstParameter)
3218 Opt.AddChunk(CodeCompletionString::CK_Comma);
3219 // Optional sections are nested.
3220 AddOverloadParameterChunks(Context, Policy, Function, Prototype, Opt,
3221 CurrentArg, P, /*InOptional=*/true);
3222 Result.AddOptionalChunk(Opt.TakeString());
3223 return;
3224 }
3225
3226 if (FirstParameter)
3227 FirstParameter = false;
3228 else
3229 Result.AddChunk(CodeCompletionString::CK_Comma);
3230
3231 InOptional = false;
3232
3233 // Format the placeholder string.
3234 std::string Placeholder;
Erik Verbruggen11338c52017-07-19 10:45:40 +00003235 if (Function) {
3236 const ParmVarDecl *Param = Function->getParamDecl(P);
3237 Placeholder = FormatFunctionParameter(Policy, Param);
3238 if (Param->hasDefaultArg())
3239 Placeholder += GetDefaultValueString(Param, Context.getSourceManager(), Context.getLangOpts());
3240 } else {
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003241 Placeholder = Prototype->getParamType(P).getAsString(Policy);
Erik Verbruggen11338c52017-07-19 10:45:40 +00003242 }
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003243
3244 if (P == CurrentArg)
3245 Result.AddCurrentParameterChunk(
3246 Result.getAllocator().CopyString(Placeholder));
3247 else
3248 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Placeholder));
3249 }
3250
3251 if (Prototype && Prototype->isVariadic()) {
3252 CodeCompletionBuilder Opt(Result.getAllocator(),
3253 Result.getCodeCompletionTUInfo());
3254 if (!FirstParameter)
3255 Opt.AddChunk(CodeCompletionString::CK_Comma);
3256
3257 if (CurrentArg < NumParams)
3258 Opt.AddPlaceholderChunk("...");
3259 else
3260 Opt.AddCurrentParameterChunk("...");
3261
3262 Result.AddOptionalChunk(Opt.TakeString());
3263 }
3264}
3265
Douglas Gregorf0f51982009-09-23 00:34:09 +00003266CodeCompletionString *
3267CodeCompleteConsumer::OverloadCandidate::CreateSignatureString(
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003268 unsigned CurrentArg, Sema &S,
3269 CodeCompletionAllocator &Allocator,
3270 CodeCompletionTUInfo &CCTUInfo,
3271 bool IncludeBriefComments) const {
Douglas Gregor75acd922011-09-27 23:30:47 +00003272 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
John McCall31168b02011-06-15 23:02:42 +00003273
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003274 // FIXME: Set priority, availability appropriately.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003275 CodeCompletionBuilder Result(Allocator,CCTUInfo, 1, CXAvailability_Available);
Douglas Gregorf0f51982009-09-23 00:34:09 +00003276 FunctionDecl *FDecl = getFunction();
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003277 const FunctionProtoType *Proto
Douglas Gregorf0f51982009-09-23 00:34:09 +00003278 = dyn_cast<FunctionProtoType>(getFunctionType());
3279 if (!FDecl && !Proto) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003280 // Function without a prototype. Just give the return type and a
Douglas Gregorf0f51982009-09-23 00:34:09 +00003281 // highlighted ellipsis.
3282 const FunctionType *FT = getFunctionType();
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003283 Result.AddResultTypeChunk(Result.getAllocator().CopyString(
3284 FT->getReturnType().getAsString(Policy)));
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003285 Result.AddChunk(CodeCompletionString::CK_LeftParen);
3286 Result.AddChunk(CodeCompletionString::CK_CurrentParameter, "...");
3287 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003288 return Result.TakeString();
Douglas Gregorf0f51982009-09-23 00:34:09 +00003289 }
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003290
3291 if (FDecl) {
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003292 if (IncludeBriefComments) {
3293 if (auto RC = getParameterComment(S.getASTContext(), *this, CurrentArg))
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003294 Result.addBriefComment(RC->getBriefText(S.getASTContext()));
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003295 }
Douglas Gregorc3425b12015-07-07 06:20:19 +00003296 AddResultTypeChunk(S.Context, Policy, FDecl, QualType(), Result);
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003297 Result.AddTextChunk(
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003298 Result.getAllocator().CopyString(FDecl->getNameAsString()));
3299 } else {
3300 Result.AddResultTypeChunk(
3301 Result.getAllocator().CopyString(
Alp Toker314cc812014-01-25 16:55:45 +00003302 Proto->getReturnType().getAsString(Policy)));
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003303 }
Alp Toker314cc812014-01-25 16:55:45 +00003304
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003305 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003306 AddOverloadParameterChunks(S.getASTContext(), Policy, FDecl, Proto, Result,
3307 CurrentArg);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003308 Result.AddChunk(CodeCompletionString::CK_RightParen);
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003309
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003310 return Result.TakeString();
Douglas Gregorf0f51982009-09-23 00:34:09 +00003311}
3312
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003313unsigned clang::getMacroUsagePriority(StringRef MacroName,
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00003314 const LangOptions &LangOpts,
Douglas Gregor6e240332010-08-16 16:18:59 +00003315 bool PreferredTypeIsPointer) {
3316 unsigned Priority = CCP_Macro;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003317
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00003318 // Treat the "nil", "Nil" and "NULL" macros as null pointer constants.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003319 if (MacroName.equals("nil") || MacroName.equals("NULL") ||
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00003320 MacroName.equals("Nil")) {
Douglas Gregor6e240332010-08-16 16:18:59 +00003321 Priority = CCP_Constant;
3322 if (PreferredTypeIsPointer)
3323 Priority = Priority / CCF_SimilarTypeMatch;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003324 }
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00003325 // Treat "YES", "NO", "true", and "false" as constants.
3326 else if (MacroName.equals("YES") || MacroName.equals("NO") ||
3327 MacroName.equals("true") || MacroName.equals("false"))
3328 Priority = CCP_Constant;
3329 // Treat "bool" as a type.
3330 else if (MacroName.equals("bool"))
3331 Priority = CCP_Type + (LangOpts.ObjC1? CCD_bool_in_ObjC : 0);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003332
3333
Douglas Gregor6e240332010-08-16 16:18:59 +00003334 return Priority;
3335}
3336
Dmitri Gribenkobdc80de2013-01-11 20:32:41 +00003337CXCursorKind clang::getCursorKindForDecl(const Decl *D) {
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003338 if (!D)
3339 return CXCursor_UnexposedDecl;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003340
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003341 switch (D->getKind()) {
3342 case Decl::Enum: return CXCursor_EnumDecl;
3343 case Decl::EnumConstant: return CXCursor_EnumConstantDecl;
3344 case Decl::Field: return CXCursor_FieldDecl;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003345 case Decl::Function:
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003346 return CXCursor_FunctionDecl;
3347 case Decl::ObjCCategory: return CXCursor_ObjCCategoryDecl;
3348 case Decl::ObjCCategoryImpl: return CXCursor_ObjCCategoryImplDecl;
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003349 case Decl::ObjCImplementation: return CXCursor_ObjCImplementationDecl;
Douglas Gregordeafd0b2011-12-27 22:43:10 +00003350
Argyrios Kyrtzidis3698cef2012-01-24 21:39:26 +00003351 case Decl::ObjCInterface: return CXCursor_ObjCInterfaceDecl;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003352 case Decl::ObjCIvar: return CXCursor_ObjCIvarDecl;
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003353 case Decl::ObjCMethod:
3354 return cast<ObjCMethodDecl>(D)->isInstanceMethod()
3355 ? CXCursor_ObjCInstanceMethodDecl : CXCursor_ObjCClassMethodDecl;
3356 case Decl::CXXMethod: return CXCursor_CXXMethod;
3357 case Decl::CXXConstructor: return CXCursor_Constructor;
3358 case Decl::CXXDestructor: return CXCursor_Destructor;
3359 case Decl::CXXConversion: return CXCursor_ConversionFunction;
3360 case Decl::ObjCProperty: return CXCursor_ObjCPropertyDecl;
Argyrios Kyrtzidis3698cef2012-01-24 21:39:26 +00003361 case Decl::ObjCProtocol: return CXCursor_ObjCProtocolDecl;
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003362 case Decl::ParmVar: return CXCursor_ParmDecl;
3363 case Decl::Typedef: return CXCursor_TypedefDecl;
Richard Smithdda56e42011-04-15 14:24:37 +00003364 case Decl::TypeAlias: return CXCursor_TypeAliasDecl;
Sergey Kalinichev8f3b1872015-11-15 13:48:32 +00003365 case Decl::TypeAliasTemplate: return CXCursor_TypeAliasTemplateDecl;
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003366 case Decl::Var: return CXCursor_VarDecl;
3367 case Decl::Namespace: return CXCursor_Namespace;
3368 case Decl::NamespaceAlias: return CXCursor_NamespaceAlias;
3369 case Decl::TemplateTypeParm: return CXCursor_TemplateTypeParameter;
3370 case Decl::NonTypeTemplateParm:return CXCursor_NonTypeTemplateParameter;
3371 case Decl::TemplateTemplateParm:return CXCursor_TemplateTemplateParameter;
3372 case Decl::FunctionTemplate: return CXCursor_FunctionTemplate;
3373 case Decl::ClassTemplate: return CXCursor_ClassTemplate;
Argyrios Kyrtzidis12afd702011-09-30 17:58:23 +00003374 case Decl::AccessSpec: return CXCursor_CXXAccessSpecifier;
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003375 case Decl::ClassTemplatePartialSpecialization:
3376 return CXCursor_ClassTemplatePartialSpecialization;
3377 case Decl::UsingDirective: return CXCursor_UsingDirective;
Olivier Goffart81978012016-06-09 16:15:55 +00003378 case Decl::StaticAssert: return CXCursor_StaticAssert;
Olivier Goffartd211c642016-11-04 06:29:27 +00003379 case Decl::Friend: return CXCursor_FriendDecl;
Douglas Gregor3e653b32012-04-30 23:41:16 +00003380 case Decl::TranslationUnit: return CXCursor_TranslationUnit;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003381
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003382 case Decl::Using:
3383 case Decl::UnresolvedUsingValue:
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003384 case Decl::UnresolvedUsingTypename:
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003385 return CXCursor_UsingDeclaration;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003386
Douglas Gregor4cd65962011-06-03 23:08:58 +00003387 case Decl::ObjCPropertyImpl:
3388 switch (cast<ObjCPropertyImplDecl>(D)->getPropertyImplementation()) {
3389 case ObjCPropertyImplDecl::Dynamic:
3390 return CXCursor_ObjCDynamicDecl;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003391
Douglas Gregor4cd65962011-06-03 23:08:58 +00003392 case ObjCPropertyImplDecl::Synthesize:
3393 return CXCursor_ObjCSynthesizeDecl;
3394 }
Argyrios Kyrtzidis50e5b1d2012-10-05 00:22:24 +00003395
3396 case Decl::Import:
3397 return CXCursor_ModuleImportDecl;
Douglas Gregor85f3f952015-07-07 03:57:15 +00003398
3399 case Decl::ObjCTypeParam: return CXCursor_TemplateTypeParameter;
3400
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003401 default:
Dmitri Gribenkobdc80de2013-01-11 20:32:41 +00003402 if (const TagDecl *TD = dyn_cast<TagDecl>(D)) {
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003403 switch (TD->getTagKind()) {
Joao Matosdc86f942012-08-31 18:45:21 +00003404 case TTK_Interface: // fall through
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003405 case TTK_Struct: return CXCursor_StructDecl;
3406 case TTK_Class: return CXCursor_ClassDecl;
3407 case TTK_Union: return CXCursor_UnionDecl;
3408 case TTK_Enum: return CXCursor_EnumDecl;
3409 }
3410 }
3411 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003412
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003413 return CXCursor_UnexposedDecl;
3414}
3415
Douglas Gregor55b037b2010-07-08 20:55:51 +00003416static void AddMacroResults(Preprocessor &PP, ResultBuilder &Results,
Eric Liu88de9f62018-09-19 09:34:55 +00003417 bool LoadExternal, bool IncludeUndefined,
Douglas Gregor55b037b2010-07-08 20:55:51 +00003418 bool TargetTypeIsPointer = false) {
John McCall276321a2010-08-25 06:19:51 +00003419 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003420
Douglas Gregorf329c7c2009-10-30 16:50:04 +00003421 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003422
Eric Liu88de9f62018-09-19 09:34:55 +00003423 for (Preprocessor::macro_iterator M = PP.macro_begin(LoadExternal),
3424 MEnd = PP.macro_end(LoadExternal);
Douglas Gregor55b037b2010-07-08 20:55:51 +00003425 M != MEnd; ++M) {
Richard Smith20e883e2015-04-29 23:20:19 +00003426 auto MD = PP.getMacroDefinition(M->first);
3427 if (IncludeUndefined || MD) {
Eric Liud485df12018-09-05 14:59:17 +00003428 MacroInfo *MI = MD.getMacroInfo();
3429 if (MI && MI->isUsedForHeaderGuard())
3430 continue;
Argyrios Kyrtzidis9ef53ce2014-04-09 18:21:23 +00003431
Eric Liud485df12018-09-05 14:59:17 +00003432 Results.AddResult(
3433 Result(M->first, MI,
3434 getMacroUsagePriority(M->first->getName(), PP.getLangOpts(),
3435 TargetTypeIsPointer)));
Argyrios Kyrtzidis9ef53ce2014-04-09 18:21:23 +00003436 }
Douglas Gregor55b037b2010-07-08 20:55:51 +00003437 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003438
Douglas Gregorf329c7c2009-10-30 16:50:04 +00003439 Results.ExitScope();
3440}
3441
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003442static void AddPrettyFunctionResults(const LangOptions &LangOpts,
Douglas Gregorce0e8562010-08-23 21:54:33 +00003443 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00003444 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003445
Douglas Gregorce0e8562010-08-23 21:54:33 +00003446 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003447
Douglas Gregorce0e8562010-08-23 21:54:33 +00003448 Results.AddResult(Result("__PRETTY_FUNCTION__", CCP_Constant));
3449 Results.AddResult(Result("__FUNCTION__", CCP_Constant));
Richard Smith2bf7fdb2013-01-02 11:42:31 +00003450 if (LangOpts.C99 || LangOpts.CPlusPlus11)
Douglas Gregorce0e8562010-08-23 21:54:33 +00003451 Results.AddResult(Result("__func__", CCP_Constant));
3452 Results.ExitScope();
3453}
3454
Daniel Dunbar242ea9a2009-11-13 08:58:20 +00003455static void HandleCodeCompleteResults(Sema *S,
3456 CodeCompleteConsumer *CodeCompleter,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003457 CodeCompletionContext Context,
John McCall276321a2010-08-25 06:19:51 +00003458 CodeCompletionResult *Results,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003459 unsigned NumResults) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00003460 if (CodeCompleter)
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003461 CodeCompleter->ProcessCodeCompleteResults(*S, Context, Results, NumResults);
Douglas Gregor3545ff42009-09-21 16:56:56 +00003462}
3463
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003464static enum CodeCompletionContext::Kind mapCodeCompletionContext(Sema &S,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003465 Sema::ParserCompletionContext PCC) {
3466 switch (PCC) {
John McCallfaf5fb42010-08-26 23:41:50 +00003467 case Sema::PCC_Namespace:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003468 return CodeCompletionContext::CCC_TopLevel;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003469
John McCallfaf5fb42010-08-26 23:41:50 +00003470 case Sema::PCC_Class:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003471 return CodeCompletionContext::CCC_ClassStructUnion;
3472
John McCallfaf5fb42010-08-26 23:41:50 +00003473 case Sema::PCC_ObjCInterface:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003474 return CodeCompletionContext::CCC_ObjCInterface;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003475
John McCallfaf5fb42010-08-26 23:41:50 +00003476 case Sema::PCC_ObjCImplementation:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003477 return CodeCompletionContext::CCC_ObjCImplementation;
3478
John McCallfaf5fb42010-08-26 23:41:50 +00003479 case Sema::PCC_ObjCInstanceVariableList:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003480 return CodeCompletionContext::CCC_ObjCIvarList;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003481
John McCallfaf5fb42010-08-26 23:41:50 +00003482 case Sema::PCC_Template:
3483 case Sema::PCC_MemberTemplate:
Douglas Gregor0ac41382010-09-23 23:01:17 +00003484 if (S.CurContext->isFileContext())
3485 return CodeCompletionContext::CCC_TopLevel;
David Blaikie8a40f702012-01-17 06:56:22 +00003486 if (S.CurContext->isRecord())
Douglas Gregor0ac41382010-09-23 23:01:17 +00003487 return CodeCompletionContext::CCC_ClassStructUnion;
David Blaikie8a40f702012-01-17 06:56:22 +00003488 return CodeCompletionContext::CCC_Other;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003489
John McCallfaf5fb42010-08-26 23:41:50 +00003490 case Sema::PCC_RecoveryInFunction:
Douglas Gregor0ac41382010-09-23 23:01:17 +00003491 return CodeCompletionContext::CCC_Recovery;
Douglas Gregorc769d6e2010-10-18 22:01:46 +00003492
John McCallfaf5fb42010-08-26 23:41:50 +00003493 case Sema::PCC_ForInit:
David Blaikiebbafb8a2012-03-11 07:00:24 +00003494 if (S.getLangOpts().CPlusPlus || S.getLangOpts().C99 ||
3495 S.getLangOpts().ObjC1)
Douglas Gregorc769d6e2010-10-18 22:01:46 +00003496 return CodeCompletionContext::CCC_ParenthesizedExpression;
3497 else
3498 return CodeCompletionContext::CCC_Expression;
3499
3500 case Sema::PCC_Expression:
John McCallfaf5fb42010-08-26 23:41:50 +00003501 case Sema::PCC_Condition:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003502 return CodeCompletionContext::CCC_Expression;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003503
John McCallfaf5fb42010-08-26 23:41:50 +00003504 case Sema::PCC_Statement:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003505 return CodeCompletionContext::CCC_Statement;
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003506
John McCallfaf5fb42010-08-26 23:41:50 +00003507 case Sema::PCC_Type:
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003508 return CodeCompletionContext::CCC_Type;
Douglas Gregor5e35d592010-09-14 23:59:36 +00003509
3510 case Sema::PCC_ParenthesizedExpression:
3511 return CodeCompletionContext::CCC_ParenthesizedExpression;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003512
Douglas Gregor80039242011-02-15 20:33:25 +00003513 case Sema::PCC_LocalDeclarationSpecifiers:
3514 return CodeCompletionContext::CCC_Type;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003515 }
David Blaikie8a40f702012-01-17 06:56:22 +00003516
3517 llvm_unreachable("Invalid ParserCompletionContext!");
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003518}
3519
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003520/// If we're in a C++ virtual member function, add completion results
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003521/// that invoke the functions we override, since it's common to invoke the
Douglas Gregorac322ec2010-08-27 21:18:54 +00003522/// overridden function as well as adding new functionality.
3523///
3524/// \param S The semantic analysis object for which we are generating results.
3525///
3526/// \param InContext This context in which the nested-name-specifier preceding
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003527/// the code-completion point
Douglas Gregorac322ec2010-08-27 21:18:54 +00003528static void MaybeAddOverrideCalls(Sema &S, DeclContext *InContext,
3529 ResultBuilder &Results) {
3530 // Look through blocks.
3531 DeclContext *CurContext = S.CurContext;
3532 while (isa<BlockDecl>(CurContext))
3533 CurContext = CurContext->getParent();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003534
3535
Douglas Gregorac322ec2010-08-27 21:18:54 +00003536 CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(CurContext);
3537 if (!Method || !Method->isVirtual())
3538 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003539
3540 // We need to have names for all of the parameters, if we're going to
Douglas Gregorac322ec2010-08-27 21:18:54 +00003541 // generate a forwarding call.
David Majnemer59f77922016-06-24 04:05:48 +00003542 for (auto P : Method->parameters())
Aaron Ballman43b68be2014-03-07 17:50:17 +00003543 if (!P->getDeclName())
Douglas Gregorac322ec2010-08-27 21:18:54 +00003544 return;
Douglas Gregorac322ec2010-08-27 21:18:54 +00003545
Douglas Gregor75acd922011-09-27 23:30:47 +00003546 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
Benjamin Krameracfa3392017-12-17 23:52:45 +00003547 for (const CXXMethodDecl *Overridden : Method->overridden_methods()) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003548 CodeCompletionBuilder Builder(Results.getAllocator(),
3549 Results.getCodeCompletionTUInfo());
Douglas Gregorac322ec2010-08-27 21:18:54 +00003550 if (Overridden->getCanonicalDecl() == Method->getCanonicalDecl())
3551 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003552
Douglas Gregorac322ec2010-08-27 21:18:54 +00003553 // If we need a nested-name-specifier, add one now.
3554 if (!InContext) {
3555 NestedNameSpecifier *NNS
3556 = getRequiredQualification(S.Context, CurContext,
3557 Overridden->getDeclContext());
3558 if (NNS) {
3559 std::string Str;
3560 llvm::raw_string_ostream OS(Str);
Douglas Gregor75acd922011-09-27 23:30:47 +00003561 NNS->print(OS, Policy);
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003562 Builder.AddTextChunk(Results.getAllocator().CopyString(OS.str()));
Douglas Gregorac322ec2010-08-27 21:18:54 +00003563 }
3564 } else if (!InContext->Equals(Overridden->getDeclContext()))
3565 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003566
3567 Builder.AddTypedTextChunk(Results.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003568 Overridden->getNameAsString()));
3569 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregorac322ec2010-08-27 21:18:54 +00003570 bool FirstParam = true;
David Majnemer59f77922016-06-24 04:05:48 +00003571 for (auto P : Method->parameters()) {
Douglas Gregorac322ec2010-08-27 21:18:54 +00003572 if (FirstParam)
3573 FirstParam = false;
3574 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003575 Builder.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregorac322ec2010-08-27 21:18:54 +00003576
Aaron Ballman43b68be2014-03-07 17:50:17 +00003577 Builder.AddPlaceholderChunk(
3578 Results.getAllocator().CopyString(P->getIdentifier()->getName()));
Douglas Gregorac322ec2010-08-27 21:18:54 +00003579 }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003580 Builder.AddChunk(CodeCompletionString::CK_RightParen);
3581 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregorac322ec2010-08-27 21:18:54 +00003582 CCP_SuperCompletion,
Douglas Gregor78254c82012-03-27 23:34:16 +00003583 CXCursor_CXXMethod,
3584 CXAvailability_Available,
3585 Overridden));
Douglas Gregorac322ec2010-08-27 21:18:54 +00003586 Results.Ignore(Overridden);
3587 }
3588}
3589
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003590void Sema::CodeCompleteModuleImport(SourceLocation ImportLoc,
Douglas Gregor07f43572012-01-29 18:15:03 +00003591 ModuleIdPath Path) {
3592 typedef CodeCompletionResult Result;
3593 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003594 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor07f43572012-01-29 18:15:03 +00003595 CodeCompletionContext::CCC_Other);
3596 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003597
Douglas Gregor07f43572012-01-29 18:15:03 +00003598 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003599 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Douglas Gregor07f43572012-01-29 18:15:03 +00003600 typedef CodeCompletionResult Result;
3601 if (Path.empty()) {
3602 // Enumerate all top-level modules.
Dmitri Gribenkof8579502013-01-12 19:30:44 +00003603 SmallVector<Module *, 8> Modules;
Douglas Gregor07f43572012-01-29 18:15:03 +00003604 PP.getHeaderSearchInfo().collectAllModules(Modules);
3605 for (unsigned I = 0, N = Modules.size(); I != N; ++I) {
3606 Builder.AddTypedTextChunk(
3607 Builder.getAllocator().CopyString(Modules[I]->Name));
3608 Results.AddResult(Result(Builder.TakeString(),
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003609 CCP_Declaration,
Argyrios Kyrtzidis345d05f2013-05-29 18:50:15 +00003610 CXCursor_ModuleImportDecl,
Douglas Gregor07f43572012-01-29 18:15:03 +00003611 Modules[I]->isAvailable()
3612 ? CXAvailability_Available
3613 : CXAvailability_NotAvailable));
3614 }
Daniel Jasper07e6c402013-08-05 20:26:17 +00003615 } else if (getLangOpts().Modules) {
Douglas Gregor07f43572012-01-29 18:15:03 +00003616 // Load the named module.
3617 Module *Mod = PP.getModuleLoader().loadModule(ImportLoc, Path,
3618 Module::AllVisible,
3619 /*IsInclusionDirective=*/false);
3620 // Enumerate submodules.
3621 if (Mod) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003622 for (Module::submodule_iterator Sub = Mod->submodule_begin(),
Douglas Gregor07f43572012-01-29 18:15:03 +00003623 SubEnd = Mod->submodule_end();
3624 Sub != SubEnd; ++Sub) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003625
Douglas Gregor07f43572012-01-29 18:15:03 +00003626 Builder.AddTypedTextChunk(
3627 Builder.getAllocator().CopyString((*Sub)->Name));
3628 Results.AddResult(Result(Builder.TakeString(),
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003629 CCP_Declaration,
Argyrios Kyrtzidis345d05f2013-05-29 18:50:15 +00003630 CXCursor_ModuleImportDecl,
Douglas Gregor07f43572012-01-29 18:15:03 +00003631 (*Sub)->isAvailable()
3632 ? CXAvailability_Available
3633 : CXAvailability_NotAvailable));
3634 }
3635 }
3636 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003637 Results.ExitScope();
Douglas Gregor07f43572012-01-29 18:15:03 +00003638 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
3639 Results.data(),Results.size());
3640}
3641
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003642void Sema::CodeCompleteOrdinaryName(Scope *S,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003643 ParserCompletionContext CompletionContext) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003644 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003645 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00003646 mapCodeCompletionContext(*this, CompletionContext));
Douglas Gregorac322ec2010-08-27 21:18:54 +00003647 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003648
Douglas Gregor504a6ae2010-01-10 23:08:15 +00003649 // Determine how to filter results, e.g., so that the names of
3650 // values (functions, enumerators, function templates, etc.) are
3651 // only allowed where we can have an expression.
3652 switch (CompletionContext) {
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003653 case PCC_Namespace:
3654 case PCC_Class:
3655 case PCC_ObjCInterface:
3656 case PCC_ObjCImplementation:
3657 case PCC_ObjCInstanceVariableList:
3658 case PCC_Template:
3659 case PCC_MemberTemplate:
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003660 case PCC_Type:
Douglas Gregor80039242011-02-15 20:33:25 +00003661 case PCC_LocalDeclarationSpecifiers:
Douglas Gregor504a6ae2010-01-10 23:08:15 +00003662 Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
3663 break;
3664
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003665 case PCC_Statement:
Douglas Gregor5e35d592010-09-14 23:59:36 +00003666 case PCC_ParenthesizedExpression:
Douglas Gregor4d755e82010-08-24 23:58:17 +00003667 case PCC_Expression:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003668 case PCC_ForInit:
3669 case PCC_Condition:
David Blaikiebbafb8a2012-03-11 07:00:24 +00003670 if (WantTypesInContext(CompletionContext, getLangOpts()))
Douglas Gregor70febae2010-05-28 00:49:12 +00003671 Results.setFilter(&ResultBuilder::IsOrdinaryName);
3672 else
3673 Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003674
David Blaikiebbafb8a2012-03-11 07:00:24 +00003675 if (getLangOpts().CPlusPlus)
Craig Topperc3ec1492014-05-26 06:22:03 +00003676 MaybeAddOverrideCalls(*this, /*InContext=*/nullptr, Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00003677 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003678
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003679 case PCC_RecoveryInFunction:
Douglas Gregor6da3db42010-05-25 05:58:43 +00003680 // Unfiltered
3681 break;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00003682 }
3683
Douglas Gregor9be0ed42010-08-26 16:36:48 +00003684 // If we are in a C++ non-static member function, check the qualifiers on
3685 // the member function to filter/prioritize the results list.
3686 if (CXXMethodDecl *CurMethod = dyn_cast<CXXMethodDecl>(CurContext))
3687 if (CurMethod->isInstance())
3688 Results.setObjectTypeQualifiers(
3689 Qualifiers::fromCVRMask(CurMethod->getTypeQualifiers()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003690
Douglas Gregorc580c522010-01-14 01:09:38 +00003691 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00003692 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00003693 CodeCompleter->includeGlobals(),
3694 CodeCompleter->loadExternal());
Douglas Gregor92253692009-12-07 09:54:55 +00003695
Douglas Gregorf98e6a22010-01-13 23:51:12 +00003696 AddOrdinaryNameResults(CompletionContext, S, *this, Results);
Douglas Gregor92253692009-12-07 09:54:55 +00003697 Results.ExitScope();
3698
Douglas Gregorce0e8562010-08-23 21:54:33 +00003699 switch (CompletionContext) {
Douglas Gregor5e35d592010-09-14 23:59:36 +00003700 case PCC_ParenthesizedExpression:
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003701 case PCC_Expression:
3702 case PCC_Statement:
3703 case PCC_RecoveryInFunction:
3704 if (S->getFnParent())
Craig Topper12126262015-11-15 17:27:57 +00003705 AddPrettyFunctionResults(getLangOpts(), Results);
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003706 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003707
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003708 case PCC_Namespace:
3709 case PCC_Class:
3710 case PCC_ObjCInterface:
3711 case PCC_ObjCImplementation:
3712 case PCC_ObjCInstanceVariableList:
3713 case PCC_Template:
3714 case PCC_MemberTemplate:
3715 case PCC_ForInit:
3716 case PCC_Condition:
3717 case PCC_Type:
Douglas Gregor80039242011-02-15 20:33:25 +00003718 case PCC_LocalDeclarationSpecifiers:
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003719 break;
Douglas Gregorce0e8562010-08-23 21:54:33 +00003720 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003721
Douglas Gregor9eb77012009-11-07 00:00:49 +00003722 if (CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00003723 AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003724
Douglas Gregor50832e02010-09-20 22:39:41 +00003725 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003726 Results.data(),Results.size());
Douglas Gregor9d64c5e2009-09-21 20:51:25 +00003727}
3728
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003729static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003730 ParsedType Receiver,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00003731 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00003732 bool AtArgumentExpression,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003733 bool IsSuper,
3734 ResultBuilder &Results);
3735
3736void Sema::CodeCompleteDeclSpec(Scope *S, DeclSpec &DS,
3737 bool AllowNonIdentifiers,
3738 bool AllowNestedNameSpecifiers) {
John McCall276321a2010-08-25 06:19:51 +00003739 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003740 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003741 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00003742 AllowNestedNameSpecifiers
3743 ? CodeCompletionContext::CCC_PotentiallyQualifiedName
3744 : CodeCompletionContext::CCC_Name);
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003745 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003746
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003747 // Type qualifiers can come after names.
3748 Results.AddResult(Result("const"));
3749 Results.AddResult(Result("volatile"));
David Blaikiebbafb8a2012-03-11 07:00:24 +00003750 if (getLangOpts().C99)
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003751 Results.AddResult(Result("restrict"));
3752
David Blaikiebbafb8a2012-03-11 07:00:24 +00003753 if (getLangOpts().CPlusPlus) {
Alex Lorenz8f4d3992017-02-13 23:19:40 +00003754 if (getLangOpts().CPlusPlus11 &&
3755 (DS.getTypeSpecType() == DeclSpec::TST_class ||
3756 DS.getTypeSpecType() == DeclSpec::TST_struct))
3757 Results.AddResult("final");
3758
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003759 if (AllowNonIdentifiers) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003760 Results.AddResult(Result("operator"));
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003761 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003762
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003763 // Add nested-name-specifiers.
3764 if (AllowNestedNameSpecifiers) {
3765 Results.allowNestedNameSpecifiers();
Douglas Gregor0ac41382010-09-23 23:01:17 +00003766 Results.setFilter(&ResultBuilder::IsImpossibleToSatisfy);
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003767 CodeCompletionDeclConsumer Consumer(Results, CurContext);
3768 LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00003769 CodeCompleter->includeGlobals(),
3770 CodeCompleter->loadExternal());
Craig Topperc3ec1492014-05-26 06:22:03 +00003771 Results.setFilter(nullptr);
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003772 }
3773 }
3774 Results.ExitScope();
3775
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003776 // If we're in a context where we might have an expression (rather than a
3777 // declaration), and what we've seen so far is an Objective-C type that could
3778 // be a receiver of a class message, this may be a class message send with
3779 // the initial opening bracket '[' missing. Add appropriate completions.
3780 if (AllowNonIdentifiers && !AllowNestedNameSpecifiers &&
Richard Smithb4a9e862013-04-12 22:46:28 +00003781 DS.getParsedSpecifiers() == DeclSpec::PQ_TypeSpecifier &&
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003782 DS.getTypeSpecType() == DeclSpec::TST_typename &&
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003783 DS.getTypeSpecComplex() == DeclSpec::TSC_unspecified &&
3784 DS.getTypeSpecSign() == DeclSpec::TSS_unspecified &&
Richard Smithb4a9e862013-04-12 22:46:28 +00003785 !DS.isTypeAltiVecVector() &&
3786 S &&
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003787 (S->getFlags() & Scope::DeclScope) != 0 &&
3788 (S->getFlags() & (Scope::ClassScope | Scope::TemplateParamScope |
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003789 Scope::FunctionPrototypeScope |
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003790 Scope::AtCatchScope)) == 0) {
3791 ParsedType T = DS.getRepAsType();
3792 if (!T.get().isNull() && T.get()->isObjCObjectOrInterfaceType())
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00003793 AddClassMessageCompletions(*this, S, T, None, false, false, Results);
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003794 }
3795
Douglas Gregor56ccce02010-08-24 04:59:56 +00003796 // Note that we intentionally suppress macro results here, since we do not
3797 // encourage using macros to produce the names of entities.
3798
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003799 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0ac41382010-09-23 23:01:17 +00003800 Results.getCompletionContext(),
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003801 Results.data(), Results.size());
3802}
3803
Douglas Gregor68762e72010-08-23 21:17:50 +00003804struct Sema::CodeCompleteExpressionData {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003805 CodeCompleteExpressionData(QualType PreferredType = QualType())
Douglas Gregor68762e72010-08-23 21:17:50 +00003806 : PreferredType(PreferredType), IntegralConstantExpression(false),
3807 ObjCCollection(false) { }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003808
Douglas Gregor68762e72010-08-23 21:17:50 +00003809 QualType PreferredType;
3810 bool IntegralConstantExpression;
3811 bool ObjCCollection;
Chris Lattner0e62c1c2011-07-23 10:55:15 +00003812 SmallVector<Decl *, 4> IgnoreDecls;
Douglas Gregor68762e72010-08-23 21:17:50 +00003813};
3814
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003815/// Perform code-completion in an expression context when we know what
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003816/// type we're looking for.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003817void Sema::CodeCompleteExpression(Scope *S,
Douglas Gregor68762e72010-08-23 21:17:50 +00003818 const CodeCompleteExpressionData &Data) {
Eric Liuf5ba09f2018-07-04 10:01:18 +00003819 ResultBuilder Results(
3820 *this, CodeCompleter->getAllocator(),
3821 CodeCompleter->getCodeCompletionTUInfo(),
3822 CodeCompletionContext(CodeCompletionContext::CCC_Expression,
3823 Data.PreferredType));
Douglas Gregor68762e72010-08-23 21:17:50 +00003824 if (Data.ObjCCollection)
3825 Results.setFilter(&ResultBuilder::IsObjCCollection);
3826 else if (Data.IntegralConstantExpression)
Douglas Gregor85b50632010-07-28 21:50:18 +00003827 Results.setFilter(&ResultBuilder::IsIntegralConstantValue);
David Blaikiebbafb8a2012-03-11 07:00:24 +00003828 else if (WantTypesInContext(PCC_Expression, getLangOpts()))
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003829 Results.setFilter(&ResultBuilder::IsOrdinaryName);
3830 else
3831 Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
Douglas Gregor68762e72010-08-23 21:17:50 +00003832
3833 if (!Data.PreferredType.isNull())
3834 Results.setPreferredType(Data.PreferredType.getNonReferenceType());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003835
Douglas Gregor68762e72010-08-23 21:17:50 +00003836 // Ignore any declarations that we were told that we don't care about.
3837 for (unsigned I = 0, N = Data.IgnoreDecls.size(); I != N; ++I)
3838 Results.Ignore(Data.IgnoreDecls[I]);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003839
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003840 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00003841 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00003842 CodeCompleter->includeGlobals(),
3843 CodeCompleter->loadExternal());
3844
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003845 Results.EnterNewScope();
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003846 AddOrdinaryNameResults(PCC_Expression, S, *this, Results);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003847 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003848
Douglas Gregor55b037b2010-07-08 20:55:51 +00003849 bool PreferredTypeIsPointer = false;
Douglas Gregor68762e72010-08-23 21:17:50 +00003850 if (!Data.PreferredType.isNull())
3851 PreferredTypeIsPointer = Data.PreferredType->isAnyPointerType()
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003852 || Data.PreferredType->isMemberPointerType()
Douglas Gregor68762e72010-08-23 21:17:50 +00003853 || Data.PreferredType->isBlockPointerType();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003854
3855 if (S->getFnParent() &&
3856 !Data.ObjCCollection &&
Douglas Gregorce0e8562010-08-23 21:54:33 +00003857 !Data.IntegralConstantExpression)
Craig Topper12126262015-11-15 17:27:57 +00003858 AddPrettyFunctionResults(getLangOpts(), Results);
Douglas Gregorce0e8562010-08-23 21:54:33 +00003859
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003860 if (CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00003861 AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false,
3862 PreferredTypeIsPointer);
Eric Liuf5ba09f2018-07-04 10:01:18 +00003863 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
3864 Results.data(), Results.size());
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003865}
3866
Ilya Biryukov832c4af2018-09-07 14:04:39 +00003867void Sema::CodeCompleteExpression(Scope *S, QualType PreferredType) {
3868 return CodeCompleteExpression(S, CodeCompleteExpressionData(PreferredType));
3869}
3870
Douglas Gregoreda7e542010-09-18 01:28:11 +00003871void Sema::CodeCompletePostfixExpression(Scope *S, ExprResult E) {
3872 if (E.isInvalid())
3873 CodeCompleteOrdinaryName(S, PCC_RecoveryInFunction);
David Blaikiebbafb8a2012-03-11 07:00:24 +00003874 else if (getLangOpts().ObjC1)
Nikola Smiljanic01a75982014-05-29 10:55:11 +00003875 CodeCompleteObjCInstanceMessage(S, E.get(), None, false);
Douglas Gregored0b69d2010-09-15 16:23:04 +00003876}
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003877
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003878/// The set of properties that have already been added, referenced by
Douglas Gregorb888acf2010-12-09 23:01:55 +00003879/// property name.
3880typedef llvm::SmallPtrSet<IdentifierInfo*, 16> AddedPropertiesSet;
3881
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003882/// Retrieve the container definition, if any?
Douglas Gregor9b4f3702012-06-12 13:44:08 +00003883static ObjCContainerDecl *getContainerDef(ObjCContainerDecl *Container) {
3884 if (ObjCInterfaceDecl *Interface = dyn_cast<ObjCInterfaceDecl>(Container)) {
3885 if (Interface->hasDefinition())
3886 return Interface->getDefinition();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003887
Douglas Gregor9b4f3702012-06-12 13:44:08 +00003888 return Interface;
3889 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003890
Douglas Gregor9b4f3702012-06-12 13:44:08 +00003891 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
3892 if (Protocol->hasDefinition())
3893 return Protocol->getDefinition();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003894
Douglas Gregor9b4f3702012-06-12 13:44:08 +00003895 return Protocol;
3896 }
3897 return Container;
3898}
3899
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003900/// Adds a block invocation code completion result for the given block
Alex Lorenzbaef8022016-11-09 13:43:18 +00003901/// declaration \p BD.
3902static void AddObjCBlockCall(ASTContext &Context, const PrintingPolicy &Policy,
3903 CodeCompletionBuilder &Builder,
3904 const NamedDecl *BD,
3905 const FunctionTypeLoc &BlockLoc,
3906 const FunctionProtoTypeLoc &BlockProtoLoc) {
3907 Builder.AddResultTypeChunk(
3908 GetCompletionTypeString(BlockLoc.getReturnLoc().getType(), Context,
3909 Policy, Builder.getAllocator()));
3910
3911 AddTypedNameChunk(Context, Policy, BD, Builder);
3912 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
3913
3914 if (BlockProtoLoc && BlockProtoLoc.getTypePtr()->isVariadic()) {
3915 Builder.AddPlaceholderChunk("...");
3916 } else {
3917 for (unsigned I = 0, N = BlockLoc.getNumParams(); I != N; ++I) {
3918 if (I)
3919 Builder.AddChunk(CodeCompletionString::CK_Comma);
3920
3921 // Format the placeholder string.
3922 std::string PlaceholderStr =
3923 FormatFunctionParameter(Policy, BlockLoc.getParam(I));
3924
3925 if (I == N - 1 && BlockProtoLoc &&
3926 BlockProtoLoc.getTypePtr()->isVariadic())
3927 PlaceholderStr += ", ...";
3928
3929 // Add the placeholder string.
3930 Builder.AddPlaceholderChunk(
3931 Builder.getAllocator().CopyString(PlaceholderStr));
3932 }
3933 }
3934
3935 Builder.AddChunk(CodeCompletionString::CK_RightParen);
3936}
3937
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003938static void AddObjCProperties(
3939 const CodeCompletionContext &CCContext, ObjCContainerDecl *Container,
3940 bool AllowCategories, bool AllowNullaryMethods, DeclContext *CurContext,
3941 AddedPropertiesSet &AddedProperties, ResultBuilder &Results,
3942 bool IsBaseExprStatement = false, bool IsClassProperty = false) {
John McCall276321a2010-08-25 06:19:51 +00003943 typedef CodeCompletionResult Result;
Douglas Gregor9291bad2009-11-18 01:29:26 +00003944
Douglas Gregor9b4f3702012-06-12 13:44:08 +00003945 // Retrieve the definition.
3946 Container = getContainerDef(Container);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003947
Douglas Gregor9291bad2009-11-18 01:29:26 +00003948 // Add properties in this container.
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003949 const auto AddProperty = [&](const ObjCPropertyDecl *P) {
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003950 if (!AddedProperties.insert(P->getIdentifier()).second)
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003951 return;
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003952
Alex Lorenzbaef8022016-11-09 13:43:18 +00003953 // FIXME: Provide block invocation completion for non-statement
3954 // expressions.
3955 if (!P->getType().getTypePtr()->isBlockPointerType() ||
3956 !IsBaseExprStatement) {
3957 Results.MaybeAddResult(Result(P, Results.getBasePriority(P), nullptr),
3958 CurContext);
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003959 return;
Alex Lorenzbaef8022016-11-09 13:43:18 +00003960 }
3961
3962 // Block setter and invocation completion is provided only when we are able
3963 // to find the FunctionProtoTypeLoc with parameter names for the block.
3964 FunctionTypeLoc BlockLoc;
3965 FunctionProtoTypeLoc BlockProtoLoc;
3966 findTypeLocationForBlockDecl(P->getTypeSourceInfo(), BlockLoc,
3967 BlockProtoLoc);
3968 if (!BlockLoc) {
3969 Results.MaybeAddResult(Result(P, Results.getBasePriority(P), nullptr),
3970 CurContext);
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003971 return;
Alex Lorenzbaef8022016-11-09 13:43:18 +00003972 }
3973
3974 // The default completion result for block properties should be the block
3975 // invocation completion when the base expression is a statement.
3976 CodeCompletionBuilder Builder(Results.getAllocator(),
3977 Results.getCodeCompletionTUInfo());
3978 AddObjCBlockCall(Container->getASTContext(),
3979 getCompletionPrintingPolicy(Results.getSema()), Builder, P,
3980 BlockLoc, BlockProtoLoc);
3981 Results.MaybeAddResult(
3982 Result(Builder.TakeString(), P, Results.getBasePriority(P)),
3983 CurContext);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003984
3985 // Provide additional block setter completion iff the base expression is a
Alex Lorenzbaef8022016-11-09 13:43:18 +00003986 // statement and the block property is mutable.
3987 if (!P->isReadOnly()) {
3988 CodeCompletionBuilder Builder(Results.getAllocator(),
3989 Results.getCodeCompletionTUInfo());
3990 AddResultTypeChunk(Container->getASTContext(),
3991 getCompletionPrintingPolicy(Results.getSema()), P,
3992 CCContext.getBaseType(), Builder);
3993 Builder.AddTypedTextChunk(
3994 Results.getAllocator().CopyString(P->getName()));
3995 Builder.AddChunk(CodeCompletionString::CK_Equal);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003996
Alex Lorenzbaef8022016-11-09 13:43:18 +00003997 std::string PlaceholderStr = formatBlockPlaceholder(
3998 getCompletionPrintingPolicy(Results.getSema()), P, BlockLoc,
3999 BlockProtoLoc, /*SuppressBlockName=*/true);
4000 // Add the placeholder string.
4001 Builder.AddPlaceholderChunk(
4002 Builder.getAllocator().CopyString(PlaceholderStr));
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004003
Alex Lorenz6e0f3932017-01-06 12:00:44 +00004004 // When completing blocks properties that return void the default
4005 // property completion result should show up before the setter,
4006 // otherwise the setter completion should show up before the default
4007 // property completion, as we normally want to use the result of the
4008 // call.
Alex Lorenzbaef8022016-11-09 13:43:18 +00004009 Results.MaybeAddResult(
4010 Result(Builder.TakeString(), P,
Alex Lorenz6e0f3932017-01-06 12:00:44 +00004011 Results.getBasePriority(P) +
4012 (BlockLoc.getTypePtr()->getReturnType()->isVoidType()
4013 ? CCD_BlockPropertySetter
4014 : -CCD_BlockPropertySetter)),
Alex Lorenzbaef8022016-11-09 13:43:18 +00004015 CurContext);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004016 }
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004017 };
4018
4019 if (IsClassProperty) {
4020 for (const auto *P : Container->class_properties())
4021 AddProperty(P);
4022 } else {
4023 for (const auto *P : Container->instance_properties())
4024 AddProperty(P);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004025 }
Craig Topperc3ec1492014-05-26 06:22:03 +00004026
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004027 // Add nullary methods or implicit class properties
Douglas Gregor95147142011-05-05 15:50:42 +00004028 if (AllowNullaryMethods) {
4029 ASTContext &Context = Container->getASTContext();
Douglas Gregor75acd922011-09-27 23:30:47 +00004030 PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema());
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004031 // Adds a method result
4032 const auto AddMethod = [&](const ObjCMethodDecl *M) {
4033 IdentifierInfo *Name = M->getSelector().getIdentifierInfoForSlot(0);
4034 if (!Name)
4035 return;
4036 if (!AddedProperties.insert(Name).second)
4037 return;
4038 CodeCompletionBuilder Builder(Results.getAllocator(),
4039 Results.getCodeCompletionTUInfo());
4040 AddResultTypeChunk(Context, Policy, M, CCContext.getBaseType(), Builder);
4041 Builder.AddTypedTextChunk(
4042 Results.getAllocator().CopyString(Name->getName()));
4043 Results.MaybeAddResult(
4044 Result(Builder.TakeString(), M,
4045 CCP_MemberDeclaration + CCD_MethodAsProperty),
4046 CurContext);
4047 };
4048
4049 if (IsClassProperty) {
4050 for (const auto *M : Container->methods()) {
4051 // Gather the class method that can be used as implicit property
4052 // getters. Methods with arguments or methods that return void aren't
4053 // added to the results as they can't be used as a getter.
4054 if (!M->getSelector().isUnarySelector() ||
4055 M->getReturnType()->isVoidType() || M->isInstanceMethod())
4056 continue;
4057 AddMethod(M);
4058 }
4059 } else {
4060 for (auto *M : Container->methods()) {
4061 if (M->getSelector().isUnarySelector())
4062 AddMethod(M);
4063 }
Douglas Gregor95147142011-05-05 15:50:42 +00004064 }
4065 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004066
Douglas Gregor9291bad2009-11-18 01:29:26 +00004067 // Add properties in referenced protocols.
4068 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Aaron Ballman0f6e64d2014-03-13 22:58:06 +00004069 for (auto *P : Protocol->protocols())
Douglas Gregorc3425b12015-07-07 06:20:19 +00004070 AddObjCProperties(CCContext, P, AllowCategories, AllowNullaryMethods,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004071 CurContext, AddedProperties, Results,
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004072 IsBaseExprStatement, IsClassProperty);
Douglas Gregor9291bad2009-11-18 01:29:26 +00004073 } else if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)){
Douglas Gregor5d649882009-11-18 22:32:06 +00004074 if (AllowCategories) {
4075 // Look through categories.
Aaron Ballman15063e12014-03-13 21:35:02 +00004076 for (auto *Cat : IFace->known_categories())
Douglas Gregorc3425b12015-07-07 06:20:19 +00004077 AddObjCProperties(CCContext, Cat, AllowCategories, AllowNullaryMethods,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004078 CurContext, AddedProperties, Results,
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004079 IsBaseExprStatement, IsClassProperty);
Douglas Gregor5d649882009-11-18 22:32:06 +00004080 }
Aaron Ballman15063e12014-03-13 21:35:02 +00004081
Douglas Gregor9291bad2009-11-18 01:29:26 +00004082 // Look through protocols.
Aaron Ballmana9f49e32014-03-13 20:55:22 +00004083 for (auto *I : IFace->all_referenced_protocols())
Douglas Gregorc3425b12015-07-07 06:20:19 +00004084 AddObjCProperties(CCContext, I, AllowCategories, AllowNullaryMethods,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004085 CurContext, AddedProperties, Results,
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004086 IsBaseExprStatement, IsClassProperty);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004087
Douglas Gregor9291bad2009-11-18 01:29:26 +00004088 // Look in the superclass.
4089 if (IFace->getSuperClass())
Douglas Gregorc3425b12015-07-07 06:20:19 +00004090 AddObjCProperties(CCContext, IFace->getSuperClass(), AllowCategories,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004091 AllowNullaryMethods, CurContext, AddedProperties,
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004092 Results, IsBaseExprStatement, IsClassProperty);
Douglas Gregor9291bad2009-11-18 01:29:26 +00004093 } else if (const ObjCCategoryDecl *Category
4094 = dyn_cast<ObjCCategoryDecl>(Container)) {
4095 // Look through protocols.
Aaron Ballman19a41762014-03-14 12:55:57 +00004096 for (auto *P : Category->protocols())
Douglas Gregorc3425b12015-07-07 06:20:19 +00004097 AddObjCProperties(CCContext, P, AllowCategories, AllowNullaryMethods,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004098 CurContext, AddedProperties, Results,
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004099 IsBaseExprStatement, IsClassProperty);
Douglas Gregor9291bad2009-11-18 01:29:26 +00004100 }
4101}
4102
Alex Lorenz0fe0d982017-05-11 13:41:00 +00004103static void AddRecordMembersCompletionResults(Sema &SemaRef,
4104 ResultBuilder &Results, Scope *S,
4105 QualType BaseType,
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004106 RecordDecl *RD,
4107 Optional<FixItHint> AccessOpFixIt) {
Alex Lorenz0fe0d982017-05-11 13:41:00 +00004108 // Indicate that we are performing a member access, and the cv-qualifiers
4109 // for the base object type.
4110 Results.setObjectTypeQualifiers(BaseType.getQualifiers());
4111
4112 // Access to a C/C++ class, struct, or union.
4113 Results.allowNestedNameSpecifiers();
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004114 std::vector<FixItHint> FixIts;
4115 if (AccessOpFixIt)
4116 FixIts.emplace_back(AccessOpFixIt.getValue());
Eric Liub91e0812018-10-02 10:29:00 +00004117 CodeCompletionDeclConsumer Consumer(Results, SemaRef.CurContext,
4118 std::move(FixIts), RD);
Alex Lorenz0fe0d982017-05-11 13:41:00 +00004119 SemaRef.LookupVisibleDecls(RD, Sema::LookupMemberName, Consumer,
Alex Lorenze6afa392017-05-11 13:48:57 +00004120 SemaRef.CodeCompleter->includeGlobals(),
Sam McCallbb2cf632018-01-12 14:51:47 +00004121 /*IncludeDependentBases=*/true,
4122 SemaRef.CodeCompleter->loadExternal());
Alex Lorenz0fe0d982017-05-11 13:41:00 +00004123
4124 if (SemaRef.getLangOpts().CPlusPlus) {
4125 if (!Results.empty()) {
4126 // The "template" keyword can follow "->" or "." in the grammar.
4127 // However, we only want to suggest the template keyword if something
4128 // is dependent.
4129 bool IsDependent = BaseType->isDependentType();
4130 if (!IsDependent) {
4131 for (Scope *DepScope = S; DepScope; DepScope = DepScope->getParent())
4132 if (DeclContext *Ctx = DepScope->getEntity()) {
4133 IsDependent = Ctx->isDependentContext();
4134 break;
4135 }
4136 }
4137
4138 if (IsDependent)
4139 Results.AddResult(CodeCompletionResult("template"));
4140 }
4141 }
4142}
4143
Douglas Gregor1cc88a92012-01-23 15:59:30 +00004144void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base,
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004145 Expr *OtherOpBase,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004146 SourceLocation OpLoc, bool IsArrow,
4147 bool IsBaseExprStatement) {
Douglas Gregor1cc88a92012-01-23 15:59:30 +00004148 if (!Base || !CodeCompleter)
Douglas Gregor2436e712009-09-17 21:32:03 +00004149 return;
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004150
Douglas Gregor1cc88a92012-01-23 15:59:30 +00004151 ExprResult ConvertedBase = PerformMemberExprBaseConversion(Base, IsArrow);
4152 if (ConvertedBase.isInvalid())
4153 return;
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004154 QualType ConvertedBaseType = ConvertedBase.get()->getType();
4155
4156 enum CodeCompletionContext::Kind contextKind;
Douglas Gregor3545ff42009-09-21 16:56:56 +00004157
4158 if (IsArrow) {
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004159 if (const PointerType *Ptr = ConvertedBaseType->getAs<PointerType>())
4160 ConvertedBaseType = Ptr->getPointeeType();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004161 }
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004162
Douglas Gregor21325842011-07-07 16:03:39 +00004163 if (IsArrow) {
4164 contextKind = CodeCompletionContext::CCC_ArrowMemberAccess;
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004165 } else {
4166 if (ConvertedBaseType->isObjCObjectPointerType() ||
4167 ConvertedBaseType->isObjCObjectOrInterfaceType()) {
Douglas Gregor21325842011-07-07 16:03:39 +00004168 contextKind = CodeCompletionContext::CCC_ObjCPropertyAccess;
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004169 } else {
Douglas Gregor21325842011-07-07 16:03:39 +00004170 contextKind = CodeCompletionContext::CCC_DotMemberAccess;
4171 }
4172 }
Douglas Gregorc3425b12015-07-07 06:20:19 +00004173
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004174 CodeCompletionContext CCContext(contextKind, ConvertedBaseType);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004175 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004176 CodeCompleter->getCodeCompletionTUInfo(), CCContext,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004177 &ResultBuilder::IsMember);
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004178
4179 auto DoCompletion = [&](Expr *Base, bool IsArrow, Optional<FixItHint> AccessOpFixIt) -> bool {
4180 if (!Base)
4181 return false;
4182
4183 ExprResult ConvertedBase = PerformMemberExprBaseConversion(Base, IsArrow);
4184 if (ConvertedBase.isInvalid())
4185 return false;
4186 Base = ConvertedBase.get();
4187
4188 QualType BaseType = Base->getType();
4189
4190 if (IsArrow) {
4191 if (const PointerType *Ptr = BaseType->getAs<PointerType>())
4192 BaseType = Ptr->getPointeeType();
4193 else if (BaseType->isObjCObjectPointerType())
4194 /*Do nothing*/;
4195 else
4196 return false;
4197 }
4198
4199 if (const RecordType *Record = BaseType->getAs<RecordType>()) {
4200 AddRecordMembersCompletionResults(*this, Results, S, BaseType,
4201 Record->getDecl(),
4202 std::move(AccessOpFixIt));
4203 } else if (const auto *TST =
4204 BaseType->getAs<TemplateSpecializationType>()) {
4205 TemplateName TN = TST->getTemplateName();
4206 if (const auto *TD =
4207 dyn_cast_or_null<ClassTemplateDecl>(TN.getAsTemplateDecl())) {
4208 CXXRecordDecl *RD = TD->getTemplatedDecl();
4209 AddRecordMembersCompletionResults(*this, Results, S, BaseType, RD,
4210 std::move(AccessOpFixIt));
4211 }
4212 } else if (const auto *ICNT = BaseType->getAs<InjectedClassNameType>()) {
4213 if (auto *RD = ICNT->getDecl())
4214 AddRecordMembersCompletionResults(*this, Results, S, BaseType, RD,
4215 std::move(AccessOpFixIt));
4216 } else if (!IsArrow && BaseType->isObjCObjectPointerType()) {
4217 // Objective-C property reference.
4218 AddedPropertiesSet AddedProperties;
4219
4220 if (const ObjCObjectPointerType *ObjCPtr =
4221 BaseType->getAsObjCInterfacePointerType()) {
4222 // Add property results based on our interface.
4223 assert(ObjCPtr && "Non-NULL pointer guaranteed above!");
4224 AddObjCProperties(CCContext, ObjCPtr->getInterfaceDecl(), true,
4225 /*AllowNullaryMethods=*/true, CurContext,
4226 AddedProperties, Results, IsBaseExprStatement);
4227 }
4228
4229 // Add properties from the protocols in a qualified interface.
4230 for (auto *I : BaseType->getAs<ObjCObjectPointerType>()->quals())
4231 AddObjCProperties(CCContext, I, true, /*AllowNullaryMethods=*/true,
4232 CurContext, AddedProperties, Results,
4233 IsBaseExprStatement);
4234 } else if ((IsArrow && BaseType->isObjCObjectPointerType()) ||
4235 (!IsArrow && BaseType->isObjCObjectType())) {
4236 // Objective-C instance variable access.
4237 ObjCInterfaceDecl *Class = nullptr;
4238 if (const ObjCObjectPointerType *ObjCPtr =
4239 BaseType->getAs<ObjCObjectPointerType>())
4240 Class = ObjCPtr->getInterfaceDecl();
4241 else
4242 Class = BaseType->getAs<ObjCObjectType>()->getInterface();
4243
4244 // Add all ivars from this class and its superclasses.
4245 if (Class) {
4246 CodeCompletionDeclConsumer Consumer(Results, CurContext);
4247 Results.setFilter(&ResultBuilder::IsObjCIvar);
4248 LookupVisibleDecls(
4249 Class, LookupMemberName, Consumer, CodeCompleter->includeGlobals(),
4250 /*IncludeDependentBases=*/false, CodeCompleter->loadExternal());
4251 }
4252 }
4253
4254 // FIXME: How do we cope with isa?
4255 return true;
4256 };
4257
Douglas Gregor9291bad2009-11-18 01:29:26 +00004258 Results.EnterNewScope();
Alex Lorenz06cfa992016-10-12 11:40:15 +00004259
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004260 bool CompletionSucceded = DoCompletion(Base, IsArrow, None);
4261 if (CodeCompleter->includeFixIts()) {
4262 const CharSourceRange OpRange =
4263 CharSourceRange::getTokenRange(OpLoc, OpLoc);
4264 CompletionSucceded |= DoCompletion(
4265 OtherOpBase, !IsArrow,
4266 FixItHint::CreateReplacement(OpRange, IsArrow ? "." : "->"));
Douglas Gregor3545ff42009-09-21 16:56:56 +00004267 }
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004268
Douglas Gregor9291bad2009-11-18 01:29:26 +00004269 Results.ExitScope();
Daniel Dunbar242ea9a2009-11-13 08:58:20 +00004270
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004271 if (!CompletionSucceded)
4272 return;
4273
Daniel Dunbar242ea9a2009-11-13 08:58:20 +00004274 // Hand off the results found for code completion.
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004275 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4276 Results.data(), Results.size());
Douglas Gregor2436e712009-09-17 21:32:03 +00004277}
4278
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004279void Sema::CodeCompleteObjCClassPropertyRefExpr(Scope *S,
4280 IdentifierInfo &ClassName,
4281 SourceLocation ClassNameLoc,
4282 bool IsBaseExprStatement) {
4283 IdentifierInfo *ClassNamePtr = &ClassName;
4284 ObjCInterfaceDecl *IFace = getObjCInterfaceDecl(ClassNamePtr, ClassNameLoc);
4285 if (!IFace)
4286 return;
4287 CodeCompletionContext CCContext(
4288 CodeCompletionContext::CCC_ObjCPropertyAccess);
4289 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4290 CodeCompleter->getCodeCompletionTUInfo(), CCContext,
4291 &ResultBuilder::IsMember);
4292 Results.EnterNewScope();
4293 AddedPropertiesSet AddedProperties;
4294 AddObjCProperties(CCContext, IFace, true,
4295 /*AllowNullaryMethods=*/true, CurContext, AddedProperties,
4296 Results, IsBaseExprStatement,
4297 /*IsClassProperty=*/true);
4298 Results.ExitScope();
4299 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4300 Results.data(), Results.size());
4301}
4302
Faisal Vali090da2d2018-01-01 18:23:28 +00004303void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) {
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004304 if (!CodeCompleter)
4305 return;
Craig Topperc3ec1492014-05-26 06:22:03 +00004306
4307 ResultBuilder::LookupFilter Filter = nullptr;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004308 enum CodeCompletionContext::Kind ContextKind
4309 = CodeCompletionContext::CCC_Other;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004310 switch ((DeclSpec::TST)TagSpec) {
4311 case DeclSpec::TST_enum:
Douglas Gregor3545ff42009-09-21 16:56:56 +00004312 Filter = &ResultBuilder::IsEnum;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004313 ContextKind = CodeCompletionContext::CCC_EnumTag;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004314 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004315
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004316 case DeclSpec::TST_union:
Douglas Gregor3545ff42009-09-21 16:56:56 +00004317 Filter = &ResultBuilder::IsUnion;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004318 ContextKind = CodeCompletionContext::CCC_UnionTag;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004319 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004320
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004321 case DeclSpec::TST_struct:
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004322 case DeclSpec::TST_class:
Joao Matosdc86f942012-08-31 18:45:21 +00004323 case DeclSpec::TST_interface:
Douglas Gregor3545ff42009-09-21 16:56:56 +00004324 Filter = &ResultBuilder::IsClassOrStruct;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004325 ContextKind = CodeCompletionContext::CCC_ClassOrStructTag;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004326 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004327
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004328 default:
David Blaikie83d382b2011-09-23 05:06:16 +00004329 llvm_unreachable("Unknown type specifier kind in CodeCompleteTag");
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004330 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004331
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004332 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4333 CodeCompleter->getCodeCompletionTUInfo(), ContextKind);
Douglas Gregora6e2edc2010-01-14 03:27:13 +00004334 CodeCompletionDeclConsumer Consumer(Results, CurContext);
John McCalle87beb22010-04-23 18:46:30 +00004335
4336 // First pass: look for tags.
4337 Results.setFilter(Filter);
Douglas Gregor39982192010-08-15 06:18:01 +00004338 LookupVisibleDecls(S, LookupTagName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00004339 CodeCompleter->includeGlobals(),
4340 CodeCompleter->loadExternal());
John McCalle87beb22010-04-23 18:46:30 +00004341
Douglas Gregor39982192010-08-15 06:18:01 +00004342 if (CodeCompleter->includeGlobals()) {
4343 // Second pass: look for nested name specifiers.
4344 Results.setFilter(&ResultBuilder::IsNestedNameSpecifier);
Sam McCallbb2cf632018-01-12 14:51:47 +00004345 LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer,
4346 CodeCompleter->includeGlobals(),
4347 CodeCompleter->loadExternal());
Douglas Gregor39982192010-08-15 06:18:01 +00004348 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004349
Douglas Gregor0ac41382010-09-23 23:01:17 +00004350 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004351 Results.data(),Results.size());
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004352}
4353
Alex Lorenz8f4d3992017-02-13 23:19:40 +00004354static void AddTypeQualifierResults(DeclSpec &DS, ResultBuilder &Results,
4355 const LangOptions &LangOpts) {
4356 if (!(DS.getTypeQualifiers() & DeclSpec::TQ_const))
4357 Results.AddResult("const");
4358 if (!(DS.getTypeQualifiers() & DeclSpec::TQ_volatile))
4359 Results.AddResult("volatile");
4360 if (LangOpts.C99 && !(DS.getTypeQualifiers() & DeclSpec::TQ_restrict))
4361 Results.AddResult("restrict");
4362 if (LangOpts.C11 && !(DS.getTypeQualifiers() & DeclSpec::TQ_atomic))
4363 Results.AddResult("_Atomic");
4364 if (LangOpts.MSVCCompat && !(DS.getTypeQualifiers() & DeclSpec::TQ_unaligned))
4365 Results.AddResult("__unaligned");
4366}
4367
Douglas Gregor28c78432010-08-27 17:35:51 +00004368void Sema::CodeCompleteTypeQualifiers(DeclSpec &DS) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004369 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004370 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004371 CodeCompletionContext::CCC_TypeQualifiers);
Douglas Gregor28c78432010-08-27 17:35:51 +00004372 Results.EnterNewScope();
Alex Lorenz8f4d3992017-02-13 23:19:40 +00004373 AddTypeQualifierResults(DS, Results, LangOpts);
Douglas Gregor28c78432010-08-27 17:35:51 +00004374 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004375 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004376 Results.getCompletionContext(),
Douglas Gregor28c78432010-08-27 17:35:51 +00004377 Results.data(), Results.size());
4378}
4379
Alex Lorenz8f4d3992017-02-13 23:19:40 +00004380void Sema::CodeCompleteFunctionQualifiers(DeclSpec &DS, Declarator &D,
4381 const VirtSpecifiers *VS) {
4382 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4383 CodeCompleter->getCodeCompletionTUInfo(),
4384 CodeCompletionContext::CCC_TypeQualifiers);
4385 Results.EnterNewScope();
4386 AddTypeQualifierResults(DS, Results, LangOpts);
4387 if (LangOpts.CPlusPlus11) {
4388 Results.AddResult("noexcept");
Faisal Vali421b2d12017-12-29 05:41:00 +00004389 if (D.getContext() == DeclaratorContext::MemberContext &&
4390 !D.isCtorOrDtor() && !D.isStaticMember()) {
Alex Lorenz8f4d3992017-02-13 23:19:40 +00004391 if (!VS || !VS->isFinalSpecified())
4392 Results.AddResult("final");
4393 if (!VS || !VS->isOverrideSpecified())
4394 Results.AddResult("override");
4395 }
4396 }
4397 Results.ExitScope();
4398 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4399 Results.data(), Results.size());
4400}
4401
Benjamin Kramer72dae622016-02-18 15:30:24 +00004402void Sema::CodeCompleteBracketDeclarator(Scope *S) {
4403 CodeCompleteExpression(S, QualType(getASTContext().getSizeType()));
4404}
4405
Douglas Gregord328d572009-09-21 18:10:23 +00004406void Sema::CodeCompleteCase(Scope *S) {
John McCallaab3e412010-08-25 08:40:02 +00004407 if (getCurFunction()->SwitchStack.empty() || !CodeCompleter)
Douglas Gregord328d572009-09-21 18:10:23 +00004408 return;
John McCall5939b162011-08-06 07:30:58 +00004409
Richard Smithef6c43d2018-07-26 18:41:30 +00004410 SwitchStmt *Switch = getCurFunction()->SwitchStack.back().getPointer();
John McCall5939b162011-08-06 07:30:58 +00004411 QualType type = Switch->getCond()->IgnoreImplicit()->getType();
4412 if (!type->isEnumeralType()) {
4413 CodeCompleteExpressionData Data(type);
Douglas Gregor68762e72010-08-23 21:17:50 +00004414 Data.IntegralConstantExpression = true;
4415 CodeCompleteExpression(S, Data);
Douglas Gregord328d572009-09-21 18:10:23 +00004416 return;
Douglas Gregor85b50632010-07-28 21:50:18 +00004417 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004418
Douglas Gregord328d572009-09-21 18:10:23 +00004419 // Code-complete the cases of a switch statement over an enumeration type
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004420 // by providing the list of
John McCall5939b162011-08-06 07:30:58 +00004421 EnumDecl *Enum = type->castAs<EnumType>()->getDecl();
Douglas Gregor9b4f3702012-06-12 13:44:08 +00004422 if (EnumDecl *Def = Enum->getDefinition())
4423 Enum = Def;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004424
Douglas Gregord328d572009-09-21 18:10:23 +00004425 // Determine which enumerators we have already seen in the switch statement.
4426 // FIXME: Ideally, we would also be able to look *past* the code-completion
4427 // token, in case we are code-completing in the middle of the switch and not
4428 // at the end. However, we aren't able to do so at the moment.
4429 llvm::SmallPtrSet<EnumConstantDecl *, 8> EnumeratorsSeen;
Craig Topperc3ec1492014-05-26 06:22:03 +00004430 NestedNameSpecifier *Qualifier = nullptr;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004431 for (SwitchCase *SC = Switch->getSwitchCaseList(); SC;
Douglas Gregord328d572009-09-21 18:10:23 +00004432 SC = SC->getNextSwitchCase()) {
4433 CaseStmt *Case = dyn_cast<CaseStmt>(SC);
4434 if (!Case)
4435 continue;
4436
4437 Expr *CaseVal = Case->getLHS()->IgnoreParenCasts();
4438 if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CaseVal))
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004439 if (EnumConstantDecl *Enumerator
Douglas Gregord328d572009-09-21 18:10:23 +00004440 = dyn_cast<EnumConstantDecl>(DRE->getDecl())) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004441 // We look into the AST of the case statement to determine which
4442 // enumerator was named. Alternatively, we could compute the value of
Douglas Gregord328d572009-09-21 18:10:23 +00004443 // the integral constant expression, then compare it against the
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004444 // values of each enumerator. However, value-based approach would not
4445 // work as well with C++ templates where enumerators declared within a
Douglas Gregord328d572009-09-21 18:10:23 +00004446 // template are type- and value-dependent.
4447 EnumeratorsSeen.insert(Enumerator);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004448
Douglas Gregorf2510672009-09-21 19:57:38 +00004449 // If this is a qualified-id, keep track of the nested-name-specifier
4450 // so that we can reproduce it as part of code completion, e.g.,
Douglas Gregord328d572009-09-21 18:10:23 +00004451 //
4452 // switch (TagD.getKind()) {
4453 // case TagDecl::TK_enum:
4454 // break;
4455 // case XXX
4456 //
Douglas Gregorf2510672009-09-21 19:57:38 +00004457 // At the XXX, our completions are TagDecl::TK_union,
Douglas Gregord328d572009-09-21 18:10:23 +00004458 // TagDecl::TK_struct, and TagDecl::TK_class, rather than TK_union,
4459 // TK_struct, and TK_class.
Douglas Gregor4bd90e52009-10-23 18:54:35 +00004460 Qualifier = DRE->getQualifier();
Douglas Gregord328d572009-09-21 18:10:23 +00004461 }
4462 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004463
David Blaikiebbafb8a2012-03-11 07:00:24 +00004464 if (getLangOpts().CPlusPlus && !Qualifier && EnumeratorsSeen.empty()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004465 // If there are no prior enumerators in C++, check whether we have to
Douglas Gregorf2510672009-09-21 19:57:38 +00004466 // qualify the names of the enumerators that we suggest, because they
4467 // may not be visible in this scope.
Douglas Gregord3cebdb2012-02-01 05:02:47 +00004468 Qualifier = getRequiredQualification(Context, CurContext, Enum);
Douglas Gregorf2510672009-09-21 19:57:38 +00004469 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004470
Douglas Gregord328d572009-09-21 18:10:23 +00004471 // Add any enumerators that have not yet been mentioned.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004472 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004473 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004474 CodeCompletionContext::CCC_Expression);
Douglas Gregord328d572009-09-21 18:10:23 +00004475 Results.EnterNewScope();
Aaron Ballman23a6dcb2014-03-08 18:45:14 +00004476 for (auto *E : Enum->enumerators()) {
4477 if (EnumeratorsSeen.count(E))
Douglas Gregord328d572009-09-21 18:10:23 +00004478 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004479
Aaron Ballman23a6dcb2014-03-08 18:45:14 +00004480 CodeCompletionResult R(E, CCP_EnumInCase, Qualifier);
Craig Topperc3ec1492014-05-26 06:22:03 +00004481 Results.AddResult(R, CurContext, nullptr, false);
Douglas Gregord328d572009-09-21 18:10:23 +00004482 }
4483 Results.ExitScope();
Douglas Gregor285560922010-04-06 20:02:15 +00004484
Douglas Gregor21325842011-07-07 16:03:39 +00004485 if (CodeCompleter->includeMacros()) {
Eric Liu88de9f62018-09-19 09:34:55 +00004486 AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false);
Douglas Gregor21325842011-07-07 16:03:39 +00004487 }
Eric Liuf5ba09f2018-07-04 10:01:18 +00004488 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4489 Results.data(), Results.size());
Douglas Gregord328d572009-09-21 18:10:23 +00004490}
4491
Robert Wilhelm16e94b92013-08-09 18:02:13 +00004492static bool anyNullArguments(ArrayRef<Expr *> Args) {
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00004493 if (Args.size() && !Args.data())
Douglas Gregor6ed3eb82010-05-30 06:10:08 +00004494 return true;
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00004495
4496 for (unsigned I = 0; I != Args.size(); ++I)
Douglas Gregor6ed3eb82010-05-30 06:10:08 +00004497 if (!Args[I])
4498 return true;
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00004499
Douglas Gregor6ed3eb82010-05-30 06:10:08 +00004500 return false;
4501}
4502
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004503typedef CodeCompleteConsumer::OverloadCandidate ResultCandidate;
4504
Francisco Lopes da Silva8cafefa2015-01-29 05:54:59 +00004505static void mergeCandidatesWithResults(Sema &SemaRef,
4506 SmallVectorImpl<ResultCandidate> &Results,
4507 OverloadCandidateSet &CandidateSet,
4508 SourceLocation Loc) {
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004509 if (!CandidateSet.empty()) {
4510 // Sort the overload candidate set by placing the best overloads first.
4511 std::stable_sort(
4512 CandidateSet.begin(), CandidateSet.end(),
4513 [&](const OverloadCandidate &X, const OverloadCandidate &Y) {
Richard Smith67ef14f2017-09-26 18:37:55 +00004514 return isBetterOverloadCandidate(SemaRef, X, Y, Loc,
4515 CandidateSet.getKind());
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004516 });
4517
4518 // Add the remaining viable overload candidates as code-completion results.
Erik Verbruggen7ec91072017-09-08 10:23:08 +00004519 for (auto &Candidate : CandidateSet) {
4520 if (Candidate.Function && Candidate.Function->isDeleted())
4521 continue;
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004522 if (Candidate.Viable)
4523 Results.push_back(ResultCandidate(Candidate.Function));
Erik Verbruggen7ec91072017-09-08 10:23:08 +00004524 }
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004525 }
4526}
4527
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00004528/// Get the type of the Nth parameter from a given set of overload
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004529/// candidates.
Francisco Lopes da Silva8cafefa2015-01-29 05:54:59 +00004530static QualType getParamType(Sema &SemaRef,
4531 ArrayRef<ResultCandidate> Candidates,
4532 unsigned N) {
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004533
4534 // Given the overloads 'Candidates' for a function call matching all arguments
4535 // up to N, return the type of the Nth parameter if it is the same for all
4536 // overload candidates.
4537 QualType ParamType;
4538 for (auto &Candidate : Candidates) {
4539 if (auto FType = Candidate.getFunctionType())
4540 if (auto Proto = dyn_cast<FunctionProtoType>(FType))
4541 if (N < Proto->getNumParams()) {
4542 if (ParamType.isNull())
4543 ParamType = Proto->getParamType(N);
4544 else if (!SemaRef.Context.hasSameUnqualifiedType(
4545 ParamType.getNonReferenceType(),
4546 Proto->getParamType(N).getNonReferenceType()))
4547 // Otherwise return a default-constructed QualType.
4548 return QualType();
4549 }
4550 }
4551
4552 return ParamType;
4553}
4554
Ilya Biryukov832c4af2018-09-07 14:04:39 +00004555static QualType
4556ProduceSignatureHelp(Sema &SemaRef, Scope *S,
4557 MutableArrayRef<ResultCandidate> Candidates,
4558 unsigned CurrentArg, SourceLocation OpenParLoc) {
4559 if (Candidates.empty())
4560 return QualType();
4561 SemaRef.CodeCompleter->ProcessOverloadCandidates(
4562 SemaRef, CurrentArg, Candidates.data(), Candidates.size(), OpenParLoc);
4563 return getParamType(SemaRef, Candidates, CurrentArg);
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004564}
4565
Ilya Biryukov832c4af2018-09-07 14:04:39 +00004566QualType Sema::ProduceCallSignatureHelp(Scope *S, Expr *Fn,
4567 ArrayRef<Expr *> Args,
4568 SourceLocation OpenParLoc) {
Douglas Gregorcabea402009-09-22 15:41:20 +00004569 if (!CodeCompleter)
Ilya Biryukov832c4af2018-09-07 14:04:39 +00004570 return QualType();
Douglas Gregor3ef59522009-12-11 19:06:04 +00004571
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004572 // FIXME: Provide support for variadic template functions.
Douglas Gregorcabea402009-09-22 15:41:20 +00004573 // Ignore type-dependent call expressions entirely.
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00004574 if (!Fn || Fn->isTypeDependent() || anyNullArguments(Args) ||
4575 Expr::hasAnyTypeDependentArguments(Args)) {
Ilya Biryukov832c4af2018-09-07 14:04:39 +00004576 return QualType();
Douglas Gregor3ef59522009-12-11 19:06:04 +00004577 }
Douglas Gregorcabea402009-09-22 15:41:20 +00004578
John McCall57500772009-12-16 12:17:52 +00004579 // Build an overload candidate set based on the functions we find.
John McCallbc077cf2010-02-08 23:07:23 +00004580 SourceLocation Loc = Fn->getExprLoc();
Richard Smith100b24a2014-04-17 01:52:14 +00004581 OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal);
John McCall57500772009-12-16 12:17:52 +00004582
Chris Lattner0e62c1c2011-07-23 10:55:15 +00004583 SmallVector<ResultCandidate, 8> Results;
Douglas Gregorff59f672010-01-21 15:46:19 +00004584
John McCall57500772009-12-16 12:17:52 +00004585 Expr *NakedFn = Fn->IgnoreParenCasts();
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004586 if (auto ULE = dyn_cast<UnresolvedLookupExpr>(NakedFn))
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00004587 AddOverloadedCallCandidates(ULE, Args, CandidateSet,
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004588 /*PartialOverloading=*/true);
4589 else if (auto UME = dyn_cast<UnresolvedMemberExpr>(NakedFn)) {
4590 TemplateArgumentListInfo TemplateArgsBuffer, *TemplateArgs = nullptr;
4591 if (UME->hasExplicitTemplateArgs()) {
4592 UME->copyTemplateArgumentsInto(TemplateArgsBuffer);
4593 TemplateArgs = &TemplateArgsBuffer;
Douglas Gregorff59f672010-01-21 15:46:19 +00004594 }
Erik Verbruggenf1898cf2017-03-28 07:22:21 +00004595
4596 // Add the base as first argument (use a nullptr if the base is implicit).
4597 SmallVector<Expr *, 12> ArgExprs(
4598 1, UME->isImplicitAccess() ? nullptr : UME->getBase());
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004599 ArgExprs.append(Args.begin(), Args.end());
4600 UnresolvedSet<8> Decls;
4601 Decls.append(UME->decls_begin(), UME->decls_end());
Benjamin Kramere3962ae2017-10-26 08:41:28 +00004602 const bool FirstArgumentIsBase = !UME->isImplicitAccess() && UME->getBase();
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004603 AddFunctionCandidates(Decls, ArgExprs, CandidateSet, TemplateArgs,
4604 /*SuppressUsedConversions=*/false,
Benjamin Kramere3962ae2017-10-26 08:41:28 +00004605 /*PartialOverloading=*/true,
4606 FirstArgumentIsBase);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004607 } else {
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004608 FunctionDecl *FD = nullptr;
4609 if (auto MCE = dyn_cast<MemberExpr>(NakedFn))
4610 FD = dyn_cast<FunctionDecl>(MCE->getMemberDecl());
4611 else if (auto DRE = dyn_cast<DeclRefExpr>(NakedFn))
4612 FD = dyn_cast<FunctionDecl>(DRE->getDecl());
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00004613 if (FD) { // We check whether it's a resolved function declaration.
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00004614 if (!getLangOpts().CPlusPlus ||
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004615 !FD->getType()->getAs<FunctionProtoType>())
4616 Results.push_back(ResultCandidate(FD));
4617 else
4618 AddOverloadCandidate(FD, DeclAccessPair::make(FD, FD->getAccess()),
4619 Args, CandidateSet,
4620 /*SuppressUsedConversions=*/false,
4621 /*PartialOverloading=*/true);
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00004622
4623 } else if (auto DC = NakedFn->getType()->getAsCXXRecordDecl()) {
4624 // If expression's type is CXXRecordDecl, it may overload the function
4625 // call operator, so we check if it does and add them as candidates.
Francisco Lopes da Silvaa349a8a2015-01-25 08:47:59 +00004626 // A complete type is needed to lookup for member function call operators.
Richard Smithdb0ac552015-12-18 22:40:25 +00004627 if (isCompleteType(Loc, NakedFn->getType())) {
Francisco Lopes da Silvaa349a8a2015-01-25 08:47:59 +00004628 DeclarationName OpName = Context.DeclarationNames
4629 .getCXXOperatorName(OO_Call);
4630 LookupResult R(*this, OpName, Loc, LookupOrdinaryName);
4631 LookupQualifiedName(R, DC);
4632 R.suppressDiagnostics();
4633 SmallVector<Expr *, 12> ArgExprs(1, NakedFn);
4634 ArgExprs.append(Args.begin(), Args.end());
4635 AddFunctionCandidates(R.asUnresolvedSet(), ArgExprs, CandidateSet,
4636 /*ExplicitArgs=*/nullptr,
4637 /*SuppressUsedConversions=*/false,
4638 /*PartialOverloading=*/true);
4639 }
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00004640 } else {
4641 // Lastly we check whether expression's type is function pointer or
4642 // function.
4643 QualType T = NakedFn->getType();
4644 if (!T->getPointeeType().isNull())
4645 T = T->getPointeeType();
4646
4647 if (auto FP = T->getAs<FunctionProtoType>()) {
4648 if (!TooManyArguments(FP->getNumParams(), Args.size(),
Francisco Lopes da Silva62a9a4f2015-01-23 13:17:51 +00004649 /*PartialOverloading=*/true) ||
4650 FP->isVariadic())
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00004651 Results.push_back(ResultCandidate(FP));
4652 } else if (auto FT = T->getAs<FunctionType>())
Francisco Lopes da Silva62a9a4f2015-01-23 13:17:51 +00004653 // No prototype and declaration, it may be a K & R style function.
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00004654 Results.push_back(ResultCandidate(FT));
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004655 }
Douglas Gregorcabea402009-09-22 15:41:20 +00004656 }
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004657 mergeCandidatesWithResults(*this, Results, CandidateSet, Loc);
Ilya Biryukov832c4af2018-09-07 14:04:39 +00004658 QualType ParamType =
4659 ProduceSignatureHelp(*this, S, Results, Args.size(), OpenParLoc);
4660 return !CandidateSet.empty() ? ParamType : QualType();
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004661}
4662
Ilya Biryukov832c4af2018-09-07 14:04:39 +00004663QualType Sema::ProduceConstructorSignatureHelp(Scope *S, QualType Type,
4664 SourceLocation Loc,
4665 ArrayRef<Expr *> Args,
4666 SourceLocation OpenParLoc) {
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004667 if (!CodeCompleter)
Ilya Biryukov832c4af2018-09-07 14:04:39 +00004668 return QualType();
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004669
4670 // A complete type is needed to lookup for constructors.
Ilya Biryukovfb9dde72018-05-14 13:50:36 +00004671 CXXRecordDecl *RD =
4672 isCompleteType(Loc, Type) ? Type->getAsCXXRecordDecl() : nullptr;
Ilya Biryukov832c4af2018-09-07 14:04:39 +00004673 if (!RD)
4674 return Type;
Argyrios Kyrtzidisee1d76f2015-03-13 07:39:30 +00004675
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004676 // FIXME: Provide support for member initializers.
4677 // FIXME: Provide support for variadic template constructors.
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004678
4679 OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal);
4680
Argyrios Kyrtzidisee1d76f2015-03-13 07:39:30 +00004681 for (auto C : LookupConstructors(RD)) {
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004682 if (auto FD = dyn_cast<FunctionDecl>(C)) {
4683 AddOverloadCandidate(FD, DeclAccessPair::make(FD, C->getAccess()),
4684 Args, CandidateSet,
4685 /*SuppressUsedConversions=*/false,
4686 /*PartialOverloading=*/true);
4687 } else if (auto FTD = dyn_cast<FunctionTemplateDecl>(C)) {
4688 AddTemplateOverloadCandidate(FTD,
4689 DeclAccessPair::make(FTD, C->getAccess()),
4690 /*ExplicitTemplateArgs=*/nullptr,
4691 Args, CandidateSet,
4692 /*SuppressUsedConversions=*/false,
4693 /*PartialOverloading=*/true);
4694 }
4695 }
4696
4697 SmallVector<ResultCandidate, 8> Results;
4698 mergeCandidatesWithResults(*this, Results, CandidateSet, Loc);
Ilya Biryukov832c4af2018-09-07 14:04:39 +00004699 return ProduceSignatureHelp(*this, S, Results, Args.size(), OpenParLoc);
Douglas Gregorcabea402009-09-22 15:41:20 +00004700}
4701
Kadir Cetinkaya84774c32018-09-11 15:02:18 +00004702QualType Sema::ProduceCtorInitMemberSignatureHelp(
4703 Scope *S, Decl *ConstructorDecl, CXXScopeSpec SS, ParsedType TemplateTypeTy,
4704 ArrayRef<Expr *> ArgExprs, IdentifierInfo *II, SourceLocation OpenParLoc) {
4705 if (!CodeCompleter)
4706 return QualType();
4707
4708 CXXConstructorDecl *Constructor =
4709 dyn_cast<CXXConstructorDecl>(ConstructorDecl);
4710 if (!Constructor)
4711 return QualType();
4712 // FIXME: Add support for Base class constructors as well.
4713 if (ValueDecl *MemberDecl = tryLookupCtorInitMemberDecl(
4714 Constructor->getParent(), SS, TemplateTypeTy, II))
4715 return ProduceConstructorSignatureHelp(getCurScope(), MemberDecl->getType(),
4716 MemberDecl->getLocation(), ArgExprs,
4717 OpenParLoc);
4718 return QualType();
4719}
4720
John McCall48871652010-08-21 09:40:31 +00004721void Sema::CodeCompleteInitializer(Scope *S, Decl *D) {
4722 ValueDecl *VD = dyn_cast_or_null<ValueDecl>(D);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004723 if (!VD) {
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004724 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004725 return;
4726 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004727
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004728 CodeCompleteExpression(S, VD->getType());
4729}
4730
4731void Sema::CodeCompleteReturn(Scope *S) {
4732 QualType ResultType;
4733 if (isa<BlockDecl>(CurContext)) {
4734 if (BlockScopeInfo *BSI = getCurBlock())
4735 ResultType = BSI->ReturnType;
4736 } else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(CurContext))
Alp Toker314cc812014-01-25 16:55:45 +00004737 ResultType = Function->getReturnType();
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004738 else if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(CurContext))
Alp Toker314cc812014-01-25 16:55:45 +00004739 ResultType = Method->getReturnType();
4740
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004741 if (ResultType.isNull())
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004742 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004743 else
4744 CodeCompleteExpression(S, ResultType);
4745}
4746
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004747void Sema::CodeCompleteAfterIf(Scope *S) {
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004748 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004749 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004750 mapCodeCompletionContext(*this, PCC_Statement));
4751 Results.setFilter(&ResultBuilder::IsOrdinaryName);
4752 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004753
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004754 CodeCompletionDeclConsumer Consumer(Results, CurContext);
4755 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00004756 CodeCompleter->includeGlobals(),
4757 CodeCompleter->loadExternal());
4758
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004759 AddOrdinaryNameResults(PCC_Statement, S, *this, Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004760
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004761 // "else" block
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004762 CodeCompletionBuilder Builder(Results.getAllocator(),
4763 Results.getCodeCompletionTUInfo());
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004764 Builder.AddTypedTextChunk("else");
Douglas Gregor3a5d6c22012-02-16 17:49:04 +00004765 if (Results.includeCodePatterns()) {
4766 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4767 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4768 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
4769 Builder.AddPlaceholderChunk("statements");
4770 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
4771 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4772 }
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004773 Results.AddResult(Builder.TakeString());
4774
4775 // "else if" block
4776 Builder.AddTypedTextChunk("else");
4777 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4778 Builder.AddTextChunk("if");
4779 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4780 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00004781 if (getLangOpts().CPlusPlus)
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004782 Builder.AddPlaceholderChunk("condition");
4783 else
4784 Builder.AddPlaceholderChunk("expression");
4785 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor3a5d6c22012-02-16 17:49:04 +00004786 if (Results.includeCodePatterns()) {
4787 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4788 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4789 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
4790 Builder.AddPlaceholderChunk("statements");
4791 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
4792 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4793 }
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004794 Results.AddResult(Builder.TakeString());
4795
4796 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004797
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004798 if (S->getFnParent())
Craig Topper12126262015-11-15 17:27:57 +00004799 AddPrettyFunctionResults(getLangOpts(), Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004800
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004801 if (CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00004802 AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004803
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004804 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4805 Results.data(),Results.size());
4806}
4807
Richard Trieu2bd04012011-09-09 02:00:50 +00004808void Sema::CodeCompleteAssignmentRHS(Scope *S, Expr *LHS) {
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004809 if (LHS)
4810 CodeCompleteExpression(S, static_cast<Expr *>(LHS)->getType());
4811 else
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004812 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004813}
4814
Jeffrey Yasskinc76498d2010-04-08 16:38:48 +00004815void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS,
Douglas Gregor2436e712009-09-17 21:32:03 +00004816 bool EnteringContext) {
Eric Liu06d34022017-12-12 11:35:46 +00004817 if (SS.isEmpty() || !CodeCompleter)
Douglas Gregor2436e712009-09-17 21:32:03 +00004818 return;
Alex Lorenz8a7a4cf2017-06-15 21:40:54 +00004819
Eric Liu06d34022017-12-12 11:35:46 +00004820 // We want to keep the scope specifier even if it's invalid (e.g. the scope
4821 // "a::b::" is not corresponding to any context/namespace in the AST), since
4822 // it can be useful for global code completion which have information about
4823 // contexts/symbols that are not in the AST.
4824 if (SS.isInvalid()) {
4825 CodeCompletionContext CC(CodeCompletionContext::CCC_Name);
4826 CC.setCXXScopeSpecifier(SS);
4827 HandleCodeCompleteResults(this, CodeCompleter, CC, nullptr, 0);
4828 return;
4829 }
Alex Lorenz8a7a4cf2017-06-15 21:40:54 +00004830 // Always pretend to enter a context to ensure that a dependent type
4831 // resolves to a dependent record.
4832 DeclContext *Ctx = computeDeclContext(SS, /*EnteringContext=*/true);
Douglas Gregor3545ff42009-09-21 16:56:56 +00004833 if (!Ctx)
4834 return;
Douglas Gregor800f2f02009-12-11 18:28:39 +00004835
4836 // Try to instantiate any non-dependent declaration contexts before
4837 // we look in them.
John McCall0b66eb32010-05-01 00:40:08 +00004838 if (!isDependentScopeSpecifier(SS) && RequireCompleteDeclContext(SS, Ctx))
Douglas Gregor800f2f02009-12-11 18:28:39 +00004839 return;
4840
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004841 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004842 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004843 CodeCompletionContext::CCC_Name);
Douglas Gregorac322ec2010-08-27 21:18:54 +00004844 Results.EnterNewScope();
Eric Liu06d34022017-12-12 11:35:46 +00004845
Douglas Gregor3545ff42009-09-21 16:56:56 +00004846 // The "template" keyword can follow "::" in the grammar, but only
4847 // put it into the grammar if the nested-name-specifier is dependent.
Aaron Ballman4a979672014-01-03 13:56:08 +00004848 NestedNameSpecifier *NNS = SS.getScopeRep();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004849 if (!Results.empty() && NNS->isDependent())
Douglas Gregor78a21012010-01-14 16:01:26 +00004850 Results.AddResult("template");
Douglas Gregorac322ec2010-08-27 21:18:54 +00004851
4852 // Add calls to overridden virtual functions, if there are any.
4853 //
4854 // FIXME: This isn't wonderful, because we don't know whether we're actually
4855 // in a context that permits expressions. This is a general issue with
4856 // qualified-id completions.
4857 if (!EnteringContext)
4858 MaybeAddOverrideCalls(*this, Ctx, Results);
Eric Liu06d34022017-12-12 11:35:46 +00004859 Results.ExitScope();
4860
Eric Liufead6ae2017-12-13 10:26:49 +00004861 if (CodeCompleter->includeNamespaceLevelDecls() ||
4862 (!Ctx->isNamespace() && !Ctx->isTranslationUnit())) {
4863 CodeCompletionDeclConsumer Consumer(Results, CurContext);
4864 LookupVisibleDecls(Ctx, LookupOrdinaryName, Consumer,
4865 /*IncludeGlobalScope=*/true,
Sam McCallbb2cf632018-01-12 14:51:47 +00004866 /*IncludeDependentBases=*/true,
4867 CodeCompleter->loadExternal());
Eric Liufead6ae2017-12-13 10:26:49 +00004868 }
Douglas Gregorac322ec2010-08-27 21:18:54 +00004869
Eric Liu06d34022017-12-12 11:35:46 +00004870 auto CC = Results.getCompletionContext();
4871 CC.setCXXScopeSpecifier(SS);
4872
4873 HandleCodeCompleteResults(this, CodeCompleter, CC, Results.data(),
4874 Results.size());
Douglas Gregor2436e712009-09-17 21:32:03 +00004875}
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00004876
4877void Sema::CodeCompleteUsing(Scope *S) {
4878 if (!CodeCompleter)
4879 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004880
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004881 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004882 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00004883 CodeCompletionContext::CCC_PotentiallyQualifiedName,
4884 &ResultBuilder::IsNestedNameSpecifier);
Douglas Gregor64b12b52009-09-22 23:31:26 +00004885 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004886
Douglas Gregor3545ff42009-09-21 16:56:56 +00004887 // If we aren't in class scope, we could see the "namespace" keyword.
4888 if (!S->isClassScope())
John McCall276321a2010-08-25 06:19:51 +00004889 Results.AddResult(CodeCompletionResult("namespace"));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004890
4891 // After "using", we can see anything that would start a
Douglas Gregor3545ff42009-09-21 16:56:56 +00004892 // nested-name-specifier.
Douglas Gregora6e2edc2010-01-14 03:27:13 +00004893 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00004894 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00004895 CodeCompleter->includeGlobals(),
4896 CodeCompleter->loadExternal());
Douglas Gregor64b12b52009-09-22 23:31:26 +00004897 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00004898
4899 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4900 Results.data(), Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00004901}
4902
4903void Sema::CodeCompleteUsingDirective(Scope *S) {
4904 if (!CodeCompleter)
4905 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004906
Douglas Gregor3545ff42009-09-21 16:56:56 +00004907 // After "using namespace", we expect to see a namespace name or namespace
4908 // alias.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004909 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004910 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004911 CodeCompletionContext::CCC_Namespace,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004912 &ResultBuilder::IsNamespaceOrAlias);
Douglas Gregor64b12b52009-09-22 23:31:26 +00004913 Results.EnterNewScope();
Douglas Gregora6e2edc2010-01-14 03:27:13 +00004914 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00004915 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00004916 CodeCompleter->includeGlobals(),
4917 CodeCompleter->loadExternal());
Douglas Gregor64b12b52009-09-22 23:31:26 +00004918 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00004919 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4920 Results.data(), Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00004921}
4922
4923void Sema::CodeCompleteNamespaceDecl(Scope *S) {
4924 if (!CodeCompleter)
4925 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004926
Ted Kremenekc37877d2013-10-08 17:08:03 +00004927 DeclContext *Ctx = S->getEntity();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004928 if (!S->getParent())
4929 Ctx = Context.getTranslationUnitDecl();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004930
Douglas Gregor0ac41382010-09-23 23:01:17 +00004931 bool SuppressedGlobalResults
4932 = Ctx && !CodeCompleter->includeGlobals() && isa<TranslationUnitDecl>(Ctx);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004933
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004934 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004935 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00004936 SuppressedGlobalResults
4937 ? CodeCompletionContext::CCC_Namespace
4938 : CodeCompletionContext::CCC_Other,
4939 &ResultBuilder::IsNamespace);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004940
Douglas Gregor0ac41382010-09-23 23:01:17 +00004941 if (Ctx && Ctx->isFileContext() && !SuppressedGlobalResults) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00004942 // We only want to see those namespaces that have already been defined
4943 // within this scope, because its likely that the user is creating an
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004944 // extended namespace declaration. Keep track of the most recent
Douglas Gregor3545ff42009-09-21 16:56:56 +00004945 // definition of each namespace.
4946 std::map<NamespaceDecl *, NamespaceDecl *> OrigToLatest;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004947 for (DeclContext::specific_decl_iterator<NamespaceDecl>
Douglas Gregor3545ff42009-09-21 16:56:56 +00004948 NS(Ctx->decls_begin()), NSEnd(Ctx->decls_end());
4949 NS != NSEnd; ++NS)
David Blaikie40ed2972012-06-06 20:45:41 +00004950 OrigToLatest[NS->getOriginalNamespace()] = *NS;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004951
4952 // Add the most recent definition (or extended definition) of each
Douglas Gregor3545ff42009-09-21 16:56:56 +00004953 // namespace to the list of results.
Douglas Gregor64b12b52009-09-22 23:31:26 +00004954 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004955 for (std::map<NamespaceDecl *, NamespaceDecl *>::iterator
Douglas Gregor78254c82012-03-27 23:34:16 +00004956 NS = OrigToLatest.begin(),
4957 NSEnd = OrigToLatest.end();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004958 NS != NSEnd; ++NS)
Douglas Gregor0a0e2b32013-01-31 04:52:16 +00004959 Results.AddResult(CodeCompletionResult(
Craig Topperc3ec1492014-05-26 06:22:03 +00004960 NS->second, Results.getBasePriority(NS->second),
4961 nullptr),
4962 CurContext, nullptr, false);
Douglas Gregor64b12b52009-09-22 23:31:26 +00004963 Results.ExitScope();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004964 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004965
4966 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004967 Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004968 Results.data(),Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00004969}
4970
4971void Sema::CodeCompleteNamespaceAliasDecl(Scope *S) {
4972 if (!CodeCompleter)
4973 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004974
Douglas Gregor3545ff42009-09-21 16:56:56 +00004975 // After "namespace", we expect to see a namespace or alias.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004976 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004977 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004978 CodeCompletionContext::CCC_Namespace,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004979 &ResultBuilder::IsNamespaceOrAlias);
Douglas Gregora6e2edc2010-01-14 03:27:13 +00004980 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00004981 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00004982 CodeCompleter->includeGlobals(),
4983 CodeCompleter->loadExternal());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004984 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004985 Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004986 Results.data(),Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00004987}
4988
Douglas Gregorc811ede2009-09-18 20:05:18 +00004989void Sema::CodeCompleteOperatorName(Scope *S) {
4990 if (!CodeCompleter)
4991 return;
Douglas Gregor3545ff42009-09-21 16:56:56 +00004992
John McCall276321a2010-08-25 06:19:51 +00004993 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004994 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004995 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004996 CodeCompletionContext::CCC_Type,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004997 &ResultBuilder::IsType);
Douglas Gregor64b12b52009-09-22 23:31:26 +00004998 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004999
Douglas Gregor3545ff42009-09-21 16:56:56 +00005000 // Add the names of overloadable operators.
5001#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
5002 if (std::strcmp(Spelling, "?")) \
Douglas Gregor78a21012010-01-14 16:01:26 +00005003 Results.AddResult(Result(Spelling));
Douglas Gregor3545ff42009-09-21 16:56:56 +00005004#include "clang/Basic/OperatorKinds.def"
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005005
Douglas Gregor3545ff42009-09-21 16:56:56 +00005006 // Add any type names visible from the current scope
Douglas Gregor6ae4c522010-01-14 03:21:49 +00005007 Results.allowNestedNameSpecifiers();
Douglas Gregora6e2edc2010-01-14 03:27:13 +00005008 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00005009 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00005010 CodeCompleter->includeGlobals(),
5011 CodeCompleter->loadExternal());
5012
Douglas Gregor3545ff42009-09-21 16:56:56 +00005013 // Add any type specifiers
David Blaikiebbafb8a2012-03-11 07:00:24 +00005014 AddTypeSpecifierResults(getLangOpts(), Results);
Douglas Gregor64b12b52009-09-22 23:31:26 +00005015 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005016
5017 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5018 Results.data(), Results.size());
Douglas Gregorc811ede2009-09-18 20:05:18 +00005019}
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00005020
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00005021void Sema::CodeCompleteConstructorInitializer(
5022 Decl *ConstructorD,
5023 ArrayRef <CXXCtorInitializer *> Initializers) {
Benjamin Kramera4f8df02015-07-09 15:31:10 +00005024 if (!ConstructorD)
5025 return;
5026
5027 AdjustDeclIfTemplate(ConstructorD);
5028
5029 CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(ConstructorD);
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005030 if (!Constructor)
5031 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005032
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005033 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005034 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00005035 CodeCompletionContext::CCC_PotentiallyQualifiedName);
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005036 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005037
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005038 // Fill in any already-initialized fields or base classes.
5039 llvm::SmallPtrSet<FieldDecl *, 4> InitializedFields;
5040 llvm::SmallPtrSet<CanQualType, 4> InitializedBases;
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00005041 for (unsigned I = 0, E = Initializers.size(); I != E; ++I) {
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005042 if (Initializers[I]->isBaseInitializer())
5043 InitializedBases.insert(
5044 Context.getCanonicalType(QualType(Initializers[I]->getBaseClass(), 0)));
5045 else
Francois Pichetd583da02010-12-04 09:14:42 +00005046 InitializedFields.insert(cast<FieldDecl>(
5047 Initializers[I]->getAnyMember()));
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005048 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005049
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005050 // Add completions for base classes.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005051 CodeCompletionBuilder Builder(Results.getAllocator(),
5052 Results.getCodeCompletionTUInfo());
Benjamin Kramera4f8df02015-07-09 15:31:10 +00005053 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00005054 bool SawLastInitializer = Initializers.empty();
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005055 CXXRecordDecl *ClassDecl = Constructor->getParent();
Aaron Ballman574705e2014-03-13 15:41:46 +00005056 for (const auto &Base : ClassDecl->bases()) {
David Blaikie82e95a32014-11-19 07:49:47 +00005057 if (!InitializedBases.insert(Context.getCanonicalType(Base.getType()))
5058 .second) {
Douglas Gregor99129ef2010-08-29 19:27:27 +00005059 SawLastInitializer
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005060 = !Initializers.empty() &&
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00005061 Initializers.back()->isBaseInitializer() &&
Aaron Ballman574705e2014-03-13 15:41:46 +00005062 Context.hasSameUnqualifiedType(Base.getType(),
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00005063 QualType(Initializers.back()->getBaseClass(), 0));
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005064 continue;
Douglas Gregor99129ef2010-08-29 19:27:27 +00005065 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005066
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005067 Builder.AddTypedTextChunk(
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005068 Results.getAllocator().CopyString(
Aaron Ballman574705e2014-03-13 15:41:46 +00005069 Base.getType().getAsString(Policy)));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005070 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5071 Builder.AddPlaceholderChunk("args");
5072 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005073 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor99129ef2010-08-29 19:27:27 +00005074 SawLastInitializer? CCP_NextInitializer
5075 : CCP_MemberDeclaration));
5076 SawLastInitializer = false;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005077 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005078
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005079 // Add completions for virtual base classes.
Aaron Ballman445a9392014-03-13 16:15:17 +00005080 for (const auto &Base : ClassDecl->vbases()) {
David Blaikie82e95a32014-11-19 07:49:47 +00005081 if (!InitializedBases.insert(Context.getCanonicalType(Base.getType()))
5082 .second) {
Douglas Gregor99129ef2010-08-29 19:27:27 +00005083 SawLastInitializer
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005084 = !Initializers.empty() &&
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00005085 Initializers.back()->isBaseInitializer() &&
Aaron Ballman445a9392014-03-13 16:15:17 +00005086 Context.hasSameUnqualifiedType(Base.getType(),
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00005087 QualType(Initializers.back()->getBaseClass(), 0));
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005088 continue;
Douglas Gregor99129ef2010-08-29 19:27:27 +00005089 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005090
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005091 Builder.AddTypedTextChunk(
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005092 Builder.getAllocator().CopyString(
Aaron Ballman445a9392014-03-13 16:15:17 +00005093 Base.getType().getAsString(Policy)));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005094 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5095 Builder.AddPlaceholderChunk("args");
5096 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005097 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor99129ef2010-08-29 19:27:27 +00005098 SawLastInitializer? CCP_NextInitializer
5099 : CCP_MemberDeclaration));
5100 SawLastInitializer = false;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005101 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005102
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005103 // Add completions for members.
Aaron Ballmane8a8bae2014-03-08 20:12:42 +00005104 for (auto *Field : ClassDecl->fields()) {
David Blaikie82e95a32014-11-19 07:49:47 +00005105 if (!InitializedFields.insert(cast<FieldDecl>(Field->getCanonicalDecl()))
5106 .second) {
Douglas Gregor99129ef2010-08-29 19:27:27 +00005107 SawLastInitializer
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005108 = !Initializers.empty() &&
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00005109 Initializers.back()->isAnyMemberInitializer() &&
Aaron Ballmane8a8bae2014-03-08 20:12:42 +00005110 Initializers.back()->getAnyMember() == Field;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005111 continue;
Douglas Gregor99129ef2010-08-29 19:27:27 +00005112 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005113
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005114 if (!Field->getDeclName())
5115 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005116
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005117 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005118 Field->getIdentifier()->getName()));
5119 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5120 Builder.AddPlaceholderChunk("args");
5121 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005122 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor99129ef2010-08-29 19:27:27 +00005123 SawLastInitializer? CCP_NextInitializer
Douglas Gregorf3af3112010-09-09 21:42:20 +00005124 : CCP_MemberDeclaration,
Douglas Gregor78254c82012-03-27 23:34:16 +00005125 CXCursor_MemberRef,
5126 CXAvailability_Available,
Aaron Ballmane8a8bae2014-03-08 20:12:42 +00005127 Field));
Douglas Gregor99129ef2010-08-29 19:27:27 +00005128 SawLastInitializer = false;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005129 }
5130 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005131
Douglas Gregor0ac41382010-09-23 23:01:17 +00005132 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005133 Results.data(), Results.size());
5134}
5135
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00005136/// Determine whether this scope denotes a namespace.
Douglas Gregord8c61782012-02-15 15:34:24 +00005137static bool isNamespaceScope(Scope *S) {
Ted Kremenekc37877d2013-10-08 17:08:03 +00005138 DeclContext *DC = S->getEntity();
Douglas Gregord8c61782012-02-15 15:34:24 +00005139 if (!DC)
5140 return false;
5141
5142 return DC->isFileContext();
5143}
5144
5145void Sema::CodeCompleteLambdaIntroducer(Scope *S, LambdaIntroducer &Intro,
5146 bool AfterAmpersand) {
5147 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005148 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregord8c61782012-02-15 15:34:24 +00005149 CodeCompletionContext::CCC_Other);
5150 Results.EnterNewScope();
5151
5152 // Note what has already been captured.
5153 llvm::SmallPtrSet<IdentifierInfo *, 4> Known;
5154 bool IncludedThis = false;
Benjamin Kramerf3ca26982014-05-10 16:31:55 +00005155 for (const auto &C : Intro.Captures) {
5156 if (C.Kind == LCK_This) {
Douglas Gregord8c61782012-02-15 15:34:24 +00005157 IncludedThis = true;
5158 continue;
5159 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005160
Benjamin Kramerf3ca26982014-05-10 16:31:55 +00005161 Known.insert(C.Id);
Douglas Gregord8c61782012-02-15 15:34:24 +00005162 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005163
Douglas Gregord8c61782012-02-15 15:34:24 +00005164 // Look for other capturable variables.
5165 for (; S && !isNamespaceScope(S); S = S->getParent()) {
Aaron Ballman35c54952014-03-17 16:55:25 +00005166 for (const auto *D : S->decls()) {
5167 const auto *Var = dyn_cast<VarDecl>(D);
Douglas Gregord8c61782012-02-15 15:34:24 +00005168 if (!Var ||
5169 !Var->hasLocalStorage() ||
5170 Var->hasAttr<BlocksAttr>())
5171 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005172
David Blaikie82e95a32014-11-19 07:49:47 +00005173 if (Known.insert(Var->getIdentifier()).second)
Douglas Gregor0a0e2b32013-01-31 04:52:16 +00005174 Results.AddResult(CodeCompletionResult(Var, CCP_LocalDeclaration),
Craig Topperc3ec1492014-05-26 06:22:03 +00005175 CurContext, nullptr, false);
Douglas Gregord8c61782012-02-15 15:34:24 +00005176 }
5177 }
5178
5179 // Add 'this', if it would be valid.
5180 if (!IncludedThis && !AfterAmpersand && Intro.Default != LCD_ByCopy)
5181 addThisCompletion(*this, Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005182
Douglas Gregord8c61782012-02-15 15:34:24 +00005183 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005184
Douglas Gregord8c61782012-02-15 15:34:24 +00005185 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5186 Results.data(), Results.size());
5187}
5188
James Dennett596e4752012-06-14 03:11:41 +00005189/// Macro that optionally prepends an "@" to the string literal passed in via
5190/// Keyword, depending on whether NeedAt is true or false.
5191#define OBJC_AT_KEYWORD_NAME(NeedAt,Keyword) ((NeedAt)? "@" Keyword : Keyword)
5192
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005193static void AddObjCImplementationResults(const LangOptions &LangOpts,
Douglas Gregorf1934162010-01-13 21:24:21 +00005194 ResultBuilder &Results,
5195 bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005196 typedef CodeCompletionResult Result;
Douglas Gregorf1934162010-01-13 21:24:21 +00005197 // Since we have an implementation, we can end it.
James Dennett596e4752012-06-14 03:11:41 +00005198 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"end")));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005199
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005200 CodeCompletionBuilder Builder(Results.getAllocator(),
5201 Results.getCodeCompletionTUInfo());
Douglas Gregorf1934162010-01-13 21:24:21 +00005202 if (LangOpts.ObjC2) {
5203 // @dynamic
James Dennett596e4752012-06-14 03:11:41 +00005204 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"dynamic"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005205 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5206 Builder.AddPlaceholderChunk("property");
5207 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005208
Douglas Gregorf1934162010-01-13 21:24:21 +00005209 // @synthesize
James Dennett596e4752012-06-14 03:11:41 +00005210 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"synthesize"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005211 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5212 Builder.AddPlaceholderChunk("property");
5213 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005214 }
Douglas Gregorf1934162010-01-13 21:24:21 +00005215}
5216
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005217static void AddObjCInterfaceResults(const LangOptions &LangOpts,
Douglas Gregorf1934162010-01-13 21:24:21 +00005218 ResultBuilder &Results,
5219 bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005220 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005221
Douglas Gregorf1934162010-01-13 21:24:21 +00005222 // Since we have an interface or protocol, we can end it.
James Dennett596e4752012-06-14 03:11:41 +00005223 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"end")));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005224
Douglas Gregorf1934162010-01-13 21:24:21 +00005225 if (LangOpts.ObjC2) {
5226 // @property
James Dennett596e4752012-06-14 03:11:41 +00005227 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"property")));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005228
Douglas Gregorf1934162010-01-13 21:24:21 +00005229 // @required
James Dennett596e4752012-06-14 03:11:41 +00005230 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"required")));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005231
Douglas Gregorf1934162010-01-13 21:24:21 +00005232 // @optional
James Dennett596e4752012-06-14 03:11:41 +00005233 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"optional")));
Douglas Gregorf1934162010-01-13 21:24:21 +00005234 }
5235}
5236
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005237static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005238 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005239 CodeCompletionBuilder Builder(Results.getAllocator(),
5240 Results.getCodeCompletionTUInfo());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005241
Douglas Gregorf1934162010-01-13 21:24:21 +00005242 // @class name ;
James Dennett596e4752012-06-14 03:11:41 +00005243 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"class"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005244 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5245 Builder.AddPlaceholderChunk("name");
5246 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005247
Douglas Gregorf4c33342010-05-28 00:22:41 +00005248 if (Results.includeCodePatterns()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005249 // @interface name
5250 // FIXME: Could introduce the whole pattern, including superclasses and
Douglas Gregorf4c33342010-05-28 00:22:41 +00005251 // such.
James Dennett596e4752012-06-14 03:11:41 +00005252 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"interface"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005253 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5254 Builder.AddPlaceholderChunk("class");
5255 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005256
Douglas Gregorf4c33342010-05-28 00:22:41 +00005257 // @protocol name
James Dennett596e4752012-06-14 03:11:41 +00005258 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"protocol"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005259 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5260 Builder.AddPlaceholderChunk("protocol");
5261 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005262
Douglas Gregorf4c33342010-05-28 00:22:41 +00005263 // @implementation name
James Dennett596e4752012-06-14 03:11:41 +00005264 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"implementation"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005265 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5266 Builder.AddPlaceholderChunk("class");
5267 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00005268 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005269
Douglas Gregorf1934162010-01-13 21:24:21 +00005270 // @compatibility_alias name
James Dennett596e4752012-06-14 03:11:41 +00005271 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"compatibility_alias"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005272 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5273 Builder.AddPlaceholderChunk("alias");
5274 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5275 Builder.AddPlaceholderChunk("class");
5276 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor61e36812013-03-07 23:26:24 +00005277
5278 if (Results.getSema().getLangOpts().Modules) {
5279 // @import name
5280 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "import"));
5281 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5282 Builder.AddPlaceholderChunk("module");
5283 Results.AddResult(Result(Builder.TakeString()));
5284 }
Douglas Gregorf1934162010-01-13 21:24:21 +00005285}
5286
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005287void Sema::CodeCompleteObjCAtDirective(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005288 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005289 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005290 CodeCompletionContext::CCC_Other);
Douglas Gregorf48706c2009-12-07 09:27:33 +00005291 Results.EnterNewScope();
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005292 if (isa<ObjCImplDecl>(CurContext))
David Blaikiebbafb8a2012-03-11 07:00:24 +00005293 AddObjCImplementationResults(getLangOpts(), Results, false);
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005294 else if (CurContext->isObjCContainer())
David Blaikiebbafb8a2012-03-11 07:00:24 +00005295 AddObjCInterfaceResults(getLangOpts(), Results, false);
Douglas Gregorf1934162010-01-13 21:24:21 +00005296 else
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005297 AddObjCTopLevelResults(Results, false);
Douglas Gregorf48706c2009-12-07 09:27:33 +00005298 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005299 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5300 Results.data(), Results.size());
Douglas Gregorf48706c2009-12-07 09:27:33 +00005301}
5302
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005303static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005304 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005305 CodeCompletionBuilder Builder(Results.getAllocator(),
5306 Results.getCodeCompletionTUInfo());
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005307
5308 // @encode ( type-name )
Douglas Gregore5c79d52011-10-18 21:20:17 +00005309 const char *EncodeType = "char[]";
David Blaikiebbafb8a2012-03-11 07:00:24 +00005310 if (Results.getSema().getLangOpts().CPlusPlus ||
5311 Results.getSema().getLangOpts().ConstStrings)
Jordan Rose9da05852012-06-15 18:19:56 +00005312 EncodeType = "const char[]";
Douglas Gregore5c79d52011-10-18 21:20:17 +00005313 Builder.AddResultTypeChunk(EncodeType);
James Dennett596e4752012-06-14 03:11:41 +00005314 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"encode"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005315 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5316 Builder.AddPlaceholderChunk("type-name");
5317 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5318 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005319
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005320 // @protocol ( protocol-name )
Douglas Gregore5c79d52011-10-18 21:20:17 +00005321 Builder.AddResultTypeChunk("Protocol *");
James Dennett596e4752012-06-14 03:11:41 +00005322 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"protocol"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005323 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5324 Builder.AddPlaceholderChunk("protocol-name");
5325 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5326 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005327
5328 // @selector ( selector )
Douglas Gregore5c79d52011-10-18 21:20:17 +00005329 Builder.AddResultTypeChunk("SEL");
James Dennett596e4752012-06-14 03:11:41 +00005330 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"selector"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005331 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5332 Builder.AddPlaceholderChunk("selector");
5333 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5334 Results.AddResult(Result(Builder.TakeString()));
Jordan Rose9da05852012-06-15 18:19:56 +00005335
5336 // @"string"
5337 Builder.AddResultTypeChunk("NSString *");
5338 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"\""));
5339 Builder.AddPlaceholderChunk("string");
5340 Builder.AddTextChunk("\"");
5341 Results.AddResult(Result(Builder.TakeString()));
5342
Douglas Gregor951de302012-07-17 23:24:47 +00005343 // @[objects, ...]
Jordan Rose9da05852012-06-15 18:19:56 +00005344 Builder.AddResultTypeChunk("NSArray *");
James Dennett596e4752012-06-14 03:11:41 +00005345 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"["));
Ted Kremeneke65b0862012-03-06 20:05:56 +00005346 Builder.AddPlaceholderChunk("objects, ...");
Ted Kremeneke65b0862012-03-06 20:05:56 +00005347 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
5348 Results.AddResult(Result(Builder.TakeString()));
5349
Douglas Gregor951de302012-07-17 23:24:47 +00005350 // @{key : object, ...}
Jordan Rose9da05852012-06-15 18:19:56 +00005351 Builder.AddResultTypeChunk("NSDictionary *");
James Dennett596e4752012-06-14 03:11:41 +00005352 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"{"));
Ted Kremeneke65b0862012-03-06 20:05:56 +00005353 Builder.AddPlaceholderChunk("key");
Ted Kremeneke65b0862012-03-06 20:05:56 +00005354 Builder.AddChunk(CodeCompletionString::CK_Colon);
5355 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5356 Builder.AddPlaceholderChunk("object, ...");
Ted Kremeneke65b0862012-03-06 20:05:56 +00005357 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5358 Results.AddResult(Result(Builder.TakeString()));
Jordan Rose9da05852012-06-15 18:19:56 +00005359
Douglas Gregor951de302012-07-17 23:24:47 +00005360 // @(expression)
Jordan Rose9da05852012-06-15 18:19:56 +00005361 Builder.AddResultTypeChunk("id");
5362 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "("));
Jordan Rose9da05852012-06-15 18:19:56 +00005363 Builder.AddPlaceholderChunk("expression");
Jordan Rose9da05852012-06-15 18:19:56 +00005364 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5365 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005366}
5367
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005368static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005369 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005370 CodeCompletionBuilder Builder(Results.getAllocator(),
5371 Results.getCodeCompletionTUInfo());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005372
Douglas Gregorf4c33342010-05-28 00:22:41 +00005373 if (Results.includeCodePatterns()) {
5374 // @try { statements } @catch ( declaration ) { statements } @finally
5375 // { statements }
James Dennett596e4752012-06-14 03:11:41 +00005376 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"try"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005377 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5378 Builder.AddPlaceholderChunk("statements");
5379 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5380 Builder.AddTextChunk("@catch");
5381 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5382 Builder.AddPlaceholderChunk("parameter");
5383 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5384 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5385 Builder.AddPlaceholderChunk("statements");
5386 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5387 Builder.AddTextChunk("@finally");
5388 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5389 Builder.AddPlaceholderChunk("statements");
5390 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5391 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00005392 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005393
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005394 // @throw
James Dennett596e4752012-06-14 03:11:41 +00005395 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"throw"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005396 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5397 Builder.AddPlaceholderChunk("expression");
5398 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005399
Douglas Gregorf4c33342010-05-28 00:22:41 +00005400 if (Results.includeCodePatterns()) {
5401 // @synchronized ( expression ) { statements }
James Dennett596e4752012-06-14 03:11:41 +00005402 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"synchronized"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005403 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5404 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5405 Builder.AddPlaceholderChunk("expression");
5406 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5407 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5408 Builder.AddPlaceholderChunk("statements");
5409 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5410 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00005411 }
Douglas Gregorf1934162010-01-13 21:24:21 +00005412}
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005413
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005414static void AddObjCVisibilityResults(const LangOptions &LangOpts,
Douglas Gregor48d46252010-01-13 21:54:15 +00005415 ResultBuilder &Results,
5416 bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005417 typedef CodeCompletionResult Result;
James Dennett596e4752012-06-14 03:11:41 +00005418 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"private")));
5419 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"protected")));
5420 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"public")));
Douglas Gregor48d46252010-01-13 21:54:15 +00005421 if (LangOpts.ObjC2)
James Dennett596e4752012-06-14 03:11:41 +00005422 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"package")));
Douglas Gregor48d46252010-01-13 21:54:15 +00005423}
5424
5425void Sema::CodeCompleteObjCAtVisibility(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005426 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005427 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005428 CodeCompletionContext::CCC_Other);
Douglas Gregor48d46252010-01-13 21:54:15 +00005429 Results.EnterNewScope();
David Blaikiebbafb8a2012-03-11 07:00:24 +00005430 AddObjCVisibilityResults(getLangOpts(), Results, false);
Douglas Gregor48d46252010-01-13 21:54:15 +00005431 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005432 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5433 Results.data(), Results.size());
Douglas Gregor48d46252010-01-13 21:54:15 +00005434}
5435
5436void Sema::CodeCompleteObjCAtStatement(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005437 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005438 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005439 CodeCompletionContext::CCC_Other);
Douglas Gregorf1934162010-01-13 21:24:21 +00005440 Results.EnterNewScope();
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005441 AddObjCStatementResults(Results, false);
5442 AddObjCExpressionResults(Results, false);
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005443 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005444 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5445 Results.data(), Results.size());
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005446}
5447
5448void Sema::CodeCompleteObjCAtExpression(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005449 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005450 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005451 CodeCompletionContext::CCC_Other);
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005452 Results.EnterNewScope();
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005453 AddObjCExpressionResults(Results, false);
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005454 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005455 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5456 Results.data(), Results.size());
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005457}
5458
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00005459/// Determine whether the addition of the given flag to an Objective-C
Douglas Gregore6078da2009-11-19 00:14:45 +00005460/// property's attributes will cause a conflict.
Bill Wendling44426052012-12-20 19:22:21 +00005461static bool ObjCPropertyFlagConflicts(unsigned Attributes, unsigned NewFlag) {
Douglas Gregore6078da2009-11-19 00:14:45 +00005462 // Check if we've already added this flag.
Bill Wendling44426052012-12-20 19:22:21 +00005463 if (Attributes & NewFlag)
Douglas Gregore6078da2009-11-19 00:14:45 +00005464 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005465
Bill Wendling44426052012-12-20 19:22:21 +00005466 Attributes |= NewFlag;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005467
Douglas Gregore6078da2009-11-19 00:14:45 +00005468 // Check for collisions with "readonly".
Bill Wendling44426052012-12-20 19:22:21 +00005469 if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) &&
5470 (Attributes & ObjCDeclSpec::DQ_PR_readwrite))
Douglas Gregore6078da2009-11-19 00:14:45 +00005471 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005472
Jordan Rose53cb2f32012-08-20 20:01:13 +00005473 // Check for more than one of { assign, copy, retain, strong, weak }.
Bill Wendling44426052012-12-20 19:22:21 +00005474 unsigned AssignCopyRetMask = Attributes & (ObjCDeclSpec::DQ_PR_assign |
John McCall31168b02011-06-15 23:02:42 +00005475 ObjCDeclSpec::DQ_PR_unsafe_unretained |
Douglas Gregore6078da2009-11-19 00:14:45 +00005476 ObjCDeclSpec::DQ_PR_copy |
Jordan Rose53cb2f32012-08-20 20:01:13 +00005477 ObjCDeclSpec::DQ_PR_retain |
5478 ObjCDeclSpec::DQ_PR_strong |
5479 ObjCDeclSpec::DQ_PR_weak);
Douglas Gregore6078da2009-11-19 00:14:45 +00005480 if (AssignCopyRetMask &&
5481 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_assign &&
John McCall31168b02011-06-15 23:02:42 +00005482 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_unsafe_unretained &&
Douglas Gregore6078da2009-11-19 00:14:45 +00005483 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_copy &&
John McCall31168b02011-06-15 23:02:42 +00005484 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_retain &&
Jordan Rose53cb2f32012-08-20 20:01:13 +00005485 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_strong &&
5486 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_weak)
Douglas Gregore6078da2009-11-19 00:14:45 +00005487 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005488
Douglas Gregore6078da2009-11-19 00:14:45 +00005489 return false;
5490}
5491
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005492void Sema::CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS) {
Steve Naroff936354c2009-10-08 21:55:05 +00005493 if (!CodeCompleter)
5494 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005495
Bill Wendling44426052012-12-20 19:22:21 +00005496 unsigned Attributes = ODS.getPropertyAttributes();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005497
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005498 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005499 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005500 CodeCompletionContext::CCC_Other);
Steve Naroff936354c2009-10-08 21:55:05 +00005501 Results.EnterNewScope();
Bill Wendling44426052012-12-20 19:22:21 +00005502 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readonly))
John McCall276321a2010-08-25 06:19:51 +00005503 Results.AddResult(CodeCompletionResult("readonly"));
Bill Wendling44426052012-12-20 19:22:21 +00005504 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_assign))
John McCall276321a2010-08-25 06:19:51 +00005505 Results.AddResult(CodeCompletionResult("assign"));
Bill Wendling44426052012-12-20 19:22:21 +00005506 if (!ObjCPropertyFlagConflicts(Attributes,
John McCall31168b02011-06-15 23:02:42 +00005507 ObjCDeclSpec::DQ_PR_unsafe_unretained))
5508 Results.AddResult(CodeCompletionResult("unsafe_unretained"));
Bill Wendling44426052012-12-20 19:22:21 +00005509 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readwrite))
John McCall276321a2010-08-25 06:19:51 +00005510 Results.AddResult(CodeCompletionResult("readwrite"));
Bill Wendling44426052012-12-20 19:22:21 +00005511 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_retain))
John McCall276321a2010-08-25 06:19:51 +00005512 Results.AddResult(CodeCompletionResult("retain"));
Bill Wendling44426052012-12-20 19:22:21 +00005513 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_strong))
John McCall31168b02011-06-15 23:02:42 +00005514 Results.AddResult(CodeCompletionResult("strong"));
Bill Wendling44426052012-12-20 19:22:21 +00005515 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_copy))
John McCall276321a2010-08-25 06:19:51 +00005516 Results.AddResult(CodeCompletionResult("copy"));
Bill Wendling44426052012-12-20 19:22:21 +00005517 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_nonatomic))
John McCall276321a2010-08-25 06:19:51 +00005518 Results.AddResult(CodeCompletionResult("nonatomic"));
Bill Wendling44426052012-12-20 19:22:21 +00005519 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_atomic))
Fariborz Jahanian1c2d29e2011-06-11 17:14:27 +00005520 Results.AddResult(CodeCompletionResult("atomic"));
Jordan Rose53cb2f32012-08-20 20:01:13 +00005521
5522 // Only suggest "weak" if we're compiling for ARC-with-weak-references or GC.
John McCall460ce582015-10-22 18:38:17 +00005523 if (getLangOpts().ObjCWeak || getLangOpts().getGC() != LangOptions::NonGC)
Bill Wendling44426052012-12-20 19:22:21 +00005524 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_weak))
Jordan Rose53cb2f32012-08-20 20:01:13 +00005525 Results.AddResult(CodeCompletionResult("weak"));
5526
Bill Wendling44426052012-12-20 19:22:21 +00005527 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_setter)) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005528 CodeCompletionBuilder Setter(Results.getAllocator(),
5529 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005530 Setter.AddTypedTextChunk("setter");
Argyrios Kyrtzidis7bbb8812014-02-20 07:55:15 +00005531 Setter.AddTextChunk("=");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005532 Setter.AddPlaceholderChunk("method");
5533 Results.AddResult(CodeCompletionResult(Setter.TakeString()));
Douglas Gregor45f83ee2009-11-19 00:01:57 +00005534 }
Bill Wendling44426052012-12-20 19:22:21 +00005535 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_getter)) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005536 CodeCompletionBuilder Getter(Results.getAllocator(),
5537 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005538 Getter.AddTypedTextChunk("getter");
Argyrios Kyrtzidis7bbb8812014-02-20 07:55:15 +00005539 Getter.AddTextChunk("=");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005540 Getter.AddPlaceholderChunk("method");
5541 Results.AddResult(CodeCompletionResult(Getter.TakeString()));
Douglas Gregor45f83ee2009-11-19 00:01:57 +00005542 }
Douglas Gregor86b42682015-06-19 18:27:52 +00005543 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_nullability)) {
5544 Results.AddResult(CodeCompletionResult("nonnull"));
5545 Results.AddResult(CodeCompletionResult("nullable"));
5546 Results.AddResult(CodeCompletionResult("null_unspecified"));
5547 Results.AddResult(CodeCompletionResult("null_resettable"));
5548 }
Steve Naroff936354c2009-10-08 21:55:05 +00005549 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005550 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5551 Results.data(), Results.size());
Steve Naroff936354c2009-10-08 21:55:05 +00005552}
Steve Naroffeae65032009-11-07 02:08:14 +00005553
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00005554/// Describes the kind of Objective-C method that we want to find
Douglas Gregorc8537c52009-11-19 07:41:15 +00005555/// via code completion.
5556enum ObjCMethodKind {
Dmitri Gribenko4280e5c2012-06-08 23:13:42 +00005557 MK_Any, ///< Any kind of method, provided it means other specified criteria.
5558 MK_ZeroArgSelector, ///< Zero-argument (unary) selector.
5559 MK_OneArgSelector ///< One-argument selector.
Douglas Gregorc8537c52009-11-19 07:41:15 +00005560};
5561
Douglas Gregor67c692c2010-08-26 15:07:07 +00005562static bool isAcceptableObjCSelector(Selector Sel,
5563 ObjCMethodKind WantKind,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005564 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005565 bool AllowSameLength = true) {
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005566 unsigned NumSelIdents = SelIdents.size();
Douglas Gregor67c692c2010-08-26 15:07:07 +00005567 if (NumSelIdents > Sel.getNumArgs())
5568 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005569
Douglas Gregor67c692c2010-08-26 15:07:07 +00005570 switch (WantKind) {
5571 case MK_Any: break;
5572 case MK_ZeroArgSelector: return Sel.isUnarySelector();
5573 case MK_OneArgSelector: return Sel.getNumArgs() == 1;
5574 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005575
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005576 if (!AllowSameLength && NumSelIdents && NumSelIdents == Sel.getNumArgs())
5577 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005578
Douglas Gregor67c692c2010-08-26 15:07:07 +00005579 for (unsigned I = 0; I != NumSelIdents; ++I)
5580 if (SelIdents[I] != Sel.getIdentifierInfoForSlot(I))
5581 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005582
Douglas Gregor67c692c2010-08-26 15:07:07 +00005583 return true;
5584}
5585
Douglas Gregorc8537c52009-11-19 07:41:15 +00005586static bool isAcceptableObjCMethod(ObjCMethodDecl *Method,
5587 ObjCMethodKind WantKind,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005588 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005589 bool AllowSameLength = true) {
Douglas Gregor67c692c2010-08-26 15:07:07 +00005590 return isAcceptableObjCSelector(Method->getSelector(), WantKind, SelIdents,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005591 AllowSameLength);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005592}
Douglas Gregor1154e272010-09-16 16:06:31 +00005593
5594namespace {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005595 /// A set of selectors, which is used to avoid introducing multiple
Douglas Gregor1154e272010-09-16 16:06:31 +00005596 /// completions with the same selector into the result set.
5597 typedef llvm::SmallPtrSet<Selector, 16> VisitedSelectorSet;
5598}
5599
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005600/// Add all of the Objective-C methods in the given Objective-C
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005601/// container to the set of results.
5602///
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005603/// The container will be a class, protocol, category, or implementation of
5604/// any of the above. This mether will recurse to include methods from
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005605/// the superclasses of classes along with their categories, protocols, and
5606/// implementations.
5607///
5608/// \param Container the container in which we'll look to find methods.
5609///
James Dennett596e4752012-06-14 03:11:41 +00005610/// \param WantInstanceMethods Whether to add instance methods (only); if
5611/// false, this routine will add factory methods (only).
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005612///
5613/// \param CurContext the context in which we're performing the lookup that
5614/// finds methods.
5615///
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005616/// \param AllowSameLength Whether we allow a method to be added to the list
5617/// when it has the same number of parameters as we have selector identifiers.
5618///
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005619/// \param Results the structure into which we'll add results.
Alex Lorenz638dbc32017-01-24 14:15:08 +00005620static void AddObjCMethods(ObjCContainerDecl *Container,
5621 bool WantInstanceMethods, ObjCMethodKind WantKind,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005622 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005623 DeclContext *CurContext,
Alex Lorenz638dbc32017-01-24 14:15:08 +00005624 VisitedSelectorSet &Selectors, bool AllowSameLength,
5625 ResultBuilder &Results, bool InOriginalClass = true,
5626 bool IsRootClass = false) {
John McCall276321a2010-08-25 06:19:51 +00005627 typedef CodeCompletionResult Result;
Douglas Gregor9b4f3702012-06-12 13:44:08 +00005628 Container = getContainerDef(Container);
Douglas Gregor41778c32013-01-30 06:58:39 +00005629 ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container);
Alex Lorenz638dbc32017-01-24 14:15:08 +00005630 IsRootClass = IsRootClass || (IFace && !IFace->getSuperClass());
Aaron Ballmanaff18c02014-03-13 19:03:34 +00005631 for (auto *M : Container->methods()) {
Douglas Gregor41778c32013-01-30 06:58:39 +00005632 // The instance methods on the root class can be messaged via the
5633 // metaclass.
5634 if (M->isInstanceMethod() == WantInstanceMethods ||
Alex Lorenz638dbc32017-01-24 14:15:08 +00005635 (IsRootClass && !WantInstanceMethods)) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005636 // Check whether the selector identifiers we've been given are a
Douglas Gregor1b605f72009-11-19 01:08:35 +00005637 // subset of the identifiers for this particular method.
Aaron Ballmanaff18c02014-03-13 19:03:34 +00005638 if (!isAcceptableObjCMethod(M, WantKind, SelIdents, AllowSameLength))
Douglas Gregor1b605f72009-11-19 01:08:35 +00005639 continue;
Douglas Gregorc8537c52009-11-19 07:41:15 +00005640
David Blaikie82e95a32014-11-19 07:49:47 +00005641 if (!Selectors.insert(M->getSelector()).second)
Douglas Gregor1154e272010-09-16 16:06:31 +00005642 continue;
Craig Topperc3ec1492014-05-26 06:22:03 +00005643
5644 Result R = Result(M, Results.getBasePriority(M), nullptr);
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005645 R.StartParameter = SelIdents.size();
Douglas Gregorc8537c52009-11-19 07:41:15 +00005646 R.AllParametersAreInformative = (WantKind != MK_Any);
Douglas Gregor416b5752010-08-25 01:08:01 +00005647 if (!InOriginalClass)
5648 R.Priority += CCD_InBaseClass;
Douglas Gregor1b605f72009-11-19 01:08:35 +00005649 Results.MaybeAddResult(R, CurContext);
5650 }
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005651 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005652
Douglas Gregorf37c9492010-09-16 15:34:59 +00005653 // Visit the protocols of protocols.
5654 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Douglas Gregore6e48b12012-01-01 19:29:29 +00005655 if (Protocol->hasDefinition()) {
5656 const ObjCList<ObjCProtocolDecl> &Protocols
5657 = Protocol->getReferencedProtocols();
5658 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005659 E = Protocols.end();
Douglas Gregore6e48b12012-01-01 19:29:29 +00005660 I != E; ++I)
Alex Lorenz638dbc32017-01-24 14:15:08 +00005661 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, CurContext,
5662 Selectors, AllowSameLength, Results, false, IsRootClass);
Douglas Gregore6e48b12012-01-01 19:29:29 +00005663 }
Douglas Gregorf37c9492010-09-16 15:34:59 +00005664 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005665
Douglas Gregorc0ac7d62011-12-15 05:27:12 +00005666 if (!IFace || !IFace->hasDefinition())
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005667 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005668
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005669 // Add methods in protocols.
Aaron Ballmana49c5062014-03-13 20:29:09 +00005670 for (auto *I : IFace->protocols())
Alex Lorenz638dbc32017-01-24 14:15:08 +00005671 AddObjCMethods(I, WantInstanceMethods, WantKind, SelIdents, CurContext,
5672 Selectors, AllowSameLength, Results, false, IsRootClass);
5673
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005674 // Add methods in categories.
Aaron Ballman15063e12014-03-13 21:35:02 +00005675 for (auto *CatDecl : IFace->known_categories()) {
Douglas Gregor048fbfa2013-01-16 23:00:23 +00005676 AddObjCMethods(CatDecl, WantInstanceMethods, WantKind, SelIdents,
Alex Lorenz638dbc32017-01-24 14:15:08 +00005677 CurContext, Selectors, AllowSameLength, Results,
5678 InOriginalClass, IsRootClass);
5679
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005680 // Add a categories protocol methods.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005681 const ObjCList<ObjCProtocolDecl> &Protocols
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005682 = CatDecl->getReferencedProtocols();
5683 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
5684 E = Protocols.end();
5685 I != E; ++I)
Alex Lorenz638dbc32017-01-24 14:15:08 +00005686 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, CurContext,
5687 Selectors, AllowSameLength, Results, false, IsRootClass);
5688
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005689 // Add methods in category implementations.
5690 if (ObjCCategoryImplDecl *Impl = CatDecl->getImplementation())
Alex Lorenz638dbc32017-01-24 14:15:08 +00005691 AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents, CurContext,
5692 Selectors, AllowSameLength, Results, InOriginalClass,
5693 IsRootClass);
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005694 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005695
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005696 // Add methods in superclass.
Alex Lorenz638dbc32017-01-24 14:15:08 +00005697 // Avoid passing in IsRootClass since root classes won't have super classes.
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005698 if (IFace->getSuperClass())
Alex Lorenz638dbc32017-01-24 14:15:08 +00005699 AddObjCMethods(IFace->getSuperClass(), WantInstanceMethods, WantKind,
5700 SelIdents, CurContext, Selectors, AllowSameLength, Results,
5701 /*IsRootClass=*/false);
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005702
5703 // Add methods in our implementation, if any.
5704 if (ObjCImplementationDecl *Impl = IFace->getImplementation())
Alex Lorenz638dbc32017-01-24 14:15:08 +00005705 AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents, CurContext,
5706 Selectors, AllowSameLength, Results, InOriginalClass,
5707 IsRootClass);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005708}
5709
5710
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005711void Sema::CodeCompleteObjCPropertyGetter(Scope *S) {
Douglas Gregorc8537c52009-11-19 07:41:15 +00005712 // Try to find the interface where getters might live.
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005713 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005714 if (!Class) {
5715 if (ObjCCategoryDecl *Category
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005716 = dyn_cast_or_null<ObjCCategoryDecl>(CurContext))
Douglas Gregorc8537c52009-11-19 07:41:15 +00005717 Class = Category->getClassInterface();
5718
5719 if (!Class)
5720 return;
5721 }
5722
5723 // Find all of the potential getters.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005724 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005725 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005726 CodeCompletionContext::CCC_Other);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005727 Results.EnterNewScope();
5728
Douglas Gregor1154e272010-09-16 16:06:31 +00005729 VisitedSelectorSet Selectors;
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005730 AddObjCMethods(Class, true, MK_ZeroArgSelector, None, CurContext, Selectors,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005731 /*AllowSameLength=*/true, Results);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005732 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005733 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5734 Results.data(), Results.size());
Douglas Gregorc8537c52009-11-19 07:41:15 +00005735}
5736
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005737void Sema::CodeCompleteObjCPropertySetter(Scope *S) {
Douglas Gregorc8537c52009-11-19 07:41:15 +00005738 // Try to find the interface where setters might live.
5739 ObjCInterfaceDecl *Class
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005740 = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005741 if (!Class) {
5742 if (ObjCCategoryDecl *Category
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005743 = dyn_cast_or_null<ObjCCategoryDecl>(CurContext))
Douglas Gregorc8537c52009-11-19 07:41:15 +00005744 Class = Category->getClassInterface();
5745
5746 if (!Class)
5747 return;
5748 }
5749
5750 // Find all of the potential getters.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005751 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005752 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005753 CodeCompletionContext::CCC_Other);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005754 Results.EnterNewScope();
5755
Douglas Gregor1154e272010-09-16 16:06:31 +00005756 VisitedSelectorSet Selectors;
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005757 AddObjCMethods(Class, true, MK_OneArgSelector, None, CurContext,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005758 Selectors, /*AllowSameLength=*/true, Results);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005759
5760 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005761 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5762 Results.data(), Results.size());
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005763}
5764
Douglas Gregorf34a6f02011-02-15 22:19:42 +00005765void Sema::CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS,
5766 bool IsParameter) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005767 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005768 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005769 CodeCompletionContext::CCC_Type);
Douglas Gregor99fa2642010-08-24 01:06:58 +00005770 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005771
Douglas Gregor99fa2642010-08-24 01:06:58 +00005772 // Add context-sensitive, Objective-C parameter-passing keywords.
5773 bool AddedInOut = false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005774 if ((DS.getObjCDeclQualifier() &
Douglas Gregor99fa2642010-08-24 01:06:58 +00005775 (ObjCDeclSpec::DQ_In | ObjCDeclSpec::DQ_Inout)) == 0) {
5776 Results.AddResult("in");
5777 Results.AddResult("inout");
5778 AddedInOut = true;
5779 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005780 if ((DS.getObjCDeclQualifier() &
Douglas Gregor99fa2642010-08-24 01:06:58 +00005781 (ObjCDeclSpec::DQ_Out | ObjCDeclSpec::DQ_Inout)) == 0) {
5782 Results.AddResult("out");
5783 if (!AddedInOut)
5784 Results.AddResult("inout");
5785 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005786 if ((DS.getObjCDeclQualifier() &
Douglas Gregor99fa2642010-08-24 01:06:58 +00005787 (ObjCDeclSpec::DQ_Bycopy | ObjCDeclSpec::DQ_Byref |
5788 ObjCDeclSpec::DQ_Oneway)) == 0) {
5789 Results.AddResult("bycopy");
5790 Results.AddResult("byref");
5791 Results.AddResult("oneway");
5792 }
Douglas Gregor86b42682015-06-19 18:27:52 +00005793 if ((DS.getObjCDeclQualifier() & ObjCDeclSpec::DQ_CSNullability) == 0) {
5794 Results.AddResult("nonnull");
5795 Results.AddResult("nullable");
5796 Results.AddResult("null_unspecified");
5797 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005798
5799 // If we're completing the return type of an Objective-C method and the
Douglas Gregorf34a6f02011-02-15 22:19:42 +00005800 // identifier IBAction refers to a macro, provide a completion item for
5801 // an action, e.g.,
5802 // IBAction)<#selector#>:(id)sender
5803 if (DS.getObjCDeclQualifier() == 0 && !IsParameter &&
Richard Smith20e883e2015-04-29 23:20:19 +00005804 PP.isMacroDefined("IBAction")) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005805 CodeCompletionBuilder Builder(Results.getAllocator(),
5806 Results.getCodeCompletionTUInfo(),
5807 CCP_CodePattern, CXAvailability_Available);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00005808 Builder.AddTypedTextChunk("IBAction");
Benjamin Kramerdb534a42012-03-26 16:57:36 +00005809 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00005810 Builder.AddPlaceholderChunk("selector");
Benjamin Kramerdb534a42012-03-26 16:57:36 +00005811 Builder.AddChunk(CodeCompletionString::CK_Colon);
5812 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00005813 Builder.AddTextChunk("id");
Benjamin Kramerdb534a42012-03-26 16:57:36 +00005814 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00005815 Builder.AddTextChunk("sender");
5816 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
5817 }
Douglas Gregored1f5972013-01-30 07:11:43 +00005818
5819 // If we're completing the return type, provide 'instancetype'.
5820 if (!IsParameter) {
5821 Results.AddResult(CodeCompletionResult("instancetype"));
5822 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005823
Douglas Gregor99fa2642010-08-24 01:06:58 +00005824 // Add various builtin type names and specifiers.
5825 AddOrdinaryNameResults(PCC_Type, S, *this, Results);
5826 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005827
Douglas Gregor99fa2642010-08-24 01:06:58 +00005828 // Add the various type names
5829 Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
5830 CodeCompletionDeclConsumer Consumer(Results, CurContext);
5831 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00005832 CodeCompleter->includeGlobals(),
5833 CodeCompleter->loadExternal());
5834
Douglas Gregor99fa2642010-08-24 01:06:58 +00005835 if (CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00005836 AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false);
Douglas Gregor99fa2642010-08-24 01:06:58 +00005837
Eric Liuf5ba09f2018-07-04 10:01:18 +00005838 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor99fa2642010-08-24 01:06:58 +00005839 Results.data(), Results.size());
5840}
5841
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00005842/// When we have an expression with type "id", we may assume
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005843/// that it has some more-specific class type based on knowledge of
5844/// common uses of Objective-C. This routine returns that class type,
5845/// or NULL if no better result could be determined.
5846static ObjCInterfaceDecl *GetAssumedMessageSendExprType(Expr *E) {
Douglas Gregored0b69d2010-09-15 16:23:04 +00005847 ObjCMessageExpr *Msg = dyn_cast_or_null<ObjCMessageExpr>(E);
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005848 if (!Msg)
Craig Topperc3ec1492014-05-26 06:22:03 +00005849 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005850
5851 Selector Sel = Msg->getSelector();
5852 if (Sel.isNull())
Craig Topperc3ec1492014-05-26 06:22:03 +00005853 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005854
5855 IdentifierInfo *Id = Sel.getIdentifierInfoForSlot(0);
5856 if (!Id)
Craig Topperc3ec1492014-05-26 06:22:03 +00005857 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005858
5859 ObjCMethodDecl *Method = Msg->getMethodDecl();
5860 if (!Method)
Craig Topperc3ec1492014-05-26 06:22:03 +00005861 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005862
5863 // Determine the class that we're sending the message to.
Craig Topperc3ec1492014-05-26 06:22:03 +00005864 ObjCInterfaceDecl *IFace = nullptr;
Douglas Gregor9a129192010-04-21 00:45:42 +00005865 switch (Msg->getReceiverKind()) {
5866 case ObjCMessageExpr::Class:
John McCall8b07ec22010-05-15 11:32:37 +00005867 if (const ObjCObjectType *ObjType
5868 = Msg->getClassReceiver()->getAs<ObjCObjectType>())
5869 IFace = ObjType->getInterface();
Douglas Gregor9a129192010-04-21 00:45:42 +00005870 break;
5871
5872 case ObjCMessageExpr::Instance: {
5873 QualType T = Msg->getInstanceReceiver()->getType();
5874 if (const ObjCObjectPointerType *Ptr = T->getAs<ObjCObjectPointerType>())
5875 IFace = Ptr->getInterfaceDecl();
5876 break;
5877 }
5878
5879 case ObjCMessageExpr::SuperInstance:
5880 case ObjCMessageExpr::SuperClass:
5881 break;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005882 }
5883
5884 if (!IFace)
Craig Topperc3ec1492014-05-26 06:22:03 +00005885 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005886
5887 ObjCInterfaceDecl *Super = IFace->getSuperClass();
5888 if (Method->isInstanceMethod())
5889 return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
5890 .Case("retain", IFace)
John McCall31168b02011-06-15 23:02:42 +00005891 .Case("strong", IFace)
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005892 .Case("autorelease", IFace)
5893 .Case("copy", IFace)
5894 .Case("copyWithZone", IFace)
5895 .Case("mutableCopy", IFace)
5896 .Case("mutableCopyWithZone", IFace)
5897 .Case("awakeFromCoder", IFace)
5898 .Case("replacementObjectFromCoder", IFace)
5899 .Case("class", IFace)
5900 .Case("classForCoder", IFace)
5901 .Case("superclass", Super)
Craig Topperc3ec1492014-05-26 06:22:03 +00005902 .Default(nullptr);
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005903
5904 return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
5905 .Case("new", IFace)
5906 .Case("alloc", IFace)
5907 .Case("allocWithZone", IFace)
5908 .Case("class", IFace)
5909 .Case("superclass", Super)
Craig Topperc3ec1492014-05-26 06:22:03 +00005910 .Default(nullptr);
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005911}
5912
Douglas Gregor6fc04132010-08-27 15:10:57 +00005913// Add a special completion for a message send to "super", which fills in the
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005914// most likely case of forwarding all of our arguments to the superclass
Douglas Gregor6fc04132010-08-27 15:10:57 +00005915// function.
5916///
5917/// \param S The semantic analysis object.
5918///
Dmitri Gribenkoadba9be2012-08-23 17:58:28 +00005919/// \param NeedSuperKeyword Whether we need to prefix this completion with
Douglas Gregor6fc04132010-08-27 15:10:57 +00005920/// the "super" keyword. Otherwise, we just need to provide the arguments.
5921///
5922/// \param SelIdents The identifiers in the selector that have already been
5923/// provided as arguments for a send to "super".
5924///
Douglas Gregor6fc04132010-08-27 15:10:57 +00005925/// \param Results The set of results to augment.
5926///
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005927/// \returns the Objective-C method declaration that would be invoked by
Douglas Gregor6fc04132010-08-27 15:10:57 +00005928/// this "super" completion. If NULL, no completion was added.
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005929static ObjCMethodDecl *AddSuperSendCompletion(
5930 Sema &S, bool NeedSuperKeyword,
5931 ArrayRef<IdentifierInfo *> SelIdents,
5932 ResultBuilder &Results) {
Douglas Gregor6fc04132010-08-27 15:10:57 +00005933 ObjCMethodDecl *CurMethod = S.getCurMethodDecl();
5934 if (!CurMethod)
Craig Topperc3ec1492014-05-26 06:22:03 +00005935 return nullptr;
5936
Douglas Gregor6fc04132010-08-27 15:10:57 +00005937 ObjCInterfaceDecl *Class = CurMethod->getClassInterface();
5938 if (!Class)
Craig Topperc3ec1492014-05-26 06:22:03 +00005939 return nullptr;
5940
Douglas Gregor6fc04132010-08-27 15:10:57 +00005941 // Try to find a superclass method with the same selector.
Craig Topperc3ec1492014-05-26 06:22:03 +00005942 ObjCMethodDecl *SuperMethod = nullptr;
Douglas Gregorb5f1e462011-02-16 00:51:18 +00005943 while ((Class = Class->getSuperClass()) && !SuperMethod) {
5944 // Check in the class
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005945 SuperMethod = Class->getMethod(CurMethod->getSelector(),
Douglas Gregor6fc04132010-08-27 15:10:57 +00005946 CurMethod->isInstanceMethod());
5947
Douglas Gregorb5f1e462011-02-16 00:51:18 +00005948 // Check in categories or class extensions.
5949 if (!SuperMethod) {
Aaron Ballman15063e12014-03-13 21:35:02 +00005950 for (const auto *Cat : Class->known_categories()) {
Douglas Gregor048fbfa2013-01-16 23:00:23 +00005951 if ((SuperMethod = Cat->getMethod(CurMethod->getSelector(),
Douglas Gregorb5f1e462011-02-16 00:51:18 +00005952 CurMethod->isInstanceMethod())))
5953 break;
Douglas Gregor048fbfa2013-01-16 23:00:23 +00005954 }
Douglas Gregorb5f1e462011-02-16 00:51:18 +00005955 }
5956 }
5957
Douglas Gregor6fc04132010-08-27 15:10:57 +00005958 if (!SuperMethod)
Craig Topperc3ec1492014-05-26 06:22:03 +00005959 return nullptr;
5960
Douglas Gregor6fc04132010-08-27 15:10:57 +00005961 // Check whether the superclass method has the same signature.
5962 if (CurMethod->param_size() != SuperMethod->param_size() ||
5963 CurMethod->isVariadic() != SuperMethod->isVariadic())
Craig Topperc3ec1492014-05-26 06:22:03 +00005964 return nullptr;
5965
Douglas Gregor6fc04132010-08-27 15:10:57 +00005966 for (ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin(),
5967 CurPEnd = CurMethod->param_end(),
5968 SuperP = SuperMethod->param_begin();
5969 CurP != CurPEnd; ++CurP, ++SuperP) {
5970 // Make sure the parameter types are compatible.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005971 if (!S.Context.hasSameUnqualifiedType((*CurP)->getType(),
Douglas Gregor6fc04132010-08-27 15:10:57 +00005972 (*SuperP)->getType()))
Craig Topperc3ec1492014-05-26 06:22:03 +00005973 return nullptr;
5974
Douglas Gregor6fc04132010-08-27 15:10:57 +00005975 // Make sure we have a parameter name to forward!
5976 if (!(*CurP)->getIdentifier())
Craig Topperc3ec1492014-05-26 06:22:03 +00005977 return nullptr;
Douglas Gregor6fc04132010-08-27 15:10:57 +00005978 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005979
Douglas Gregor6fc04132010-08-27 15:10:57 +00005980 // We have a superclass method. Now, form the send-to-super completion.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005981 CodeCompletionBuilder Builder(Results.getAllocator(),
5982 Results.getCodeCompletionTUInfo());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005983
Douglas Gregor6fc04132010-08-27 15:10:57 +00005984 // Give this completion a return type.
Douglas Gregorc3425b12015-07-07 06:20:19 +00005985 AddResultTypeChunk(S.Context, getCompletionPrintingPolicy(S), SuperMethod,
5986 Results.getCompletionContext().getBaseType(),
Douglas Gregor75acd922011-09-27 23:30:47 +00005987 Builder);
Douglas Gregor6fc04132010-08-27 15:10:57 +00005988
5989 // If we need the "super" keyword, add it (plus some spacing).
5990 if (NeedSuperKeyword) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005991 Builder.AddTypedTextChunk("super");
5992 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregor6fc04132010-08-27 15:10:57 +00005993 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005994
Douglas Gregor6fc04132010-08-27 15:10:57 +00005995 Selector Sel = CurMethod->getSelector();
5996 if (Sel.isUnarySelector()) {
5997 if (NeedSuperKeyword)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005998 Builder.AddTextChunk(Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00005999 Sel.getNameForSlot(0)));
Douglas Gregor6fc04132010-08-27 15:10:57 +00006000 else
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00006001 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00006002 Sel.getNameForSlot(0)));
Douglas Gregor6fc04132010-08-27 15:10:57 +00006003 } else {
6004 ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin();
6005 for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I, ++CurP) {
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006006 if (I > SelIdents.size())
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006007 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006008
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006009 if (I < SelIdents.size())
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006010 Builder.AddInformativeChunk(
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00006011 Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00006012 Sel.getNameForSlot(I) + ":"));
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006013 else if (NeedSuperKeyword || I > SelIdents.size()) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006014 Builder.AddTextChunk(
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00006015 Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00006016 Sel.getNameForSlot(I) + ":"));
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00006017 Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006018 (*CurP)->getIdentifier()->getName()));
Douglas Gregor6fc04132010-08-27 15:10:57 +00006019 } else {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006020 Builder.AddTypedTextChunk(
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00006021 Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00006022 Sel.getNameForSlot(I) + ":"));
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00006023 Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006024 (*CurP)->getIdentifier()->getName()));
Douglas Gregor6fc04132010-08-27 15:10:57 +00006025 }
6026 }
6027 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006028
Douglas Gregor78254c82012-03-27 23:34:16 +00006029 Results.AddResult(CodeCompletionResult(Builder.TakeString(), SuperMethod,
6030 CCP_SuperCompletion));
Douglas Gregor6fc04132010-08-27 15:10:57 +00006031 return SuperMethod;
6032}
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006033
Douglas Gregora817a192010-05-27 23:06:34 +00006034void Sema::CodeCompleteObjCMessageReceiver(Scope *S) {
John McCall276321a2010-08-25 06:19:51 +00006035 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006036 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006037 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006038 CodeCompletionContext::CCC_ObjCMessageReceiver,
Richard Smith2bf7fdb2013-01-02 11:42:31 +00006039 getLangOpts().CPlusPlus11
Douglas Gregord8c61782012-02-15 15:34:24 +00006040 ? &ResultBuilder::IsObjCMessageReceiverOrLambdaCapture
6041 : &ResultBuilder::IsObjCMessageReceiver);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006042
Douglas Gregora817a192010-05-27 23:06:34 +00006043 CodeCompletionDeclConsumer Consumer(Results, CurContext);
6044 Results.EnterNewScope();
Douglas Gregor39982192010-08-15 06:18:01 +00006045 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00006046 CodeCompleter->includeGlobals(),
6047 CodeCompleter->loadExternal());
6048
Douglas Gregora817a192010-05-27 23:06:34 +00006049 // If we are in an Objective-C method inside a class that has a superclass,
6050 // add "super" as an option.
6051 if (ObjCMethodDecl *Method = getCurMethodDecl())
6052 if (ObjCInterfaceDecl *Iface = Method->getClassInterface())
Douglas Gregor6fc04132010-08-27 15:10:57 +00006053 if (Iface->getSuperClass()) {
Douglas Gregora817a192010-05-27 23:06:34 +00006054 Results.AddResult(Result("super"));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006055
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006056 AddSuperSendCompletion(*this, /*NeedSuperKeyword=*/true, None, Results);
Douglas Gregor6fc04132010-08-27 15:10:57 +00006057 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006058
Richard Smith2bf7fdb2013-01-02 11:42:31 +00006059 if (getLangOpts().CPlusPlus11)
Douglas Gregord8c61782012-02-15 15:34:24 +00006060 addThisCompletion(*this, Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006061
Douglas Gregora817a192010-05-27 23:06:34 +00006062 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006063
Douglas Gregora817a192010-05-27 23:06:34 +00006064 if (CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00006065 AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false);
Douglas Gregor50832e02010-09-20 22:39:41 +00006066 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006067 Results.data(), Results.size());
Douglas Gregora817a192010-05-27 23:06:34 +00006068}
6069
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006070void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006071 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006072 bool AtArgumentExpression) {
Craig Topperc3ec1492014-05-26 06:22:03 +00006073 ObjCInterfaceDecl *CDecl = nullptr;
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006074 if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
6075 // Figure out which interface we're in.
6076 CDecl = CurMethod->getClassInterface();
6077 if (!CDecl)
6078 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006079
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006080 // Find the superclass of this class.
6081 CDecl = CDecl->getSuperClass();
6082 if (!CDecl)
6083 return;
6084
6085 if (CurMethod->isInstanceMethod()) {
6086 // We are inside an instance method, which means that the message
6087 // send [super ...] is actually calling an instance method on the
Douglas Gregor392a84b2010-10-13 21:24:53 +00006088 // current object.
Craig Topperc3ec1492014-05-26 06:22:03 +00006089 return CodeCompleteObjCInstanceMessage(S, nullptr, SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006090 AtArgumentExpression,
Douglas Gregor392a84b2010-10-13 21:24:53 +00006091 CDecl);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006092 }
6093
6094 // Fall through to send to the superclass in CDecl.
6095 } else {
6096 // "super" may be the name of a type or variable. Figure out which
6097 // it is.
Argyrios Kyrtzidis3e56dd42013-03-14 22:56:43 +00006098 IdentifierInfo *Super = getSuperIdentifier();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006099 NamedDecl *ND = LookupSingleName(S, Super, SuperLoc,
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006100 LookupOrdinaryName);
6101 if ((CDecl = dyn_cast_or_null<ObjCInterfaceDecl>(ND))) {
6102 // "super" names an interface. Use it.
6103 } else if (TypeDecl *TD = dyn_cast_or_null<TypeDecl>(ND)) {
John McCall8b07ec22010-05-15 11:32:37 +00006104 if (const ObjCObjectType *Iface
6105 = Context.getTypeDeclType(TD)->getAs<ObjCObjectType>())
6106 CDecl = Iface->getInterface();
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006107 } else if (ND && isa<UnresolvedUsingTypenameDecl>(ND)) {
6108 // "super" names an unresolved type; we can't be more specific.
6109 } else {
6110 // Assume that "super" names some kind of value and parse that way.
6111 CXXScopeSpec SS;
Abramo Bagnara7945c982012-01-27 09:46:47 +00006112 SourceLocation TemplateKWLoc;
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006113 UnqualifiedId id;
6114 id.setIdentifier(Super, SuperLoc);
Abramo Bagnara7945c982012-01-27 09:46:47 +00006115 ExprResult SuperExpr = ActOnIdExpression(S, SS, TemplateKWLoc, id,
6116 false, false);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006117 return CodeCompleteObjCInstanceMessage(S, (Expr *)SuperExpr.get(),
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006118 SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006119 AtArgumentExpression);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006120 }
6121
6122 // Fall through
6123 }
6124
John McCallba7bf592010-08-24 05:47:05 +00006125 ParsedType Receiver;
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006126 if (CDecl)
John McCallba7bf592010-08-24 05:47:05 +00006127 Receiver = ParsedType::make(Context.getObjCInterfaceType(CDecl));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006128 return CodeCompleteObjCClassMessage(S, Receiver, SelIdents,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006129 AtArgumentExpression,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006130 /*IsSuper=*/true);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006131}
6132
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006133/// Given a set of code-completion results for the argument of a message
Douglas Gregor74661272010-09-21 00:03:25 +00006134/// send, determine the preferred type (if any) for that argument expression.
6135static QualType getPreferredArgumentTypeForMessageSend(ResultBuilder &Results,
6136 unsigned NumSelIdents) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006137 typedef CodeCompletionResult Result;
Douglas Gregor74661272010-09-21 00:03:25 +00006138 ASTContext &Context = Results.getSema().Context;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006139
Douglas Gregor74661272010-09-21 00:03:25 +00006140 QualType PreferredType;
6141 unsigned BestPriority = CCP_Unlikely * 2;
6142 Result *ResultsData = Results.data();
6143 for (unsigned I = 0, N = Results.size(); I != N; ++I) {
6144 Result &R = ResultsData[I];
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006145 if (R.Kind == Result::RK_Declaration &&
Douglas Gregor74661272010-09-21 00:03:25 +00006146 isa<ObjCMethodDecl>(R.Declaration)) {
6147 if (R.Priority <= BestPriority) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00006148 const ObjCMethodDecl *Method = cast<ObjCMethodDecl>(R.Declaration);
Douglas Gregor74661272010-09-21 00:03:25 +00006149 if (NumSelIdents <= Method->param_size()) {
Alp Toker03376dc2014-07-07 09:02:20 +00006150 QualType MyPreferredType = Method->parameters()[NumSelIdents - 1]
Douglas Gregor74661272010-09-21 00:03:25 +00006151 ->getType();
6152 if (R.Priority < BestPriority || PreferredType.isNull()) {
6153 BestPriority = R.Priority;
6154 PreferredType = MyPreferredType;
6155 } else if (!Context.hasSameUnqualifiedType(PreferredType,
6156 MyPreferredType)) {
6157 PreferredType = QualType();
6158 }
6159 }
6160 }
6161 }
6162 }
6163
6164 return PreferredType;
6165}
6166
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006167static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006168 ParsedType Receiver,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006169 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006170 bool AtArgumentExpression,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006171 bool IsSuper,
6172 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00006173 typedef CodeCompletionResult Result;
Craig Topperc3ec1492014-05-26 06:22:03 +00006174 ObjCInterfaceDecl *CDecl = nullptr;
6175
Douglas Gregor8ce33212009-11-17 17:59:40 +00006176 // If the given name refers to an interface type, retrieve the
6177 // corresponding declaration.
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006178 if (Receiver) {
Craig Topperc3ec1492014-05-26 06:22:03 +00006179 QualType T = SemaRef.GetTypeFromParser(Receiver, nullptr);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006180 if (!T.isNull())
John McCall8b07ec22010-05-15 11:32:37 +00006181 if (const ObjCObjectType *Interface = T->getAs<ObjCObjectType>())
6182 CDecl = Interface->getInterface();
Douglas Gregor8ce33212009-11-17 17:59:40 +00006183 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006184
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006185 // Add all of the factory methods in this Objective-C class, its protocols,
6186 // superclasses, categories, implementation, etc.
Steve Naroffeae65032009-11-07 02:08:14 +00006187 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006188
6189 // If this is a send-to-super, try to add the special "super" send
Douglas Gregor6fc04132010-08-27 15:10:57 +00006190 // completion.
6191 if (IsSuper) {
6192 if (ObjCMethodDecl *SuperMethod
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006193 = AddSuperSendCompletion(SemaRef, false, SelIdents, Results))
Douglas Gregor6fc04132010-08-27 15:10:57 +00006194 Results.Ignore(SuperMethod);
6195 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006196
Douglas Gregorc2cb2e22010-08-27 15:29:55 +00006197 // If we're inside an Objective-C method definition, prefer its selector to
6198 // others.
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006199 if (ObjCMethodDecl *CurMethod = SemaRef.getCurMethodDecl())
Douglas Gregorc2cb2e22010-08-27 15:29:55 +00006200 Results.setPreferredSelector(CurMethod->getSelector());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006201
Douglas Gregor1154e272010-09-16 16:06:31 +00006202 VisitedSelectorSet Selectors;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006203 if (CDecl)
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006204 AddObjCMethods(CDecl, false, MK_Any, SelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00006205 SemaRef.CurContext, Selectors, AtArgumentExpression,
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006206 Results);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006207 else {
Douglas Gregor6285f752010-04-06 16:40:00 +00006208 // We're messaging "id" as a type; provide all class/factory methods.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006209
Douglas Gregord720daf2010-04-06 17:30:22 +00006210 // If we have an external source, load the entire class method
Sebastian Redld44cd6a2010-08-18 23:57:06 +00006211 // pool from the AST file.
Axel Naumanndd433f02012-10-18 19:05:02 +00006212 if (SemaRef.getExternalSource()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006213 for (uint32_t I = 0,
Axel Naumanndd433f02012-10-18 19:05:02 +00006214 N = SemaRef.getExternalSource()->GetNumExternalSelectors();
John McCall75b960e2010-06-01 09:23:16 +00006215 I != N; ++I) {
Axel Naumanndd433f02012-10-18 19:05:02 +00006216 Selector Sel = SemaRef.getExternalSource()->GetExternalSelector(I);
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006217 if (Sel.isNull() || SemaRef.MethodPool.count(Sel))
Douglas Gregord720daf2010-04-06 17:30:22 +00006218 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006219
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006220 SemaRef.ReadMethodPool(Sel);
Douglas Gregord720daf2010-04-06 17:30:22 +00006221 }
6222 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006223
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006224 for (Sema::GlobalMethodPool::iterator M = SemaRef.MethodPool.begin(),
6225 MEnd = SemaRef.MethodPool.end();
Sebastian Redl75d8a322010-08-02 23:18:59 +00006226 M != MEnd; ++M) {
6227 for (ObjCMethodList *MethList = &M->second.second;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006228 MethList && MethList->getMethod();
Argyrios Kyrtzidisd3da6e02013-04-17 00:08:58 +00006229 MethList = MethList->getNext()) {
Nico Weber2e0c8f72014-12-27 03:58:08 +00006230 if (!isAcceptableObjCMethod(MethList->getMethod(), MK_Any, SelIdents))
Douglas Gregor6285f752010-04-06 16:40:00 +00006231 continue;
Craig Topperc3ec1492014-05-26 06:22:03 +00006232
Nico Weber2e0c8f72014-12-27 03:58:08 +00006233 Result R(MethList->getMethod(),
6234 Results.getBasePriority(MethList->getMethod()), nullptr);
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006235 R.StartParameter = SelIdents.size();
Douglas Gregor6285f752010-04-06 16:40:00 +00006236 R.AllParametersAreInformative = false;
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006237 Results.MaybeAddResult(R, SemaRef.CurContext);
Douglas Gregor6285f752010-04-06 16:40:00 +00006238 }
6239 }
6240 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006241
6242 Results.ExitScope();
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006243}
Douglas Gregor6285f752010-04-06 16:40:00 +00006244
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006245void Sema::CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006246 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006247 bool AtArgumentExpression,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006248 bool IsSuper) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006249
Douglas Gregor63745d52011-07-21 01:05:26 +00006250 QualType T = this->GetTypeFromParser(Receiver);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006251
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006252 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006253 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor63745d52011-07-21 01:05:26 +00006254 CodeCompletionContext(CodeCompletionContext::CCC_ObjCClassMessage,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006255 T, SelIdents));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006256
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006257 AddClassMessageCompletions(*this, S, Receiver, SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006258 AtArgumentExpression, IsSuper, Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006259
6260 // If we're actually at the argument expression (rather than prior to the
Douglas Gregor74661272010-09-21 00:03:25 +00006261 // selector), we're actually performing code completion for an expression.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006262 // Determine whether we have a single, best method. If so, we can
Douglas Gregor74661272010-09-21 00:03:25 +00006263 // code-complete the expression using the corresponding parameter type as
6264 // our preferred type, improving completion results.
6265 if (AtArgumentExpression) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006266 QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006267 SelIdents.size());
Douglas Gregor74661272010-09-21 00:03:25 +00006268 if (PreferredType.isNull())
6269 CodeCompleteOrdinaryName(S, PCC_Expression);
6270 else
6271 CodeCompleteExpression(S, PreferredType);
6272 return;
6273 }
6274
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006275 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor63745d52011-07-21 01:05:26 +00006276 Results.getCompletionContext(),
Douglas Gregor6fc04132010-08-27 15:10:57 +00006277 Results.data(), Results.size());
Steve Naroffeae65032009-11-07 02:08:14 +00006278}
6279
Richard Trieu2bd04012011-09-09 02:00:50 +00006280void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006281 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006282 bool AtArgumentExpression,
Douglas Gregor392a84b2010-10-13 21:24:53 +00006283 ObjCInterfaceDecl *Super) {
John McCall276321a2010-08-25 06:19:51 +00006284 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006285
Steve Naroffeae65032009-11-07 02:08:14 +00006286 Expr *RecExpr = static_cast<Expr *>(Receiver);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006287
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006288 // If necessary, apply function/array conversion to the receiver.
6289 // C99 6.7.5.3p[7,8].
John Wiegley01296292011-04-08 18:41:53 +00006290 if (RecExpr) {
6291 ExprResult Conv = DefaultFunctionArrayLvalueConversion(RecExpr);
6292 if (Conv.isInvalid()) // conversion failed. bail.
6293 return;
Nikola Smiljanic01a75982014-05-29 10:55:11 +00006294 RecExpr = Conv.get();
John Wiegley01296292011-04-08 18:41:53 +00006295 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006296 QualType ReceiverType = RecExpr? RecExpr->getType()
Douglas Gregor392a84b2010-10-13 21:24:53 +00006297 : Super? Context.getObjCObjectPointerType(
6298 Context.getObjCInterfaceType(Super))
6299 : Context.getObjCIdType();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006300
Douglas Gregordc520b02010-11-08 21:12:30 +00006301 // If we're messaging an expression with type "id" or "Class", check
6302 // whether we know something special about the receiver that allows
6303 // us to assume a more-specific receiver type.
Anders Carlsson382ba412014-02-28 19:07:22 +00006304 if (ReceiverType->isObjCIdType() || ReceiverType->isObjCClassType()) {
Douglas Gregordc520b02010-11-08 21:12:30 +00006305 if (ObjCInterfaceDecl *IFace = GetAssumedMessageSendExprType(RecExpr)) {
6306 if (ReceiverType->isObjCClassType())
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006307 return CodeCompleteObjCClassMessage(S,
Douglas Gregordc520b02010-11-08 21:12:30 +00006308 ParsedType::make(Context.getObjCInterfaceType(IFace)),
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006309 SelIdents,
Douglas Gregordc520b02010-11-08 21:12:30 +00006310 AtArgumentExpression, Super);
6311
6312 ReceiverType = Context.getObjCObjectPointerType(
6313 Context.getObjCInterfaceType(IFace));
6314 }
Anders Carlsson382ba412014-02-28 19:07:22 +00006315 } else if (RecExpr && getLangOpts().CPlusPlus) {
6316 ExprResult Conv = PerformContextuallyConvertToObjCPointer(RecExpr);
6317 if (Conv.isUsable()) {
Nikola Smiljanic01a75982014-05-29 10:55:11 +00006318 RecExpr = Conv.get();
Anders Carlsson382ba412014-02-28 19:07:22 +00006319 ReceiverType = RecExpr->getType();
6320 }
6321 }
Douglas Gregordc520b02010-11-08 21:12:30 +00006322
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006323 // Build the set of methods we can see.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006324 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006325 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor63745d52011-07-21 01:05:26 +00006326 CodeCompletionContext(CodeCompletionContext::CCC_ObjCInstanceMessage,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006327 ReceiverType, SelIdents));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006328
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006329 Results.EnterNewScope();
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006330
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006331 // If this is a send-to-super, try to add the special "super" send
Douglas Gregor6fc04132010-08-27 15:10:57 +00006332 // completion.
Douglas Gregor392a84b2010-10-13 21:24:53 +00006333 if (Super) {
Douglas Gregor6fc04132010-08-27 15:10:57 +00006334 if (ObjCMethodDecl *SuperMethod
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006335 = AddSuperSendCompletion(*this, false, SelIdents, Results))
Douglas Gregor6fc04132010-08-27 15:10:57 +00006336 Results.Ignore(SuperMethod);
6337 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006338
Douglas Gregorc2cb2e22010-08-27 15:29:55 +00006339 // If we're inside an Objective-C method definition, prefer its selector to
6340 // others.
6341 if (ObjCMethodDecl *CurMethod = getCurMethodDecl())
6342 Results.setPreferredSelector(CurMethod->getSelector());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006343
Douglas Gregor1154e272010-09-16 16:06:31 +00006344 // Keep track of the selectors we've already added.
6345 VisitedSelectorSet Selectors;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006346
Douglas Gregora3329fa2009-11-18 00:06:18 +00006347 // Handle messages to Class. This really isn't a message to an instance
6348 // method, so we treat it the same way we would treat a message send to a
6349 // class method.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006350 if (ReceiverType->isObjCClassType() ||
Douglas Gregora3329fa2009-11-18 00:06:18 +00006351 ReceiverType->isObjCQualifiedClassType()) {
6352 if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
6353 if (ObjCInterfaceDecl *ClassDecl = CurMethod->getClassInterface())
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006354 AddObjCMethods(ClassDecl, false, MK_Any, SelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00006355 CurContext, Selectors, AtArgumentExpression, Results);
Douglas Gregora3329fa2009-11-18 00:06:18 +00006356 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006357 }
Douglas Gregora3329fa2009-11-18 00:06:18 +00006358 // Handle messages to a qualified ID ("id<foo>").
6359 else if (const ObjCObjectPointerType *QualID
6360 = ReceiverType->getAsObjCQualifiedIdType()) {
6361 // Search protocols for instance methods.
Aaron Ballman83731462014-03-17 16:14:00 +00006362 for (auto *I : QualID->quals())
6363 AddObjCMethods(I, true, MK_Any, SelIdents, CurContext,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00006364 Selectors, AtArgumentExpression, Results);
Douglas Gregora3329fa2009-11-18 00:06:18 +00006365 }
6366 // Handle messages to a pointer to interface type.
6367 else if (const ObjCObjectPointerType *IFacePtr
6368 = ReceiverType->getAsObjCInterfacePointerType()) {
6369 // Search the class, its superclasses, etc., for instance methods.
Douglas Gregorc8537c52009-11-19 07:41:15 +00006370 AddObjCMethods(IFacePtr->getInterfaceDecl(), true, MK_Any, SelIdents,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006371 CurContext, Selectors, AtArgumentExpression,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00006372 Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006373
Douglas Gregora3329fa2009-11-18 00:06:18 +00006374 // Search protocols for instance methods.
Aaron Ballman83731462014-03-17 16:14:00 +00006375 for (auto *I : IFacePtr->quals())
6376 AddObjCMethods(I, true, MK_Any, SelIdents, CurContext,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00006377 Selectors, AtArgumentExpression, Results);
Douglas Gregora3329fa2009-11-18 00:06:18 +00006378 }
Douglas Gregor6285f752010-04-06 16:40:00 +00006379 // Handle messages to "id".
6380 else if (ReceiverType->isObjCIdType()) {
Douglas Gregord720daf2010-04-06 17:30:22 +00006381 // We're messaging "id", so provide all instance methods we know
6382 // about as code-completion results.
6383
6384 // If we have an external source, load the entire class method
Sebastian Redld44cd6a2010-08-18 23:57:06 +00006385 // pool from the AST file.
Douglas Gregord720daf2010-04-06 17:30:22 +00006386 if (ExternalSource) {
John McCall75b960e2010-06-01 09:23:16 +00006387 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
6388 I != N; ++I) {
6389 Selector Sel = ExternalSource->GetExternalSelector(I);
Sebastian Redl75d8a322010-08-02 23:18:59 +00006390 if (Sel.isNull() || MethodPool.count(Sel))
Douglas Gregord720daf2010-04-06 17:30:22 +00006391 continue;
6392
Sebastian Redl75d8a322010-08-02 23:18:59 +00006393 ReadMethodPool(Sel);
Douglas Gregord720daf2010-04-06 17:30:22 +00006394 }
6395 }
6396
Sebastian Redl75d8a322010-08-02 23:18:59 +00006397 for (GlobalMethodPool::iterator M = MethodPool.begin(),
6398 MEnd = MethodPool.end();
6399 M != MEnd; ++M) {
6400 for (ObjCMethodList *MethList = &M->second.first;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006401 MethList && MethList->getMethod();
Argyrios Kyrtzidisd3da6e02013-04-17 00:08:58 +00006402 MethList = MethList->getNext()) {
Nico Weber2e0c8f72014-12-27 03:58:08 +00006403 if (!isAcceptableObjCMethod(MethList->getMethod(), MK_Any, SelIdents))
Douglas Gregor6285f752010-04-06 16:40:00 +00006404 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006405
Nico Weber2e0c8f72014-12-27 03:58:08 +00006406 if (!Selectors.insert(MethList->getMethod()->getSelector()).second)
Douglas Gregor1154e272010-09-16 16:06:31 +00006407 continue;
Craig Topperc3ec1492014-05-26 06:22:03 +00006408
Nico Weber2e0c8f72014-12-27 03:58:08 +00006409 Result R(MethList->getMethod(),
6410 Results.getBasePriority(MethList->getMethod()), nullptr);
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006411 R.StartParameter = SelIdents.size();
Douglas Gregor6285f752010-04-06 16:40:00 +00006412 R.AllParametersAreInformative = false;
6413 Results.MaybeAddResult(R, CurContext);
6414 }
6415 }
6416 }
Steve Naroffeae65032009-11-07 02:08:14 +00006417 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006418
6419
6420 // If we're actually at the argument expression (rather than prior to the
Douglas Gregor74661272010-09-21 00:03:25 +00006421 // selector), we're actually performing code completion for an expression.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006422 // Determine whether we have a single, best method. If so, we can
Douglas Gregor74661272010-09-21 00:03:25 +00006423 // code-complete the expression using the corresponding parameter type as
6424 // our preferred type, improving completion results.
6425 if (AtArgumentExpression) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006426 QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006427 SelIdents.size());
Douglas Gregor74661272010-09-21 00:03:25 +00006428 if (PreferredType.isNull())
6429 CodeCompleteOrdinaryName(S, PCC_Expression);
6430 else
6431 CodeCompleteExpression(S, PreferredType);
6432 return;
6433 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006434
6435 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor63745d52011-07-21 01:05:26 +00006436 Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006437 Results.data(),Results.size());
Steve Naroffeae65032009-11-07 02:08:14 +00006438}
Douglas Gregorbaf69612009-11-18 04:19:12 +00006439
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006440void Sema::CodeCompleteObjCForCollection(Scope *S,
Douglas Gregor68762e72010-08-23 21:17:50 +00006441 DeclGroupPtrTy IterationVar) {
6442 CodeCompleteExpressionData Data;
6443 Data.ObjCCollection = true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006444
Douglas Gregor68762e72010-08-23 21:17:50 +00006445 if (IterationVar.getAsOpaquePtr()) {
Serge Pavlov9ddb76e2013-08-27 13:15:56 +00006446 DeclGroupRef DG = IterationVar.get();
Douglas Gregor68762e72010-08-23 21:17:50 +00006447 for (DeclGroupRef::iterator I = DG.begin(), End = DG.end(); I != End; ++I) {
6448 if (*I)
6449 Data.IgnoreDecls.push_back(*I);
6450 }
6451 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006452
Douglas Gregor68762e72010-08-23 21:17:50 +00006453 CodeCompleteExpression(S, Data);
6454}
6455
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006456void Sema::CodeCompleteObjCSelector(Scope *S,
6457 ArrayRef<IdentifierInfo *> SelIdents) {
Douglas Gregor67c692c2010-08-26 15:07:07 +00006458 // If we have an external source, load the entire class method
6459 // pool from the AST file.
6460 if (ExternalSource) {
6461 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
6462 I != N; ++I) {
6463 Selector Sel = ExternalSource->GetExternalSelector(I);
6464 if (Sel.isNull() || MethodPool.count(Sel))
6465 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006466
Douglas Gregor67c692c2010-08-26 15:07:07 +00006467 ReadMethodPool(Sel);
6468 }
6469 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006470
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006471 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006472 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006473 CodeCompletionContext::CCC_SelectorName);
Douglas Gregor67c692c2010-08-26 15:07:07 +00006474 Results.EnterNewScope();
6475 for (GlobalMethodPool::iterator M = MethodPool.begin(),
6476 MEnd = MethodPool.end();
6477 M != MEnd; ++M) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006478
Douglas Gregor67c692c2010-08-26 15:07:07 +00006479 Selector Sel = M->first;
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006480 if (!isAcceptableObjCSelector(Sel, MK_Any, SelIdents))
Douglas Gregor67c692c2010-08-26 15:07:07 +00006481 continue;
6482
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006483 CodeCompletionBuilder Builder(Results.getAllocator(),
6484 Results.getCodeCompletionTUInfo());
Douglas Gregor67c692c2010-08-26 15:07:07 +00006485 if (Sel.isUnarySelector()) {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00006486 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00006487 Sel.getNameForSlot(0)));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006488 Results.AddResult(Builder.TakeString());
Douglas Gregor67c692c2010-08-26 15:07:07 +00006489 continue;
6490 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006491
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00006492 std::string Accumulator;
Douglas Gregor67c692c2010-08-26 15:07:07 +00006493 for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I) {
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006494 if (I == SelIdents.size()) {
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00006495 if (!Accumulator.empty()) {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00006496 Builder.AddInformativeChunk(Builder.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006497 Accumulator));
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00006498 Accumulator.clear();
6499 }
6500 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006501
Benjamin Kramer632500c2011-07-26 16:59:25 +00006502 Accumulator += Sel.getNameForSlot(I);
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00006503 Accumulator += ':';
Douglas Gregor67c692c2010-08-26 15:07:07 +00006504 }
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00006505 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString( Accumulator));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006506 Results.AddResult(Builder.TakeString());
Douglas Gregor67c692c2010-08-26 15:07:07 +00006507 }
6508 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00006509
6510 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor67c692c2010-08-26 15:07:07 +00006511 Results.data(), Results.size());
6512}
6513
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006514/// Add all of the protocol declarations that we find in the given
Douglas Gregorbaf69612009-11-18 04:19:12 +00006515/// (translation unit) context.
6516static void AddProtocolResults(DeclContext *Ctx, DeclContext *CurContext,
Douglas Gregor5b4671c2009-11-18 04:49:41 +00006517 bool OnlyForwardDeclarations,
Douglas Gregorbaf69612009-11-18 04:19:12 +00006518 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00006519 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006520
Aaron Ballman629afae2014-03-07 19:56:05 +00006521 for (const auto *D : Ctx->decls()) {
Douglas Gregorbaf69612009-11-18 04:19:12 +00006522 // Record any protocols we find.
Aaron Ballman629afae2014-03-07 19:56:05 +00006523 if (const auto *Proto = dyn_cast<ObjCProtocolDecl>(D))
Douglas Gregore6e48b12012-01-01 19:29:29 +00006524 if (!OnlyForwardDeclarations || !Proto->hasDefinition())
Craig Topperc3ec1492014-05-26 06:22:03 +00006525 Results.AddResult(Result(Proto, Results.getBasePriority(Proto),nullptr),
6526 CurContext, nullptr, false);
Douglas Gregorbaf69612009-11-18 04:19:12 +00006527 }
6528}
6529
Craig Topper883dd332015-12-24 23:58:11 +00006530void Sema::CodeCompleteObjCProtocolReferences(
6531 ArrayRef<IdentifierLocPair> Protocols) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006532 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006533 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006534 CodeCompletionContext::CCC_ObjCProtocolName);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006535
Chandler Carruthede11632016-11-04 06:06:50 +00006536 if (CodeCompleter->includeGlobals()) {
Douglas Gregora3b23b02010-12-09 21:44:02 +00006537 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006538
Douglas Gregora3b23b02010-12-09 21:44:02 +00006539 // Tell the result set to ignore all of the protocols we have
6540 // already seen.
6541 // FIXME: This doesn't work when caching code-completion results.
Craig Topper883dd332015-12-24 23:58:11 +00006542 for (const IdentifierLocPair &Pair : Protocols)
6543 if (ObjCProtocolDecl *Protocol = LookupProtocol(Pair.first,
6544 Pair.second))
Douglas Gregora3b23b02010-12-09 21:44:02 +00006545 Results.Ignore(Protocol);
Douglas Gregorbaf69612009-11-18 04:19:12 +00006546
Douglas Gregora3b23b02010-12-09 21:44:02 +00006547 // Add all protocols.
6548 AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, false,
6549 Results);
Douglas Gregor5b4671c2009-11-18 04:49:41 +00006550
Douglas Gregora3b23b02010-12-09 21:44:02 +00006551 Results.ExitScope();
6552 }
Eric Liuf5ba09f2018-07-04 10:01:18 +00006553
6554 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6555 Results.data(), Results.size());
Douglas Gregor5b4671c2009-11-18 04:49:41 +00006556}
6557
6558void Sema::CodeCompleteObjCProtocolDecl(Scope *) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006559 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006560 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006561 CodeCompletionContext::CCC_ObjCProtocolName);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006562
Chandler Carruthede11632016-11-04 06:06:50 +00006563 if (CodeCompleter->includeGlobals()) {
Douglas Gregora3b23b02010-12-09 21:44:02 +00006564 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006565
Douglas Gregora3b23b02010-12-09 21:44:02 +00006566 // Add all protocols.
6567 AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, true,
6568 Results);
Douglas Gregorbaf69612009-11-18 04:19:12 +00006569
Douglas Gregora3b23b02010-12-09 21:44:02 +00006570 Results.ExitScope();
6571 }
Eric Liuf5ba09f2018-07-04 10:01:18 +00006572
6573 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6574 Results.data(), Results.size());
Douglas Gregorbaf69612009-11-18 04:19:12 +00006575}
Douglas Gregor49c22a72009-11-18 16:26:39 +00006576
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006577/// Add all of the Objective-C interface declarations that we find in
Douglas Gregor49c22a72009-11-18 16:26:39 +00006578/// the given (translation unit) context.
6579static void AddInterfaceResults(DeclContext *Ctx, DeclContext *CurContext,
6580 bool OnlyForwardDeclarations,
6581 bool OnlyUnimplemented,
6582 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00006583 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006584
Aaron Ballman629afae2014-03-07 19:56:05 +00006585 for (const auto *D : Ctx->decls()) {
Douglas Gregor1c283312010-08-11 12:19:30 +00006586 // Record any interfaces we find.
Aaron Ballman629afae2014-03-07 19:56:05 +00006587 if (const auto *Class = dyn_cast<ObjCInterfaceDecl>(D))
Douglas Gregordc9166c2011-12-15 20:29:51 +00006588 if ((!OnlyForwardDeclarations || !Class->hasDefinition()) &&
Douglas Gregor1c283312010-08-11 12:19:30 +00006589 (!OnlyUnimplemented || !Class->getImplementation()))
Craig Topperc3ec1492014-05-26 06:22:03 +00006590 Results.AddResult(Result(Class, Results.getBasePriority(Class),nullptr),
6591 CurContext, nullptr, false);
Douglas Gregor49c22a72009-11-18 16:26:39 +00006592 }
6593}
6594
Eric Liuf5ba09f2018-07-04 10:01:18 +00006595void Sema::CodeCompleteObjCInterfaceDecl(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006596 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006597 CodeCompleter->getCodeCompletionTUInfo(),
Eric Liuf5ba09f2018-07-04 10:01:18 +00006598 CodeCompletionContext::CCC_ObjCInterfaceName);
Douglas Gregor49c22a72009-11-18 16:26:39 +00006599 Results.EnterNewScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00006600
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006601 if (CodeCompleter->includeGlobals()) {
6602 // Add all classes.
6603 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
6604 false, Results);
6605 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006606
Douglas Gregor49c22a72009-11-18 16:26:39 +00006607 Results.ExitScope();
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006608
Eric Liuf5ba09f2018-07-04 10:01:18 +00006609 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6610 Results.data(), Results.size());
Douglas Gregor49c22a72009-11-18 16:26:39 +00006611}
6612
Douglas Gregorb2ccf012010-04-15 22:33:43 +00006613void Sema::CodeCompleteObjCSuperclass(Scope *S, IdentifierInfo *ClassName,
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006614 SourceLocation ClassNameLoc) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006615 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006616 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006617 CodeCompletionContext::CCC_ObjCInterfaceName);
Douglas Gregor49c22a72009-11-18 16:26:39 +00006618 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006619
Douglas Gregor49c22a72009-11-18 16:26:39 +00006620 // Make sure that we ignore the class we're currently defining.
6621 NamedDecl *CurClass
Douglas Gregorb2ccf012010-04-15 22:33:43 +00006622 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006623 if (CurClass && isa<ObjCInterfaceDecl>(CurClass))
Douglas Gregor49c22a72009-11-18 16:26:39 +00006624 Results.Ignore(CurClass);
6625
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006626 if (CodeCompleter->includeGlobals()) {
6627 // Add all classes.
6628 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
6629 false, Results);
6630 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006631
Douglas Gregor49c22a72009-11-18 16:26:39 +00006632 Results.ExitScope();
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006633
Eric Liuf5ba09f2018-07-04 10:01:18 +00006634 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6635 Results.data(), Results.size());
Douglas Gregor49c22a72009-11-18 16:26:39 +00006636}
6637
Eric Liuf5ba09f2018-07-04 10:01:18 +00006638void Sema::CodeCompleteObjCImplementationDecl(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006639 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006640 CodeCompleter->getCodeCompletionTUInfo(),
Eric Liuf5ba09f2018-07-04 10:01:18 +00006641 CodeCompletionContext::CCC_ObjCImplementation);
Douglas Gregor49c22a72009-11-18 16:26:39 +00006642 Results.EnterNewScope();
6643
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006644 if (CodeCompleter->includeGlobals()) {
6645 // Add all unimplemented classes.
6646 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
6647 true, Results);
6648 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006649
Douglas Gregor49c22a72009-11-18 16:26:39 +00006650 Results.ExitScope();
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006651
Eric Liuf5ba09f2018-07-04 10:01:18 +00006652 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6653 Results.data(), Results.size());
Douglas Gregor49c22a72009-11-18 16:26:39 +00006654}
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006655
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006656void Sema::CodeCompleteObjCInterfaceCategory(Scope *S,
Douglas Gregorb2ccf012010-04-15 22:33:43 +00006657 IdentifierInfo *ClassName,
6658 SourceLocation ClassNameLoc) {
John McCall276321a2010-08-25 06:19:51 +00006659 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006660
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006661 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006662 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor21325842011-07-07 16:03:39 +00006663 CodeCompletionContext::CCC_ObjCCategoryName);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006664
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006665 // Ignore any categories we find that have already been implemented by this
6666 // interface.
6667 llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
6668 NamedDecl *CurClass
Douglas Gregorb2ccf012010-04-15 22:33:43 +00006669 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006670 if (ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass)){
Aaron Ballman3fe486a2014-03-13 21:23:55 +00006671 for (const auto *Cat : Class->visible_categories())
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006672 CategoryNames.insert(Cat->getIdentifier());
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006673 }
6674
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006675 // Add all of the categories we know about.
6676 Results.EnterNewScope();
6677 TranslationUnitDecl *TU = Context.getTranslationUnitDecl();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006678 for (const auto *D : TU->decls())
Aaron Ballman629afae2014-03-07 19:56:05 +00006679 if (const auto *Category = dyn_cast<ObjCCategoryDecl>(D))
David Blaikie82e95a32014-11-19 07:49:47 +00006680 if (CategoryNames.insert(Category->getIdentifier()).second)
Craig Topperc3ec1492014-05-26 06:22:03 +00006681 Results.AddResult(Result(Category, Results.getBasePriority(Category),
6682 nullptr),
6683 CurContext, nullptr, false);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006684 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00006685
6686 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6687 Results.data(), Results.size());
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006688}
6689
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006690void Sema::CodeCompleteObjCImplementationCategory(Scope *S,
Douglas Gregorb2ccf012010-04-15 22:33:43 +00006691 IdentifierInfo *ClassName,
6692 SourceLocation ClassNameLoc) {
John McCall276321a2010-08-25 06:19:51 +00006693 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006694
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006695 // Find the corresponding interface. If we couldn't find the interface, the
6696 // program itself is ill-formed. However, we'll try to be helpful still by
6697 // providing the list of all of the categories we know about.
6698 NamedDecl *CurClass
Douglas Gregorb2ccf012010-04-15 22:33:43 +00006699 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006700 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass);
6701 if (!Class)
Douglas Gregorb2ccf012010-04-15 22:33:43 +00006702 return CodeCompleteObjCInterfaceCategory(S, ClassName, ClassNameLoc);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006703
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006704 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006705 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor21325842011-07-07 16:03:39 +00006706 CodeCompletionContext::CCC_ObjCCategoryName);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006707
6708 // Add all of the categories that have have corresponding interface
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006709 // declarations in this class and any of its superclasses, except for
6710 // already-implemented categories in the class itself.
6711 llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
6712 Results.EnterNewScope();
6713 bool IgnoreImplemented = true;
6714 while (Class) {
Aaron Ballman3fe486a2014-03-13 21:23:55 +00006715 for (const auto *Cat : Class->visible_categories()) {
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006716 if ((!IgnoreImplemented || !Cat->getImplementation()) &&
David Blaikie82e95a32014-11-19 07:49:47 +00006717 CategoryNames.insert(Cat->getIdentifier()).second)
Craig Topperc3ec1492014-05-26 06:22:03 +00006718 Results.AddResult(Result(Cat, Results.getBasePriority(Cat), nullptr),
6719 CurContext, nullptr, false);
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006720 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006721
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006722 Class = Class->getSuperClass();
6723 IgnoreImplemented = false;
6724 }
6725 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00006726
6727 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6728 Results.data(), Results.size());
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006729}
Douglas Gregor5d649882009-11-18 22:32:06 +00006730
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00006731void Sema::CodeCompleteObjCPropertyDefinition(Scope *S) {
Douglas Gregorc3425b12015-07-07 06:20:19 +00006732 CodeCompletionContext CCContext(CodeCompletionContext::CCC_Other);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006733 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006734 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorc3425b12015-07-07 06:20:19 +00006735 CCContext);
Douglas Gregor5d649882009-11-18 22:32:06 +00006736
6737 // Figure out where this @synthesize lives.
6738 ObjCContainerDecl *Container
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00006739 = dyn_cast_or_null<ObjCContainerDecl>(CurContext);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006740 if (!Container ||
6741 (!isa<ObjCImplementationDecl>(Container) &&
Douglas Gregor5d649882009-11-18 22:32:06 +00006742 !isa<ObjCCategoryImplDecl>(Container)))
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006743 return;
Douglas Gregor5d649882009-11-18 22:32:06 +00006744
6745 // Ignore any properties that have already been implemented.
Douglas Gregor9b4f3702012-06-12 13:44:08 +00006746 Container = getContainerDef(Container);
Aaron Ballman629afae2014-03-07 19:56:05 +00006747 for (const auto *D : Container->decls())
6748 if (const auto *PropertyImpl = dyn_cast<ObjCPropertyImplDecl>(D))
Douglas Gregor5d649882009-11-18 22:32:06 +00006749 Results.Ignore(PropertyImpl->getPropertyDecl());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006750
Douglas Gregor5d649882009-11-18 22:32:06 +00006751 // Add any properties that we find.
Douglas Gregorb888acf2010-12-09 23:01:55 +00006752 AddedPropertiesSet AddedProperties;
Douglas Gregor5d649882009-11-18 22:32:06 +00006753 Results.EnterNewScope();
6754 if (ObjCImplementationDecl *ClassImpl
6755 = dyn_cast<ObjCImplementationDecl>(Container))
Douglas Gregorc3425b12015-07-07 06:20:19 +00006756 AddObjCProperties(CCContext, ClassImpl->getClassInterface(), false,
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006757 /*AllowNullaryMethods=*/false, CurContext,
Douglas Gregorb888acf2010-12-09 23:01:55 +00006758 AddedProperties, Results);
Douglas Gregor5d649882009-11-18 22:32:06 +00006759 else
Douglas Gregorc3425b12015-07-07 06:20:19 +00006760 AddObjCProperties(CCContext,
6761 cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl(),
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006762 false, /*AllowNullaryMethods=*/false, CurContext,
Douglas Gregor95147142011-05-05 15:50:42 +00006763 AddedProperties, Results);
Douglas Gregor5d649882009-11-18 22:32:06 +00006764 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00006765
6766 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6767 Results.data(), Results.size());
Douglas Gregor5d649882009-11-18 22:32:06 +00006768}
6769
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006770void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S,
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00006771 IdentifierInfo *PropertyName) {
John McCall276321a2010-08-25 06:19:51 +00006772 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006773 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006774 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006775 CodeCompletionContext::CCC_Other);
Douglas Gregor5d649882009-11-18 22:32:06 +00006776
6777 // Figure out where this @synthesize lives.
6778 ObjCContainerDecl *Container
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00006779 = dyn_cast_or_null<ObjCContainerDecl>(CurContext);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006780 if (!Container ||
6781 (!isa<ObjCImplementationDecl>(Container) &&
Douglas Gregor5d649882009-11-18 22:32:06 +00006782 !isa<ObjCCategoryImplDecl>(Container)))
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006783 return;
6784
Douglas Gregor5d649882009-11-18 22:32:06 +00006785 // Figure out which interface we're looking into.
Craig Topperc3ec1492014-05-26 06:22:03 +00006786 ObjCInterfaceDecl *Class = nullptr;
Douglas Gregor5d649882009-11-18 22:32:06 +00006787 if (ObjCImplementationDecl *ClassImpl
Manman Ren5b786402016-01-28 18:49:28 +00006788 = dyn_cast<ObjCImplementationDecl>(Container))
Douglas Gregor5d649882009-11-18 22:32:06 +00006789 Class = ClassImpl->getClassInterface();
6790 else
6791 Class = cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl()
6792 ->getClassInterface();
6793
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006794 // Determine the type of the property we're synthesizing.
6795 QualType PropertyType = Context.getObjCIdType();
6796 if (Class) {
Manman Ren5b786402016-01-28 18:49:28 +00006797 if (ObjCPropertyDecl *Property = Class->FindPropertyDeclaration(
6798 PropertyName, ObjCPropertyQueryKind::OBJC_PR_query_instance)) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006799 PropertyType
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006800 = Property->getType().getNonReferenceType().getUnqualifiedType();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006801
6802 // Give preference to ivars
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006803 Results.setPreferredType(PropertyType);
6804 }
6805 }
6806
Douglas Gregor5d649882009-11-18 22:32:06 +00006807 // Add all of the instance variables in this class and its superclasses.
6808 Results.EnterNewScope();
Douglas Gregor331faa02011-04-18 14:13:53 +00006809 bool SawSimilarlyNamedIvar = false;
6810 std::string NameWithPrefix;
6811 NameWithPrefix += '_';
Benjamin Kramer632500c2011-07-26 16:59:25 +00006812 NameWithPrefix += PropertyName->getName();
Douglas Gregor331faa02011-04-18 14:13:53 +00006813 std::string NameWithSuffix = PropertyName->getName().str();
6814 NameWithSuffix += '_';
Douglas Gregor5d649882009-11-18 22:32:06 +00006815 for(; Class; Class = Class->getSuperClass()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006816 for (ObjCIvarDecl *Ivar = Class->all_declared_ivar_begin(); Ivar;
Douglas Gregor331faa02011-04-18 14:13:53 +00006817 Ivar = Ivar->getNextIvar()) {
Craig Topperc3ec1492014-05-26 06:22:03 +00006818 Results.AddResult(Result(Ivar, Results.getBasePriority(Ivar), nullptr),
6819 CurContext, nullptr, false);
6820
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006821 // Determine whether we've seen an ivar with a name similar to the
Douglas Gregor331faa02011-04-18 14:13:53 +00006822 // property.
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006823 if ((PropertyName == Ivar->getIdentifier() ||
Douglas Gregor331faa02011-04-18 14:13:53 +00006824 NameWithPrefix == Ivar->getName() ||
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006825 NameWithSuffix == Ivar->getName())) {
Douglas Gregor331faa02011-04-18 14:13:53 +00006826 SawSimilarlyNamedIvar = true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006827
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006828 // Reduce the priority of this result by one, to give it a slight
6829 // advantage over other results whose names don't match so closely.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006830 if (Results.size() &&
6831 Results.data()[Results.size() - 1].Kind
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006832 == CodeCompletionResult::RK_Declaration &&
6833 Results.data()[Results.size() - 1].Declaration == Ivar)
6834 Results.data()[Results.size() - 1].Priority--;
6835 }
Douglas Gregor331faa02011-04-18 14:13:53 +00006836 }
Douglas Gregor5d649882009-11-18 22:32:06 +00006837 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006838
Douglas Gregor331faa02011-04-18 14:13:53 +00006839 if (!SawSimilarlyNamedIvar) {
6840 // Create ivar result _propName, that the user can use to synthesize
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006841 // an ivar of the appropriate type.
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006842 unsigned Priority = CCP_MemberDeclaration + 1;
Douglas Gregor331faa02011-04-18 14:13:53 +00006843 typedef CodeCompletionResult Result;
6844 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006845 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo(),
6846 Priority,CXAvailability_Available);
Douglas Gregor331faa02011-04-18 14:13:53 +00006847
Douglas Gregor75acd922011-09-27 23:30:47 +00006848 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006849 Builder.AddResultTypeChunk(GetCompletionTypeString(PropertyType, Context,
Douglas Gregor75acd922011-09-27 23:30:47 +00006850 Policy, Allocator));
Douglas Gregor331faa02011-04-18 14:13:53 +00006851 Builder.AddTypedTextChunk(Allocator.CopyString(NameWithPrefix));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006852 Results.AddResult(Result(Builder.TakeString(), Priority,
Douglas Gregor331faa02011-04-18 14:13:53 +00006853 CXCursor_ObjCIvarDecl));
6854 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006855
Douglas Gregor5d649882009-11-18 22:32:06 +00006856 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00006857
6858 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6859 Results.data(), Results.size());
Douglas Gregor5d649882009-11-18 22:32:06 +00006860}
Douglas Gregor636a61e2010-04-07 00:21:17 +00006861
Douglas Gregor416b5752010-08-25 01:08:01 +00006862// Mapping from selectors to the methods that implement that selector, along
6863// with the "in original class" flag.
Benjamin Kramereb8c4462013-06-29 17:52:13 +00006864typedef llvm::DenseMap<
6865 Selector, llvm::PointerIntPair<ObjCMethodDecl *, 1, bool> > KnownMethodsMap;
Douglas Gregor636a61e2010-04-07 00:21:17 +00006866
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006867/// Find all of the methods that reside in the given container
Douglas Gregor636a61e2010-04-07 00:21:17 +00006868/// (and its superclasses, protocols, etc.) that meet the given
6869/// criteria. Insert those methods into the map of known methods,
6870/// indexed by selector so they can be easily found.
6871static void FindImplementableMethods(ASTContext &Context,
6872 ObjCContainerDecl *Container,
Alex Lorenzb8740422017-10-24 16:39:37 +00006873 Optional<bool> WantInstanceMethods,
Douglas Gregor636a61e2010-04-07 00:21:17 +00006874 QualType ReturnType,
Douglas Gregor416b5752010-08-25 01:08:01 +00006875 KnownMethodsMap &KnownMethods,
6876 bool InOriginalClass = true) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00006877 if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)) {
Douglas Gregor9b4f3702012-06-12 13:44:08 +00006878 // Make sure we have a definition; that's what we'll walk.
Douglas Gregorc0ac7d62011-12-15 05:27:12 +00006879 if (!IFace->hasDefinition())
6880 return;
Douglas Gregor9b4f3702012-06-12 13:44:08 +00006881
6882 IFace = IFace->getDefinition();
6883 Container = IFace;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006884
Douglas Gregor636a61e2010-04-07 00:21:17 +00006885 const ObjCList<ObjCProtocolDecl> &Protocols
6886 = IFace->getReferencedProtocols();
6887 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006888 E = Protocols.end();
Douglas Gregor636a61e2010-04-07 00:21:17 +00006889 I != E; ++I)
6890 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006891 KnownMethods, InOriginalClass);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006892
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006893 // Add methods from any class extensions and categories.
Aaron Ballman3fe486a2014-03-13 21:23:55 +00006894 for (auto *Cat : IFace->visible_categories()) {
6895 FindImplementableMethods(Context, Cat, WantInstanceMethods, ReturnType,
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006896 KnownMethods, false);
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006897 }
6898
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006899 // Visit the superclass.
6900 if (IFace->getSuperClass())
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006901 FindImplementableMethods(Context, IFace->getSuperClass(),
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006902 WantInstanceMethods, ReturnType,
6903 KnownMethods, false);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006904 }
6905
6906 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(Container)) {
6907 // Recurse into protocols.
6908 const ObjCList<ObjCProtocolDecl> &Protocols
6909 = Category->getReferencedProtocols();
6910 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006911 E = Protocols.end();
Douglas Gregor636a61e2010-04-07 00:21:17 +00006912 I != E; ++I)
6913 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006914 KnownMethods, InOriginalClass);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006915
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006916 // If this category is the original class, jump to the interface.
6917 if (InOriginalClass && Category->getClassInterface())
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006918 FindImplementableMethods(Context, Category->getClassInterface(),
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006919 WantInstanceMethods, ReturnType, KnownMethods,
6920 false);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006921 }
6922
6923 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Douglas Gregor9b4f3702012-06-12 13:44:08 +00006924 // Make sure we have a definition; that's what we'll walk.
6925 if (!Protocol->hasDefinition())
6926 return;
6927 Protocol = Protocol->getDefinition();
6928 Container = Protocol;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006929
Douglas Gregor9b4f3702012-06-12 13:44:08 +00006930 // Recurse into protocols.
6931 const ObjCList<ObjCProtocolDecl> &Protocols
6932 = Protocol->getReferencedProtocols();
6933 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006934 E = Protocols.end();
Douglas Gregor9b4f3702012-06-12 13:44:08 +00006935 I != E; ++I)
6936 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
6937 KnownMethods, false);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006938 }
6939
6940 // Add methods in this container. This operation occurs last because
6941 // we want the methods from this container to override any methods
6942 // we've previously seen with the same selector.
Aaron Ballmanaff18c02014-03-13 19:03:34 +00006943 for (auto *M : Container->methods()) {
Alex Lorenzb8740422017-10-24 16:39:37 +00006944 if (!WantInstanceMethods || M->isInstanceMethod() == *WantInstanceMethods) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00006945 if (!ReturnType.isNull() &&
Alp Toker314cc812014-01-25 16:55:45 +00006946 !Context.hasSameUnqualifiedType(ReturnType, M->getReturnType()))
Douglas Gregor636a61e2010-04-07 00:21:17 +00006947 continue;
6948
Benjamin Kramereb8c4462013-06-29 17:52:13 +00006949 KnownMethods[M->getSelector()] =
Aaron Ballmanaff18c02014-03-13 19:03:34 +00006950 KnownMethodsMap::mapped_type(M, InOriginalClass);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006951 }
6952 }
6953}
6954
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006955/// Add the parenthesized return or parameter type chunk to a code
Douglas Gregor669a25a2011-02-17 00:22:45 +00006956/// completion string.
6957static void AddObjCPassingTypeChunk(QualType Type,
Douglas Gregor29979142012-04-10 18:35:07 +00006958 unsigned ObjCDeclQuals,
Douglas Gregor669a25a2011-02-17 00:22:45 +00006959 ASTContext &Context,
Douglas Gregor75acd922011-09-27 23:30:47 +00006960 const PrintingPolicy &Policy,
Douglas Gregor669a25a2011-02-17 00:22:45 +00006961 CodeCompletionBuilder &Builder) {
6962 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregor86b42682015-06-19 18:27:52 +00006963 std::string Quals = formatObjCParamQualifiers(ObjCDeclQuals, Type);
Douglas Gregor29979142012-04-10 18:35:07 +00006964 if (!Quals.empty())
6965 Builder.AddTextChunk(Builder.getAllocator().CopyString(Quals));
Douglas Gregor75acd922011-09-27 23:30:47 +00006966 Builder.AddTextChunk(GetCompletionTypeString(Type, Context, Policy,
Douglas Gregor669a25a2011-02-17 00:22:45 +00006967 Builder.getAllocator()));
6968 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6969}
6970
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006971/// Determine whether the given class is or inherits from a class by
Douglas Gregor669a25a2011-02-17 00:22:45 +00006972/// the given name.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006973static bool InheritsFromClassNamed(ObjCInterfaceDecl *Class,
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006974 StringRef Name) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006975 if (!Class)
6976 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006977
Douglas Gregor669a25a2011-02-17 00:22:45 +00006978 if (Class->getIdentifier() && Class->getIdentifier()->getName() == Name)
6979 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006980
Douglas Gregor669a25a2011-02-17 00:22:45 +00006981 return InheritsFromClassNamed(Class->getSuperClass(), Name);
6982}
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006983
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006984/// Add code completions for Objective-C Key-Value Coding (KVC) and
Douglas Gregor669a25a2011-02-17 00:22:45 +00006985/// Key-Value Observing (KVO).
6986static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
6987 bool IsInstanceMethod,
6988 QualType ReturnType,
6989 ASTContext &Context,
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006990 VisitedSelectorSet &KnownSelectors,
Douglas Gregor669a25a2011-02-17 00:22:45 +00006991 ResultBuilder &Results) {
6992 IdentifierInfo *PropName = Property->getIdentifier();
6993 if (!PropName || PropName->getLength() == 0)
6994 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006995
Douglas Gregor75acd922011-09-27 23:30:47 +00006996 PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema());
6997
Douglas Gregor669a25a2011-02-17 00:22:45 +00006998 // Builder that will create each code completion.
6999 typedef CodeCompletionResult Result;
7000 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007001 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007002
Douglas Gregor669a25a2011-02-17 00:22:45 +00007003 // The selector table.
7004 SelectorTable &Selectors = Context.Selectors;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007005
Douglas Gregor669a25a2011-02-17 00:22:45 +00007006 // The property name, copied into the code completion allocation region
7007 // on demand.
7008 struct KeyHolder {
7009 CodeCompletionAllocator &Allocator;
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007010 StringRef Key;
Douglas Gregor669a25a2011-02-17 00:22:45 +00007011 const char *CopiedKey;
Craig Topperc3ec1492014-05-26 06:22:03 +00007012
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007013 KeyHolder(CodeCompletionAllocator &Allocator, StringRef Key)
Craig Topperc3ec1492014-05-26 06:22:03 +00007014 : Allocator(Allocator), Key(Key), CopiedKey(nullptr) {}
7015
Douglas Gregor669a25a2011-02-17 00:22:45 +00007016 operator const char *() {
7017 if (CopiedKey)
7018 return CopiedKey;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007019
Douglas Gregor669a25a2011-02-17 00:22:45 +00007020 return CopiedKey = Allocator.CopyString(Key);
7021 }
7022 } Key(Allocator, PropName->getName());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007023
Douglas Gregor669a25a2011-02-17 00:22:45 +00007024 // The uppercased name of the property name.
7025 std::string UpperKey = PropName->getName();
7026 if (!UpperKey.empty())
Jordan Rose4938f272013-02-09 10:09:43 +00007027 UpperKey[0] = toUppercase(UpperKey[0]);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007028
Douglas Gregor669a25a2011-02-17 00:22:45 +00007029 bool ReturnTypeMatchesProperty = ReturnType.isNull() ||
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007030 Context.hasSameUnqualifiedType(ReturnType.getNonReferenceType(),
Douglas Gregor669a25a2011-02-17 00:22:45 +00007031 Property->getType());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007032 bool ReturnTypeMatchesVoid
Douglas Gregor669a25a2011-02-17 00:22:45 +00007033 = ReturnType.isNull() || ReturnType->isVoidType();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007034
Douglas Gregor669a25a2011-02-17 00:22:45 +00007035 // Add the normal accessor -(type)key.
7036 if (IsInstanceMethod &&
David Blaikie82e95a32014-11-19 07:49:47 +00007037 KnownSelectors.insert(Selectors.getNullarySelector(PropName)).second &&
Douglas Gregor669a25a2011-02-17 00:22:45 +00007038 ReturnTypeMatchesProperty && !Property->getGetterMethodDecl()) {
7039 if (ReturnType.isNull())
Douglas Gregor29979142012-04-10 18:35:07 +00007040 AddObjCPassingTypeChunk(Property->getType(), /*Quals=*/0,
7041 Context, Policy, Builder);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007042
Douglas Gregor669a25a2011-02-17 00:22:45 +00007043 Builder.AddTypedTextChunk(Key);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007044 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007045 CXCursor_ObjCInstanceMethodDecl));
7046 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007047
Douglas Gregor669a25a2011-02-17 00:22:45 +00007048 // If we have an integral or boolean property (or the user has provided
7049 // an integral or boolean return type), add the accessor -(type)isKey.
7050 if (IsInstanceMethod &&
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007051 ((!ReturnType.isNull() &&
Douglas Gregor669a25a2011-02-17 00:22:45 +00007052 (ReturnType->isIntegerType() || ReturnType->isBooleanType())) ||
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007053 (ReturnType.isNull() &&
7054 (Property->getType()->isIntegerType() ||
Douglas Gregor669a25a2011-02-17 00:22:45 +00007055 Property->getType()->isBooleanType())))) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007056 std::string SelectorName = (Twine("is") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007057 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007058 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
7059 .second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007060 if (ReturnType.isNull()) {
7061 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7062 Builder.AddTextChunk("BOOL");
7063 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7064 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007065
Douglas Gregor669a25a2011-02-17 00:22:45 +00007066 Builder.AddTypedTextChunk(
7067 Allocator.CopyString(SelectorId->getName()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007068 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007069 CXCursor_ObjCInstanceMethodDecl));
7070 }
7071 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007072
Douglas Gregor669a25a2011-02-17 00:22:45 +00007073 // Add the normal mutator.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007074 if (IsInstanceMethod && ReturnTypeMatchesVoid &&
Douglas Gregor669a25a2011-02-17 00:22:45 +00007075 !Property->getSetterMethodDecl()) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007076 std::string SelectorName = (Twine("set") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007077 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007078 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007079 if (ReturnType.isNull()) {
7080 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7081 Builder.AddTextChunk("void");
7082 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7083 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007084
Douglas Gregor669a25a2011-02-17 00:22:45 +00007085 Builder.AddTypedTextChunk(
7086 Allocator.CopyString(SelectorId->getName()));
7087 Builder.AddTypedTextChunk(":");
Douglas Gregor29979142012-04-10 18:35:07 +00007088 AddObjCPassingTypeChunk(Property->getType(), /*Quals=*/0,
7089 Context, Policy, Builder);
Douglas Gregor669a25a2011-02-17 00:22:45 +00007090 Builder.AddTextChunk(Key);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007091 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007092 CXCursor_ObjCInstanceMethodDecl));
7093 }
7094 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007095
Douglas Gregor669a25a2011-02-17 00:22:45 +00007096 // Indexed and unordered accessors
7097 unsigned IndexedGetterPriority = CCP_CodePattern;
7098 unsigned IndexedSetterPriority = CCP_CodePattern;
7099 unsigned UnorderedGetterPriority = CCP_CodePattern;
7100 unsigned UnorderedSetterPriority = CCP_CodePattern;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007101 if (const ObjCObjectPointerType *ObjCPointer
Douglas Gregor669a25a2011-02-17 00:22:45 +00007102 = Property->getType()->getAs<ObjCObjectPointerType>()) {
7103 if (ObjCInterfaceDecl *IFace = ObjCPointer->getInterfaceDecl()) {
7104 // If this interface type is not provably derived from a known
7105 // collection, penalize the corresponding completions.
7106 if (!InheritsFromClassNamed(IFace, "NSMutableArray")) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007107 IndexedSetterPriority += CCD_ProbablyNotObjCCollection;
Douglas Gregor669a25a2011-02-17 00:22:45 +00007108 if (!InheritsFromClassNamed(IFace, "NSArray"))
7109 IndexedGetterPriority += CCD_ProbablyNotObjCCollection;
7110 }
7111
7112 if (!InheritsFromClassNamed(IFace, "NSMutableSet")) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007113 UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;
Douglas Gregor669a25a2011-02-17 00:22:45 +00007114 if (!InheritsFromClassNamed(IFace, "NSSet"))
7115 UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;
7116 }
7117 }
7118 } else {
7119 IndexedGetterPriority += CCD_ProbablyNotObjCCollection;
7120 IndexedSetterPriority += CCD_ProbablyNotObjCCollection;
7121 UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;
7122 UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;
7123 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007124
Douglas Gregor669a25a2011-02-17 00:22:45 +00007125 // Add -(NSUInteger)countOf<key>
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007126 if (IsInstanceMethod &&
Douglas Gregor669a25a2011-02-17 00:22:45 +00007127 (ReturnType.isNull() || ReturnType->isIntegerType())) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007128 std::string SelectorName = (Twine("countOf") + UpperKey).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.getNullarySelector(SelectorId))
7131 .second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007132 if (ReturnType.isNull()) {
7133 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7134 Builder.AddTextChunk("NSUInteger");
7135 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7136 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007137
Douglas Gregor669a25a2011-02-17 00:22:45 +00007138 Builder.AddTypedTextChunk(
7139 Allocator.CopyString(SelectorId->getName()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007140 Results.AddResult(Result(Builder.TakeString(),
7141 std::min(IndexedGetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007142 UnorderedGetterPriority),
7143 CXCursor_ObjCInstanceMethodDecl));
7144 }
7145 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007146
Douglas Gregor669a25a2011-02-17 00:22:45 +00007147 // Indexed getters
7148 // Add -(id)objectInKeyAtIndex:(NSUInteger)index
7149 if (IsInstanceMethod &&
7150 (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007151 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007152 = (Twine("objectIn") + UpperKey + "AtIndex").str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007153 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007154 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007155 if (ReturnType.isNull()) {
7156 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7157 Builder.AddTextChunk("id");
7158 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7159 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007160
Douglas Gregor669a25a2011-02-17 00:22:45 +00007161 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7162 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7163 Builder.AddTextChunk("NSUInteger");
7164 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7165 Builder.AddTextChunk("index");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007166 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007167 CXCursor_ObjCInstanceMethodDecl));
7168 }
7169 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007170
Douglas Gregor669a25a2011-02-17 00:22:45 +00007171 // Add -(NSArray *)keyAtIndexes:(NSIndexSet *)indexes
7172 if (IsInstanceMethod &&
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007173 (ReturnType.isNull() ||
Douglas Gregor669a25a2011-02-17 00:22:45 +00007174 (ReturnType->isObjCObjectPointerType() &&
7175 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
7176 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
7177 ->getName() == "NSArray"))) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007178 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007179 = (Twine(Property->getName()) + "AtIndexes").str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007180 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007181 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007182 if (ReturnType.isNull()) {
7183 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7184 Builder.AddTextChunk("NSArray *");
7185 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7186 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007187
Douglas Gregor669a25a2011-02-17 00:22:45 +00007188 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7189 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7190 Builder.AddTextChunk("NSIndexSet *");
7191 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7192 Builder.AddTextChunk("indexes");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007193 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007194 CXCursor_ObjCInstanceMethodDecl));
7195 }
7196 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007197
Douglas Gregor669a25a2011-02-17 00:22:45 +00007198 // Add -(void)getKey:(type **)buffer range:(NSRange)inRange
7199 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007200 std::string SelectorName = (Twine("get") + UpperKey).str();
Douglas Gregor669a25a2011-02-17 00:22:45 +00007201 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007202 &Context.Idents.get(SelectorName),
Douglas Gregor669a25a2011-02-17 00:22:45 +00007203 &Context.Idents.get("range")
7204 };
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007205
David Blaikie82e95a32014-11-19 07:49:47 +00007206 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007207 if (ReturnType.isNull()) {
7208 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7209 Builder.AddTextChunk("void");
7210 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7211 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007212
Douglas Gregor669a25a2011-02-17 00:22:45 +00007213 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7214 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7215 Builder.AddPlaceholderChunk("object-type");
7216 Builder.AddTextChunk(" **");
7217 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7218 Builder.AddTextChunk("buffer");
7219 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7220 Builder.AddTypedTextChunk("range:");
7221 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7222 Builder.AddTextChunk("NSRange");
7223 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7224 Builder.AddTextChunk("inRange");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007225 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007226 CXCursor_ObjCInstanceMethodDecl));
7227 }
7228 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007229
Douglas Gregor669a25a2011-02-17 00:22:45 +00007230 // Mutable indexed accessors
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007231
Douglas Gregor669a25a2011-02-17 00:22:45 +00007232 // - (void)insertObject:(type *)object inKeyAtIndex:(NSUInteger)index
7233 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007234 std::string SelectorName = (Twine("in") + UpperKey + "AtIndex").str();
Douglas Gregor669a25a2011-02-17 00:22:45 +00007235 IdentifierInfo *SelectorIds[2] = {
7236 &Context.Idents.get("insertObject"),
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007237 &Context.Idents.get(SelectorName)
Douglas Gregor669a25a2011-02-17 00:22:45 +00007238 };
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007239
David Blaikie82e95a32014-11-19 07:49:47 +00007240 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007241 if (ReturnType.isNull()) {
7242 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7243 Builder.AddTextChunk("void");
7244 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7245 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007246
Douglas Gregor669a25a2011-02-17 00:22:45 +00007247 Builder.AddTypedTextChunk("insertObject:");
7248 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7249 Builder.AddPlaceholderChunk("object-type");
7250 Builder.AddTextChunk(" *");
7251 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7252 Builder.AddTextChunk("object");
7253 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7254 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7255 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7256 Builder.AddPlaceholderChunk("NSUInteger");
7257 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7258 Builder.AddTextChunk("index");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007259 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007260 CXCursor_ObjCInstanceMethodDecl));
7261 }
7262 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007263
Douglas Gregor669a25a2011-02-17 00:22:45 +00007264 // - (void)insertKey:(NSArray *)array atIndexes:(NSIndexSet *)indexes
7265 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007266 std::string SelectorName = (Twine("insert") + UpperKey).str();
Douglas Gregor669a25a2011-02-17 00:22:45 +00007267 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007268 &Context.Idents.get(SelectorName),
Douglas Gregor669a25a2011-02-17 00:22:45 +00007269 &Context.Idents.get("atIndexes")
7270 };
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007271
David Blaikie82e95a32014-11-19 07:49:47 +00007272 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007273 if (ReturnType.isNull()) {
7274 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7275 Builder.AddTextChunk("void");
7276 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7277 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007278
Douglas Gregor669a25a2011-02-17 00:22:45 +00007279 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7280 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7281 Builder.AddTextChunk("NSArray *");
7282 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7283 Builder.AddTextChunk("array");
7284 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7285 Builder.AddTypedTextChunk("atIndexes:");
7286 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7287 Builder.AddPlaceholderChunk("NSIndexSet *");
7288 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7289 Builder.AddTextChunk("indexes");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007290 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007291 CXCursor_ObjCInstanceMethodDecl));
7292 }
7293 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007294
Douglas Gregor669a25a2011-02-17 00:22:45 +00007295 // -(void)removeObjectFromKeyAtIndex:(NSUInteger)index
7296 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007297 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007298 = (Twine("removeObjectFrom") + UpperKey + "AtIndex").str();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007299 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007300 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007301 if (ReturnType.isNull()) {
7302 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7303 Builder.AddTextChunk("void");
7304 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7305 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007306
Douglas Gregor669a25a2011-02-17 00:22:45 +00007307 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7308 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7309 Builder.AddTextChunk("NSUInteger");
7310 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7311 Builder.AddTextChunk("index");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007312 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007313 CXCursor_ObjCInstanceMethodDecl));
7314 }
7315 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007316
Douglas Gregor669a25a2011-02-17 00:22:45 +00007317 // -(void)removeKeyAtIndexes:(NSIndexSet *)indexes
7318 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007319 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007320 = (Twine("remove") + UpperKey + "AtIndexes").str();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007321 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007322 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007323 if (ReturnType.isNull()) {
7324 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7325 Builder.AddTextChunk("void");
7326 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7327 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007328
Douglas Gregor669a25a2011-02-17 00:22:45 +00007329 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7330 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7331 Builder.AddTextChunk("NSIndexSet *");
7332 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7333 Builder.AddTextChunk("indexes");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007334 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007335 CXCursor_ObjCInstanceMethodDecl));
7336 }
7337 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007338
Douglas Gregor669a25a2011-02-17 00:22:45 +00007339 // - (void)replaceObjectInKeyAtIndex:(NSUInteger)index withObject:(id)object
7340 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007341 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007342 = (Twine("replaceObjectIn") + UpperKey + "AtIndex").str();
Douglas Gregor669a25a2011-02-17 00:22:45 +00007343 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007344 &Context.Idents.get(SelectorName),
Douglas Gregor669a25a2011-02-17 00:22:45 +00007345 &Context.Idents.get("withObject")
7346 };
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007347
David Blaikie82e95a32014-11-19 07:49:47 +00007348 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007349 if (ReturnType.isNull()) {
7350 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7351 Builder.AddTextChunk("void");
7352 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7353 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007354
Douglas Gregor669a25a2011-02-17 00:22:45 +00007355 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7356 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7357 Builder.AddPlaceholderChunk("NSUInteger");
7358 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7359 Builder.AddTextChunk("index");
7360 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7361 Builder.AddTypedTextChunk("withObject:");
7362 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7363 Builder.AddTextChunk("id");
7364 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7365 Builder.AddTextChunk("object");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007366 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007367 CXCursor_ObjCInstanceMethodDecl));
7368 }
7369 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007370
Douglas Gregor669a25a2011-02-17 00:22:45 +00007371 // - (void)replaceKeyAtIndexes:(NSIndexSet *)indexes withKey:(NSArray *)array
7372 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007373 std::string SelectorName1
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007374 = (Twine("replace") + UpperKey + "AtIndexes").str();
7375 std::string SelectorName2 = (Twine("with") + UpperKey).str();
Douglas Gregor669a25a2011-02-17 00:22:45 +00007376 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007377 &Context.Idents.get(SelectorName1),
7378 &Context.Idents.get(SelectorName2)
Douglas Gregor669a25a2011-02-17 00:22:45 +00007379 };
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007380
David Blaikie82e95a32014-11-19 07:49:47 +00007381 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).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 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007387
Douglas Gregor669a25a2011-02-17 00:22:45 +00007388 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName1 + ":"));
7389 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7390 Builder.AddPlaceholderChunk("NSIndexSet *");
7391 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7392 Builder.AddTextChunk("indexes");
7393 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7394 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName2 + ":"));
7395 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7396 Builder.AddTextChunk("NSArray *");
7397 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7398 Builder.AddTextChunk("array");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007399 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007400 CXCursor_ObjCInstanceMethodDecl));
7401 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007402 }
7403
Douglas Gregor669a25a2011-02-17 00:22:45 +00007404 // Unordered getters
7405 // - (NSEnumerator *)enumeratorOfKey
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007406 if (IsInstanceMethod &&
7407 (ReturnType.isNull() ||
Douglas Gregor669a25a2011-02-17 00:22:45 +00007408 (ReturnType->isObjCObjectPointerType() &&
7409 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
7410 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
7411 ->getName() == "NSEnumerator"))) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007412 std::string SelectorName = (Twine("enumeratorOf") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007413 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007414 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
7415 .second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007416 if (ReturnType.isNull()) {
7417 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7418 Builder.AddTextChunk("NSEnumerator *");
7419 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7420 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007421
Douglas Gregor669a25a2011-02-17 00:22:45 +00007422 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007423 Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007424 CXCursor_ObjCInstanceMethodDecl));
7425 }
7426 }
7427
7428 // - (type *)memberOfKey:(type *)object
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007429 if (IsInstanceMethod &&
Douglas Gregor669a25a2011-02-17 00:22:45 +00007430 (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007431 std::string SelectorName = (Twine("memberOf") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007432 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007433 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007434 if (ReturnType.isNull()) {
7435 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7436 Builder.AddPlaceholderChunk("object-type");
7437 Builder.AddTextChunk(" *");
7438 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7439 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007440
Douglas Gregor669a25a2011-02-17 00:22:45 +00007441 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7442 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7443 if (ReturnType.isNull()) {
7444 Builder.AddPlaceholderChunk("object-type");
7445 Builder.AddTextChunk(" *");
7446 } else {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007447 Builder.AddTextChunk(GetCompletionTypeString(ReturnType, Context,
Douglas Gregor75acd922011-09-27 23:30:47 +00007448 Policy,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007449 Builder.getAllocator()));
7450 }
7451 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7452 Builder.AddTextChunk("object");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007453 Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007454 CXCursor_ObjCInstanceMethodDecl));
7455 }
7456 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007457
Douglas Gregor669a25a2011-02-17 00:22:45 +00007458 // Mutable unordered accessors
7459 // - (void)addKeyObject:(type *)object
7460 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007461 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007462 = (Twine("add") + UpperKey + Twine("Object")).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007463 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007464 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007465 if (ReturnType.isNull()) {
7466 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7467 Builder.AddTextChunk("void");
7468 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7469 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007470
Douglas Gregor669a25a2011-02-17 00:22:45 +00007471 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7472 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7473 Builder.AddPlaceholderChunk("object-type");
7474 Builder.AddTextChunk(" *");
7475 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7476 Builder.AddTextChunk("object");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007477 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007478 CXCursor_ObjCInstanceMethodDecl));
7479 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007480 }
Douglas Gregor669a25a2011-02-17 00:22:45 +00007481
7482 // - (void)addKey:(NSSet *)objects
7483 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007484 std::string SelectorName = (Twine("add") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007485 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007486 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007487 if (ReturnType.isNull()) {
7488 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7489 Builder.AddTextChunk("void");
7490 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7491 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007492
Douglas Gregor669a25a2011-02-17 00:22:45 +00007493 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7494 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7495 Builder.AddTextChunk("NSSet *");
7496 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7497 Builder.AddTextChunk("objects");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007498 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007499 CXCursor_ObjCInstanceMethodDecl));
7500 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007501 }
7502
Douglas Gregor669a25a2011-02-17 00:22:45 +00007503 // - (void)removeKeyObject:(type *)object
7504 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007505 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007506 = (Twine("remove") + UpperKey + Twine("Object")).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007507 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007508 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007509 if (ReturnType.isNull()) {
7510 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7511 Builder.AddTextChunk("void");
7512 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7513 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007514
Douglas Gregor669a25a2011-02-17 00:22:45 +00007515 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7516 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7517 Builder.AddPlaceholderChunk("object-type");
7518 Builder.AddTextChunk(" *");
7519 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7520 Builder.AddTextChunk("object");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007521 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007522 CXCursor_ObjCInstanceMethodDecl));
7523 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007524 }
7525
Douglas Gregor669a25a2011-02-17 00:22:45 +00007526 // - (void)removeKey:(NSSet *)objects
7527 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007528 std::string SelectorName = (Twine("remove") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007529 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007530 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007531 if (ReturnType.isNull()) {
7532 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7533 Builder.AddTextChunk("void");
7534 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7535 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007536
Douglas Gregor669a25a2011-02-17 00:22:45 +00007537 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7538 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7539 Builder.AddTextChunk("NSSet *");
7540 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7541 Builder.AddTextChunk("objects");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007542 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007543 CXCursor_ObjCInstanceMethodDecl));
7544 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007545 }
Douglas Gregor669a25a2011-02-17 00:22:45 +00007546
7547 // - (void)intersectKey:(NSSet *)objects
7548 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007549 std::string SelectorName = (Twine("intersect") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007550 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007551 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007552 if (ReturnType.isNull()) {
7553 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7554 Builder.AddTextChunk("void");
7555 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7556 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007557
Douglas Gregor669a25a2011-02-17 00:22:45 +00007558 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7559 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7560 Builder.AddTextChunk("NSSet *");
7561 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7562 Builder.AddTextChunk("objects");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007563 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007564 CXCursor_ObjCInstanceMethodDecl));
7565 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007566 }
7567
Douglas Gregor669a25a2011-02-17 00:22:45 +00007568 // Key-Value Observing
7569 // + (NSSet *)keyPathsForValuesAffectingKey
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007570 if (!IsInstanceMethod &&
7571 (ReturnType.isNull() ||
Douglas Gregor669a25a2011-02-17 00:22:45 +00007572 (ReturnType->isObjCObjectPointerType() &&
7573 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
7574 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
7575 ->getName() == "NSSet"))) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007576 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007577 = (Twine("keyPathsForValuesAffecting") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007578 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007579 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
7580 .second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007581 if (ReturnType.isNull()) {
7582 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Alex Lorenz71ecb072016-12-08 16:49:05 +00007583 Builder.AddTextChunk("NSSet<NSString *> *");
Douglas Gregor669a25a2011-02-17 00:22:45 +00007584 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7585 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007586
Douglas Gregor669a25a2011-02-17 00:22:45 +00007587 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007588 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Douglas Gregor857bcda2011-06-02 04:02:27 +00007589 CXCursor_ObjCClassMethodDecl));
7590 }
7591 }
7592
7593 // + (BOOL)automaticallyNotifiesObserversForKey
7594 if (!IsInstanceMethod &&
7595 (ReturnType.isNull() ||
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007596 ReturnType->isIntegerType() ||
Douglas Gregor857bcda2011-06-02 04:02:27 +00007597 ReturnType->isBooleanType())) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007598 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007599 = (Twine("automaticallyNotifiesObserversOf") + UpperKey).str();
Douglas Gregor857bcda2011-06-02 04:02:27 +00007600 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007601 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
7602 .second) {
Douglas Gregor857bcda2011-06-02 04:02:27 +00007603 if (ReturnType.isNull()) {
7604 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7605 Builder.AddTextChunk("BOOL");
7606 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7607 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007608
Douglas Gregor857bcda2011-06-02 04:02:27 +00007609 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007610 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Douglas Gregor857bcda2011-06-02 04:02:27 +00007611 CXCursor_ObjCClassMethodDecl));
Douglas Gregor669a25a2011-02-17 00:22:45 +00007612 }
7613 }
7614}
7615
Alex Lorenzb8740422017-10-24 16:39:37 +00007616void Sema::CodeCompleteObjCMethodDecl(Scope *S, Optional<bool> IsInstanceMethod,
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00007617 ParsedType ReturnTy) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00007618 // Determine the return type of the method we're declaring, if
7619 // provided.
7620 QualType ReturnType = GetTypeFromParser(ReturnTy);
Craig Topperc3ec1492014-05-26 06:22:03 +00007621 Decl *IDecl = nullptr;
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00007622 if (CurContext->isObjCContainer()) {
7623 ObjCContainerDecl *OCD = dyn_cast<ObjCContainerDecl>(CurContext);
George Burgess IV00f70bd2018-03-01 05:43:23 +00007624 IDecl = OCD;
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00007625 }
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007626 // Determine where we should start searching for methods.
Craig Topperc3ec1492014-05-26 06:22:03 +00007627 ObjCContainerDecl *SearchDecl = nullptr;
Douglas Gregor636a61e2010-04-07 00:21:17 +00007628 bool IsInImplementation = false;
John McCall48871652010-08-21 09:40:31 +00007629 if (Decl *D = IDecl) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00007630 if (ObjCImplementationDecl *Impl = dyn_cast<ObjCImplementationDecl>(D)) {
7631 SearchDecl = Impl->getClassInterface();
Douglas Gregor636a61e2010-04-07 00:21:17 +00007632 IsInImplementation = true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007633 } else if (ObjCCategoryImplDecl *CatImpl
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007634 = dyn_cast<ObjCCategoryImplDecl>(D)) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00007635 SearchDecl = CatImpl->getCategoryDecl();
Douglas Gregor636a61e2010-04-07 00:21:17 +00007636 IsInImplementation = true;
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007637 } else
Douglas Gregor636a61e2010-04-07 00:21:17 +00007638 SearchDecl = dyn_cast<ObjCContainerDecl>(D);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007639 }
7640
7641 if (!SearchDecl && S) {
Ted Kremenekc37877d2013-10-08 17:08:03 +00007642 if (DeclContext *DC = S->getEntity())
Douglas Gregor636a61e2010-04-07 00:21:17 +00007643 SearchDecl = dyn_cast<ObjCContainerDecl>(DC);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007644 }
7645
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007646 if (!SearchDecl) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007647 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00007648 CodeCompletionContext::CCC_Other,
Craig Topperc3ec1492014-05-26 06:22:03 +00007649 nullptr, 0);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007650 return;
7651 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007652
Douglas Gregor636a61e2010-04-07 00:21:17 +00007653 // Find all of the methods that we could declare/implement here.
7654 KnownMethodsMap KnownMethods;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007655 FindImplementableMethods(Context, SearchDecl, IsInstanceMethod,
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007656 ReturnType, KnownMethods);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007657
Douglas Gregor636a61e2010-04-07 00:21:17 +00007658 // Add declarations or definitions for each of the known methods.
John McCall276321a2010-08-25 06:19:51 +00007659 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007660 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007661 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007662 CodeCompletionContext::CCC_Other);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007663 Results.EnterNewScope();
Douglas Gregor75acd922011-09-27 23:30:47 +00007664 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007665 for (KnownMethodsMap::iterator M = KnownMethods.begin(),
Douglas Gregor636a61e2010-04-07 00:21:17 +00007666 MEnd = KnownMethods.end();
7667 M != MEnd; ++M) {
Benjamin Kramereb8c4462013-06-29 17:52:13 +00007668 ObjCMethodDecl *Method = M->second.getPointer();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007669 CodeCompletionBuilder Builder(Results.getAllocator(),
7670 Results.getCodeCompletionTUInfo());
Alex Lorenzb8740422017-10-24 16:39:37 +00007671
7672 // Add the '-'/'+' prefix if it wasn't provided yet.
7673 if (!IsInstanceMethod) {
7674 Builder.AddTextChunk(Method->isInstanceMethod() ? "-" : "+");
7675 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7676 }
7677
Douglas Gregor636a61e2010-04-07 00:21:17 +00007678 // If the result type was not already provided, add it to the
7679 // pattern as (type).
Argyrios Kyrtzidisf0917ab2015-07-24 17:00:19 +00007680 if (ReturnType.isNull()) {
7681 QualType ResTy = Method->getSendResultType().stripObjCKindOfType(Context);
7682 AttributedType::stripOuterNullability(ResTy);
7683 AddObjCPassingTypeChunk(ResTy,
Alp Toker314cc812014-01-25 16:55:45 +00007684 Method->getObjCDeclQualifier(), Context, Policy,
7685 Builder);
Argyrios Kyrtzidisf0917ab2015-07-24 17:00:19 +00007686 }
Douglas Gregor636a61e2010-04-07 00:21:17 +00007687
7688 Selector Sel = Method->getSelector();
7689
7690 // Add the first part of the selector to the pattern.
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00007691 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00007692 Sel.getNameForSlot(0)));
Douglas Gregor636a61e2010-04-07 00:21:17 +00007693
7694 // Add parameters to the pattern.
7695 unsigned I = 0;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007696 for (ObjCMethodDecl::param_iterator P = Method->param_begin(),
Douglas Gregor636a61e2010-04-07 00:21:17 +00007697 PEnd = Method->param_end();
7698 P != PEnd; (void)++P, ++I) {
7699 // Add the part of the selector name.
7700 if (I == 0)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007701 Builder.AddTypedTextChunk(":");
Douglas Gregor636a61e2010-04-07 00:21:17 +00007702 else if (I < Sel.getNumArgs()) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007703 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7704 Builder.AddTypedTextChunk(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00007705 Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":"));
Douglas Gregor636a61e2010-04-07 00:21:17 +00007706 } else
7707 break;
7708
7709 // Add the parameter type.
Douglas Gregor86b42682015-06-19 18:27:52 +00007710 QualType ParamType;
7711 if ((*P)->getObjCDeclQualifier() & Decl::OBJC_TQ_CSNullability)
7712 ParamType = (*P)->getType();
7713 else
7714 ParamType = (*P)->getOriginalType();
Douglas Gregor9b7b3e92015-07-07 06:20:27 +00007715 ParamType = ParamType.substObjCTypeArgs(Context, {},
7716 ObjCSubstitutionContext::Parameter);
Argyrios Kyrtzidisf0917ab2015-07-24 17:00:19 +00007717 AttributedType::stripOuterNullability(ParamType);
Douglas Gregor86b42682015-06-19 18:27:52 +00007718 AddObjCPassingTypeChunk(ParamType,
Douglas Gregor29979142012-04-10 18:35:07 +00007719 (*P)->getObjCDeclQualifier(),
7720 Context, Policy,
Douglas Gregor75acd922011-09-27 23:30:47 +00007721 Builder);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007722
Douglas Gregor636a61e2010-04-07 00:21:17 +00007723 if (IdentifierInfo *Id = (*P)->getIdentifier())
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007724 Builder.AddTextChunk(Builder.getAllocator().CopyString( Id->getName()));
Douglas Gregor636a61e2010-04-07 00:21:17 +00007725 }
7726
7727 if (Method->isVariadic()) {
7728 if (Method->param_size() > 0)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007729 Builder.AddChunk(CodeCompletionString::CK_Comma);
7730 Builder.AddTextChunk("...");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007731 }
Douglas Gregor636a61e2010-04-07 00:21:17 +00007732
Douglas Gregord37c59d2010-05-28 00:57:46 +00007733 if (IsInImplementation && Results.includeCodePatterns()) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00007734 // We will be defining the method here, so add a compound statement.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007735 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7736 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
7737 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
Alp Toker314cc812014-01-25 16:55:45 +00007738 if (!Method->getReturnType()->isVoidType()) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00007739 // If the result type is not void, add a return clause.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007740 Builder.AddTextChunk("return");
7741 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7742 Builder.AddPlaceholderChunk("expression");
7743 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007744 } else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007745 Builder.AddPlaceholderChunk("statements");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007746
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007747 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
7748 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007749 }
7750
Douglas Gregor416b5752010-08-25 01:08:01 +00007751 unsigned Priority = CCP_CodePattern;
Benjamin Kramereb8c4462013-06-29 17:52:13 +00007752 if (!M->second.getInt())
Douglas Gregor416b5752010-08-25 01:08:01 +00007753 Priority += CCD_InBaseClass;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007754
Douglas Gregor78254c82012-03-27 23:34:16 +00007755 Results.AddResult(Result(Builder.TakeString(), Method, Priority));
Douglas Gregor636a61e2010-04-07 00:21:17 +00007756 }
7757
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007758 // Add Key-Value-Coding and Key-Value-Observing accessor methods for all of
Douglas Gregor669a25a2011-02-17 00:22:45 +00007759 // the properties in this class and its categories.
David Blaikiebbafb8a2012-03-11 07:00:24 +00007760 if (Context.getLangOpts().ObjC2) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007761 SmallVector<ObjCContainerDecl *, 4> Containers;
Douglas Gregor669a25a2011-02-17 00:22:45 +00007762 Containers.push_back(SearchDecl);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007763
Douglas Gregord4a8ced2011-05-04 23:50:46 +00007764 VisitedSelectorSet KnownSelectors;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007765 for (KnownMethodsMap::iterator M = KnownMethods.begin(),
Douglas Gregord4a8ced2011-05-04 23:50:46 +00007766 MEnd = KnownMethods.end();
7767 M != MEnd; ++M)
7768 KnownSelectors.insert(M->first);
7769
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007770
Douglas Gregor669a25a2011-02-17 00:22:45 +00007771 ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(SearchDecl);
7772 if (!IFace)
7773 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(SearchDecl))
7774 IFace = Category->getClassInterface();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007775
Aaron Ballman3fe486a2014-03-13 21:23:55 +00007776 if (IFace)
7777 for (auto *Cat : IFace->visible_categories())
7778 Containers.push_back(Cat);
Alex Lorenzb8740422017-10-24 16:39:37 +00007779
7780 if (IsInstanceMethod) {
7781 for (unsigned I = 0, N = Containers.size(); I != N; ++I)
7782 for (auto *P : Containers[I]->instance_properties())
7783 AddObjCKeyValueCompletions(P, *IsInstanceMethod, ReturnType, Context,
7784 KnownSelectors, Results);
7785 }
Douglas Gregor669a25a2011-02-17 00:22:45 +00007786 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007787
Douglas Gregor636a61e2010-04-07 00:21:17 +00007788 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00007789
7790 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
7791 Results.data(), Results.size());
Douglas Gregor636a61e2010-04-07 00:21:17 +00007792}
Douglas Gregor95887f92010-07-08 23:20:03 +00007793
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007794void Sema::CodeCompleteObjCMethodDeclSelector(Scope *S,
Douglas Gregor95887f92010-07-08 23:20:03 +00007795 bool IsInstanceMethod,
Douglas Gregor45879692010-07-08 23:37:41 +00007796 bool AtParameterName,
John McCallba7bf592010-08-24 05:47:05 +00007797 ParsedType ReturnTy,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00007798 ArrayRef<IdentifierInfo *> SelIdents) {
Douglas Gregor95887f92010-07-08 23:20:03 +00007799 // If we have an external source, load the entire class method
Sebastian Redld44cd6a2010-08-18 23:57:06 +00007800 // pool from the AST file.
Douglas Gregor95887f92010-07-08 23:20:03 +00007801 if (ExternalSource) {
7802 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
7803 I != N; ++I) {
7804 Selector Sel = ExternalSource->GetExternalSelector(I);
Sebastian Redl75d8a322010-08-02 23:18:59 +00007805 if (Sel.isNull() || MethodPool.count(Sel))
Douglas Gregor95887f92010-07-08 23:20:03 +00007806 continue;
Sebastian Redl75d8a322010-08-02 23:18:59 +00007807
7808 ReadMethodPool(Sel);
Douglas Gregor95887f92010-07-08 23:20:03 +00007809 }
7810 }
7811
7812 // Build the set of methods we can see.
John McCall276321a2010-08-25 06:19:51 +00007813 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007814 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007815 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007816 CodeCompletionContext::CCC_Other);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007817
Douglas Gregor95887f92010-07-08 23:20:03 +00007818 if (ReturnTy)
7819 Results.setPreferredType(GetTypeFromParser(ReturnTy).getNonReferenceType());
Sebastian Redl75d8a322010-08-02 23:18:59 +00007820
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007821 Results.EnterNewScope();
Sebastian Redl75d8a322010-08-02 23:18:59 +00007822 for (GlobalMethodPool::iterator M = MethodPool.begin(),
7823 MEnd = MethodPool.end();
7824 M != MEnd; ++M) {
7825 for (ObjCMethodList *MethList = IsInstanceMethod ? &M->second.first :
7826 &M->second.second;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007827 MethList && MethList->getMethod();
Argyrios Kyrtzidisd3da6e02013-04-17 00:08:58 +00007828 MethList = MethList->getNext()) {
Nico Weber2e0c8f72014-12-27 03:58:08 +00007829 if (!isAcceptableObjCMethod(MethList->getMethod(), MK_Any, SelIdents))
Douglas Gregor95887f92010-07-08 23:20:03 +00007830 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007831
Douglas Gregor45879692010-07-08 23:37:41 +00007832 if (AtParameterName) {
7833 // Suggest parameter names we've seen before.
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00007834 unsigned NumSelIdents = SelIdents.size();
Nico Weber2e0c8f72014-12-27 03:58:08 +00007835 if (NumSelIdents &&
7836 NumSelIdents <= MethList->getMethod()->param_size()) {
7837 ParmVarDecl *Param =
7838 MethList->getMethod()->parameters()[NumSelIdents - 1];
Douglas Gregor45879692010-07-08 23:37:41 +00007839 if (Param->getIdentifier()) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007840 CodeCompletionBuilder Builder(Results.getAllocator(),
7841 Results.getCodeCompletionTUInfo());
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00007842 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007843 Param->getIdentifier()->getName()));
7844 Results.AddResult(Builder.TakeString());
Douglas Gregor45879692010-07-08 23:37:41 +00007845 }
7846 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007847
Douglas Gregor45879692010-07-08 23:37:41 +00007848 continue;
7849 }
Craig Topperc3ec1492014-05-26 06:22:03 +00007850
Nico Weber2e0c8f72014-12-27 03:58:08 +00007851 Result R(MethList->getMethod(),
7852 Results.getBasePriority(MethList->getMethod()), nullptr);
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00007853 R.StartParameter = SelIdents.size();
Douglas Gregor95887f92010-07-08 23:20:03 +00007854 R.AllParametersAreInformative = false;
7855 R.DeclaringEntity = true;
7856 Results.MaybeAddResult(R, CurContext);
7857 }
7858 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007859
Douglas Gregor95887f92010-07-08 23:20:03 +00007860 Results.ExitScope();
Alex Lorenz847fda12017-01-03 11:56:40 +00007861
7862 if (!AtParameterName && !SelIdents.empty() &&
7863 SelIdents.front()->getName().startswith("init")) {
7864 for (const auto &M : PP.macros()) {
7865 if (M.first->getName() != "NS_DESIGNATED_INITIALIZER")
7866 continue;
7867 Results.EnterNewScope();
7868 CodeCompletionBuilder Builder(Results.getAllocator(),
7869 Results.getCodeCompletionTUInfo());
7870 Builder.AddTypedTextChunk(
7871 Builder.getAllocator().CopyString(M.first->getName()));
7872 Results.AddResult(CodeCompletionResult(Builder.TakeString(), CCP_Macro,
7873 CXCursor_MacroDefinition));
7874 Results.ExitScope();
7875 }
7876 }
7877
Eric Liuf5ba09f2018-07-04 10:01:18 +00007878 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
7879 Results.data(), Results.size());
Douglas Gregor95887f92010-07-08 23:20:03 +00007880}
Douglas Gregorb14904c2010-08-13 22:48:40 +00007881
Douglas Gregorec00a262010-08-24 22:20:20 +00007882void Sema::CodeCompletePreprocessorDirective(bool InConditional) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007883 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007884 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00007885 CodeCompletionContext::CCC_PreprocessorDirective);
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007886 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007887
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007888 // #if <condition>
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007889 CodeCompletionBuilder Builder(Results.getAllocator(),
7890 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007891 Builder.AddTypedTextChunk("if");
7892 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7893 Builder.AddPlaceholderChunk("condition");
7894 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007895
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007896 // #ifdef <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007897 Builder.AddTypedTextChunk("ifdef");
7898 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7899 Builder.AddPlaceholderChunk("macro");
7900 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007901
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007902 // #ifndef <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007903 Builder.AddTypedTextChunk("ifndef");
7904 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7905 Builder.AddPlaceholderChunk("macro");
7906 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007907
7908 if (InConditional) {
7909 // #elif <condition>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007910 Builder.AddTypedTextChunk("elif");
7911 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7912 Builder.AddPlaceholderChunk("condition");
7913 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007914
7915 // #else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007916 Builder.AddTypedTextChunk("else");
7917 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007918
7919 // #endif
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007920 Builder.AddTypedTextChunk("endif");
7921 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007922 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007923
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007924 // #include "header"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007925 Builder.AddTypedTextChunk("include");
7926 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7927 Builder.AddTextChunk("\"");
7928 Builder.AddPlaceholderChunk("header");
7929 Builder.AddTextChunk("\"");
7930 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007931
7932 // #include <header>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007933 Builder.AddTypedTextChunk("include");
7934 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7935 Builder.AddTextChunk("<");
7936 Builder.AddPlaceholderChunk("header");
7937 Builder.AddTextChunk(">");
7938 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007939
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007940 // #define <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007941 Builder.AddTypedTextChunk("define");
7942 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7943 Builder.AddPlaceholderChunk("macro");
7944 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007945
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007946 // #define <macro>(<args>)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007947 Builder.AddTypedTextChunk("define");
7948 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7949 Builder.AddPlaceholderChunk("macro");
7950 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7951 Builder.AddPlaceholderChunk("args");
7952 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7953 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007954
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007955 // #undef <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007956 Builder.AddTypedTextChunk("undef");
7957 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7958 Builder.AddPlaceholderChunk("macro");
7959 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007960
7961 // #line <number>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007962 Builder.AddTypedTextChunk("line");
7963 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7964 Builder.AddPlaceholderChunk("number");
7965 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007966
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007967 // #line <number> "filename"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007968 Builder.AddTypedTextChunk("line");
7969 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7970 Builder.AddPlaceholderChunk("number");
7971 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7972 Builder.AddTextChunk("\"");
7973 Builder.AddPlaceholderChunk("filename");
7974 Builder.AddTextChunk("\"");
7975 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007976
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007977 // #error <message>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007978 Builder.AddTypedTextChunk("error");
7979 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7980 Builder.AddPlaceholderChunk("message");
7981 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007982
7983 // #pragma <arguments>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007984 Builder.AddTypedTextChunk("pragma");
7985 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7986 Builder.AddPlaceholderChunk("arguments");
7987 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007988
David Blaikiebbafb8a2012-03-11 07:00:24 +00007989 if (getLangOpts().ObjC1) {
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007990 // #import "header"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007991 Builder.AddTypedTextChunk("import");
7992 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7993 Builder.AddTextChunk("\"");
7994 Builder.AddPlaceholderChunk("header");
7995 Builder.AddTextChunk("\"");
7996 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007997
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007998 // #import <header>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007999 Builder.AddTypedTextChunk("import");
8000 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8001 Builder.AddTextChunk("<");
8002 Builder.AddPlaceholderChunk("header");
8003 Builder.AddTextChunk(">");
8004 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008005 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008006
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008007 // #include_next "header"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008008 Builder.AddTypedTextChunk("include_next");
8009 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8010 Builder.AddTextChunk("\"");
8011 Builder.AddPlaceholderChunk("header");
8012 Builder.AddTextChunk("\"");
8013 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008014
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008015 // #include_next <header>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008016 Builder.AddTypedTextChunk("include_next");
8017 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8018 Builder.AddTextChunk("<");
8019 Builder.AddPlaceholderChunk("header");
8020 Builder.AddTextChunk(">");
8021 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008022
8023 // #warning <message>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008024 Builder.AddTypedTextChunk("warning");
8025 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8026 Builder.AddPlaceholderChunk("message");
8027 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008028
8029 // Note: #ident and #sccs are such crazy anachronisms that we don't provide
8030 // completions for them. And __include_macros is a Clang-internal extension
8031 // that we don't want to encourage anyone to use.
8032
8033 // FIXME: we don't support #assert or #unassert, so don't suggest them.
8034 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00008035
8036 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008037 Results.data(), Results.size());
8038}
8039
8040void Sema::CodeCompleteInPreprocessorConditionalExclusion(Scope *S) {
Douglas Gregorec00a262010-08-24 22:20:20 +00008041 CodeCompleteOrdinaryName(S,
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008042 S->getFnParent()? Sema::PCC_RecoveryInFunction
John McCallfaf5fb42010-08-26 23:41:50 +00008043 : Sema::PCC_Namespace);
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008044}
8045
Douglas Gregorec00a262010-08-24 22:20:20 +00008046void Sema::CodeCompletePreprocessorMacroName(bool IsDefinition) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008047 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008048 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00008049 IsDefinition? CodeCompletionContext::CCC_MacroName
8050 : CodeCompletionContext::CCC_MacroNameUse);
Douglas Gregor12785102010-08-24 20:21:13 +00008051 if (!IsDefinition && (!CodeCompleter || CodeCompleter->includeMacros())) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008052 // Add just the names of macros, not their arguments.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008053 CodeCompletionBuilder Builder(Results.getAllocator(),
8054 Results.getCodeCompletionTUInfo());
Douglas Gregor12785102010-08-24 20:21:13 +00008055 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008056 for (Preprocessor::macro_iterator M = PP.macro_begin(),
Douglas Gregor12785102010-08-24 20:21:13 +00008057 MEnd = PP.macro_end();
8058 M != MEnd; ++M) {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00008059 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008060 M->first->getName()));
Argyrios Kyrtzidis5c8b1cd2012-09-27 00:24:09 +00008061 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
8062 CCP_CodePattern,
8063 CXCursor_MacroDefinition));
Douglas Gregor12785102010-08-24 20:21:13 +00008064 }
8065 Results.ExitScope();
8066 } else if (IsDefinition) {
8067 // FIXME: Can we detect when the user just wrote an include guard above?
8068 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008069
Douglas Gregor0ac41382010-09-23 23:01:17 +00008070 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008071 Results.data(), Results.size());
Douglas Gregor12785102010-08-24 20:21:13 +00008072}
8073
Douglas Gregorec00a262010-08-24 22:20:20 +00008074void Sema::CodeCompletePreprocessorExpression() {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008075 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008076 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00008077 CodeCompletionContext::CCC_PreprocessorExpression);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008078
Douglas Gregorec00a262010-08-24 22:20:20 +00008079 if (!CodeCompleter || CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00008080 AddMacroResults(PP, Results,
8081 CodeCompleter ? CodeCompleter->loadExternal() : false,
8082 true);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008083
Douglas Gregorec00a262010-08-24 22:20:20 +00008084 // defined (<macro>)
8085 Results.EnterNewScope();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008086 CodeCompletionBuilder Builder(Results.getAllocator(),
8087 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008088 Builder.AddTypedTextChunk("defined");
8089 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8090 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
8091 Builder.AddPlaceholderChunk("macro");
8092 Builder.AddChunk(CodeCompletionString::CK_RightParen);
8093 Results.AddResult(Builder.TakeString());
Douglas Gregorec00a262010-08-24 22:20:20 +00008094 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00008095
8096 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
8097 Results.data(), Results.size());
Douglas Gregorec00a262010-08-24 22:20:20 +00008098}
8099
8100void Sema::CodeCompletePreprocessorMacroArgument(Scope *S,
8101 IdentifierInfo *Macro,
8102 MacroInfo *MacroInfo,
8103 unsigned Argument) {
8104 // FIXME: In the future, we could provide "overload" results, much like we
8105 // do for function calls.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008106
Argyrios Kyrtzidis75f6cd22011-08-18 19:41:28 +00008107 // Now just ignore this. There will be another code-completion callback
8108 // for the expanded tokens.
Douglas Gregorec00a262010-08-24 22:20:20 +00008109}
8110
Sam McCall3d8051a2018-09-18 08:40:41 +00008111// This handles completion inside an #include filename, e.g. #include <foo/ba
8112// We look for the directory "foo" under each directory on the include path,
8113// list its files, and reassemble the appropriate #include.
8114void Sema::CodeCompleteIncludedFile(llvm::StringRef Dir, bool Angled) {
8115 // RelDir should use /, but unescaped \ is possible on windows!
8116 // Our completions will normalize to / for simplicity, this case is rare.
8117 std::string RelDir = llvm::sys::path::convert_to_slash(Dir);
8118 // We need the native slashes for the actual file system interactions.
8119 SmallString<128> NativeRelDir = StringRef(RelDir);
8120 llvm::sys::path::native(NativeRelDir);
8121 auto FS = getSourceManager().getFileManager().getVirtualFileSystem();
8122
8123 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
8124 CodeCompleter->getCodeCompletionTUInfo(),
8125 CodeCompletionContext::CCC_IncludedFile);
8126 llvm::DenseSet<StringRef> SeenResults; // To deduplicate results.
8127
8128 // Helper: adds one file or directory completion result.
8129 auto AddCompletion = [&](StringRef Filename, bool IsDirectory) {
8130 SmallString<64> TypedChunk = Filename;
8131 // Directory completion is up to the slash, e.g. <sys/
8132 TypedChunk.push_back(IsDirectory ? '/' : Angled ? '>' : '"');
8133 auto R = SeenResults.insert(TypedChunk);
8134 if (R.second) { // New completion
8135 const char *InternedTyped = Results.getAllocator().CopyString(TypedChunk);
8136 *R.first = InternedTyped; // Avoid dangling StringRef.
8137 CodeCompletionBuilder Builder(CodeCompleter->getAllocator(),
8138 CodeCompleter->getCodeCompletionTUInfo());
8139 Builder.AddTypedTextChunk(InternedTyped);
8140 // The result is a "Pattern", which is pretty opaque.
8141 // We may want to include the real filename to allow smart ranking.
8142 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
8143 }
8144 };
8145
8146 // Helper: scans IncludeDir for nice files, and adds results for each.
8147 auto AddFilesFromIncludeDir = [&](StringRef IncludeDir, bool IsSystem) {
8148 llvm::SmallString<128> Dir = IncludeDir;
8149 if (!NativeRelDir.empty())
8150 llvm::sys::path::append(Dir, NativeRelDir);
8151
8152 std::error_code EC;
8153 unsigned Count = 0;
8154 for (auto It = FS->dir_begin(Dir, EC);
8155 !EC && It != vfs::directory_iterator(); It.increment(EC)) {
8156 if (++Count == 2500) // If we happen to hit a huge directory,
8157 break; // bail out early so we're not too slow.
8158 StringRef Filename = llvm::sys::path::filename(It->path());
8159 switch (It->type()) {
8160 case llvm::sys::fs::file_type::directory_file:
8161 AddCompletion(Filename, /*IsDirectory=*/true);
8162 break;
8163 case llvm::sys::fs::file_type::regular_file:
8164 // Only files that really look like headers. (Except in system dirs).
8165 if (!IsSystem) {
8166 // Header extensions from Types.def, which we can't depend on here.
8167 if (!(Filename.endswith_lower(".h") ||
8168 Filename.endswith_lower(".hh") ||
8169 Filename.endswith_lower(".hpp") ||
8170 Filename.endswith_lower(".inc")))
8171 break;
8172 }
8173 AddCompletion(Filename, /*IsDirectory=*/false);
8174 break;
8175 default:
8176 break;
8177 }
8178 }
8179 };
8180
8181 // Helper: adds results relative to IncludeDir, if possible.
8182 auto AddFilesFromDirLookup = [&](const DirectoryLookup &IncludeDir,
8183 bool IsSystem) {
8184 llvm::SmallString<128> Dir;
8185 switch (IncludeDir.getLookupType()) {
8186 case DirectoryLookup::LT_HeaderMap:
8187 // header maps are not (currently) enumerable.
8188 break;
8189 case DirectoryLookup::LT_NormalDir:
8190 AddFilesFromIncludeDir(IncludeDir.getDir()->getName(), IsSystem);
8191 break;
8192 case DirectoryLookup::LT_Framework:
8193 AddFilesFromIncludeDir(IncludeDir.getFrameworkDir()->getName(), IsSystem);
8194 break;
8195 }
8196 };
8197
8198 // Finally with all our helpers, we can scan the include path.
8199 // Do this in standard order so deduplication keeps the right file.
8200 // (In case we decide to add more details to the results later).
8201 const auto &S = PP.getHeaderSearchInfo();
8202 using llvm::make_range;
8203 if (!Angled) {
8204 // The current directory is on the include path for "quoted" includes.
8205 auto *CurFile = PP.getCurrentFileLexer()->getFileEntry();
8206 if (CurFile && CurFile->getDir())
8207 AddFilesFromIncludeDir(CurFile->getDir()->getName(), false);
8208 for (const auto &D : make_range(S.quoted_dir_begin(), S.quoted_dir_end()))
8209 AddFilesFromDirLookup(D, false);
8210 }
8211 for (const auto &D : make_range(S.angled_dir_begin(), S.angled_dir_end()))
Sam McCall3e4f5eb2018-10-01 11:56:42 +00008212 AddFilesFromDirLookup(D, false);
Sam McCall3d8051a2018-09-18 08:40:41 +00008213 for (const auto &D : make_range(S.system_dir_begin(), S.system_dir_end()))
8214 AddFilesFromDirLookup(D, true);
8215
8216 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
8217 Results.data(), Results.size());
8218}
8219
Douglas Gregor11583702010-08-25 17:04:25 +00008220void Sema::CodeCompleteNaturalLanguage() {
Douglas Gregor11583702010-08-25 17:04:25 +00008221 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregorea736372010-08-25 17:10:00 +00008222 CodeCompletionContext::CCC_NaturalLanguage,
Craig Topperc3ec1492014-05-26 06:22:03 +00008223 nullptr, 0);
Douglas Gregor11583702010-08-25 17:04:25 +00008224}
8225
Alex Lorenzf7f6f822017-05-09 16:05:04 +00008226void Sema::CodeCompleteAvailabilityPlatformName() {
8227 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
8228 CodeCompleter->getCodeCompletionTUInfo(),
8229 CodeCompletionContext::CCC_Other);
8230 Results.EnterNewScope();
8231 static const char *Platforms[] = {"macOS", "iOS", "watchOS", "tvOS"};
8232 for (const char *Platform : llvm::makeArrayRef(Platforms)) {
8233 Results.AddResult(CodeCompletionResult(Platform));
8234 Results.AddResult(CodeCompletionResult(Results.getAllocator().CopyString(
8235 Twine(Platform) + "ApplicationExtension")));
8236 }
8237 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00008238 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
8239 Results.data(), Results.size());
Alex Lorenzf7f6f822017-05-09 16:05:04 +00008240}
8241
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00008242void Sema::GatherGlobalCodeCompletions(CodeCompletionAllocator &Allocator,
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008243 CodeCompletionTUInfo &CCTUInfo,
Chris Lattner0e62c1c2011-07-23 10:55:15 +00008244 SmallVectorImpl<CodeCompletionResult> &Results) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008245 ResultBuilder Builder(*this, Allocator, CCTUInfo,
8246 CodeCompletionContext::CCC_Recovery);
Douglas Gregor39982192010-08-15 06:18:01 +00008247 if (!CodeCompleter || CodeCompleter->includeGlobals()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008248 CodeCompletionDeclConsumer Consumer(Builder,
Douglas Gregor39982192010-08-15 06:18:01 +00008249 Context.getTranslationUnitDecl());
Sam McCallbb2cf632018-01-12 14:51:47 +00008250 LookupVisibleDecls(Context.getTranslationUnitDecl(), LookupAnyName,
8251 Consumer,
8252 !CodeCompleter || CodeCompleter->loadExternal());
Douglas Gregor39982192010-08-15 06:18:01 +00008253 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008254
Douglas Gregorb14904c2010-08-13 22:48:40 +00008255 if (!CodeCompleter || CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00008256 AddMacroResults(PP, Builder,
8257 CodeCompleter ? CodeCompleter->loadExternal() : false,
8258 true);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008259
Douglas Gregorb14904c2010-08-13 22:48:40 +00008260 Results.clear();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008261 Results.insert(Results.end(),
Douglas Gregorb14904c2010-08-13 22:48:40 +00008262 Builder.data(), Builder.data() + Builder.size());
8263}