blob: acf43650bb423d907416c005a4c3244cbf8f2b55 [file] [log] [blame]
Douglas Gregor2436e712009-09-17 21:32:03 +00001//===---------------- SemaCodeComplete.cpp - Code Completion ----*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file defines the code-completion semantic actions.
11//
12//===----------------------------------------------------------------------===//
Ilya Biryukov4e7a6fe2017-09-22 19:07:37 +000013#include "clang/AST/DeclCXX.h"
John McCallde6836a2010-08-24 07:21:54 +000014#include "clang/AST/DeclObjC.h"
Douglas Gregorf2510672009-09-21 19:57:38 +000015#include "clang/AST/ExprCXX.h"
Douglas Gregor8ce33212009-11-17 17:59:40 +000016#include "clang/AST/ExprObjC.h"
Ilya Biryukovb5da91c2017-11-08 10:39:09 +000017#include "clang/AST/QualTypeNames.h"
Jordan Rose4938f272013-02-09 10:09:43 +000018#include "clang/Basic/CharInfo.h"
Douglas Gregor07f43572012-01-29 18:15:03 +000019#include "clang/Lex/HeaderSearch.h"
Douglas Gregorf329c7c2009-10-30 16:50:04 +000020#include "clang/Lex/MacroInfo.h"
21#include "clang/Lex/Preprocessor.h"
Chandler Carruth3a022472012-12-04 09:13:33 +000022#include "clang/Sema/CodeCompleteConsumer.h"
Chandler Carruth3a022472012-12-04 09:13:33 +000023#include "clang/Sema/Lookup.h"
24#include "clang/Sema/Overload.h"
25#include "clang/Sema/Scope.h"
26#include "clang/Sema/ScopeInfo.h"
Ilya Biryukov4e7a6fe2017-09-22 19:07:37 +000027#include "clang/Sema/SemaInternal.h"
Douglas Gregor1154e272010-09-16 16:06:31 +000028#include "llvm/ADT/DenseSet.h"
Benjamin Kramere0513cb2012-01-30 16:17:39 +000029#include "llvm/ADT/SmallBitVector.h"
Douglas Gregor3545ff42009-09-21 16:56:56 +000030#include "llvm/ADT/SmallPtrSet.h"
Benjamin Kramer49038022012-02-04 13:45:25 +000031#include "llvm/ADT/SmallString.h"
Douglas Gregore6688e62009-09-28 03:51:44 +000032#include "llvm/ADT/StringExtras.h"
Douglas Gregor9d2ddb22010-04-06 19:22:33 +000033#include "llvm/ADT/StringSwitch.h"
Douglas Gregor67c692c2010-08-26 15:07:07 +000034#include "llvm/ADT/Twine.h"
Sam McCall3d8051a2018-09-18 08:40:41 +000035#include "llvm/ADT/iterator_range.h"
36#include "llvm/Support/Path.h"
Douglas Gregor3545ff42009-09-21 16:56:56 +000037#include <list>
38#include <map>
39#include <vector>
Douglas Gregor2436e712009-09-17 21:32:03 +000040
41using namespace clang;
John McCallaab3e412010-08-25 08:40:02 +000042using namespace sema;
Douglas Gregor2436e712009-09-17 21:32:03 +000043
Douglas Gregor3545ff42009-09-21 16:56:56 +000044namespace {
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000045 /// A container of code-completion results.
Douglas Gregor3545ff42009-09-21 16:56:56 +000046 class ResultBuilder {
47 public:
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000048 /// The type of a name-lookup filter, which can be provided to the
Douglas Gregor3545ff42009-09-21 16:56:56 +000049 /// name-lookup routines to specify which declarations should be included in
50 /// the result set (when it returns true) and which declarations should be
51 /// filtered out (returns false).
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +000052 typedef bool (ResultBuilder::*LookupFilter)(const NamedDecl *) const;
Ivan Donchevskii13d90542017-10-27 11:05:40 +000053
John McCall276321a2010-08-25 06:19:51 +000054 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +000055
Douglas Gregor3545ff42009-09-21 16:56:56 +000056 private:
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000057 /// The actual results we have found.
Douglas Gregor3545ff42009-09-21 16:56:56 +000058 std::vector<Result> Results;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +000059
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000060 /// A record of all of the declarations we have found and placed
Douglas Gregor3545ff42009-09-21 16:56:56 +000061 /// into the result set, used to ensure that no declaration ever gets into
62 /// the result set twice.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +000063 llvm::SmallPtrSet<const Decl*, 16> AllDeclsFound;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +000064
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +000065 typedef std::pair<const NamedDecl *, unsigned> DeclIndexPair;
Douglas Gregor05e7ca32009-12-06 20:23:50 +000066
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000067 /// An entry in the shadow map, which is optimized to store
Douglas Gregor05e7ca32009-12-06 20:23:50 +000068 /// a single (declaration, index) mapping (the common case) but
69 /// can also store a list of (declaration, index) mappings.
70 class ShadowMapEntry {
Chris Lattner0e62c1c2011-07-23 10:55:15 +000071 typedef SmallVector<DeclIndexPair, 4> DeclIndexPairVector;
Douglas Gregor05e7ca32009-12-06 20:23:50 +000072
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000073 /// Contains either the solitary NamedDecl * or a vector
Douglas Gregor05e7ca32009-12-06 20:23:50 +000074 /// of (declaration, index) pairs.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +000075 llvm::PointerUnion<const NamedDecl *, DeclIndexPairVector*> DeclOrVector;
Douglas Gregor05e7ca32009-12-06 20:23:50 +000076
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000077 /// When the entry contains a single declaration, this is
Douglas Gregor05e7ca32009-12-06 20:23:50 +000078 /// the index associated with that entry.
79 unsigned SingleDeclIndex;
80
81 public:
82 ShadowMapEntry() : DeclOrVector(), SingleDeclIndex(0) { }
83
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +000084 void Add(const NamedDecl *ND, unsigned Index) {
Douglas Gregor05e7ca32009-12-06 20:23:50 +000085 if (DeclOrVector.isNull()) {
86 // 0 - > 1 elements: just set the single element information.
87 DeclOrVector = ND;
88 SingleDeclIndex = Index;
89 return;
90 }
91
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +000092 if (const NamedDecl *PrevND =
93 DeclOrVector.dyn_cast<const NamedDecl *>()) {
Douglas Gregor05e7ca32009-12-06 20:23:50 +000094 // 1 -> 2 elements: create the vector of results and push in the
95 // existing declaration.
96 DeclIndexPairVector *Vec = new DeclIndexPairVector;
97 Vec->push_back(DeclIndexPair(PrevND, SingleDeclIndex));
98 DeclOrVector = Vec;
99 }
100
101 // Add the new element to the end of the vector.
102 DeclOrVector.get<DeclIndexPairVector*>()->push_back(
103 DeclIndexPair(ND, Index));
104 }
105
106 void Destroy() {
107 if (DeclIndexPairVector *Vec
108 = DeclOrVector.dyn_cast<DeclIndexPairVector *>()) {
109 delete Vec;
Craig Topperc3ec1492014-05-26 06:22:03 +0000110 DeclOrVector = ((NamedDecl *)nullptr);
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000111 }
112 }
113
114 // Iteration.
115 class iterator;
116 iterator begin() const;
117 iterator end() const;
118 };
119
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000120 /// A mapping from declaration names to the declarations that have
Douglas Gregor3545ff42009-09-21 16:56:56 +0000121 /// this name within a particular scope and their index within the list of
122 /// results.
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000123 typedef llvm::DenseMap<DeclarationName, ShadowMapEntry> ShadowMap;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000124
125 /// The semantic analysis object for which results are being
Douglas Gregor3545ff42009-09-21 16:56:56 +0000126 /// produced.
127 Sema &SemaRef;
Douglas Gregorb278aaf2011-02-01 19:23:04 +0000128
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000129 /// The allocator used to allocate new code-completion strings.
Douglas Gregorbcbf46c2011-02-01 22:57:45 +0000130 CodeCompletionAllocator &Allocator;
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +0000131
132 CodeCompletionTUInfo &CCTUInfo;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000133
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000134 /// If non-NULL, a filter function used to remove any code-completion
Douglas Gregor3545ff42009-09-21 16:56:56 +0000135 /// results that are not desirable.
136 LookupFilter Filter;
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000137
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000138 /// Whether we should allow declarations as
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000139 /// nested-name-specifiers that would otherwise be filtered out.
140 bool AllowNestedNameSpecifiers;
141
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000142 /// If set, the type that we would prefer our resulting value
Douglas Gregor7aa6b222010-05-30 01:49:25 +0000143 /// declarations to have.
144 ///
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000145 /// Closely matching the preferred type gives a boost to a result's
Douglas Gregor7aa6b222010-05-30 01:49:25 +0000146 /// priority.
147 CanQualType PreferredType;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000148
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000149 /// A list of shadow maps, which is used to model name hiding at
Douglas Gregor3545ff42009-09-21 16:56:56 +0000150 /// different levels of, e.g., the inheritance hierarchy.
151 std::list<ShadowMap> ShadowMaps;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000152
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000153 /// If we're potentially referring to a C++ member function, the set
Douglas Gregor9be0ed42010-08-26 16:36:48 +0000154 /// of qualifiers applied to the object type.
155 Qualifiers ObjectTypeQualifiers;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000156
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000157 /// Whether the \p ObjectTypeQualifiers field is active.
Douglas Gregor9be0ed42010-08-26 16:36:48 +0000158 bool HasObjectTypeQualifiers;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000159
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000160 /// The selector that we prefer.
Douglas Gregorc2cb2e22010-08-27 15:29:55 +0000161 Selector PreferredSelector;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000162
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000163 /// The completion context in which we are gathering results.
Douglas Gregor50832e02010-09-20 22:39:41 +0000164 CodeCompletionContext CompletionContext;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000165
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000166 /// If we are in an instance method definition, the \@implementation
Douglas Gregor05fcf842010-11-02 20:36:02 +0000167 /// object.
168 ObjCImplementationDecl *ObjCImplementation;
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000169
Douglas Gregor50832e02010-09-20 22:39:41 +0000170 void AdjustResultPriorityForDecl(Result &R);
Douglas Gregor95887f92010-07-08 23:20:03 +0000171
Douglas Gregor0212fd72010-09-21 16:06:22 +0000172 void MaybeAddConstructorResults(Result R);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000173
Douglas Gregor3545ff42009-09-21 16:56:56 +0000174 public:
Douglas Gregorbcbf46c2011-02-01 22:57:45 +0000175 explicit ResultBuilder(Sema &SemaRef, CodeCompletionAllocator &Allocator,
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +0000176 CodeCompletionTUInfo &CCTUInfo,
Douglas Gregor0ac41382010-09-23 23:01:17 +0000177 const CodeCompletionContext &CompletionContext,
Craig Topperc3ec1492014-05-26 06:22:03 +0000178 LookupFilter Filter = nullptr)
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +0000179 : SemaRef(SemaRef), Allocator(Allocator), CCTUInfo(CCTUInfo),
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000180 Filter(Filter),
181 AllowNestedNameSpecifiers(false), HasObjectTypeQualifiers(false),
Douglas Gregor05fcf842010-11-02 20:36:02 +0000182 CompletionContext(CompletionContext),
Craig Topperc3ec1492014-05-26 06:22:03 +0000183 ObjCImplementation(nullptr)
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000184 {
185 // If this is an Objective-C instance method definition, dig out the
Douglas Gregor05fcf842010-11-02 20:36:02 +0000186 // corresponding implementation.
187 switch (CompletionContext.getKind()) {
188 case CodeCompletionContext::CCC_Expression:
189 case CodeCompletionContext::CCC_ObjCMessageReceiver:
190 case CodeCompletionContext::CCC_ParenthesizedExpression:
191 case CodeCompletionContext::CCC_Statement:
192 case CodeCompletionContext::CCC_Recovery:
193 if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl())
194 if (Method->isInstanceMethod())
195 if (ObjCInterfaceDecl *Interface = Method->getClassInterface())
196 ObjCImplementation = Interface->getImplementation();
197 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000198
Douglas Gregor05fcf842010-11-02 20:36:02 +0000199 default:
200 break;
201 }
202 }
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000203
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000204 /// Determine the priority for a reference to the given declaration.
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000205 unsigned getBasePriority(const NamedDecl *D);
206
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000207 /// Whether we should include code patterns in the completion
Douglas Gregorf64acca2010-05-25 21:41:55 +0000208 /// results.
209 bool includeCodePatterns() const {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000210 return SemaRef.CodeCompleter &&
Douglas Gregorac322ec2010-08-27 21:18:54 +0000211 SemaRef.CodeCompleter->includeCodePatterns();
Douglas Gregorf64acca2010-05-25 21:41:55 +0000212 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000213
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000214 /// Set the filter used for code-completion results.
Douglas Gregor3545ff42009-09-21 16:56:56 +0000215 void setFilter(LookupFilter Filter) {
216 this->Filter = Filter;
217 }
Craig Topperc3ec1492014-05-26 06:22:03 +0000218
219 Result *data() { return Results.empty()? nullptr : &Results.front(); }
Douglas Gregor3545ff42009-09-21 16:56:56 +0000220 unsigned size() const { return Results.size(); }
221 bool empty() const { return Results.empty(); }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000222
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000223 /// Specify the preferred type.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000224 void setPreferredType(QualType T) {
225 PreferredType = SemaRef.Context.getCanonicalType(T);
Douglas Gregor7aa6b222010-05-30 01:49:25 +0000226 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000227
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000228 /// Set the cv-qualifiers on the object type, for us in filtering
Douglas Gregor9be0ed42010-08-26 16:36:48 +0000229 /// calls to member functions.
230 ///
231 /// When there are qualifiers in this set, they will be used to filter
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000232 /// out member functions that aren't available (because there will be a
Douglas Gregor9be0ed42010-08-26 16:36:48 +0000233 /// cv-qualifier mismatch) or prefer functions with an exact qualifier
234 /// match.
235 void setObjectTypeQualifiers(Qualifiers Quals) {
236 ObjectTypeQualifiers = Quals;
237 HasObjectTypeQualifiers = true;
238 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000239
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000240 /// Set the preferred selector.
Douglas Gregorc2cb2e22010-08-27 15:29:55 +0000241 ///
242 /// When an Objective-C method declaration result is added, and that
243 /// method's selector matches this preferred selector, we give that method
244 /// a slight priority boost.
245 void setPreferredSelector(Selector Sel) {
246 PreferredSelector = Sel;
247 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000248
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000249 /// Retrieve the code-completion context for which results are
Douglas Gregor50832e02010-09-20 22:39:41 +0000250 /// being collected.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000251 const CodeCompletionContext &getCompletionContext() const {
252 return CompletionContext;
Douglas Gregor50832e02010-09-20 22:39:41 +0000253 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000254
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000255 /// Specify whether nested-name-specifiers are allowed.
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000256 void allowNestedNameSpecifiers(bool Allow = true) {
257 AllowNestedNameSpecifiers = Allow;
258 }
259
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000260 /// Return the semantic analysis object for which we are collecting
Douglas Gregor74661272010-09-21 00:03:25 +0000261 /// code completion results.
262 Sema &getSema() const { return SemaRef; }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000263
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000264 /// Retrieve the allocator used to allocate code completion strings.
Douglas Gregorbcbf46c2011-02-01 22:57:45 +0000265 CodeCompletionAllocator &getAllocator() const { return Allocator; }
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +0000266
267 CodeCompletionTUInfo &getCodeCompletionTUInfo() const { return CCTUInfo; }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000268
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000269 /// Determine whether the given declaration is at all interesting
Douglas Gregor7c208612010-01-14 00:20:49 +0000270 /// as a code-completion result.
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000271 ///
272 /// \param ND the declaration that we are inspecting.
273 ///
274 /// \param AsNestedNameSpecifier will be set true if this declaration is
275 /// only interesting when it is a nested-name-specifier.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000276 bool isInterestingDecl(const NamedDecl *ND,
277 bool &AsNestedNameSpecifier) const;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000278
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000279 /// Check whether the result is hidden by the Hiding declaration.
Douglas Gregore0717ab2010-01-14 00:41:07 +0000280 ///
281 /// \returns true if the result is hidden and cannot be found, false if
282 /// the hidden result could still be found. When false, \p R may be
283 /// modified to describe how the result can be found (e.g., via extra
284 /// qualification).
285 bool CheckHiddenResult(Result &R, DeclContext *CurContext,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000286 const NamedDecl *Hiding);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000287
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000288 /// Add a new result to this result set (if it isn't already in one
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000289 /// of the shadow maps), or replace an existing result (for, e.g., a
Douglas Gregor3545ff42009-09-21 16:56:56 +0000290 /// redeclaration).
Douglas Gregor2af2f672009-09-21 20:12:40 +0000291 ///
Douglas Gregord8c61782012-02-15 15:34:24 +0000292 /// \param R the result to add (if it is unique).
Douglas Gregor2af2f672009-09-21 20:12:40 +0000293 ///
Douglas Gregord8c61782012-02-15 15:34:24 +0000294 /// \param CurContext the context in which this result will be named.
Craig Topperc3ec1492014-05-26 06:22:03 +0000295 void MaybeAddResult(Result R, DeclContext *CurContext = nullptr);
296
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000297 /// Add a new result to this result set, where we already know
Yaron Keren8fbe43982014-11-14 18:33:42 +0000298 /// the hiding declaration (if any).
Douglas Gregorc580c522010-01-14 01:09:38 +0000299 ///
300 /// \param R the result to add (if it is unique).
301 ///
302 /// \param CurContext the context in which this result will be named.
303 ///
304 /// \param Hiding the declaration that hides the result.
Douglas Gregor09bbc652010-01-14 15:47:35 +0000305 ///
306 /// \param InBaseClass whether the result was found in a base
307 /// class of the searched context.
308 void AddResult(Result R, DeclContext *CurContext, NamedDecl *Hiding,
309 bool InBaseClass);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000310
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000311 /// Add a new non-declaration result to this result set.
Douglas Gregor78a21012010-01-14 16:01:26 +0000312 void AddResult(Result R);
313
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000314 /// Enter into a new scope.
Douglas Gregor3545ff42009-09-21 16:56:56 +0000315 void EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000316
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000317 /// Exit from the current scope.
Douglas Gregor3545ff42009-09-21 16:56:56 +0000318 void ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000319
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000320 /// Ignore this declaration, if it is seen again.
Dmitri Gribenko6cfb1532013-02-14 13:53:30 +0000321 void Ignore(const Decl *D) { AllDeclsFound.insert(D->getCanonicalDecl()); }
Douglas Gregorbaf69612009-11-18 04:19:12 +0000322
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000323 /// Add a visited context.
Haojian Wu10d95c52018-01-17 14:29:25 +0000324 void addVisitedContext(DeclContext *Ctx) {
325 CompletionContext.addVisitedContext(Ctx);
326 }
327
Douglas Gregor3545ff42009-09-21 16:56:56 +0000328 /// \name Name lookup predicates
329 ///
330 /// These predicates can be passed to the name lookup functions to filter the
331 /// results of name lookup. All of the predicates have the same type, so that
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000332 ///
Douglas Gregor3545ff42009-09-21 16:56:56 +0000333 //@{
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000334 bool IsOrdinaryName(const NamedDecl *ND) const;
335 bool IsOrdinaryNonTypeName(const NamedDecl *ND) const;
336 bool IsIntegralConstantValue(const NamedDecl *ND) const;
337 bool IsOrdinaryNonValueName(const NamedDecl *ND) const;
338 bool IsNestedNameSpecifier(const NamedDecl *ND) const;
339 bool IsEnum(const NamedDecl *ND) const;
340 bool IsClassOrStruct(const NamedDecl *ND) const;
341 bool IsUnion(const NamedDecl *ND) const;
342 bool IsNamespace(const NamedDecl *ND) const;
343 bool IsNamespaceOrAlias(const NamedDecl *ND) const;
344 bool IsType(const NamedDecl *ND) const;
345 bool IsMember(const NamedDecl *ND) const;
346 bool IsObjCIvar(const NamedDecl *ND) const;
347 bool IsObjCMessageReceiver(const NamedDecl *ND) const;
348 bool IsObjCMessageReceiverOrLambdaCapture(const NamedDecl *ND) const;
349 bool IsObjCCollection(const NamedDecl *ND) const;
350 bool IsImpossibleToSatisfy(const NamedDecl *ND) const;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000351 //@}
352 };
Alexander Kornienkoab9db512015-06-22 23:07:51 +0000353}
Douglas Gregor3545ff42009-09-21 16:56:56 +0000354
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000355class ResultBuilder::ShadowMapEntry::iterator {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000356 llvm::PointerUnion<const NamedDecl *, const DeclIndexPair *> DeclOrIterator;
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000357 unsigned SingleDeclIndex;
358
359public:
360 typedef DeclIndexPair value_type;
361 typedef value_type reference;
362 typedef std::ptrdiff_t difference_type;
363 typedef std::input_iterator_tag iterator_category;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000364
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000365 class pointer {
366 DeclIndexPair Value;
367
368 public:
369 pointer(const DeclIndexPair &Value) : Value(Value) { }
370
371 const DeclIndexPair *operator->() const {
372 return &Value;
373 }
374 };
Craig Topperc3ec1492014-05-26 06:22:03 +0000375
376 iterator() : DeclOrIterator((NamedDecl *)nullptr), SingleDeclIndex(0) {}
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000377
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000378 iterator(const NamedDecl *SingleDecl, unsigned Index)
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000379 : DeclOrIterator(SingleDecl), SingleDeclIndex(Index) { }
380
381 iterator(const DeclIndexPair *Iterator)
382 : DeclOrIterator(Iterator), SingleDeclIndex(0) { }
383
384 iterator &operator++() {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000385 if (DeclOrIterator.is<const NamedDecl *>()) {
Craig Topperc3ec1492014-05-26 06:22:03 +0000386 DeclOrIterator = (NamedDecl *)nullptr;
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000387 SingleDeclIndex = 0;
388 return *this;
389 }
390
391 const DeclIndexPair *I = DeclOrIterator.get<const DeclIndexPair*>();
392 ++I;
393 DeclOrIterator = I;
394 return *this;
395 }
396
Chris Lattner9795b392010-09-04 18:12:20 +0000397 /*iterator operator++(int) {
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000398 iterator tmp(*this);
399 ++(*this);
400 return tmp;
Chris Lattner9795b392010-09-04 18:12:20 +0000401 }*/
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000402
403 reference operator*() const {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000404 if (const NamedDecl *ND = DeclOrIterator.dyn_cast<const NamedDecl *>())
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000405 return reference(ND, SingleDeclIndex);
406
Douglas Gregor94bb5e82009-12-06 21:27:58 +0000407 return *DeclOrIterator.get<const DeclIndexPair*>();
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000408 }
409
410 pointer operator->() const {
411 return pointer(**this);
412 }
413
414 friend bool operator==(const iterator &X, const iterator &Y) {
Douglas Gregor94bb5e82009-12-06 21:27:58 +0000415 return X.DeclOrIterator.getOpaqueValue()
416 == Y.DeclOrIterator.getOpaqueValue() &&
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000417 X.SingleDeclIndex == Y.SingleDeclIndex;
418 }
419
420 friend bool operator!=(const iterator &X, const iterator &Y) {
Douglas Gregor94bb5e82009-12-06 21:27:58 +0000421 return !(X == Y);
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000422 }
423};
424
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000425ResultBuilder::ShadowMapEntry::iterator
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000426ResultBuilder::ShadowMapEntry::begin() const {
427 if (DeclOrVector.isNull())
428 return iterator();
429
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000430 if (const NamedDecl *ND = DeclOrVector.dyn_cast<const NamedDecl *>())
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000431 return iterator(ND, SingleDeclIndex);
432
433 return iterator(DeclOrVector.get<DeclIndexPairVector *>()->begin());
434}
435
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000436ResultBuilder::ShadowMapEntry::iterator
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000437ResultBuilder::ShadowMapEntry::end() const {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000438 if (DeclOrVector.is<const NamedDecl *>() || DeclOrVector.isNull())
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000439 return iterator();
440
441 return iterator(DeclOrVector.get<DeclIndexPairVector *>()->end());
442}
443
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000444/// Compute the qualification required to get from the current context
Douglas Gregor2af2f672009-09-21 20:12:40 +0000445/// (\p CurContext) to the target context (\p TargetContext).
446///
447/// \param Context the AST context in which the qualification will be used.
448///
449/// \param CurContext the context where an entity is being named, which is
450/// typically based on the current scope.
451///
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000452/// \param TargetContext the context in which the named entity actually
Douglas Gregor2af2f672009-09-21 20:12:40 +0000453/// resides.
454///
455/// \returns a nested name specifier that refers into the target context, or
456/// NULL if no qualification is needed.
457static NestedNameSpecifier *
458getRequiredQualification(ASTContext &Context,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000459 const DeclContext *CurContext,
460 const DeclContext *TargetContext) {
461 SmallVector<const DeclContext *, 4> TargetParents;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000462
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000463 for (const DeclContext *CommonAncestor = TargetContext;
Douglas Gregor2af2f672009-09-21 20:12:40 +0000464 CommonAncestor && !CommonAncestor->Encloses(CurContext);
465 CommonAncestor = CommonAncestor->getLookupParent()) {
466 if (CommonAncestor->isTransparentContext() ||
467 CommonAncestor->isFunctionOrMethod())
468 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000469
Douglas Gregor2af2f672009-09-21 20:12:40 +0000470 TargetParents.push_back(CommonAncestor);
471 }
Craig Topperc3ec1492014-05-26 06:22:03 +0000472
473 NestedNameSpecifier *Result = nullptr;
Douglas Gregor2af2f672009-09-21 20:12:40 +0000474 while (!TargetParents.empty()) {
Robert Wilhelm25284cc2013-08-23 16:11:15 +0000475 const DeclContext *Parent = TargetParents.pop_back_val();
476
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000477 if (const NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Parent)) {
Douglas Gregor68762e72010-08-23 21:17:50 +0000478 if (!Namespace->getIdentifier())
479 continue;
480
Douglas Gregor2af2f672009-09-21 20:12:40 +0000481 Result = NestedNameSpecifier::Create(Context, Result, Namespace);
Douglas Gregor68762e72010-08-23 21:17:50 +0000482 }
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000483 else if (const TagDecl *TD = dyn_cast<TagDecl>(Parent))
Douglas Gregor2af2f672009-09-21 20:12:40 +0000484 Result = NestedNameSpecifier::Create(Context, Result,
485 false,
486 Context.getTypeDeclType(TD).getTypePtr());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000487 }
Douglas Gregor2af2f672009-09-21 20:12:40 +0000488 return Result;
489}
490
Alp Toker034bbd52014-06-30 01:33:53 +0000491/// Determine whether \p Id is a name reserved for the implementation (C99
492/// 7.1.3, C++ [lib.global.names]).
Argyrios Kyrtzidis5d8006d2016-07-01 01:17:02 +0000493static bool isReservedName(const IdentifierInfo *Id,
494 bool doubleUnderscoreOnly = false) {
Alp Toker034bbd52014-06-30 01:33:53 +0000495 if (Id->getLength() < 2)
496 return false;
497 const char *Name = Id->getNameStart();
498 return Name[0] == '_' &&
Argyrios Kyrtzidis5d8006d2016-07-01 01:17:02 +0000499 (Name[1] == '_' || (Name[1] >= 'A' && Name[1] <= 'Z' &&
500 !doubleUnderscoreOnly));
501}
502
503// Some declarations have reserved names that we don't want to ever show.
504// Filter out names reserved for the implementation if they come from a
505// system header.
506static bool shouldIgnoreDueToReservedName(const NamedDecl *ND, Sema &SemaRef) {
507 const IdentifierInfo *Id = ND->getIdentifier();
508 if (!Id)
509 return false;
510
511 // Ignore reserved names for compiler provided decls.
512 if (isReservedName(Id) && ND->getLocation().isInvalid())
513 return true;
514
515 // For system headers ignore only double-underscore names.
516 // This allows for system headers providing private symbols with a single
517 // underscore.
518 if (isReservedName(Id, /*doubleUnderscoreOnly=*/true) &&
519 SemaRef.SourceMgr.isInSystemHeader(
520 SemaRef.SourceMgr.getSpellingLoc(ND->getLocation())))
521 return true;
522
523 return false;
Alp Toker034bbd52014-06-30 01:33:53 +0000524}
525
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000526bool ResultBuilder::isInterestingDecl(const NamedDecl *ND,
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000527 bool &AsNestedNameSpecifier) const {
528 AsNestedNameSpecifier = false;
529
Richard Smithf2005d32015-12-29 23:34:32 +0000530 auto *Named = ND;
Douglas Gregor7c208612010-01-14 00:20:49 +0000531 ND = ND->getUnderlyingDecl();
Douglas Gregor58acf322009-10-09 22:16:47 +0000532
533 // Skip unnamed entities.
Douglas Gregor7c208612010-01-14 00:20:49 +0000534 if (!ND->getDeclName())
535 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000536
Douglas Gregor3545ff42009-09-21 16:56:56 +0000537 // Friend declarations and declarations introduced due to friends are never
538 // added as results.
Richard Smith6eece292015-01-15 02:27:20 +0000539 if (ND->getFriendObjectKind() == Decl::FOK_Undeclared)
Douglas Gregor7c208612010-01-14 00:20:49 +0000540 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000541
Douglas Gregor99fe2ad2009-12-11 17:31:05 +0000542 // Class template (partial) specializations are never added as results.
Douglas Gregor7c208612010-01-14 00:20:49 +0000543 if (isa<ClassTemplateSpecializationDecl>(ND) ||
544 isa<ClassTemplatePartialSpecializationDecl>(ND))
545 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000546
Douglas Gregor99fe2ad2009-12-11 17:31:05 +0000547 // Using declarations themselves are never added as results.
Douglas Gregor7c208612010-01-14 00:20:49 +0000548 if (isa<UsingDecl>(ND))
549 return false;
Argyrios Kyrtzidis5d8006d2016-07-01 01:17:02 +0000550
551 if (shouldIgnoreDueToReservedName(ND, SemaRef))
552 return false;
Douglas Gregor2927c0c2010-11-09 03:59:40 +0000553
Douglas Gregor59cab552010-08-16 23:05:20 +0000554 if (Filter == &ResultBuilder::IsNestedNameSpecifier ||
Richard Smithf2005d32015-12-29 23:34:32 +0000555 (isa<NamespaceDecl>(ND) &&
Douglas Gregor59cab552010-08-16 23:05:20 +0000556 Filter != &ResultBuilder::IsNamespace &&
Douglas Gregor0ac41382010-09-23 23:01:17 +0000557 Filter != &ResultBuilder::IsNamespaceOrAlias &&
Craig Topperc3ec1492014-05-26 06:22:03 +0000558 Filter != nullptr))
Douglas Gregor59cab552010-08-16 23:05:20 +0000559 AsNestedNameSpecifier = true;
560
Douglas Gregor3545ff42009-09-21 16:56:56 +0000561 // Filter out any unwanted results.
Richard Smithf2005d32015-12-29 23:34:32 +0000562 if (Filter && !(this->*Filter)(Named)) {
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000563 // Check whether it is interesting as a nested-name-specifier.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000564 if (AllowNestedNameSpecifiers && SemaRef.getLangOpts().CPlusPlus &&
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000565 IsNestedNameSpecifier(ND) &&
566 (Filter != &ResultBuilder::IsMember ||
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000567 (isa<CXXRecordDecl>(ND) &&
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000568 cast<CXXRecordDecl>(ND)->isInjectedClassName()))) {
569 AsNestedNameSpecifier = true;
570 return true;
571 }
572
Douglas Gregor7c208612010-01-14 00:20:49 +0000573 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000574 }
Douglas Gregor7c208612010-01-14 00:20:49 +0000575 // ... then it must be interesting!
576 return true;
577}
578
Douglas Gregore0717ab2010-01-14 00:41:07 +0000579bool ResultBuilder::CheckHiddenResult(Result &R, DeclContext *CurContext,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000580 const NamedDecl *Hiding) {
Douglas Gregore0717ab2010-01-14 00:41:07 +0000581 // In C, there is no way to refer to a hidden name.
582 // FIXME: This isn't true; we can find a tag name hidden by an ordinary
583 // name if we introduce the tag type.
David Blaikiebbafb8a2012-03-11 07:00:24 +0000584 if (!SemaRef.getLangOpts().CPlusPlus)
Douglas Gregore0717ab2010-01-14 00:41:07 +0000585 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000586
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000587 const DeclContext *HiddenCtx =
588 R.Declaration->getDeclContext()->getRedeclContext();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000589
Douglas Gregore0717ab2010-01-14 00:41:07 +0000590 // There is no way to qualify a name declared in a function or method.
591 if (HiddenCtx->isFunctionOrMethod())
592 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000593
Sebastian Redl50c68252010-08-31 00:36:30 +0000594 if (HiddenCtx == Hiding->getDeclContext()->getRedeclContext())
Douglas Gregore0717ab2010-01-14 00:41:07 +0000595 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000596
Douglas Gregore0717ab2010-01-14 00:41:07 +0000597 // We can refer to the result with the appropriate qualification. Do it.
598 R.Hidden = true;
599 R.QualifierIsInformative = false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000600
Douglas Gregore0717ab2010-01-14 00:41:07 +0000601 if (!R.Qualifier)
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000602 R.Qualifier = getRequiredQualification(SemaRef.Context,
603 CurContext,
Douglas Gregore0717ab2010-01-14 00:41:07 +0000604 R.Declaration->getDeclContext());
605 return false;
606}
607
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000608/// A simplified classification of types used to determine whether two
Douglas Gregor95887f92010-07-08 23:20:03 +0000609/// types are "similar enough" when adjusting priorities.
Douglas Gregor6e240332010-08-16 16:18:59 +0000610SimplifiedTypeClass clang::getSimplifiedTypeClass(CanQualType T) {
Douglas Gregor95887f92010-07-08 23:20:03 +0000611 switch (T->getTypeClass()) {
612 case Type::Builtin:
613 switch (cast<BuiltinType>(T)->getKind()) {
614 case BuiltinType::Void:
615 return STC_Void;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000616
Douglas Gregor95887f92010-07-08 23:20:03 +0000617 case BuiltinType::NullPtr:
618 return STC_Pointer;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000619
Douglas Gregor95887f92010-07-08 23:20:03 +0000620 case BuiltinType::Overload:
621 case BuiltinType::Dependent:
Douglas Gregor95887f92010-07-08 23:20:03 +0000622 return STC_Other;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000623
Douglas Gregor95887f92010-07-08 23:20:03 +0000624 case BuiltinType::ObjCId:
625 case BuiltinType::ObjCClass:
626 case BuiltinType::ObjCSel:
627 return STC_ObjectiveC;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000628
Douglas Gregor95887f92010-07-08 23:20:03 +0000629 default:
630 return STC_Arithmetic;
631 }
David Blaikie8a40f702012-01-17 06:56:22 +0000632
Douglas Gregor95887f92010-07-08 23:20:03 +0000633 case Type::Complex:
634 return STC_Arithmetic;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000635
Douglas Gregor95887f92010-07-08 23:20:03 +0000636 case Type::Pointer:
637 return STC_Pointer;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000638
Douglas Gregor95887f92010-07-08 23:20:03 +0000639 case Type::BlockPointer:
640 return STC_Block;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000641
Douglas Gregor95887f92010-07-08 23:20:03 +0000642 case Type::LValueReference:
643 case Type::RValueReference:
644 return getSimplifiedTypeClass(T->getAs<ReferenceType>()->getPointeeType());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000645
Douglas Gregor95887f92010-07-08 23:20:03 +0000646 case Type::ConstantArray:
647 case Type::IncompleteArray:
648 case Type::VariableArray:
649 case Type::DependentSizedArray:
650 return STC_Array;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000651
Douglas Gregor95887f92010-07-08 23:20:03 +0000652 case Type::DependentSizedExtVector:
653 case Type::Vector:
654 case Type::ExtVector:
655 return STC_Arithmetic;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000656
Douglas Gregor95887f92010-07-08 23:20:03 +0000657 case Type::FunctionProto:
658 case Type::FunctionNoProto:
659 return STC_Function;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000660
Douglas Gregor95887f92010-07-08 23:20:03 +0000661 case Type::Record:
662 return STC_Record;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000663
Douglas Gregor95887f92010-07-08 23:20:03 +0000664 case Type::Enum:
665 return STC_Arithmetic;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000666
Douglas Gregor95887f92010-07-08 23:20:03 +0000667 case Type::ObjCObject:
668 case Type::ObjCInterface:
669 case Type::ObjCObjectPointer:
670 return STC_ObjectiveC;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000671
Douglas Gregor95887f92010-07-08 23:20:03 +0000672 default:
673 return STC_Other;
674 }
675}
676
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000677/// Get the type that a given expression will have if this declaration
Douglas Gregor95887f92010-07-08 23:20:03 +0000678/// is used as an expression in its "typical" code-completion form.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000679QualType clang::getDeclUsageType(ASTContext &C, const NamedDecl *ND) {
George Burgess IV00f70bd2018-03-01 05:43:23 +0000680 ND = ND->getUnderlyingDecl();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000681
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000682 if (const TypeDecl *Type = dyn_cast<TypeDecl>(ND))
Douglas Gregor95887f92010-07-08 23:20:03 +0000683 return C.getTypeDeclType(Type);
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000684 if (const ObjCInterfaceDecl *Iface = dyn_cast<ObjCInterfaceDecl>(ND))
Douglas Gregor95887f92010-07-08 23:20:03 +0000685 return C.getObjCInterfaceType(Iface);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000686
Douglas Gregor95887f92010-07-08 23:20:03 +0000687 QualType T;
Alp Tokera2794f92014-01-22 07:29:52 +0000688 if (const FunctionDecl *Function = ND->getAsFunction())
Douglas Gregor603d81b2010-07-13 08:18:22 +0000689 T = Function->getCallResultType();
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000690 else if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND))
Douglas Gregor603d81b2010-07-13 08:18:22 +0000691 T = Method->getSendResultType();
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000692 else if (const EnumConstantDecl *Enumerator = dyn_cast<EnumConstantDecl>(ND))
Douglas Gregor95887f92010-07-08 23:20:03 +0000693 T = C.getTypeDeclType(cast<EnumDecl>(Enumerator->getDeclContext()));
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000694 else if (const ObjCPropertyDecl *Property = dyn_cast<ObjCPropertyDecl>(ND))
Douglas Gregor95887f92010-07-08 23:20:03 +0000695 T = Property->getType();
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000696 else if (const ValueDecl *Value = dyn_cast<ValueDecl>(ND))
Douglas Gregor95887f92010-07-08 23:20:03 +0000697 T = Value->getType();
698 else
699 return QualType();
Douglas Gregoraf670a82011-04-14 20:33:34 +0000700
701 // Dig through references, function pointers, and block pointers to
702 // get down to the likely type of an expression when the entity is
703 // used.
704 do {
705 if (const ReferenceType *Ref = T->getAs<ReferenceType>()) {
706 T = Ref->getPointeeType();
707 continue;
708 }
709
710 if (const PointerType *Pointer = T->getAs<PointerType>()) {
711 if (Pointer->getPointeeType()->isFunctionType()) {
712 T = Pointer->getPointeeType();
713 continue;
714 }
715
716 break;
717 }
718
719 if (const BlockPointerType *Block = T->getAs<BlockPointerType>()) {
720 T = Block->getPointeeType();
721 continue;
722 }
723
724 if (const FunctionType *Function = T->getAs<FunctionType>()) {
Alp Toker314cc812014-01-25 16:55:45 +0000725 T = Function->getReturnType();
Douglas Gregoraf670a82011-04-14 20:33:34 +0000726 continue;
727 }
728
729 break;
730 } while (true);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000731
Douglas Gregoraf670a82011-04-14 20:33:34 +0000732 return T;
Douglas Gregor95887f92010-07-08 23:20:03 +0000733}
734
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000735unsigned ResultBuilder::getBasePriority(const NamedDecl *ND) {
736 if (!ND)
737 return CCP_Unlikely;
738
739 // Context-based decisions.
Richard Smith541b38b2013-09-20 01:15:31 +0000740 const DeclContext *LexicalDC = ND->getLexicalDeclContext();
741 if (LexicalDC->isFunctionOrMethod()) {
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000742 // _cmd is relatively rare
743 if (const ImplicitParamDecl *ImplicitParam =
744 dyn_cast<ImplicitParamDecl>(ND))
745 if (ImplicitParam->getIdentifier() &&
746 ImplicitParam->getIdentifier()->isStr("_cmd"))
747 return CCP_ObjC_cmd;
748
749 return CCP_LocalDeclaration;
750 }
Richard Smith541b38b2013-09-20 01:15:31 +0000751
752 const DeclContext *DC = ND->getDeclContext()->getRedeclContext();
Ilya Biryukov4e7a6fe2017-09-22 19:07:37 +0000753 if (DC->isRecord() || isa<ObjCContainerDecl>(DC)) {
754 // Explicit destructor calls are very rare.
755 if (isa<CXXDestructorDecl>(ND))
756 return CCP_Unlikely;
757 // Explicit operator and conversion function calls are also very rare.
758 auto DeclNameKind = ND->getDeclName().getNameKind();
759 if (DeclNameKind == DeclarationName::CXXOperatorName ||
760 DeclNameKind == DeclarationName::CXXLiteralOperatorName ||
761 DeclNameKind == DeclarationName::CXXConversionFunctionName)
762 return CCP_Unlikely;
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000763 return CCP_MemberDeclaration;
Ilya Biryukov4e7a6fe2017-09-22 19:07:37 +0000764 }
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000765
766 // Content-based decisions.
767 if (isa<EnumConstantDecl>(ND))
768 return CCP_Constant;
769
Douglas Gregor52e0de42013-01-31 05:03:46 +0000770 // Use CCP_Type for type declarations unless we're in a statement, Objective-C
771 // message receiver, or parenthesized expression context. There, it's as
772 // likely that the user will want to write a type as other declarations.
773 if ((isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND)) &&
774 !(CompletionContext.getKind() == CodeCompletionContext::CCC_Statement ||
775 CompletionContext.getKind()
776 == CodeCompletionContext::CCC_ObjCMessageReceiver ||
777 CompletionContext.getKind()
778 == CodeCompletionContext::CCC_ParenthesizedExpression))
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000779 return CCP_Type;
780
781 return CCP_Declaration;
782}
783
Douglas Gregor50832e02010-09-20 22:39:41 +0000784void ResultBuilder::AdjustResultPriorityForDecl(Result &R) {
785 // If this is an Objective-C method declaration whose selector matches our
786 // preferred selector, give it a priority boost.
787 if (!PreferredSelector.isNull())
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000788 if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(R.Declaration))
Douglas Gregor50832e02010-09-20 22:39:41 +0000789 if (PreferredSelector == Method->getSelector())
790 R.Priority += CCD_SelectorMatch;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000791
Douglas Gregor50832e02010-09-20 22:39:41 +0000792 // If we have a preferred type, adjust the priority for results with exactly-
793 // matching or nearly-matching types.
794 if (!PreferredType.isNull()) {
795 QualType T = getDeclUsageType(SemaRef.Context, R.Declaration);
796 if (!T.isNull()) {
797 CanQualType TC = SemaRef.Context.getCanonicalType(T);
798 // Check for exactly-matching types (modulo qualifiers).
799 if (SemaRef.Context.hasSameUnqualifiedType(PreferredType, TC))
800 R.Priority /= CCF_ExactTypeMatch;
801 // Check for nearly-matching types, based on classification of each.
802 else if ((getSimplifiedTypeClass(PreferredType)
Douglas Gregor95887f92010-07-08 23:20:03 +0000803 == getSimplifiedTypeClass(TC)) &&
Douglas Gregor50832e02010-09-20 22:39:41 +0000804 !(PreferredType->isEnumeralType() && TC->isEnumeralType()))
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000805 R.Priority /= CCF_SimilarTypeMatch;
Douglas Gregor50832e02010-09-20 22:39:41 +0000806 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000807 }
Douglas Gregor95887f92010-07-08 23:20:03 +0000808}
809
Douglas Gregor0212fd72010-09-21 16:06:22 +0000810void ResultBuilder::MaybeAddConstructorResults(Result R) {
David Blaikiebbafb8a2012-03-11 07:00:24 +0000811 if (!SemaRef.getLangOpts().CPlusPlus || !R.Declaration ||
Douglas Gregor0212fd72010-09-21 16:06:22 +0000812 !CompletionContext.wantConstructorResults())
813 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000814
Douglas Gregor0212fd72010-09-21 16:06:22 +0000815 ASTContext &Context = SemaRef.Context;
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000816 const NamedDecl *D = R.Declaration;
Craig Topperc3ec1492014-05-26 06:22:03 +0000817 const CXXRecordDecl *Record = nullptr;
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000818 if (const ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(D))
Douglas Gregor0212fd72010-09-21 16:06:22 +0000819 Record = ClassTemplate->getTemplatedDecl();
820 else if ((Record = dyn_cast<CXXRecordDecl>(D))) {
821 // Skip specializations and partial specializations.
822 if (isa<ClassTemplateSpecializationDecl>(Record))
823 return;
824 } else {
825 // There are no constructors here.
826 return;
827 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000828
Douglas Gregor0212fd72010-09-21 16:06:22 +0000829 Record = Record->getDefinition();
830 if (!Record)
831 return;
832
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000833
Douglas Gregor0212fd72010-09-21 16:06:22 +0000834 QualType RecordTy = Context.getTypeDeclType(Record);
835 DeclarationName ConstructorName
836 = Context.DeclarationNames.getCXXConstructorName(
837 Context.getCanonicalType(RecordTy));
Richard Smithcf4bdde2015-02-21 02:45:19 +0000838 DeclContext::lookup_result Ctors = Record->lookup(ConstructorName);
839 for (DeclContext::lookup_iterator I = Ctors.begin(),
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000840 E = Ctors.end();
841 I != E; ++I) {
David Blaikieff7d47a2012-12-19 00:45:41 +0000842 R.Declaration = *I;
Douglas Gregor0212fd72010-09-21 16:06:22 +0000843 R.CursorKind = getCursorKindForDecl(R.Declaration);
844 Results.push_back(R);
845 }
846}
847
Sam McCall63c59722018-01-22 20:44:47 +0000848static bool isConstructor(const Decl *ND) {
849 if (const auto *Tmpl = dyn_cast<FunctionTemplateDecl>(ND))
850 ND = Tmpl->getTemplatedDecl();
851 return isa<CXXConstructorDecl>(ND);
852}
853
Douglas Gregor7c208612010-01-14 00:20:49 +0000854void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) {
855 assert(!ShadowMaps.empty() && "Must enter into a results scope");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000856
Douglas Gregor7c208612010-01-14 00:20:49 +0000857 if (R.Kind != Result::RK_Declaration) {
858 // For non-declaration results, just add the result.
859 Results.push_back(R);
860 return;
861 }
862
863 // Look through using declarations.
Kirill Bobyrev47d7f522018-07-11 14:49:49 +0000864 if (const UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(R.Declaration)) {
865 CodeCompletionResult Result(Using->getTargetDecl(),
866 getBasePriority(Using->getTargetDecl()),
867 R.Qualifier);
868 Result.ShadowDecl = Using;
869 MaybeAddResult(Result, CurContext);
Douglas Gregor7c208612010-01-14 00:20:49 +0000870 return;
871 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000872
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000873 const Decl *CanonDecl = R.Declaration->getCanonicalDecl();
Douglas Gregor7c208612010-01-14 00:20:49 +0000874 unsigned IDNS = CanonDecl->getIdentifierNamespace();
875
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000876 bool AsNestedNameSpecifier = false;
877 if (!isInterestingDecl(R.Declaration, AsNestedNameSpecifier))
Douglas Gregor7c208612010-01-14 00:20:49 +0000878 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000879
Douglas Gregor0212fd72010-09-21 16:06:22 +0000880 // C++ constructors are never found by name lookup.
Sam McCall63c59722018-01-22 20:44:47 +0000881 if (isConstructor(R.Declaration))
Douglas Gregor0212fd72010-09-21 16:06:22 +0000882 return;
883
Douglas Gregor3545ff42009-09-21 16:56:56 +0000884 ShadowMap &SMap = ShadowMaps.back();
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000885 ShadowMapEntry::iterator I, IEnd;
886 ShadowMap::iterator NamePos = SMap.find(R.Declaration->getDeclName());
887 if (NamePos != SMap.end()) {
888 I = NamePos->second.begin();
889 IEnd = NamePos->second.end();
890 }
891
892 for (; I != IEnd; ++I) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000893 const NamedDecl *ND = I->first;
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000894 unsigned Index = I->second;
Douglas Gregor3545ff42009-09-21 16:56:56 +0000895 if (ND->getCanonicalDecl() == CanonDecl) {
896 // This is a redeclaration. Always pick the newer declaration.
Douglas Gregor3545ff42009-09-21 16:56:56 +0000897 Results[Index].Declaration = R.Declaration;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000898
Douglas Gregor3545ff42009-09-21 16:56:56 +0000899 // We're done.
900 return;
901 }
902 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000903
Douglas Gregor3545ff42009-09-21 16:56:56 +0000904 // This is a new declaration in this scope. However, check whether this
905 // declaration name is hidden by a similarly-named declaration in an outer
906 // scope.
907 std::list<ShadowMap>::iterator SM, SMEnd = ShadowMaps.end();
908 --SMEnd;
909 for (SM = ShadowMaps.begin(); SM != SMEnd; ++SM) {
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000910 ShadowMapEntry::iterator I, IEnd;
911 ShadowMap::iterator NamePos = SM->find(R.Declaration->getDeclName());
912 if (NamePos != SM->end()) {
913 I = NamePos->second.begin();
914 IEnd = NamePos->second.end();
915 }
916 for (; I != IEnd; ++I) {
Douglas Gregor3545ff42009-09-21 16:56:56 +0000917 // A tag declaration does not hide a non-tag declaration.
John McCalle87beb22010-04-23 18:46:30 +0000918 if (I->first->hasTagIdentifierNamespace() &&
Richard Smith541b38b2013-09-20 01:15:31 +0000919 (IDNS & (Decl::IDNS_Member | Decl::IDNS_Ordinary |
920 Decl::IDNS_LocalExtern | Decl::IDNS_ObjCProtocol)))
Douglas Gregor3545ff42009-09-21 16:56:56 +0000921 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000922
Douglas Gregor3545ff42009-09-21 16:56:56 +0000923 // Protocols are in distinct namespaces from everything else.
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000924 if (((I->first->getIdentifierNamespace() & Decl::IDNS_ObjCProtocol)
Douglas Gregor3545ff42009-09-21 16:56:56 +0000925 || (IDNS & Decl::IDNS_ObjCProtocol)) &&
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000926 I->first->getIdentifierNamespace() != IDNS)
Douglas Gregor3545ff42009-09-21 16:56:56 +0000927 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000928
Douglas Gregor3545ff42009-09-21 16:56:56 +0000929 // The newly-added result is hidden by an entry in the shadow map.
Douglas Gregore0717ab2010-01-14 00:41:07 +0000930 if (CheckHiddenResult(R, CurContext, I->first))
Douglas Gregor3545ff42009-09-21 16:56:56 +0000931 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000932
Douglas Gregor3545ff42009-09-21 16:56:56 +0000933 break;
934 }
935 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000936
Douglas Gregor3545ff42009-09-21 16:56:56 +0000937 // Make sure that any given declaration only shows up in the result set once.
David Blaikie82e95a32014-11-19 07:49:47 +0000938 if (!AllDeclsFound.insert(CanonDecl).second)
Douglas Gregor3545ff42009-09-21 16:56:56 +0000939 return;
Douglas Gregorc2cb2e22010-08-27 15:29:55 +0000940
Douglas Gregore412a5a2009-09-23 22:26:46 +0000941 // If the filter is for nested-name-specifiers, then this result starts a
942 // nested-name-specifier.
Douglas Gregora2db7932010-05-26 22:00:08 +0000943 if (AsNestedNameSpecifier) {
Douglas Gregore412a5a2009-09-23 22:26:46 +0000944 R.StartsNestedNameSpecifier = true;
Douglas Gregora2db7932010-05-26 22:00:08 +0000945 R.Priority = CCP_NestedNameSpecifier;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000946 } else
Douglas Gregor50832e02010-09-20 22:39:41 +0000947 AdjustResultPriorityForDecl(R);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000948
Douglas Gregor5bf52692009-09-22 23:15:58 +0000949 // If this result is supposed to have an informative qualifier, add one.
Douglas Gregore412a5a2009-09-23 22:26:46 +0000950 if (R.QualifierIsInformative && !R.Qualifier &&
951 !R.StartsNestedNameSpecifier) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000952 const DeclContext *Ctx = R.Declaration->getDeclContext();
953 if (const NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Ctx))
Craig Topperc3ec1492014-05-26 06:22:03 +0000954 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, nullptr,
955 Namespace);
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000956 else if (const TagDecl *Tag = dyn_cast<TagDecl>(Ctx))
Craig Topperc3ec1492014-05-26 06:22:03 +0000957 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, nullptr,
958 false, SemaRef.Context.getTypeDeclType(Tag).getTypePtr());
Douglas Gregor5bf52692009-09-22 23:15:58 +0000959 else
960 R.QualifierIsInformative = false;
961 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000962
Douglas Gregor3545ff42009-09-21 16:56:56 +0000963 // Insert this result into the set of results and into the current shadow
964 // map.
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000965 SMap[R.Declaration->getDeclName()].Add(R.Declaration, Results.size());
Douglas Gregor3545ff42009-09-21 16:56:56 +0000966 Results.push_back(R);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000967
Douglas Gregor0212fd72010-09-21 16:06:22 +0000968 if (!AsNestedNameSpecifier)
969 MaybeAddConstructorResults(R);
Douglas Gregor3545ff42009-09-21 16:56:56 +0000970}
971
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000972void ResultBuilder::AddResult(Result R, DeclContext *CurContext,
Douglas Gregor09bbc652010-01-14 15:47:35 +0000973 NamedDecl *Hiding, bool InBaseClass = false) {
Douglas Gregor78a21012010-01-14 16:01:26 +0000974 if (R.Kind != Result::RK_Declaration) {
975 // For non-declaration results, just add the result.
976 Results.push_back(R);
977 return;
978 }
979
Douglas Gregorc580c522010-01-14 01:09:38 +0000980 // Look through using declarations.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000981 if (const UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(R.Declaration)) {
Kirill Bobyrev47d7f522018-07-11 14:49:49 +0000982 CodeCompletionResult Result(Using->getTargetDecl(),
983 getBasePriority(Using->getTargetDecl()),
984 R.Qualifier);
985 Result.ShadowDecl = Using;
986 AddResult(Result, CurContext, Hiding);
Douglas Gregorc580c522010-01-14 01:09:38 +0000987 return;
988 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000989
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000990 bool AsNestedNameSpecifier = false;
991 if (!isInterestingDecl(R.Declaration, AsNestedNameSpecifier))
Douglas Gregorc580c522010-01-14 01:09:38 +0000992 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000993
Douglas Gregor0212fd72010-09-21 16:06:22 +0000994 // C++ constructors are never found by name lookup.
Sam McCall63c59722018-01-22 20:44:47 +0000995 if (isConstructor(R.Declaration))
Douglas Gregor0212fd72010-09-21 16:06:22 +0000996 return;
997
Douglas Gregorc580c522010-01-14 01:09:38 +0000998 if (Hiding && CheckHiddenResult(R, CurContext, Hiding))
999 return;
Nick Lewyckyc3921482012-04-03 21:44:08 +00001000
Douglas Gregorc580c522010-01-14 01:09:38 +00001001 // Make sure that any given declaration only shows up in the result set once.
David Blaikie82e95a32014-11-19 07:49:47 +00001002 if (!AllDeclsFound.insert(R.Declaration->getCanonicalDecl()).second)
Douglas Gregorc580c522010-01-14 01:09:38 +00001003 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001004
Douglas Gregorc580c522010-01-14 01:09:38 +00001005 // If the filter is for nested-name-specifiers, then this result starts a
1006 // nested-name-specifier.
Douglas Gregora2db7932010-05-26 22:00:08 +00001007 if (AsNestedNameSpecifier) {
Douglas Gregorc580c522010-01-14 01:09:38 +00001008 R.StartsNestedNameSpecifier = true;
Douglas Gregora2db7932010-05-26 22:00:08 +00001009 R.Priority = CCP_NestedNameSpecifier;
Kirill Bobyrev47d7f522018-07-11 14:49:49 +00001010 } else if (Filter == &ResultBuilder::IsMember && !R.Qualifier &&
1011 InBaseClass &&
1012 isa<CXXRecordDecl>(
1013 R.Declaration->getDeclContext()->getRedeclContext()))
Douglas Gregor09bbc652010-01-14 15:47:35 +00001014 R.QualifierIsInformative = true;
1015
Douglas Gregorc580c522010-01-14 01:09:38 +00001016 // If this result is supposed to have an informative qualifier, add one.
1017 if (R.QualifierIsInformative && !R.Qualifier &&
1018 !R.StartsNestedNameSpecifier) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001019 const DeclContext *Ctx = R.Declaration->getDeclContext();
1020 if (const NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Ctx))
Craig Topperc3ec1492014-05-26 06:22:03 +00001021 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, nullptr,
1022 Namespace);
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001023 else if (const TagDecl *Tag = dyn_cast<TagDecl>(Ctx))
Craig Topperc3ec1492014-05-26 06:22:03 +00001024 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, nullptr, false,
Douglas Gregor6ae4c522010-01-14 03:21:49 +00001025 SemaRef.Context.getTypeDeclType(Tag).getTypePtr());
Douglas Gregorc580c522010-01-14 01:09:38 +00001026 else
1027 R.QualifierIsInformative = false;
1028 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001029
Douglas Gregora2db7932010-05-26 22:00:08 +00001030 // Adjust the priority if this result comes from a base class.
1031 if (InBaseClass)
1032 R.Priority += CCD_InBaseClass;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001033
Douglas Gregor50832e02010-09-20 22:39:41 +00001034 AdjustResultPriorityForDecl(R);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001035
Douglas Gregor9be0ed42010-08-26 16:36:48 +00001036 if (HasObjectTypeQualifiers)
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001037 if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(R.Declaration))
Douglas Gregor9be0ed42010-08-26 16:36:48 +00001038 if (Method->isInstance()) {
1039 Qualifiers MethodQuals
1040 = Qualifiers::fromCVRMask(Method->getTypeQualifiers());
1041 if (ObjectTypeQualifiers == MethodQuals)
1042 R.Priority += CCD_ObjectQualifierMatch;
1043 else if (ObjectTypeQualifiers - MethodQuals) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001044 // The method cannot be invoked, because doing so would drop
Douglas Gregor9be0ed42010-08-26 16:36:48 +00001045 // qualifiers.
1046 return;
1047 }
1048 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001049
Douglas Gregorc580c522010-01-14 01:09:38 +00001050 // Insert this result into the set of results.
1051 Results.push_back(R);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001052
Douglas Gregor0212fd72010-09-21 16:06:22 +00001053 if (!AsNestedNameSpecifier)
1054 MaybeAddConstructorResults(R);
Douglas Gregorc580c522010-01-14 01:09:38 +00001055}
1056
Douglas Gregor78a21012010-01-14 16:01:26 +00001057void ResultBuilder::AddResult(Result R) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001058 assert(R.Kind != Result::RK_Declaration &&
Douglas Gregor78a21012010-01-14 16:01:26 +00001059 "Declaration results need more context");
1060 Results.push_back(R);
1061}
1062
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001063/// Enter into a new scope.
Benjamin Kramer3204b152015-05-29 19:42:19 +00001064void ResultBuilder::EnterNewScope() { ShadowMaps.emplace_back(); }
Douglas Gregor3545ff42009-09-21 16:56:56 +00001065
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001066/// Exit from the current scope.
Douglas Gregor3545ff42009-09-21 16:56:56 +00001067void ResultBuilder::ExitScope() {
Douglas Gregor05e7ca32009-12-06 20:23:50 +00001068 for (ShadowMap::iterator E = ShadowMaps.back().begin(),
1069 EEnd = ShadowMaps.back().end();
1070 E != EEnd;
1071 ++E)
1072 E->second.Destroy();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001073
Douglas Gregor3545ff42009-09-21 16:56:56 +00001074 ShadowMaps.pop_back();
1075}
1076
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001077/// Determines whether this given declaration will be found by
Douglas Gregor9d64c5e2009-09-21 20:51:25 +00001078/// ordinary name lookup.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001079bool ResultBuilder::IsOrdinaryName(const NamedDecl *ND) const {
George Burgess IV00f70bd2018-03-01 05:43:23 +00001080 ND = ND->getUnderlyingDecl();
Douglas Gregor70febae2010-05-28 00:49:12 +00001081
Richard Smith541b38b2013-09-20 01:15:31 +00001082 // If name lookup finds a local extern declaration, then we are in a
1083 // context where it behaves like an ordinary name.
1084 unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_LocalExtern;
David Blaikiebbafb8a2012-03-11 07:00:24 +00001085 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregor9858ed52010-06-15 20:26:51 +00001086 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member;
David Blaikiebbafb8a2012-03-11 07:00:24 +00001087 else if (SemaRef.getLangOpts().ObjC1) {
Douglas Gregor05fcf842010-11-02 20:36:02 +00001088 if (isa<ObjCIvarDecl>(ND))
1089 return true;
Douglas Gregor05fcf842010-11-02 20:36:02 +00001090 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001091
Douglas Gregor9d64c5e2009-09-21 20:51:25 +00001092 return ND->getIdentifierNamespace() & IDNS;
1093}
1094
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001095/// Determines whether this given declaration will be found by
Douglas Gregor70febae2010-05-28 00:49:12 +00001096/// ordinary name lookup but is not a type name.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001097bool ResultBuilder::IsOrdinaryNonTypeName(const NamedDecl *ND) const {
George Burgess IV00f70bd2018-03-01 05:43:23 +00001098 ND = ND->getUnderlyingDecl();
Alex Lorenzf3df1f72017-11-14 01:46:24 +00001099 if (isa<TypeDecl>(ND))
Douglas Gregor70febae2010-05-28 00:49:12 +00001100 return false;
Alex Lorenzf3df1f72017-11-14 01:46:24 +00001101 // Objective-C interfaces names are not filtered by this method because they
1102 // can be used in a class property expression. We can still filter out
1103 // @class declarations though.
1104 if (const auto *ID = dyn_cast<ObjCInterfaceDecl>(ND)) {
1105 if (!ID->getDefinition())
1106 return false;
1107 }
1108
Richard Smith541b38b2013-09-20 01:15:31 +00001109 unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_LocalExtern;
David Blaikiebbafb8a2012-03-11 07:00:24 +00001110 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregor9858ed52010-06-15 20:26:51 +00001111 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member;
David Blaikiebbafb8a2012-03-11 07:00:24 +00001112 else if (SemaRef.getLangOpts().ObjC1) {
Douglas Gregor05fcf842010-11-02 20:36:02 +00001113 if (isa<ObjCIvarDecl>(ND))
1114 return true;
Douglas Gregor05fcf842010-11-02 20:36:02 +00001115 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001116
Douglas Gregor70febae2010-05-28 00:49:12 +00001117 return ND->getIdentifierNamespace() & IDNS;
1118}
1119
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001120bool ResultBuilder::IsIntegralConstantValue(const NamedDecl *ND) const {
Douglas Gregor85b50632010-07-28 21:50:18 +00001121 if (!IsOrdinaryNonTypeName(ND))
1122 return 0;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001123
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001124 if (const ValueDecl *VD = dyn_cast<ValueDecl>(ND->getUnderlyingDecl()))
Douglas Gregor85b50632010-07-28 21:50:18 +00001125 if (VD->getType()->isIntegralOrEnumerationType())
1126 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001127
Douglas Gregor85b50632010-07-28 21:50:18 +00001128 return false;
1129}
1130
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001131/// Determines whether this given declaration will be found by
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001132/// ordinary name lookup.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001133bool ResultBuilder::IsOrdinaryNonValueName(const NamedDecl *ND) const {
George Burgess IV00f70bd2018-03-01 05:43:23 +00001134 ND = ND->getUnderlyingDecl();
Douglas Gregor70febae2010-05-28 00:49:12 +00001135
Richard Smith541b38b2013-09-20 01:15:31 +00001136 unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_LocalExtern;
David Blaikiebbafb8a2012-03-11 07:00:24 +00001137 if (SemaRef.getLangOpts().CPlusPlus)
John McCalle87beb22010-04-23 18:46:30 +00001138 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001139
1140 return (ND->getIdentifierNamespace() & IDNS) &&
1141 !isa<ValueDecl>(ND) && !isa<FunctionTemplateDecl>(ND) &&
Douglas Gregor70febae2010-05-28 00:49:12 +00001142 !isa<ObjCPropertyDecl>(ND);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001143}
1144
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001145/// Determines whether the given declaration is suitable as the
Douglas Gregor3545ff42009-09-21 16:56:56 +00001146/// start of a C++ nested-name-specifier, e.g., a class or namespace.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001147bool ResultBuilder::IsNestedNameSpecifier(const NamedDecl *ND) const {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001148 // Allow us to find class templates, too.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001149 if (const ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
Douglas Gregor3545ff42009-09-21 16:56:56 +00001150 ND = ClassTemplate->getTemplatedDecl();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001151
Douglas Gregor3545ff42009-09-21 16:56:56 +00001152 return SemaRef.isAcceptableNestedNameSpecifier(ND);
1153}
1154
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001155/// Determines whether the given declaration is an enumeration.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001156bool ResultBuilder::IsEnum(const NamedDecl *ND) const {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001157 return isa<EnumDecl>(ND);
1158}
1159
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001160/// Determines whether the given declaration is a class or struct.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001161bool ResultBuilder::IsClassOrStruct(const NamedDecl *ND) const {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001162 // Allow us to find class templates, too.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001163 if (const ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
Douglas Gregor3545ff42009-09-21 16:56:56 +00001164 ND = ClassTemplate->getTemplatedDecl();
Joao Matosdc86f942012-08-31 18:45:21 +00001165
1166 // For purposes of this check, interfaces match too.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001167 if (const RecordDecl *RD = dyn_cast<RecordDecl>(ND))
Abramo Bagnara6150c882010-05-11 21:36:43 +00001168 return RD->getTagKind() == TTK_Class ||
Joao Matosdc86f942012-08-31 18:45:21 +00001169 RD->getTagKind() == TTK_Struct ||
1170 RD->getTagKind() == TTK_Interface;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001171
Douglas Gregor3545ff42009-09-21 16:56:56 +00001172 return false;
1173}
1174
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001175/// Determines whether the given declaration is a union.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001176bool ResultBuilder::IsUnion(const NamedDecl *ND) const {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001177 // Allow us to find class templates, too.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001178 if (const ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
Douglas Gregor3545ff42009-09-21 16:56:56 +00001179 ND = ClassTemplate->getTemplatedDecl();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001180
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001181 if (const RecordDecl *RD = dyn_cast<RecordDecl>(ND))
Abramo Bagnara6150c882010-05-11 21:36:43 +00001182 return RD->getTagKind() == TTK_Union;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001183
Douglas Gregor3545ff42009-09-21 16:56:56 +00001184 return false;
1185}
1186
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001187/// Determines whether the given declaration is a namespace.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001188bool ResultBuilder::IsNamespace(const NamedDecl *ND) const {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001189 return isa<NamespaceDecl>(ND);
1190}
1191
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001192/// Determines whether the given declaration is a namespace or
Douglas Gregor3545ff42009-09-21 16:56:56 +00001193/// namespace alias.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001194bool ResultBuilder::IsNamespaceOrAlias(const NamedDecl *ND) const {
Richard Smithf2005d32015-12-29 23:34:32 +00001195 return isa<NamespaceDecl>(ND->getUnderlyingDecl());
Douglas Gregor3545ff42009-09-21 16:56:56 +00001196}
1197
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001198/// Determines whether the given declaration is a type.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001199bool ResultBuilder::IsType(const NamedDecl *ND) const {
Richard Smithf2005d32015-12-29 23:34:32 +00001200 ND = ND->getUnderlyingDecl();
Douglas Gregor99fa2642010-08-24 01:06:58 +00001201 return isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND);
Douglas Gregor3545ff42009-09-21 16:56:56 +00001202}
1203
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001204/// Determines which members of a class should be visible via
Douglas Gregor99fe2ad2009-12-11 17:31:05 +00001205/// "." or "->". Only value declarations, nested name specifiers, and
1206/// using declarations thereof should show up.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001207bool ResultBuilder::IsMember(const NamedDecl *ND) const {
Richard Smithf2005d32015-12-29 23:34:32 +00001208 ND = ND->getUnderlyingDecl();
Douglas Gregor70788392009-12-11 18:14:22 +00001209 return isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND) ||
Richard Smithf2005d32015-12-29 23:34:32 +00001210 isa<ObjCPropertyDecl>(ND);
Douglas Gregore412a5a2009-09-23 22:26:46 +00001211}
1212
Douglas Gregora817a192010-05-27 23:06:34 +00001213static bool isObjCReceiverType(ASTContext &C, QualType T) {
1214 T = C.getCanonicalType(T);
1215 switch (T->getTypeClass()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001216 case Type::ObjCObject:
Douglas Gregora817a192010-05-27 23:06:34 +00001217 case Type::ObjCInterface:
1218 case Type::ObjCObjectPointer:
1219 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001220
Douglas Gregora817a192010-05-27 23:06:34 +00001221 case Type::Builtin:
1222 switch (cast<BuiltinType>(T)->getKind()) {
1223 case BuiltinType::ObjCId:
1224 case BuiltinType::ObjCClass:
1225 case BuiltinType::ObjCSel:
1226 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001227
Douglas Gregora817a192010-05-27 23:06:34 +00001228 default:
1229 break;
1230 }
1231 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001232
Douglas Gregora817a192010-05-27 23:06:34 +00001233 default:
1234 break;
1235 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001236
David Blaikiebbafb8a2012-03-11 07:00:24 +00001237 if (!C.getLangOpts().CPlusPlus)
Douglas Gregora817a192010-05-27 23:06:34 +00001238 return false;
1239
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001240 // FIXME: We could perform more analysis here to determine whether a
Douglas Gregora817a192010-05-27 23:06:34 +00001241 // particular class type has any conversions to Objective-C types. For now,
1242 // just accept all class types.
1243 return T->isDependentType() || T->isRecordType();
1244}
1245
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001246bool ResultBuilder::IsObjCMessageReceiver(const NamedDecl *ND) const {
Douglas Gregora817a192010-05-27 23:06:34 +00001247 QualType T = getDeclUsageType(SemaRef.Context, ND);
1248 if (T.isNull())
1249 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001250
Douglas Gregora817a192010-05-27 23:06:34 +00001251 T = SemaRef.Context.getBaseElementType(T);
1252 return isObjCReceiverType(SemaRef.Context, T);
1253}
1254
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001255bool ResultBuilder::IsObjCMessageReceiverOrLambdaCapture(const NamedDecl *ND) const {
Douglas Gregord8c61782012-02-15 15:34:24 +00001256 if (IsObjCMessageReceiver(ND))
1257 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001258
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001259 const VarDecl *Var = dyn_cast<VarDecl>(ND);
Douglas Gregord8c61782012-02-15 15:34:24 +00001260 if (!Var)
1261 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001262
Douglas Gregord8c61782012-02-15 15:34:24 +00001263 return Var->hasLocalStorage() && !Var->hasAttr<BlocksAttr>();
1264}
1265
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001266bool ResultBuilder::IsObjCCollection(const NamedDecl *ND) const {
David Blaikiebbafb8a2012-03-11 07:00:24 +00001267 if ((SemaRef.getLangOpts().CPlusPlus && !IsOrdinaryName(ND)) ||
1268 (!SemaRef.getLangOpts().CPlusPlus && !IsOrdinaryNonTypeName(ND)))
Douglas Gregor68762e72010-08-23 21:17:50 +00001269 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001270
Douglas Gregor68762e72010-08-23 21:17:50 +00001271 QualType T = getDeclUsageType(SemaRef.Context, ND);
1272 if (T.isNull())
1273 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001274
Douglas Gregor68762e72010-08-23 21:17:50 +00001275 T = SemaRef.Context.getBaseElementType(T);
1276 return T->isObjCObjectType() || T->isObjCObjectPointerType() ||
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001277 T->isObjCIdType() ||
David Blaikiebbafb8a2012-03-11 07:00:24 +00001278 (SemaRef.getLangOpts().CPlusPlus && T->isRecordType());
Douglas Gregor68762e72010-08-23 21:17:50 +00001279}
Douglas Gregora817a192010-05-27 23:06:34 +00001280
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001281bool ResultBuilder::IsImpossibleToSatisfy(const NamedDecl *ND) const {
Douglas Gregor0ac41382010-09-23 23:01:17 +00001282 return false;
1283}
1284
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001285/// Determines whether the given declaration is an Objective-C
Douglas Gregor2b8162b2010-01-14 16:08:12 +00001286/// instance variable.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001287bool ResultBuilder::IsObjCIvar(const NamedDecl *ND) const {
Douglas Gregor2b8162b2010-01-14 16:08:12 +00001288 return isa<ObjCIvarDecl>(ND);
1289}
1290
Douglas Gregorc580c522010-01-14 01:09:38 +00001291namespace {
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001292 /// Visible declaration consumer that adds a code-completion result
Douglas Gregorc580c522010-01-14 01:09:38 +00001293 /// for each visible declaration.
1294 class CodeCompletionDeclConsumer : public VisibleDeclConsumer {
1295 ResultBuilder &Results;
1296 DeclContext *CurContext;
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00001297 std::vector<FixItHint> FixIts;
Haojian Wu10d95c52018-01-17 14:29:25 +00001298
Douglas Gregorc580c522010-01-14 01:09:38 +00001299 public:
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00001300 CodeCompletionDeclConsumer(
1301 ResultBuilder &Results, DeclContext *CurContext,
1302 std::vector<FixItHint> FixIts = std::vector<FixItHint>())
1303 : Results(Results), CurContext(CurContext), FixIts(std::move(FixIts)) {}
Craig Toppere14c0f82014-03-12 04:55:44 +00001304
1305 void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx,
1306 bool InBaseClass) override {
Erik Verbruggen2e657ff2011-10-06 07:27:49 +00001307 bool Accessible = true;
Ilya Biryukov55b1b152018-07-30 15:19:05 +00001308 if (Ctx)
1309 Accessible = Results.getSema().IsSimplyAccessible(ND, Ctx);
Craig Topperc3ec1492014-05-26 06:22:03 +00001310 ResultBuilder::Result Result(ND, Results.getBasePriority(ND), nullptr,
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00001311 false, Accessible, FixIts);
Erik Verbruggen2e657ff2011-10-06 07:27:49 +00001312 Results.AddResult(Result, CurContext, Hiding, InBaseClass);
Douglas Gregorc580c522010-01-14 01:09:38 +00001313 }
Haojian Wu10d95c52018-01-17 14:29:25 +00001314
1315 void EnteredContext(DeclContext* Ctx) override {
1316 Results.addVisitedContext(Ctx);
1317 }
Douglas Gregorc580c522010-01-14 01:09:38 +00001318 };
Alexander Kornienkoab9db512015-06-22 23:07:51 +00001319}
Douglas Gregorc580c522010-01-14 01:09:38 +00001320
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001321/// Add type specifiers for the current language as keyword results.
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001322static void AddTypeSpecifierResults(const LangOptions &LangOpts,
Douglas Gregor3545ff42009-09-21 16:56:56 +00001323 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00001324 typedef CodeCompletionResult Result;
Douglas Gregora2db7932010-05-26 22:00:08 +00001325 Results.AddResult(Result("short", CCP_Type));
1326 Results.AddResult(Result("long", CCP_Type));
1327 Results.AddResult(Result("signed", CCP_Type));
1328 Results.AddResult(Result("unsigned", CCP_Type));
1329 Results.AddResult(Result("void", CCP_Type));
1330 Results.AddResult(Result("char", CCP_Type));
1331 Results.AddResult(Result("int", CCP_Type));
1332 Results.AddResult(Result("float", CCP_Type));
1333 Results.AddResult(Result("double", CCP_Type));
1334 Results.AddResult(Result("enum", CCP_Type));
1335 Results.AddResult(Result("struct", CCP_Type));
1336 Results.AddResult(Result("union", CCP_Type));
1337 Results.AddResult(Result("const", CCP_Type));
1338 Results.AddResult(Result("volatile", CCP_Type));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001339
Douglas Gregor3545ff42009-09-21 16:56:56 +00001340 if (LangOpts.C99) {
1341 // C99-specific
Douglas Gregora2db7932010-05-26 22:00:08 +00001342 Results.AddResult(Result("_Complex", CCP_Type));
1343 Results.AddResult(Result("_Imaginary", CCP_Type));
1344 Results.AddResult(Result("_Bool", CCP_Type));
1345 Results.AddResult(Result("restrict", CCP_Type));
Douglas Gregor3545ff42009-09-21 16:56:56 +00001346 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001347
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00001348 CodeCompletionBuilder Builder(Results.getAllocator(),
1349 Results.getCodeCompletionTUInfo());
Douglas Gregor3545ff42009-09-21 16:56:56 +00001350 if (LangOpts.CPlusPlus) {
1351 // C++-specific
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001352 Results.AddResult(Result("bool", CCP_Type +
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00001353 (LangOpts.ObjC1? CCD_bool_in_ObjC : 0)));
Douglas Gregora2db7932010-05-26 22:00:08 +00001354 Results.AddResult(Result("class", CCP_Type));
1355 Results.AddResult(Result("wchar_t", CCP_Type));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001356
Douglas Gregorf4c33342010-05-28 00:22:41 +00001357 // typename qualified-id
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001358 Builder.AddTypedTextChunk("typename");
1359 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1360 Builder.AddPlaceholderChunk("qualifier");
1361 Builder.AddTextChunk("::");
1362 Builder.AddPlaceholderChunk("name");
1363 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001364
Richard Smith2bf7fdb2013-01-02 11:42:31 +00001365 if (LangOpts.CPlusPlus11) {
Douglas Gregora2db7932010-05-26 22:00:08 +00001366 Results.AddResult(Result("auto", CCP_Type));
1367 Results.AddResult(Result("char16_t", CCP_Type));
1368 Results.AddResult(Result("char32_t", CCP_Type));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001369
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001370 Builder.AddTypedTextChunk("decltype");
1371 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1372 Builder.AddPlaceholderChunk("expression");
1373 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1374 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor3545ff42009-09-21 16:56:56 +00001375 }
Alex Lorenz46eed9d2017-02-13 23:35:59 +00001376 } else
1377 Results.AddResult(Result("__auto_type", CCP_Type));
1378
Richard Smith7b301e22018-05-24 21:51:52 +00001379 // GNU keywords
1380 if (LangOpts.GNUKeywords) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001381 // FIXME: Enable when we actually support decimal floating point.
Douglas Gregor78a21012010-01-14 16:01:26 +00001382 // Results.AddResult(Result("_Decimal32"));
1383 // Results.AddResult(Result("_Decimal64"));
1384 // Results.AddResult(Result("_Decimal128"));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001385
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001386 Builder.AddTypedTextChunk("typeof");
1387 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1388 Builder.AddPlaceholderChunk("expression");
1389 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00001390
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001391 Builder.AddTypedTextChunk("typeof");
1392 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1393 Builder.AddPlaceholderChunk("type");
1394 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1395 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor3545ff42009-09-21 16:56:56 +00001396 }
Douglas Gregor86b42682015-06-19 18:27:52 +00001397
1398 // Nullability
Douglas Gregoraea7afd2015-06-24 22:02:08 +00001399 Results.AddResult(Result("_Nonnull", CCP_Type));
1400 Results.AddResult(Result("_Null_unspecified", CCP_Type));
1401 Results.AddResult(Result("_Nullable", CCP_Type));
Douglas Gregor3545ff42009-09-21 16:56:56 +00001402}
1403
John McCallfaf5fb42010-08-26 23:41:50 +00001404static void AddStorageSpecifiers(Sema::ParserCompletionContext CCC,
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001405 const LangOptions &LangOpts,
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001406 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00001407 typedef CodeCompletionResult Result;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001408 // Note: we don't suggest either "auto" or "register", because both
1409 // are pointless as storage specifiers. Elsewhere, we suggest "auto"
1410 // in C++0x as a type specifier.
Douglas Gregor78a21012010-01-14 16:01:26 +00001411 Results.AddResult(Result("extern"));
1412 Results.AddResult(Result("static"));
Alex Lorenz8f4d3992017-02-13 23:19:40 +00001413
1414 if (LangOpts.CPlusPlus11) {
1415 CodeCompletionAllocator &Allocator = Results.getAllocator();
1416 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
1417
1418 // alignas
1419 Builder.AddTypedTextChunk("alignas");
1420 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1421 Builder.AddPlaceholderChunk("expression");
1422 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1423 Results.AddResult(Result(Builder.TakeString()));
1424
1425 Results.AddResult(Result("constexpr"));
1426 Results.AddResult(Result("thread_local"));
1427 }
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001428}
1429
John McCallfaf5fb42010-08-26 23:41:50 +00001430static void AddFunctionSpecifiers(Sema::ParserCompletionContext CCC,
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001431 const LangOptions &LangOpts,
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001432 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00001433 typedef CodeCompletionResult Result;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001434 switch (CCC) {
John McCallfaf5fb42010-08-26 23:41:50 +00001435 case Sema::PCC_Class:
1436 case Sema::PCC_MemberTemplate:
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001437 if (LangOpts.CPlusPlus) {
Douglas Gregor78a21012010-01-14 16:01:26 +00001438 Results.AddResult(Result("explicit"));
1439 Results.AddResult(Result("friend"));
1440 Results.AddResult(Result("mutable"));
1441 Results.AddResult(Result("virtual"));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001442 }
Adrian Prantlf3b3ccd2017-12-19 22:06:11 +00001443 LLVM_FALLTHROUGH;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001444
John McCallfaf5fb42010-08-26 23:41:50 +00001445 case Sema::PCC_ObjCInterface:
1446 case Sema::PCC_ObjCImplementation:
1447 case Sema::PCC_Namespace:
1448 case Sema::PCC_Template:
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001449 if (LangOpts.CPlusPlus || LangOpts.C99)
Douglas Gregor78a21012010-01-14 16:01:26 +00001450 Results.AddResult(Result("inline"));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001451 break;
1452
John McCallfaf5fb42010-08-26 23:41:50 +00001453 case Sema::PCC_ObjCInstanceVariableList:
1454 case Sema::PCC_Expression:
1455 case Sema::PCC_Statement:
1456 case Sema::PCC_ForInit:
1457 case Sema::PCC_Condition:
1458 case Sema::PCC_RecoveryInFunction:
1459 case Sema::PCC_Type:
Douglas Gregor5e35d592010-09-14 23:59:36 +00001460 case Sema::PCC_ParenthesizedExpression:
Douglas Gregor80039242011-02-15 20:33:25 +00001461 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001462 break;
1463 }
1464}
1465
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001466static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt);
1467static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt);
1468static void AddObjCVisibilityResults(const LangOptions &LangOpts,
Douglas Gregor48d46252010-01-13 21:54:15 +00001469 ResultBuilder &Results,
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001470 bool NeedAt);
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001471static void AddObjCImplementationResults(const LangOptions &LangOpts,
Douglas Gregorf1934162010-01-13 21:24:21 +00001472 ResultBuilder &Results,
1473 bool NeedAt);
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001474static void AddObjCInterfaceResults(const LangOptions &LangOpts,
Douglas Gregorf1934162010-01-13 21:24:21 +00001475 ResultBuilder &Results,
1476 bool NeedAt);
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001477static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt);
Douglas Gregorf1934162010-01-13 21:24:21 +00001478
Douglas Gregorf4c33342010-05-28 00:22:41 +00001479static void AddTypedefResult(ResultBuilder &Results) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00001480 CodeCompletionBuilder Builder(Results.getAllocator(),
1481 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001482 Builder.AddTypedTextChunk("typedef");
1483 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1484 Builder.AddPlaceholderChunk("type");
1485 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1486 Builder.AddPlaceholderChunk("name");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001487 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00001488}
1489
John McCallfaf5fb42010-08-26 23:41:50 +00001490static bool WantTypesInContext(Sema::ParserCompletionContext CCC,
Douglas Gregor70febae2010-05-28 00:49:12 +00001491 const LangOptions &LangOpts) {
Douglas Gregor70febae2010-05-28 00:49:12 +00001492 switch (CCC) {
John McCallfaf5fb42010-08-26 23:41:50 +00001493 case Sema::PCC_Namespace:
1494 case Sema::PCC_Class:
1495 case Sema::PCC_ObjCInstanceVariableList:
1496 case Sema::PCC_Template:
1497 case Sema::PCC_MemberTemplate:
1498 case Sema::PCC_Statement:
1499 case Sema::PCC_RecoveryInFunction:
1500 case Sema::PCC_Type:
Douglas Gregor5e35d592010-09-14 23:59:36 +00001501 case Sema::PCC_ParenthesizedExpression:
Douglas Gregor80039242011-02-15 20:33:25 +00001502 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregor70febae2010-05-28 00:49:12 +00001503 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001504
John McCallfaf5fb42010-08-26 23:41:50 +00001505 case Sema::PCC_Expression:
1506 case Sema::PCC_Condition:
Douglas Gregor5e35d592010-09-14 23:59:36 +00001507 return LangOpts.CPlusPlus;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001508
Douglas Gregor5e35d592010-09-14 23:59:36 +00001509 case Sema::PCC_ObjCInterface:
1510 case Sema::PCC_ObjCImplementation:
Douglas Gregor70febae2010-05-28 00:49:12 +00001511 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001512
John McCallfaf5fb42010-08-26 23:41:50 +00001513 case Sema::PCC_ForInit:
Douglas Gregor5e35d592010-09-14 23:59:36 +00001514 return LangOpts.CPlusPlus || LangOpts.ObjC1 || LangOpts.C99;
Douglas Gregor70febae2010-05-28 00:49:12 +00001515 }
David Blaikie8a40f702012-01-17 06:56:22 +00001516
1517 llvm_unreachable("Invalid ParserCompletionContext!");
Douglas Gregor70febae2010-05-28 00:49:12 +00001518}
1519
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00001520static PrintingPolicy getCompletionPrintingPolicy(const ASTContext &Context,
1521 const Preprocessor &PP) {
1522 PrintingPolicy Policy = Sema::getPrintingPolicy(Context, PP);
Douglas Gregore5c79d52011-10-18 21:20:17 +00001523 Policy.AnonymousTagLocations = false;
1524 Policy.SuppressStrongLifetime = true;
Douglas Gregor2e10cf92011-11-03 00:16:13 +00001525 Policy.SuppressUnwrittenScope = true;
Ilya Biryukovb5da91c2017-11-08 10:39:09 +00001526 Policy.SuppressScope = true;
Douglas Gregore5c79d52011-10-18 21:20:17 +00001527 return Policy;
1528}
1529
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001530/// Retrieve a printing policy suitable for code completion.
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00001531static PrintingPolicy getCompletionPrintingPolicy(Sema &S) {
1532 return getCompletionPrintingPolicy(S.Context, S.PP);
1533}
1534
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001535/// Retrieve the string representation of the given type as a string
Douglas Gregore5c79d52011-10-18 21:20:17 +00001536/// that has the appropriate lifetime for code completion.
1537///
1538/// This routine provides a fast path where we provide constant strings for
1539/// common type names.
1540static const char *GetCompletionTypeString(QualType T,
1541 ASTContext &Context,
1542 const PrintingPolicy &Policy,
1543 CodeCompletionAllocator &Allocator) {
1544 if (!T.getLocalQualifiers()) {
1545 // Built-in type names are constant strings.
1546 if (const BuiltinType *BT = dyn_cast<BuiltinType>(T))
Argyrios Kyrtzidisbbff3da2012-05-05 04:20:28 +00001547 return BT->getNameAsCString(Policy);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001548
Douglas Gregore5c79d52011-10-18 21:20:17 +00001549 // Anonymous tag types are constant strings.
1550 if (const TagType *TagT = dyn_cast<TagType>(T))
1551 if (TagDecl *Tag = TagT->getDecl())
John McCall5ea95772013-03-09 00:54:27 +00001552 if (!Tag->hasNameForLinkage()) {
Douglas Gregore5c79d52011-10-18 21:20:17 +00001553 switch (Tag->getTagKind()) {
1554 case TTK_Struct: return "struct <anonymous>";
Joao Matosdc86f942012-08-31 18:45:21 +00001555 case TTK_Interface: return "__interface <anonymous>";
1556 case TTK_Class: return "class <anonymous>";
Douglas Gregore5c79d52011-10-18 21:20:17 +00001557 case TTK_Union: return "union <anonymous>";
1558 case TTK_Enum: return "enum <anonymous>";
1559 }
1560 }
1561 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001562
Douglas Gregore5c79d52011-10-18 21:20:17 +00001563 // Slow path: format the type as a string.
1564 std::string Result;
1565 T.getAsStringInternal(Result, Policy);
1566 return Allocator.CopyString(Result);
1567}
1568
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001569/// Add a completion for "this", if we're in a member function.
Douglas Gregord8c61782012-02-15 15:34:24 +00001570static void addThisCompletion(Sema &S, ResultBuilder &Results) {
1571 QualType ThisTy = S.getCurrentThisType();
1572 if (ThisTy.isNull())
1573 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001574
Douglas Gregord8c61782012-02-15 15:34:24 +00001575 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00001576 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Douglas Gregord8c61782012-02-15 15:34:24 +00001577 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001578 Builder.AddResultTypeChunk(GetCompletionTypeString(ThisTy,
1579 S.Context,
Douglas Gregord8c61782012-02-15 15:34:24 +00001580 Policy,
1581 Allocator));
1582 Builder.AddTypedTextChunk("this");
Joao Matosdc86f942012-08-31 18:45:21 +00001583 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
Douglas Gregord8c61782012-02-15 15:34:24 +00001584}
1585
Alex Lorenz8f4d3992017-02-13 23:19:40 +00001586static void AddStaticAssertResult(CodeCompletionBuilder &Builder,
1587 ResultBuilder &Results,
1588 const LangOptions &LangOpts) {
1589 if (!LangOpts.CPlusPlus11)
1590 return;
1591
1592 Builder.AddTypedTextChunk("static_assert");
1593 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1594 Builder.AddPlaceholderChunk("expression");
1595 Builder.AddChunk(CodeCompletionString::CK_Comma);
1596 Builder.AddPlaceholderChunk("message");
1597 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1598 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
1599}
1600
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001601/// Add language constructs that show up for "ordinary" names.
John McCallfaf5fb42010-08-26 23:41:50 +00001602static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001603 Scope *S,
1604 Sema &SemaRef,
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001605 ResultBuilder &Results) {
Douglas Gregore5c79d52011-10-18 21:20:17 +00001606 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00001607 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001608
John McCall276321a2010-08-25 06:19:51 +00001609 typedef CodeCompletionResult Result;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001610 switch (CCC) {
John McCallfaf5fb42010-08-26 23:41:50 +00001611 case Sema::PCC_Namespace:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001612 if (SemaRef.getLangOpts().CPlusPlus) {
Douglas Gregorf4c33342010-05-28 00:22:41 +00001613 if (Results.includeCodePatterns()) {
1614 // namespace <identifier> { declarations }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001615 Builder.AddTypedTextChunk("namespace");
1616 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1617 Builder.AddPlaceholderChunk("identifier");
1618 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1619 Builder.AddPlaceholderChunk("declarations");
1620 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1621 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1622 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00001623 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001624
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001625 // namespace identifier = identifier ;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001626 Builder.AddTypedTextChunk("namespace");
1627 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1628 Builder.AddPlaceholderChunk("name");
1629 Builder.AddChunk(CodeCompletionString::CK_Equal);
1630 Builder.AddPlaceholderChunk("namespace");
1631 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001632
1633 // Using directives
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001634 Builder.AddTypedTextChunk("using");
1635 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1636 Builder.AddTextChunk("namespace");
1637 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1638 Builder.AddPlaceholderChunk("identifier");
1639 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001640
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001641 // asm(string-literal)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001642 Builder.AddTypedTextChunk("asm");
1643 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1644 Builder.AddPlaceholderChunk("string-literal");
1645 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1646 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001647
Douglas Gregorf4c33342010-05-28 00:22:41 +00001648 if (Results.includeCodePatterns()) {
1649 // Explicit template instantiation
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001650 Builder.AddTypedTextChunk("template");
1651 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1652 Builder.AddPlaceholderChunk("declaration");
1653 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00001654 }
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001655 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001656
David Blaikiebbafb8a2012-03-11 07:00:24 +00001657 if (SemaRef.getLangOpts().ObjC1)
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001658 AddObjCTopLevelResults(Results, true);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001659
Douglas Gregorf4c33342010-05-28 00:22:41 +00001660 AddTypedefResult(Results);
Adrian Prantlf3b3ccd2017-12-19 22:06:11 +00001661 LLVM_FALLTHROUGH;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001662
John McCallfaf5fb42010-08-26 23:41:50 +00001663 case Sema::PCC_Class:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001664 if (SemaRef.getLangOpts().CPlusPlus) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001665 // Using declaration
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001666 Builder.AddTypedTextChunk("using");
1667 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1668 Builder.AddPlaceholderChunk("qualifier");
1669 Builder.AddTextChunk("::");
1670 Builder.AddPlaceholderChunk("name");
1671 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001672
Douglas Gregorf4c33342010-05-28 00:22:41 +00001673 // using typename qualifier::name (only in a dependent context)
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001674 if (SemaRef.CurContext->isDependentContext()) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001675 Builder.AddTypedTextChunk("using");
1676 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1677 Builder.AddTextChunk("typename");
1678 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1679 Builder.AddPlaceholderChunk("qualifier");
1680 Builder.AddTextChunk("::");
1681 Builder.AddPlaceholderChunk("name");
1682 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001683 }
1684
Alex Lorenz8f4d3992017-02-13 23:19:40 +00001685 AddStaticAssertResult(Builder, Results, SemaRef.getLangOpts());
1686
John McCallfaf5fb42010-08-26 23:41:50 +00001687 if (CCC == Sema::PCC_Class) {
Douglas Gregorf4c33342010-05-28 00:22:41 +00001688 AddTypedefResult(Results);
1689
Erik Verbruggen6524c052017-10-24 13:46:58 +00001690 bool IsNotInheritanceScope =
1691 !(S->getFlags() & Scope::ClassInheritanceScope);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001692 // public:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001693 Builder.AddTypedTextChunk("public");
Erik Verbruggen6524c052017-10-24 13:46:58 +00001694 if (IsNotInheritanceScope && Results.includeCodePatterns())
Douglas Gregor9489cdf2012-04-10 17:56:28 +00001695 Builder.AddChunk(CodeCompletionString::CK_Colon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001696 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001697
1698 // protected:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001699 Builder.AddTypedTextChunk("protected");
Erik Verbruggen6524c052017-10-24 13:46:58 +00001700 if (IsNotInheritanceScope && Results.includeCodePatterns())
Douglas Gregor9489cdf2012-04-10 17:56:28 +00001701 Builder.AddChunk(CodeCompletionString::CK_Colon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001702 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001703
1704 // private:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001705 Builder.AddTypedTextChunk("private");
Erik Verbruggen6524c052017-10-24 13:46:58 +00001706 if (IsNotInheritanceScope && Results.includeCodePatterns())
Douglas Gregor9489cdf2012-04-10 17:56:28 +00001707 Builder.AddChunk(CodeCompletionString::CK_Colon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001708 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001709 }
1710 }
Adrian Prantlf3b3ccd2017-12-19 22:06:11 +00001711 LLVM_FALLTHROUGH;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001712
John McCallfaf5fb42010-08-26 23:41:50 +00001713 case Sema::PCC_Template:
1714 case Sema::PCC_MemberTemplate:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001715 if (SemaRef.getLangOpts().CPlusPlus && Results.includeCodePatterns()) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001716 // template < parameters >
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001717 Builder.AddTypedTextChunk("template");
1718 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1719 Builder.AddPlaceholderChunk("parameters");
1720 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1721 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001722 }
1723
David Blaikiebbafb8a2012-03-11 07:00:24 +00001724 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
1725 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001726 break;
1727
John McCallfaf5fb42010-08-26 23:41:50 +00001728 case Sema::PCC_ObjCInterface:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001729 AddObjCInterfaceResults(SemaRef.getLangOpts(), Results, true);
1730 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
1731 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregorf1934162010-01-13 21:24:21 +00001732 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001733
John McCallfaf5fb42010-08-26 23:41:50 +00001734 case Sema::PCC_ObjCImplementation:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001735 AddObjCImplementationResults(SemaRef.getLangOpts(), Results, true);
1736 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
1737 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregorf1934162010-01-13 21:24:21 +00001738 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001739
John McCallfaf5fb42010-08-26 23:41:50 +00001740 case Sema::PCC_ObjCInstanceVariableList:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001741 AddObjCVisibilityResults(SemaRef.getLangOpts(), Results, true);
Douglas Gregor48d46252010-01-13 21:54:15 +00001742 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001743
John McCallfaf5fb42010-08-26 23:41:50 +00001744 case Sema::PCC_RecoveryInFunction:
1745 case Sema::PCC_Statement: {
Douglas Gregorf4c33342010-05-28 00:22:41 +00001746 AddTypedefResult(Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001747
David Blaikiebbafb8a2012-03-11 07:00:24 +00001748 if (SemaRef.getLangOpts().CPlusPlus && Results.includeCodePatterns() &&
1749 SemaRef.getLangOpts().CXXExceptions) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001750 Builder.AddTypedTextChunk("try");
1751 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1752 Builder.AddPlaceholderChunk("statements");
1753 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1754 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1755 Builder.AddTextChunk("catch");
1756 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1757 Builder.AddPlaceholderChunk("declaration");
1758 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1759 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1760 Builder.AddPlaceholderChunk("statements");
1761 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1762 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1763 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001764 }
David Blaikiebbafb8a2012-03-11 07:00:24 +00001765 if (SemaRef.getLangOpts().ObjC1)
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001766 AddObjCStatementResults(Results, true);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001767
Douglas Gregorf64acca2010-05-25 21:41:55 +00001768 if (Results.includeCodePatterns()) {
1769 // if (condition) { statements }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001770 Builder.AddTypedTextChunk("if");
1771 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00001772 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001773 Builder.AddPlaceholderChunk("condition");
Douglas Gregorf64acca2010-05-25 21:41:55 +00001774 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001775 Builder.AddPlaceholderChunk("expression");
1776 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1777 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1778 Builder.AddPlaceholderChunk("statements");
1779 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1780 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1781 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001782
Douglas Gregorf64acca2010-05-25 21:41:55 +00001783 // switch (condition) { }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001784 Builder.AddTypedTextChunk("switch");
1785 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00001786 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001787 Builder.AddPlaceholderChunk("condition");
Douglas Gregorf64acca2010-05-25 21:41:55 +00001788 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001789 Builder.AddPlaceholderChunk("expression");
1790 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1791 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1792 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1793 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1794 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf64acca2010-05-25 21:41:55 +00001795 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001796
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001797 // Switch-specific statements.
John McCallaab3e412010-08-25 08:40:02 +00001798 if (!SemaRef.getCurFunction()->SwitchStack.empty()) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001799 // case expression:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001800 Builder.AddTypedTextChunk("case");
1801 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1802 Builder.AddPlaceholderChunk("expression");
1803 Builder.AddChunk(CodeCompletionString::CK_Colon);
1804 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001805
1806 // default:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001807 Builder.AddTypedTextChunk("default");
1808 Builder.AddChunk(CodeCompletionString::CK_Colon);
1809 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001810 }
1811
Douglas Gregorf64acca2010-05-25 21:41:55 +00001812 if (Results.includeCodePatterns()) {
1813 /// while (condition) { statements }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001814 Builder.AddTypedTextChunk("while");
1815 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00001816 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001817 Builder.AddPlaceholderChunk("condition");
Douglas Gregorf64acca2010-05-25 21:41:55 +00001818 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001819 Builder.AddPlaceholderChunk("expression");
1820 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1821 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1822 Builder.AddPlaceholderChunk("statements");
1823 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1824 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1825 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf64acca2010-05-25 21:41:55 +00001826
1827 // do { statements } while ( expression );
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001828 Builder.AddTypedTextChunk("do");
1829 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1830 Builder.AddPlaceholderChunk("statements");
1831 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1832 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1833 Builder.AddTextChunk("while");
1834 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1835 Builder.AddPlaceholderChunk("expression");
1836 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1837 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001838
Douglas Gregorf64acca2010-05-25 21:41:55 +00001839 // for ( for-init-statement ; condition ; expression ) { statements }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001840 Builder.AddTypedTextChunk("for");
1841 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00001842 if (SemaRef.getLangOpts().CPlusPlus || SemaRef.getLangOpts().C99)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001843 Builder.AddPlaceholderChunk("init-statement");
Douglas Gregorf64acca2010-05-25 21:41:55 +00001844 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001845 Builder.AddPlaceholderChunk("init-expression");
1846 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
1847 Builder.AddPlaceholderChunk("condition");
1848 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
1849 Builder.AddPlaceholderChunk("inc-expression");
1850 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1851 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1852 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1853 Builder.AddPlaceholderChunk("statements");
1854 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1855 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1856 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf64acca2010-05-25 21:41:55 +00001857 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001858
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001859 if (S->getContinueParent()) {
1860 // continue ;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001861 Builder.AddTypedTextChunk("continue");
1862 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001863 }
1864
1865 if (S->getBreakParent()) {
1866 // break ;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001867 Builder.AddTypedTextChunk("break");
1868 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001869 }
1870
1871 // "return expression ;" or "return ;", depending on whether we
1872 // know the function is void or not.
1873 bool isVoid = false;
1874 if (FunctionDecl *Function = dyn_cast<FunctionDecl>(SemaRef.CurContext))
Alp Toker314cc812014-01-25 16:55:45 +00001875 isVoid = Function->getReturnType()->isVoidType();
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001876 else if (ObjCMethodDecl *Method
1877 = dyn_cast<ObjCMethodDecl>(SemaRef.CurContext))
Alp Toker314cc812014-01-25 16:55:45 +00001878 isVoid = Method->getReturnType()->isVoidType();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001879 else if (SemaRef.getCurBlock() &&
Douglas Gregor9a28e842010-03-01 23:15:13 +00001880 !SemaRef.getCurBlock()->ReturnType.isNull())
1881 isVoid = SemaRef.getCurBlock()->ReturnType->isVoidType();
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001882 Builder.AddTypedTextChunk("return");
Douglas Gregor44272ca2010-02-18 04:06:48 +00001883 if (!isVoid) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001884 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1885 Builder.AddPlaceholderChunk("expression");
Douglas Gregor44272ca2010-02-18 04:06:48 +00001886 }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001887 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001888
Douglas Gregorf4c33342010-05-28 00:22:41 +00001889 // goto identifier ;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001890 Builder.AddTypedTextChunk("goto");
1891 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1892 Builder.AddPlaceholderChunk("label");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001893 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001894
Douglas Gregorf4c33342010-05-28 00:22:41 +00001895 // Using directives
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001896 Builder.AddTypedTextChunk("using");
1897 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1898 Builder.AddTextChunk("namespace");
1899 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1900 Builder.AddPlaceholderChunk("identifier");
1901 Results.AddResult(Result(Builder.TakeString()));
Alex Lorenz8f4d3992017-02-13 23:19:40 +00001902
1903 AddStaticAssertResult(Builder, Results, SemaRef.getLangOpts());
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001904 }
Galina Kistanovabe3ba9da2017-06-07 06:31:55 +00001905 LLVM_FALLTHROUGH;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001906
1907 // Fall through (for statement expressions).
John McCallfaf5fb42010-08-26 23:41:50 +00001908 case Sema::PCC_ForInit:
1909 case Sema::PCC_Condition:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001910 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001911 // Fall through: conditions and statements can have expressions.
Galina Kistanova33399112017-06-03 06:35:06 +00001912 LLVM_FALLTHROUGH;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001913
Douglas Gregor5e35d592010-09-14 23:59:36 +00001914 case Sema::PCC_ParenthesizedExpression:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001915 if (SemaRef.getLangOpts().ObjCAutoRefCount &&
John McCall31168b02011-06-15 23:02:42 +00001916 CCC == Sema::PCC_ParenthesizedExpression) {
1917 // (__bridge <type>)<expression>
1918 Builder.AddTypedTextChunk("__bridge");
1919 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1920 Builder.AddPlaceholderChunk("type");
1921 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1922 Builder.AddPlaceholderChunk("expression");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001923 Results.AddResult(Result(Builder.TakeString()));
John McCall31168b02011-06-15 23:02:42 +00001924
1925 // (__bridge_transfer <Objective-C type>)<expression>
1926 Builder.AddTypedTextChunk("__bridge_transfer");
1927 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1928 Builder.AddPlaceholderChunk("Objective-C type");
1929 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1930 Builder.AddPlaceholderChunk("expression");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001931 Results.AddResult(Result(Builder.TakeString()));
John McCall31168b02011-06-15 23:02:42 +00001932
1933 // (__bridge_retained <CF type>)<expression>
1934 Builder.AddTypedTextChunk("__bridge_retained");
1935 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1936 Builder.AddPlaceholderChunk("CF type");
1937 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1938 Builder.AddPlaceholderChunk("expression");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001939 Results.AddResult(Result(Builder.TakeString()));
John McCall31168b02011-06-15 23:02:42 +00001940 }
1941 // Fall through
Galina Kistanova33399112017-06-03 06:35:06 +00001942 LLVM_FALLTHROUGH;
John McCall31168b02011-06-15 23:02:42 +00001943
John McCallfaf5fb42010-08-26 23:41:50 +00001944 case Sema::PCC_Expression: {
David Blaikiebbafb8a2012-03-11 07:00:24 +00001945 if (SemaRef.getLangOpts().CPlusPlus) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001946 // 'this', if we're in a non-static member function.
Douglas Gregord8c61782012-02-15 15:34:24 +00001947 addThisCompletion(SemaRef, Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001948
Douglas Gregore5c79d52011-10-18 21:20:17 +00001949 // true
1950 Builder.AddResultTypeChunk("bool");
1951 Builder.AddTypedTextChunk("true");
1952 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001953
Douglas Gregore5c79d52011-10-18 21:20:17 +00001954 // false
1955 Builder.AddResultTypeChunk("bool");
1956 Builder.AddTypedTextChunk("false");
1957 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001958
David Blaikiebbafb8a2012-03-11 07:00:24 +00001959 if (SemaRef.getLangOpts().RTTI) {
Douglas Gregorc05f6572011-04-12 02:47:21 +00001960 // dynamic_cast < type-id > ( expression )
1961 Builder.AddTypedTextChunk("dynamic_cast");
1962 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1963 Builder.AddPlaceholderChunk("type");
1964 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1965 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1966 Builder.AddPlaceholderChunk("expression");
1967 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001968 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc05f6572011-04-12 02:47:21 +00001969 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001970
Douglas Gregorf4c33342010-05-28 00:22:41 +00001971 // static_cast < type-id > ( expression )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001972 Builder.AddTypedTextChunk("static_cast");
1973 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1974 Builder.AddPlaceholderChunk("type");
1975 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1976 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1977 Builder.AddPlaceholderChunk("expression");
1978 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001979 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001980
Douglas Gregorf4c33342010-05-28 00:22:41 +00001981 // reinterpret_cast < type-id > ( expression )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001982 Builder.AddTypedTextChunk("reinterpret_cast");
1983 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1984 Builder.AddPlaceholderChunk("type");
1985 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1986 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1987 Builder.AddPlaceholderChunk("expression");
1988 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001989 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001990
Douglas Gregorf4c33342010-05-28 00:22:41 +00001991 // const_cast < type-id > ( expression )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001992 Builder.AddTypedTextChunk("const_cast");
1993 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1994 Builder.AddPlaceholderChunk("type");
1995 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1996 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1997 Builder.AddPlaceholderChunk("expression");
1998 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001999 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002000
David Blaikiebbafb8a2012-03-11 07:00:24 +00002001 if (SemaRef.getLangOpts().RTTI) {
Douglas Gregorc05f6572011-04-12 02:47:21 +00002002 // typeid ( expression-or-type )
Douglas Gregore5c79d52011-10-18 21:20:17 +00002003 Builder.AddResultTypeChunk("std::type_info");
Douglas Gregorc05f6572011-04-12 02:47:21 +00002004 Builder.AddTypedTextChunk("typeid");
2005 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2006 Builder.AddPlaceholderChunk("expression-or-type");
2007 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002008 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc05f6572011-04-12 02:47:21 +00002009 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002010
Douglas Gregorf4c33342010-05-28 00:22:41 +00002011 // new T ( ... )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002012 Builder.AddTypedTextChunk("new");
2013 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2014 Builder.AddPlaceholderChunk("type");
2015 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2016 Builder.AddPlaceholderChunk("expressions");
2017 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002018 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002019
Douglas Gregorf4c33342010-05-28 00:22:41 +00002020 // new T [ ] ( ... )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002021 Builder.AddTypedTextChunk("new");
2022 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2023 Builder.AddPlaceholderChunk("type");
2024 Builder.AddChunk(CodeCompletionString::CK_LeftBracket);
2025 Builder.AddPlaceholderChunk("size");
2026 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
2027 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2028 Builder.AddPlaceholderChunk("expressions");
2029 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002030 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002031
Douglas Gregorf4c33342010-05-28 00:22:41 +00002032 // delete expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00002033 Builder.AddResultTypeChunk("void");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002034 Builder.AddTypedTextChunk("delete");
2035 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2036 Builder.AddPlaceholderChunk("expression");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002037 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002038
Douglas Gregorf4c33342010-05-28 00:22:41 +00002039 // delete [] expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00002040 Builder.AddResultTypeChunk("void");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002041 Builder.AddTypedTextChunk("delete");
2042 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2043 Builder.AddChunk(CodeCompletionString::CK_LeftBracket);
2044 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
2045 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2046 Builder.AddPlaceholderChunk("expression");
2047 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002048
David Blaikiebbafb8a2012-03-11 07:00:24 +00002049 if (SemaRef.getLangOpts().CXXExceptions) {
Douglas Gregorc05f6572011-04-12 02:47:21 +00002050 // throw expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00002051 Builder.AddResultTypeChunk("void");
Douglas Gregorc05f6572011-04-12 02:47:21 +00002052 Builder.AddTypedTextChunk("throw");
2053 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2054 Builder.AddPlaceholderChunk("expression");
2055 Results.AddResult(Result(Builder.TakeString()));
2056 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002057
Douglas Gregora2db7932010-05-26 22:00:08 +00002058 // FIXME: Rethrow?
Douglas Gregor4205fef2011-10-18 16:29:03 +00002059
Richard Smith2bf7fdb2013-01-02 11:42:31 +00002060 if (SemaRef.getLangOpts().CPlusPlus11) {
Douglas Gregor4205fef2011-10-18 16:29:03 +00002061 // nullptr
Douglas Gregore5c79d52011-10-18 21:20:17 +00002062 Builder.AddResultTypeChunk("std::nullptr_t");
Douglas Gregor4205fef2011-10-18 16:29:03 +00002063 Builder.AddTypedTextChunk("nullptr");
2064 Results.AddResult(Result(Builder.TakeString()));
2065
2066 // alignof
Douglas Gregore5c79d52011-10-18 21:20:17 +00002067 Builder.AddResultTypeChunk("size_t");
Douglas Gregor4205fef2011-10-18 16:29:03 +00002068 Builder.AddTypedTextChunk("alignof");
2069 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2070 Builder.AddPlaceholderChunk("type");
2071 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2072 Results.AddResult(Result(Builder.TakeString()));
2073
2074 // noexcept
Douglas Gregore5c79d52011-10-18 21:20:17 +00002075 Builder.AddResultTypeChunk("bool");
Douglas Gregor4205fef2011-10-18 16:29:03 +00002076 Builder.AddTypedTextChunk("noexcept");
2077 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2078 Builder.AddPlaceholderChunk("expression");
2079 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2080 Results.AddResult(Result(Builder.TakeString()));
2081
2082 // sizeof... expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00002083 Builder.AddResultTypeChunk("size_t");
Douglas Gregor4205fef2011-10-18 16:29:03 +00002084 Builder.AddTypedTextChunk("sizeof...");
2085 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2086 Builder.AddPlaceholderChunk("parameter-pack");
2087 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2088 Results.AddResult(Result(Builder.TakeString()));
2089 }
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002090 }
2091
David Blaikiebbafb8a2012-03-11 07:00:24 +00002092 if (SemaRef.getLangOpts().ObjC1) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002093 // Add "super", if we're in an Objective-C class with a superclass.
Ted Kremenek305a0a72010-05-31 21:43:10 +00002094 if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl()) {
2095 // The interface can be NULL.
2096 if (ObjCInterfaceDecl *ID = Method->getClassInterface())
Douglas Gregore5c79d52011-10-18 21:20:17 +00002097 if (ID->getSuperClass()) {
2098 std::string SuperType;
2099 SuperType = ID->getSuperClass()->getNameAsString();
2100 if (Method->isInstanceMethod())
2101 SuperType += " *";
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002102
Douglas Gregore5c79d52011-10-18 21:20:17 +00002103 Builder.AddResultTypeChunk(Allocator.CopyString(SuperType));
2104 Builder.AddTypedTextChunk("super");
2105 Results.AddResult(Result(Builder.TakeString()));
2106 }
Ted Kremenek305a0a72010-05-31 21:43:10 +00002107 }
2108
Douglas Gregorf98e6a22010-01-13 23:51:12 +00002109 AddObjCExpressionResults(Results, true);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002110 }
2111
Jordan Rose58d54722012-06-30 21:33:57 +00002112 if (SemaRef.getLangOpts().C11) {
2113 // _Alignof
2114 Builder.AddResultTypeChunk("size_t");
Richard Smith20e883e2015-04-29 23:20:19 +00002115 if (SemaRef.PP.isMacroDefined("alignof"))
Jordan Rose58d54722012-06-30 21:33:57 +00002116 Builder.AddTypedTextChunk("alignof");
2117 else
2118 Builder.AddTypedTextChunk("_Alignof");
2119 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2120 Builder.AddPlaceholderChunk("type");
2121 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2122 Results.AddResult(Result(Builder.TakeString()));
2123 }
2124
Douglas Gregorf4c33342010-05-28 00:22:41 +00002125 // sizeof expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00002126 Builder.AddResultTypeChunk("size_t");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002127 Builder.AddTypedTextChunk("sizeof");
2128 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2129 Builder.AddPlaceholderChunk("expression-or-type");
2130 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2131 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002132 break;
2133 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002134
John McCallfaf5fb42010-08-26 23:41:50 +00002135 case Sema::PCC_Type:
Douglas Gregor80039242011-02-15 20:33:25 +00002136 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregor99fa2642010-08-24 01:06:58 +00002137 break;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002138 }
2139
David Blaikiebbafb8a2012-03-11 07:00:24 +00002140 if (WantTypesInContext(CCC, SemaRef.getLangOpts()))
2141 AddTypeSpecifierResults(SemaRef.getLangOpts(), Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002142
David Blaikiebbafb8a2012-03-11 07:00:24 +00002143 if (SemaRef.getLangOpts().CPlusPlus && CCC != Sema::PCC_Type)
Douglas Gregor78a21012010-01-14 16:01:26 +00002144 Results.AddResult(Result("operator"));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002145}
2146
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002147/// If the given declaration has an associated type, add it as a result
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002148/// type chunk.
2149static void AddResultTypeChunk(ASTContext &Context,
Douglas Gregor75acd922011-09-27 23:30:47 +00002150 const PrintingPolicy &Policy,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002151 const NamedDecl *ND,
Douglas Gregorc3425b12015-07-07 06:20:19 +00002152 QualType BaseType,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002153 CodeCompletionBuilder &Result) {
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002154 if (!ND)
2155 return;
Douglas Gregor0212fd72010-09-21 16:06:22 +00002156
2157 // Skip constructors and conversion functions, which have their return types
2158 // built into their names.
Sam McCall63c59722018-01-22 20:44:47 +00002159 if (isConstructor(ND) || isa<CXXConversionDecl>(ND))
Douglas Gregor0212fd72010-09-21 16:06:22 +00002160 return;
2161
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002162 // Determine the type of the declaration (if it has a type).
Alp Tokera2794f92014-01-22 07:29:52 +00002163 QualType T;
2164 if (const FunctionDecl *Function = ND->getAsFunction())
Alp Toker314cc812014-01-25 16:55:45 +00002165 T = Function->getReturnType();
Douglas Gregorc3425b12015-07-07 06:20:19 +00002166 else if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND)) {
2167 if (!BaseType.isNull())
2168 T = Method->getSendResultType(BaseType);
2169 else
2170 T = Method->getReturnType();
Ilya Biryukovb5da91c2017-11-08 10:39:09 +00002171 } else if (const EnumConstantDecl *Enumerator = dyn_cast<EnumConstantDecl>(ND)) {
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002172 T = Context.getTypeDeclType(cast<TypeDecl>(Enumerator->getDeclContext()));
Ilya Biryukovb5da91c2017-11-08 10:39:09 +00002173 T = clang::TypeName::getFullyQualifiedType(T, Context);
2174 } else if (isa<UnresolvedUsingValueDecl>(ND)) {
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002175 /* Do nothing: ignore unresolved using declarations*/
Douglas Gregorc3425b12015-07-07 06:20:19 +00002176 } else if (const ObjCIvarDecl *Ivar = dyn_cast<ObjCIvarDecl>(ND)) {
2177 if (!BaseType.isNull())
2178 T = Ivar->getUsageType(BaseType);
2179 else
2180 T = Ivar->getType();
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002181 } else if (const ValueDecl *Value = dyn_cast<ValueDecl>(ND)) {
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002182 T = Value->getType();
Douglas Gregorc3425b12015-07-07 06:20:19 +00002183 } else if (const ObjCPropertyDecl *Property = dyn_cast<ObjCPropertyDecl>(ND)) {
2184 if (!BaseType.isNull())
2185 T = Property->getUsageType(BaseType);
2186 else
2187 T = Property->getType();
2188 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002189
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002190 if (T.isNull() || Context.hasSameType(T, Context.DependentTy))
2191 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002192
Douglas Gregor75acd922011-09-27 23:30:47 +00002193 Result.AddResultTypeChunk(GetCompletionTypeString(T, Context, Policy,
Douglas Gregor304f9b02011-02-01 21:15:40 +00002194 Result.getAllocator()));
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002195}
2196
Richard Smith20e883e2015-04-29 23:20:19 +00002197static void MaybeAddSentinel(Preprocessor &PP,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002198 const NamedDecl *FunctionOrMethod,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002199 CodeCompletionBuilder &Result) {
Douglas Gregordbb71db2010-08-23 23:51:41 +00002200 if (SentinelAttr *Sentinel = FunctionOrMethod->getAttr<SentinelAttr>())
2201 if (Sentinel->getSentinel() == 0) {
Richard Smith20e883e2015-04-29 23:20:19 +00002202 if (PP.getLangOpts().ObjC1 && PP.isMacroDefined("nil"))
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002203 Result.AddTextChunk(", nil");
Richard Smith20e883e2015-04-29 23:20:19 +00002204 else if (PP.isMacroDefined("NULL"))
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002205 Result.AddTextChunk(", NULL");
Douglas Gregordbb71db2010-08-23 23:51:41 +00002206 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002207 Result.AddTextChunk(", (void*)0");
Douglas Gregordbb71db2010-08-23 23:51:41 +00002208 }
2209}
2210
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002211static std::string formatObjCParamQualifiers(unsigned ObjCQuals,
Douglas Gregor86b42682015-06-19 18:27:52 +00002212 QualType &Type) {
Douglas Gregor8f08d742011-07-30 07:55:26 +00002213 std::string Result;
2214 if (ObjCQuals & Decl::OBJC_TQ_In)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002215 Result += "in ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002216 else if (ObjCQuals & Decl::OBJC_TQ_Inout)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002217 Result += "inout ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002218 else if (ObjCQuals & Decl::OBJC_TQ_Out)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002219 Result += "out ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002220 if (ObjCQuals & Decl::OBJC_TQ_Bycopy)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002221 Result += "bycopy ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002222 else if (ObjCQuals & Decl::OBJC_TQ_Byref)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002223 Result += "byref ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002224 if (ObjCQuals & Decl::OBJC_TQ_Oneway)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002225 Result += "oneway ";
Douglas Gregor86b42682015-06-19 18:27:52 +00002226 if (ObjCQuals & Decl::OBJC_TQ_CSNullability) {
2227 if (auto nullability = AttributedType::stripOuterNullability(Type)) {
2228 switch (*nullability) {
2229 case NullabilityKind::NonNull:
2230 Result += "nonnull ";
2231 break;
2232
2233 case NullabilityKind::Nullable:
2234 Result += "nullable ";
2235 break;
2236
2237 case NullabilityKind::Unspecified:
2238 Result += "null_unspecified ";
2239 break;
2240 }
2241 }
2242 }
Douglas Gregor8f08d742011-07-30 07:55:26 +00002243 return Result;
2244}
2245
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002246/// Tries to find the most appropriate type location for an Objective-C
Alex Lorenza1951202016-10-18 10:35:27 +00002247/// block placeholder.
2248///
2249/// This function ignores things like typedefs and qualifiers in order to
2250/// present the most relevant and accurate block placeholders in code completion
2251/// results.
2252static void findTypeLocationForBlockDecl(const TypeSourceInfo *TSInfo,
2253 FunctionTypeLoc &Block,
2254 FunctionProtoTypeLoc &BlockProto,
2255 bool SuppressBlock = false) {
2256 if (!TSInfo)
2257 return;
2258 TypeLoc TL = TSInfo->getTypeLoc().getUnqualifiedLoc();
2259 while (true) {
2260 // Look through typedefs.
2261 if (!SuppressBlock) {
2262 if (TypedefTypeLoc TypedefTL = TL.getAs<TypedefTypeLoc>()) {
2263 if (TypeSourceInfo *InnerTSInfo =
2264 TypedefTL.getTypedefNameDecl()->getTypeSourceInfo()) {
2265 TL = InnerTSInfo->getTypeLoc().getUnqualifiedLoc();
2266 continue;
2267 }
2268 }
2269
2270 // Look through qualified types
2271 if (QualifiedTypeLoc QualifiedTL = TL.getAs<QualifiedTypeLoc>()) {
2272 TL = QualifiedTL.getUnqualifiedLoc();
2273 continue;
2274 }
2275
2276 if (AttributedTypeLoc AttrTL = TL.getAs<AttributedTypeLoc>()) {
2277 TL = AttrTL.getModifiedLoc();
2278 continue;
2279 }
2280 }
2281
2282 // Try to get the function prototype behind the block pointer type,
2283 // then we're done.
2284 if (BlockPointerTypeLoc BlockPtr = TL.getAs<BlockPointerTypeLoc>()) {
2285 TL = BlockPtr.getPointeeLoc().IgnoreParens();
2286 Block = TL.getAs<FunctionTypeLoc>();
2287 BlockProto = TL.getAs<FunctionProtoTypeLoc>();
2288 }
2289 break;
2290 }
2291}
2292
Alex Lorenz920ae142016-10-18 10:38:58 +00002293static std::string
2294formatBlockPlaceholder(const PrintingPolicy &Policy, const NamedDecl *BlockDecl,
2295 FunctionTypeLoc &Block, FunctionProtoTypeLoc &BlockProto,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002296 bool SuppressBlockName = false,
Alex Lorenz920ae142016-10-18 10:38:58 +00002297 bool SuppressBlock = false,
2298 Optional<ArrayRef<QualType>> ObjCSubsts = None);
2299
Richard Smith20e883e2015-04-29 23:20:19 +00002300static std::string FormatFunctionParameter(const PrintingPolicy &Policy,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002301 const ParmVarDecl *Param,
Douglas Gregord793e7c2011-10-18 04:23:19 +00002302 bool SuppressName = false,
Douglas Gregorc3425b12015-07-07 06:20:19 +00002303 bool SuppressBlock = false,
2304 Optional<ArrayRef<QualType>> ObjCSubsts = None) {
Douglas Gregore90dd002010-08-24 16:15:59 +00002305 bool ObjCMethodParam = isa<ObjCMethodDecl>(Param->getDeclContext());
2306 if (Param->getType()->isDependentType() ||
2307 !Param->getType()->isBlockPointerType()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002308 // The argument for a dependent or non-block parameter is a placeholder
Douglas Gregore90dd002010-08-24 16:15:59 +00002309 // containing that parameter's type.
2310 std::string Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002311
Douglas Gregor981a0c42010-08-29 19:47:46 +00002312 if (Param->getIdentifier() && !ObjCMethodParam && !SuppressName)
Douglas Gregore90dd002010-08-24 16:15:59 +00002313 Result = Param->getIdentifier()->getName();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002314
Douglas Gregor86b42682015-06-19 18:27:52 +00002315 QualType Type = Param->getType();
Douglas Gregorc3425b12015-07-07 06:20:19 +00002316 if (ObjCSubsts)
2317 Type = Type.substObjCTypeArgs(Param->getASTContext(), *ObjCSubsts,
2318 ObjCSubstitutionContext::Parameter);
Douglas Gregore90dd002010-08-24 16:15:59 +00002319 if (ObjCMethodParam) {
Douglas Gregor86b42682015-06-19 18:27:52 +00002320 Result = "(" + formatObjCParamQualifiers(Param->getObjCDeclQualifier(),
2321 Type);
2322 Result += Type.getAsString(Policy) + ")";
Douglas Gregor981a0c42010-08-29 19:47:46 +00002323 if (Param->getIdentifier() && !SuppressName)
Douglas Gregore90dd002010-08-24 16:15:59 +00002324 Result += Param->getIdentifier()->getName();
Douglas Gregor86b42682015-06-19 18:27:52 +00002325 } else {
2326 Type.getAsStringInternal(Result, Policy);
Douglas Gregore90dd002010-08-24 16:15:59 +00002327 }
2328 return Result;
2329 }
Alex Lorenza1951202016-10-18 10:35:27 +00002330
Douglas Gregore90dd002010-08-24 16:15:59 +00002331 // The argument for a block pointer parameter is a block literal with
2332 // the appropriate type.
David Blaikie6adc78e2013-02-18 22:06:02 +00002333 FunctionTypeLoc Block;
2334 FunctionProtoTypeLoc BlockProto;
Alex Lorenza1951202016-10-18 10:35:27 +00002335 findTypeLocationForBlockDecl(Param->getTypeSourceInfo(), Block, BlockProto,
2336 SuppressBlock);
Alex Lorenz6bf4a582017-03-13 15:43:42 +00002337 // Try to retrieve the block type information from the property if this is a
2338 // parameter in a setter.
2339 if (!Block && ObjCMethodParam &&
2340 cast<ObjCMethodDecl>(Param->getDeclContext())->isPropertyAccessor()) {
2341 if (const auto *PD = cast<ObjCMethodDecl>(Param->getDeclContext())
2342 ->findPropertyDecl(/*CheckOverrides=*/false))
2343 findTypeLocationForBlockDecl(PD->getTypeSourceInfo(), Block, BlockProto,
2344 SuppressBlock);
2345 }
Douglas Gregore90dd002010-08-24 16:15:59 +00002346
2347 if (!Block) {
2348 // We were unable to find a FunctionProtoTypeLoc with parameter names
2349 // for the block; just use the parameter type as a placeholder.
2350 std::string Result;
Douglas Gregord793e7c2011-10-18 04:23:19 +00002351 if (!ObjCMethodParam && Param->getIdentifier())
2352 Result = Param->getIdentifier()->getName();
2353
Douglas Gregor86b42682015-06-19 18:27:52 +00002354 QualType Type = Param->getType().getUnqualifiedType();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002355
Douglas Gregore90dd002010-08-24 16:15:59 +00002356 if (ObjCMethodParam) {
Alex Lorenz01bcfc12016-11-23 16:28:34 +00002357 Result = Type.getAsString(Policy);
2358 std::string Quals =
2359 formatObjCParamQualifiers(Param->getObjCDeclQualifier(), Type);
2360 if (!Quals.empty())
2361 Result = "(" + Quals + " " + Result + ")";
2362 if (Result.back() != ')')
2363 Result += " ";
Douglas Gregore90dd002010-08-24 16:15:59 +00002364 if (Param->getIdentifier())
2365 Result += Param->getIdentifier()->getName();
Douglas Gregor86b42682015-06-19 18:27:52 +00002366 } else {
2367 Type.getAsStringInternal(Result, Policy);
Douglas Gregore90dd002010-08-24 16:15:59 +00002368 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002369
Douglas Gregore90dd002010-08-24 16:15:59 +00002370 return Result;
2371 }
Alex Lorenz01bcfc12016-11-23 16:28:34 +00002372
Douglas Gregore90dd002010-08-24 16:15:59 +00002373 // We have the function prototype behind the block pointer type, as it was
2374 // written in the source.
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002375 return formatBlockPlaceholder(Policy, Param, Block, BlockProto,
2376 /*SuppressBlockName=*/false, SuppressBlock,
Alex Lorenz920ae142016-10-18 10:38:58 +00002377 ObjCSubsts);
2378}
2379
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002380/// Returns a placeholder string that corresponds to an Objective-C block
Alex Lorenz920ae142016-10-18 10:38:58 +00002381/// declaration.
2382///
2383/// \param BlockDecl A declaration with an Objective-C block type.
2384///
2385/// \param Block The most relevant type location for that block type.
2386///
Alexander Kornienko2a8c18d2018-04-06 15:14:32 +00002387/// \param SuppressBlockName Determines whether or not the name of the block
Alex Lorenz920ae142016-10-18 10:38:58 +00002388/// declaration is included in the resulting string.
2389static std::string
2390formatBlockPlaceholder(const PrintingPolicy &Policy, const NamedDecl *BlockDecl,
2391 FunctionTypeLoc &Block, FunctionProtoTypeLoc &BlockProto,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002392 bool SuppressBlockName, bool SuppressBlock,
Alex Lorenz920ae142016-10-18 10:38:58 +00002393 Optional<ArrayRef<QualType>> ObjCSubsts) {
Douglas Gregor67da50e2010-09-08 22:47:51 +00002394 std::string Result;
Alp Toker314cc812014-01-25 16:55:45 +00002395 QualType ResultType = Block.getTypePtr()->getReturnType();
Douglas Gregorc3425b12015-07-07 06:20:19 +00002396 if (ObjCSubsts)
Alex Lorenz920ae142016-10-18 10:38:58 +00002397 ResultType =
2398 ResultType.substObjCTypeArgs(BlockDecl->getASTContext(), *ObjCSubsts,
2399 ObjCSubstitutionContext::Result);
Douglas Gregord793e7c2011-10-18 04:23:19 +00002400 if (!ResultType->isVoidType() || SuppressBlock)
John McCall31168b02011-06-15 23:02:42 +00002401 ResultType.getAsStringInternal(Result, Policy);
Douglas Gregord793e7c2011-10-18 04:23:19 +00002402
2403 // Format the parameter list.
2404 std::string Params;
Alp Tokerb3fd5cf2014-01-21 00:32:38 +00002405 if (!BlockProto || Block.getNumParams() == 0) {
David Blaikie6adc78e2013-02-18 22:06:02 +00002406 if (BlockProto && BlockProto.getTypePtr()->isVariadic())
Douglas Gregord793e7c2011-10-18 04:23:19 +00002407 Params = "(...)";
Douglas Gregoraf25cfa2010-10-02 23:49:58 +00002408 else
Douglas Gregord793e7c2011-10-18 04:23:19 +00002409 Params = "(void)";
Douglas Gregor67da50e2010-09-08 22:47:51 +00002410 } else {
Douglas Gregord793e7c2011-10-18 04:23:19 +00002411 Params += "(";
Alp Tokerb3fd5cf2014-01-21 00:32:38 +00002412 for (unsigned I = 0, N = Block.getNumParams(); I != N; ++I) {
Douglas Gregor67da50e2010-09-08 22:47:51 +00002413 if (I)
Douglas Gregord793e7c2011-10-18 04:23:19 +00002414 Params += ", ";
Richard Smith20e883e2015-04-29 23:20:19 +00002415 Params += FormatFunctionParameter(Policy, Block.getParam(I),
Alp Tokerb3fd5cf2014-01-21 00:32:38 +00002416 /*SuppressName=*/false,
Alex Lorenz920ae142016-10-18 10:38:58 +00002417 /*SuppressBlock=*/true, ObjCSubsts);
Alp Tokerb3fd5cf2014-01-21 00:32:38 +00002418
David Blaikie6adc78e2013-02-18 22:06:02 +00002419 if (I == N - 1 && BlockProto.getTypePtr()->isVariadic())
Douglas Gregord793e7c2011-10-18 04:23:19 +00002420 Params += ", ...";
Douglas Gregor67da50e2010-09-08 22:47:51 +00002421 }
Douglas Gregord793e7c2011-10-18 04:23:19 +00002422 Params += ")";
Douglas Gregor400f5972010-08-31 05:13:43 +00002423 }
Alex Lorenz920ae142016-10-18 10:38:58 +00002424
Douglas Gregord793e7c2011-10-18 04:23:19 +00002425 if (SuppressBlock) {
2426 // Format as a parameter.
2427 Result = Result + " (^";
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002428 if (!SuppressBlockName && BlockDecl->getIdentifier())
Alex Lorenz920ae142016-10-18 10:38:58 +00002429 Result += BlockDecl->getIdentifier()->getName();
Douglas Gregord793e7c2011-10-18 04:23:19 +00002430 Result += ")";
2431 Result += Params;
2432 } else {
2433 // Format as a block literal argument.
2434 Result = '^' + Result;
2435 Result += Params;
Alex Lorenz920ae142016-10-18 10:38:58 +00002436
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002437 if (!SuppressBlockName && BlockDecl->getIdentifier())
Alex Lorenz920ae142016-10-18 10:38:58 +00002438 Result += BlockDecl->getIdentifier()->getName();
Douglas Gregord793e7c2011-10-18 04:23:19 +00002439 }
Alex Lorenz920ae142016-10-18 10:38:58 +00002440
Douglas Gregore90dd002010-08-24 16:15:59 +00002441 return Result;
2442}
2443
Erik Verbruggen11338c52017-07-19 10:45:40 +00002444static std::string GetDefaultValueString(const ParmVarDecl *Param,
2445 const SourceManager &SM,
2446 const LangOptions &LangOpts) {
Ilya Biryukovb6d1ec82017-07-21 09:24:00 +00002447 const SourceRange SrcRange = Param->getDefaultArgRange();
Erik Verbruggen11338c52017-07-19 10:45:40 +00002448 CharSourceRange CharSrcRange = CharSourceRange::getTokenRange(SrcRange);
2449 bool Invalid = CharSrcRange.isInvalid();
2450 if (Invalid)
2451 return "";
2452 StringRef srcText = Lexer::getSourceText(CharSrcRange, SM, LangOpts, &Invalid);
2453 if (Invalid)
2454 return "";
2455
2456 if (srcText.empty() || srcText == "=") {
2457 // Lexer can't determine the value.
2458 // This happens if the code is incorrect (for example class is forward declared).
2459 return "";
2460 }
Erik Verbruggen797980e2017-07-19 11:15:36 +00002461 std::string DefValue(srcText.str());
Erik Verbruggen11338c52017-07-19 10:45:40 +00002462 // FIXME: remove this check if the Lexer::getSourceText value is fixed and
2463 // this value always has (or always does not have) '=' in front of it
2464 if (DefValue.at(0) != '=') {
2465 // If we don't have '=' in front of value.
2466 // Lexer returns built-in types values without '=' and user-defined types values with it.
2467 return " = " + DefValue;
2468 }
2469 return " " + DefValue;
2470}
2471
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002472/// Add function parameter chunks to the given code completion string.
Richard Smith20e883e2015-04-29 23:20:19 +00002473static void AddFunctionParameterChunks(Preprocessor &PP,
Douglas Gregor75acd922011-09-27 23:30:47 +00002474 const PrintingPolicy &Policy,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002475 const FunctionDecl *Function,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002476 CodeCompletionBuilder &Result,
2477 unsigned Start = 0,
2478 bool InOptional = false) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002479 bool FirstParameter = true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002480
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002481 for (unsigned P = Start, N = Function->getNumParams(); P != N; ++P) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002482 const ParmVarDecl *Param = Function->getParamDecl(P);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002483
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002484 if (Param->hasDefaultArg() && !InOptional) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002485 // When we see an optional default argument, put that argument and
2486 // the remaining default arguments into a new, optional string.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00002487 CodeCompletionBuilder Opt(Result.getAllocator(),
2488 Result.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002489 if (!FirstParameter)
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002490 Opt.AddChunk(CodeCompletionString::CK_Comma);
Richard Smith20e883e2015-04-29 23:20:19 +00002491 AddFunctionParameterChunks(PP, Policy, Function, Opt, P, true);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002492 Result.AddOptionalChunk(Opt.TakeString());
2493 break;
Douglas Gregor3545ff42009-09-21 16:56:56 +00002494 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002495
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002496 if (FirstParameter)
2497 FirstParameter = false;
2498 else
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002499 Result.AddChunk(CodeCompletionString::CK_Comma);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002500
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002501 InOptional = false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002502
Douglas Gregor3545ff42009-09-21 16:56:56 +00002503 // Format the placeholder string.
Richard Smith20e883e2015-04-29 23:20:19 +00002504 std::string PlaceholderStr = FormatFunctionParameter(Policy, Param);
Erik Verbruggen11338c52017-07-19 10:45:40 +00002505 if (Param->hasDefaultArg())
2506 PlaceholderStr += GetDefaultValueString(Param, PP.getSourceManager(), PP.getLangOpts());
Richard Smith20e883e2015-04-29 23:20:19 +00002507
Douglas Gregor400f5972010-08-31 05:13:43 +00002508 if (Function->isVariadic() && P == N - 1)
2509 PlaceholderStr += ", ...";
2510
Douglas Gregor3545ff42009-09-21 16:56:56 +00002511 // Add the placeholder string.
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002512 Result.AddPlaceholderChunk(
2513 Result.getAllocator().CopyString(PlaceholderStr));
Douglas Gregor3545ff42009-09-21 16:56:56 +00002514 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002515
2516 if (const FunctionProtoType *Proto
Douglas Gregorba449032009-09-22 21:42:17 +00002517 = Function->getType()->getAs<FunctionProtoType>())
Douglas Gregordbb71db2010-08-23 23:51:41 +00002518 if (Proto->isVariadic()) {
Alp Toker9cacbab2014-01-20 20:26:09 +00002519 if (Proto->getNumParams() == 0)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002520 Result.AddPlaceholderChunk("...");
Douglas Gregordbb71db2010-08-23 23:51:41 +00002521
Richard Smith20e883e2015-04-29 23:20:19 +00002522 MaybeAddSentinel(PP, Function, Result);
Douglas Gregordbb71db2010-08-23 23:51:41 +00002523 }
Douglas Gregor3545ff42009-09-21 16:56:56 +00002524}
2525
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002526/// Add template parameter chunks to the given code completion string.
Douglas Gregor3545ff42009-09-21 16:56:56 +00002527static void AddTemplateParameterChunks(ASTContext &Context,
Douglas Gregor75acd922011-09-27 23:30:47 +00002528 const PrintingPolicy &Policy,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002529 const TemplateDecl *Template,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002530 CodeCompletionBuilder &Result,
2531 unsigned MaxParameters = 0,
2532 unsigned Start = 0,
2533 bool InDefaultArg = false) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002534 bool FirstParameter = true;
Richard Smith6eece292015-01-15 02:27:20 +00002535
2536 // Prefer to take the template parameter names from the first declaration of
2537 // the template.
2538 Template = cast<TemplateDecl>(Template->getCanonicalDecl());
2539
Douglas Gregor3545ff42009-09-21 16:56:56 +00002540 TemplateParameterList *Params = Template->getTemplateParameters();
2541 TemplateParameterList::iterator PEnd = Params->end();
2542 if (MaxParameters)
2543 PEnd = Params->begin() + MaxParameters;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002544 for (TemplateParameterList::iterator P = Params->begin() + Start;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002545 P != PEnd; ++P) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002546 bool HasDefaultArg = false;
2547 std::string PlaceholderStr;
2548 if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*P)) {
2549 if (TTP->wasDeclaredWithTypename())
2550 PlaceholderStr = "typename";
2551 else
2552 PlaceholderStr = "class";
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002553
Douglas Gregor3545ff42009-09-21 16:56:56 +00002554 if (TTP->getIdentifier()) {
2555 PlaceholderStr += ' ';
2556 PlaceholderStr += TTP->getIdentifier()->getName();
2557 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002558
Douglas Gregor3545ff42009-09-21 16:56:56 +00002559 HasDefaultArg = TTP->hasDefaultArgument();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002560 } else if (NonTypeTemplateParmDecl *NTTP
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002561 = dyn_cast<NonTypeTemplateParmDecl>(*P)) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002562 if (NTTP->getIdentifier())
2563 PlaceholderStr = NTTP->getIdentifier()->getName();
John McCall31168b02011-06-15 23:02:42 +00002564 NTTP->getType().getAsStringInternal(PlaceholderStr, Policy);
Douglas Gregor3545ff42009-09-21 16:56:56 +00002565 HasDefaultArg = NTTP->hasDefaultArgument();
2566 } else {
2567 assert(isa<TemplateTemplateParmDecl>(*P));
2568 TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*P);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002569
Douglas Gregor3545ff42009-09-21 16:56:56 +00002570 // Since putting the template argument list into the placeholder would
2571 // be very, very long, we just use an abbreviation.
2572 PlaceholderStr = "template<...> class";
2573 if (TTP->getIdentifier()) {
2574 PlaceholderStr += ' ';
2575 PlaceholderStr += TTP->getIdentifier()->getName();
2576 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002577
Douglas Gregor3545ff42009-09-21 16:56:56 +00002578 HasDefaultArg = TTP->hasDefaultArgument();
2579 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002580
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002581 if (HasDefaultArg && !InDefaultArg) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002582 // When we see an optional default argument, put that argument and
2583 // the remaining default arguments into a new, optional string.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00002584 CodeCompletionBuilder Opt(Result.getAllocator(),
2585 Result.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002586 if (!FirstParameter)
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002587 Opt.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor75acd922011-09-27 23:30:47 +00002588 AddTemplateParameterChunks(Context, Policy, Template, Opt, MaxParameters,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002589 P - Params->begin(), true);
2590 Result.AddOptionalChunk(Opt.TakeString());
2591 break;
Douglas Gregor3545ff42009-09-21 16:56:56 +00002592 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002593
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002594 InDefaultArg = false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002595
Douglas Gregor3545ff42009-09-21 16:56:56 +00002596 if (FirstParameter)
2597 FirstParameter = false;
2598 else
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002599 Result.AddChunk(CodeCompletionString::CK_Comma);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002600
Douglas Gregor3545ff42009-09-21 16:56:56 +00002601 // Add the placeholder string.
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002602 Result.AddPlaceholderChunk(
2603 Result.getAllocator().CopyString(PlaceholderStr));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002604 }
Douglas Gregor3545ff42009-09-21 16:56:56 +00002605}
2606
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002607/// Add a qualifier to the given code-completion string, if the
Douglas Gregorf2510672009-09-21 19:57:38 +00002608/// provided nested-name-specifier is non-NULL.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002609static void
2610AddQualifierToCompletionString(CodeCompletionBuilder &Result,
2611 NestedNameSpecifier *Qualifier,
Douglas Gregor0f622362009-12-11 18:44:16 +00002612 bool QualifierIsInformative,
Douglas Gregor75acd922011-09-27 23:30:47 +00002613 ASTContext &Context,
2614 const PrintingPolicy &Policy) {
Douglas Gregorf2510672009-09-21 19:57:38 +00002615 if (!Qualifier)
2616 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002617
Douglas Gregorf2510672009-09-21 19:57:38 +00002618 std::string PrintedNNS;
2619 {
2620 llvm::raw_string_ostream OS(PrintedNNS);
Douglas Gregor75acd922011-09-27 23:30:47 +00002621 Qualifier->print(OS, Policy);
Douglas Gregorf2510672009-09-21 19:57:38 +00002622 }
Douglas Gregor5bf52692009-09-22 23:15:58 +00002623 if (QualifierIsInformative)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002624 Result.AddInformativeChunk(Result.getAllocator().CopyString(PrintedNNS));
Douglas Gregor5bf52692009-09-22 23:15:58 +00002625 else
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002626 Result.AddTextChunk(Result.getAllocator().CopyString(PrintedNNS));
Douglas Gregorf2510672009-09-21 19:57:38 +00002627}
2628
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002629static void
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002630AddFunctionTypeQualsToCompletionString(CodeCompletionBuilder &Result,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002631 const FunctionDecl *Function) {
Douglas Gregor0f622362009-12-11 18:44:16 +00002632 const FunctionProtoType *Proto
2633 = Function->getType()->getAs<FunctionProtoType>();
2634 if (!Proto || !Proto->getTypeQuals())
2635 return;
2636
Douglas Gregor304f9b02011-02-01 21:15:40 +00002637 // FIXME: Add ref-qualifier!
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002638
Douglas Gregor304f9b02011-02-01 21:15:40 +00002639 // Handle single qualifiers without copying
2640 if (Proto->getTypeQuals() == Qualifiers::Const) {
2641 Result.AddInformativeChunk(" const");
2642 return;
2643 }
2644
2645 if (Proto->getTypeQuals() == Qualifiers::Volatile) {
2646 Result.AddInformativeChunk(" volatile");
2647 return;
2648 }
2649
2650 if (Proto->getTypeQuals() == Qualifiers::Restrict) {
2651 Result.AddInformativeChunk(" restrict");
2652 return;
2653 }
2654
2655 // Handle multiple qualifiers.
Douglas Gregor0f622362009-12-11 18:44:16 +00002656 std::string QualsStr;
David Blaikief5697e52012-08-10 00:55:35 +00002657 if (Proto->isConst())
Douglas Gregor0f622362009-12-11 18:44:16 +00002658 QualsStr += " const";
David Blaikief5697e52012-08-10 00:55:35 +00002659 if (Proto->isVolatile())
Douglas Gregor0f622362009-12-11 18:44:16 +00002660 QualsStr += " volatile";
David Blaikief5697e52012-08-10 00:55:35 +00002661 if (Proto->isRestrict())
Douglas Gregor0f622362009-12-11 18:44:16 +00002662 QualsStr += " restrict";
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002663 Result.AddInformativeChunk(Result.getAllocator().CopyString(QualsStr));
Douglas Gregor0f622362009-12-11 18:44:16 +00002664}
2665
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002666/// Add the name of the given declaration
Douglas Gregor75acd922011-09-27 23:30:47 +00002667static void AddTypedNameChunk(ASTContext &Context, const PrintingPolicy &Policy,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002668 const NamedDecl *ND,
2669 CodeCompletionBuilder &Result) {
Douglas Gregor0212fd72010-09-21 16:06:22 +00002670 DeclarationName Name = ND->getDeclName();
2671 if (!Name)
2672 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002673
Douglas Gregor0212fd72010-09-21 16:06:22 +00002674 switch (Name.getNameKind()) {
Douglas Gregor304f9b02011-02-01 21:15:40 +00002675 case DeclarationName::CXXOperatorName: {
Craig Topperc3ec1492014-05-26 06:22:03 +00002676 const char *OperatorName = nullptr;
Douglas Gregor304f9b02011-02-01 21:15:40 +00002677 switch (Name.getCXXOverloadedOperator()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002678 case OO_None:
Douglas Gregor304f9b02011-02-01 21:15:40 +00002679 case OO_Conditional:
2680 case NUM_OVERLOADED_OPERATORS:
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002681 OperatorName = "operator";
Douglas Gregor304f9b02011-02-01 21:15:40 +00002682 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002683
Douglas Gregor304f9b02011-02-01 21:15:40 +00002684#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
2685 case OO_##Name: OperatorName = "operator" Spelling; break;
2686#define OVERLOADED_OPERATOR_MULTI(Name,Spelling,Unary,Binary,MemberOnly)
2687#include "clang/Basic/OperatorKinds.def"
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002688
Douglas Gregor304f9b02011-02-01 21:15:40 +00002689 case OO_New: OperatorName = "operator new"; break;
2690 case OO_Delete: OperatorName = "operator delete"; break;
2691 case OO_Array_New: OperatorName = "operator new[]"; break;
2692 case OO_Array_Delete: OperatorName = "operator delete[]"; break;
2693 case OO_Call: OperatorName = "operator()"; break;
2694 case OO_Subscript: OperatorName = "operator[]"; break;
2695 }
2696 Result.AddTypedTextChunk(OperatorName);
2697 break;
2698 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002699
Douglas Gregor0212fd72010-09-21 16:06:22 +00002700 case DeclarationName::Identifier:
2701 case DeclarationName::CXXConversionFunctionName:
Douglas Gregor0212fd72010-09-21 16:06:22 +00002702 case DeclarationName::CXXDestructorName:
2703 case DeclarationName::CXXLiteralOperatorName:
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002704 Result.AddTypedTextChunk(
2705 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor0212fd72010-09-21 16:06:22 +00002706 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002707
Richard Smith35845152017-02-07 01:37:30 +00002708 case DeclarationName::CXXDeductionGuideName:
Douglas Gregor0212fd72010-09-21 16:06:22 +00002709 case DeclarationName::CXXUsingDirective:
2710 case DeclarationName::ObjCZeroArgSelector:
2711 case DeclarationName::ObjCOneArgSelector:
2712 case DeclarationName::ObjCMultiArgSelector:
2713 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002714
Douglas Gregor0212fd72010-09-21 16:06:22 +00002715 case DeclarationName::CXXConstructorName: {
Craig Topperc3ec1492014-05-26 06:22:03 +00002716 CXXRecordDecl *Record = nullptr;
Douglas Gregor0212fd72010-09-21 16:06:22 +00002717 QualType Ty = Name.getCXXNameType();
2718 if (const RecordType *RecordTy = Ty->getAs<RecordType>())
2719 Record = cast<CXXRecordDecl>(RecordTy->getDecl());
2720 else if (const InjectedClassNameType *InjectedTy
2721 = Ty->getAs<InjectedClassNameType>())
2722 Record = InjectedTy->getDecl();
2723 else {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002724 Result.AddTypedTextChunk(
2725 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor0212fd72010-09-21 16:06:22 +00002726 break;
2727 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002728
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002729 Result.AddTypedTextChunk(
2730 Result.getAllocator().CopyString(Record->getNameAsString()));
Douglas Gregor0212fd72010-09-21 16:06:22 +00002731 if (ClassTemplateDecl *Template = Record->getDescribedClassTemplate()) {
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002732 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Douglas Gregor75acd922011-09-27 23:30:47 +00002733 AddTemplateParameterChunks(Context, Policy, Template, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002734 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregor0212fd72010-09-21 16:06:22 +00002735 }
2736 break;
2737 }
2738 }
2739}
2740
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002741CodeCompletionString *CodeCompletionResult::CreateCodeCompletionString(Sema &S,
Douglas Gregorc3425b12015-07-07 06:20:19 +00002742 const CodeCompletionContext &CCContext,
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00002743 CodeCompletionAllocator &Allocator,
Dmitri Gribenko3292d062012-07-02 17:35:10 +00002744 CodeCompletionTUInfo &CCTUInfo,
2745 bool IncludeBriefComments) {
Douglas Gregorc3425b12015-07-07 06:20:19 +00002746 return CreateCodeCompletionString(S.Context, S.PP, CCContext, Allocator,
2747 CCTUInfo, IncludeBriefComments);
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002748}
2749
Eric Liu00f43c92018-07-06 09:43:57 +00002750CodeCompletionString *CodeCompletionResult::CreateCodeCompletionStringForMacro(
2751 Preprocessor &PP, CodeCompletionAllocator &Allocator,
2752 CodeCompletionTUInfo &CCTUInfo) {
2753 assert(Kind == RK_Macro);
2754 CodeCompletionBuilder Result(Allocator, CCTUInfo, Priority, Availability);
2755 const MacroInfo *MI = PP.getMacroInfo(Macro);
2756 Result.AddTypedTextChunk(Result.getAllocator().CopyString(Macro->getName()));
2757
2758 if (!MI || !MI->isFunctionLike())
2759 return Result.TakeString();
2760
2761 // Format a function-like macro with placeholders for the arguments.
2762 Result.AddChunk(CodeCompletionString::CK_LeftParen);
2763 MacroInfo::param_iterator A = MI->param_begin(), AEnd = MI->param_end();
2764
2765 // C99 variadic macros add __VA_ARGS__ at the end. Skip it.
2766 if (MI->isC99Varargs()) {
2767 --AEnd;
2768
2769 if (A == AEnd) {
2770 Result.AddPlaceholderChunk("...");
2771 }
2772 }
2773
2774 for (MacroInfo::param_iterator A = MI->param_begin(); A != AEnd; ++A) {
2775 if (A != MI->param_begin())
2776 Result.AddChunk(CodeCompletionString::CK_Comma);
2777
2778 if (MI->isVariadic() && (A + 1) == AEnd) {
2779 SmallString<32> Arg = (*A)->getName();
2780 if (MI->isC99Varargs())
2781 Arg += ", ...";
2782 else
2783 Arg += "...";
2784 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg));
2785 break;
2786 }
2787
2788 // Non-variadic macros are simple.
2789 Result.AddPlaceholderChunk(
2790 Result.getAllocator().CopyString((*A)->getName()));
2791 }
2792 Result.AddChunk(CodeCompletionString::CK_RightParen);
2793 return Result.TakeString();
2794}
2795
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002796/// If possible, create a new code completion string for the given
Douglas Gregor3545ff42009-09-21 16:56:56 +00002797/// result.
2798///
2799/// \returns Either a new, heap-allocated code completion string describing
2800/// how to use this result, or NULL to indicate that the string or name of the
2801/// result is all that is needed.
2802CodeCompletionString *
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002803CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx,
2804 Preprocessor &PP,
Douglas Gregorc3425b12015-07-07 06:20:19 +00002805 const CodeCompletionContext &CCContext,
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00002806 CodeCompletionAllocator &Allocator,
Dmitri Gribenko3292d062012-07-02 17:35:10 +00002807 CodeCompletionTUInfo &CCTUInfo,
2808 bool IncludeBriefComments) {
Eric Liu00f43c92018-07-06 09:43:57 +00002809 if (Kind == RK_Macro)
2810 return CreateCodeCompletionStringForMacro(PP, Allocator, CCTUInfo);
2811
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00002812 CodeCompletionBuilder Result(Allocator, CCTUInfo, Priority, Availability);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002813
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002814 PrintingPolicy Policy = getCompletionPrintingPolicy(Ctx, PP);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002815 if (Kind == RK_Pattern) {
2816 Pattern->Priority = Priority;
2817 Pattern->Availability = Availability;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002818
Douglas Gregor78254c82012-03-27 23:34:16 +00002819 if (Declaration) {
2820 Result.addParentContext(Declaration->getDeclContext());
Douglas Gregor78254c82012-03-27 23:34:16 +00002821 Pattern->ParentName = Result.getParentName();
Ilya Biryukova3f955b2018-05-16 12:30:01 +00002822 if (const RawComment *RC =
2823 getPatternCompletionComment(Ctx, Declaration)) {
2824 Result.addBriefComment(RC->getBriefText(Ctx));
2825 Pattern->BriefComment = Result.getBriefComment();
2826 }
Douglas Gregor78254c82012-03-27 23:34:16 +00002827 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002828
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002829 return Pattern;
2830 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002831
Douglas Gregorf09935f2009-12-01 05:55:20 +00002832 if (Kind == RK_Keyword) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002833 Result.AddTypedTextChunk(Keyword);
2834 return Result.TakeString();
Douglas Gregorf09935f2009-12-01 05:55:20 +00002835 }
Douglas Gregorf64acca2010-05-25 21:41:55 +00002836 assert(Kind == RK_Declaration && "Missed a result kind?");
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002837 const NamedDecl *ND = Declaration;
Douglas Gregor78254c82012-03-27 23:34:16 +00002838 Result.addParentContext(ND->getDeclContext());
Dmitri Gribenko3292d062012-07-02 17:35:10 +00002839
2840 if (IncludeBriefComments) {
2841 // Add documentation comment, if it exists.
Ilya Biryukova3f955b2018-05-16 12:30:01 +00002842 if (const RawComment *RC = getCompletionComment(Ctx, Declaration)) {
Dmitri Gribenko3292d062012-07-02 17:35:10 +00002843 Result.addBriefComment(RC->getBriefText(Ctx));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002844 }
Dmitri Gribenko3292d062012-07-02 17:35:10 +00002845 }
2846
Douglas Gregor9eb77012009-11-07 00:00:49 +00002847 if (StartsNestedNameSpecifier) {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002848 Result.AddTypedTextChunk(
2849 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002850 Result.AddTextChunk("::");
2851 return Result.TakeString();
Douglas Gregor9eb77012009-11-07 00:00:49 +00002852 }
Erik Verbruggen98ea7f62011-10-14 15:31:08 +00002853
Aaron Ballmanbe22bcb2014-03-10 17:08:28 +00002854 for (const auto *I : ND->specific_attrs<AnnotateAttr>())
2855 Result.AddAnnotation(Result.getAllocator().CopyString(I->getAnnotation()));
Aaron Ballmanb97112e2014-03-08 22:19:01 +00002856
Douglas Gregorc3425b12015-07-07 06:20:19 +00002857 AddResultTypeChunk(Ctx, Policy, ND, CCContext.getBaseType(), Result);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002858
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002859 if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(ND)) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002860 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002861 Ctx, Policy);
2862 AddTypedNameChunk(Ctx, Policy, ND, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002863 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Richard Smith20e883e2015-04-29 23:20:19 +00002864 AddFunctionParameterChunks(PP, Policy, Function, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002865 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor0f622362009-12-11 18:44:16 +00002866 AddFunctionTypeQualsToCompletionString(Result, Function);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002867 return Result.TakeString();
Douglas Gregor3545ff42009-09-21 16:56:56 +00002868 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002869
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002870 if (const FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND)) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002871 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002872 Ctx, Policy);
Douglas Gregor3545ff42009-09-21 16:56:56 +00002873 FunctionDecl *Function = FunTmpl->getTemplatedDecl();
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002874 AddTypedNameChunk(Ctx, Policy, Function, Result);
Douglas Gregor0212fd72010-09-21 16:06:22 +00002875
Douglas Gregor3545ff42009-09-21 16:56:56 +00002876 // Figure out which template parameters are deduced (or have default
2877 // arguments).
Benjamin Kramere0513cb2012-01-30 16:17:39 +00002878 llvm::SmallBitVector Deduced;
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002879 Sema::MarkDeducedTemplateParameters(Ctx, FunTmpl, Deduced);
Douglas Gregor3545ff42009-09-21 16:56:56 +00002880 unsigned LastDeducibleArgument;
2881 for (LastDeducibleArgument = Deduced.size(); LastDeducibleArgument > 0;
2882 --LastDeducibleArgument) {
2883 if (!Deduced[LastDeducibleArgument - 1]) {
2884 // C++0x: Figure out if the template argument has a default. If so,
2885 // the user doesn't need to type this argument.
2886 // FIXME: We need to abstract template parameters better!
2887 bool HasDefaultArg = false;
2888 NamedDecl *Param = FunTmpl->getTemplateParameters()->getParam(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002889 LastDeducibleArgument - 1);
Douglas Gregor3545ff42009-09-21 16:56:56 +00002890 if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param))
2891 HasDefaultArg = TTP->hasDefaultArgument();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002892 else if (NonTypeTemplateParmDecl *NTTP
Douglas Gregor3545ff42009-09-21 16:56:56 +00002893 = dyn_cast<NonTypeTemplateParmDecl>(Param))
2894 HasDefaultArg = NTTP->hasDefaultArgument();
2895 else {
2896 assert(isa<TemplateTemplateParmDecl>(Param));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002897 HasDefaultArg
Douglas Gregor9eb77012009-11-07 00:00:49 +00002898 = cast<TemplateTemplateParmDecl>(Param)->hasDefaultArgument();
Douglas Gregor3545ff42009-09-21 16:56:56 +00002899 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002900
Douglas Gregor3545ff42009-09-21 16:56:56 +00002901 if (!HasDefaultArg)
2902 break;
2903 }
2904 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002905
Douglas Gregor3545ff42009-09-21 16:56:56 +00002906 if (LastDeducibleArgument) {
2907 // Some of the function template arguments cannot be deduced from a
2908 // function call, so we introduce an explicit template argument list
2909 // containing all of the arguments up to the first deducible argument.
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002910 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002911 AddTemplateParameterChunks(Ctx, Policy, FunTmpl, Result,
Douglas Gregor3545ff42009-09-21 16:56:56 +00002912 LastDeducibleArgument);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002913 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregor3545ff42009-09-21 16:56:56 +00002914 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002915
Douglas Gregor3545ff42009-09-21 16:56:56 +00002916 // Add the function parameters
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002917 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Richard Smith20e883e2015-04-29 23:20:19 +00002918 AddFunctionParameterChunks(PP, Policy, Function, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002919 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor0f622362009-12-11 18:44:16 +00002920 AddFunctionTypeQualsToCompletionString(Result, Function);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002921 return Result.TakeString();
Douglas Gregor3545ff42009-09-21 16:56:56 +00002922 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002923
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002924 if (const TemplateDecl *Template = dyn_cast<TemplateDecl>(ND)) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002925 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002926 Ctx, Policy);
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002927 Result.AddTypedTextChunk(
2928 Result.getAllocator().CopyString(Template->getNameAsString()));
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002929 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002930 AddTemplateParameterChunks(Ctx, Policy, Template, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002931 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002932 return Result.TakeString();
Douglas Gregor3545ff42009-09-21 16:56:56 +00002933 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002934
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002935 if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND)) {
Douglas Gregord3c5d792009-11-17 16:44:22 +00002936 Selector Sel = Method->getSelector();
2937 if (Sel.isUnarySelector()) {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002938 Result.AddTypedTextChunk(Result.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00002939 Sel.getNameForSlot(0)));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002940 return Result.TakeString();
Douglas Gregord3c5d792009-11-17 16:44:22 +00002941 }
2942
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00002943 std::string SelName = Sel.getNameForSlot(0).str();
Douglas Gregor1b605f72009-11-19 01:08:35 +00002944 SelName += ':';
2945 if (StartParameter == 0)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002946 Result.AddTypedTextChunk(Result.getAllocator().CopyString(SelName));
Douglas Gregor1b605f72009-11-19 01:08:35 +00002947 else {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002948 Result.AddInformativeChunk(Result.getAllocator().CopyString(SelName));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002949
Douglas Gregor1b605f72009-11-19 01:08:35 +00002950 // If there is only one parameter, and we're past it, add an empty
2951 // typed-text chunk since there is nothing to type.
2952 if (Method->param_size() == 1)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002953 Result.AddTypedTextChunk("");
Douglas Gregor1b605f72009-11-19 01:08:35 +00002954 }
Douglas Gregord3c5d792009-11-17 16:44:22 +00002955 unsigned Idx = 0;
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002956 for (ObjCMethodDecl::param_const_iterator P = Method->param_begin(),
2957 PEnd = Method->param_end();
Douglas Gregord3c5d792009-11-17 16:44:22 +00002958 P != PEnd; (void)++P, ++Idx) {
2959 if (Idx > 0) {
Douglas Gregor1b605f72009-11-19 01:08:35 +00002960 std::string Keyword;
2961 if (Idx > StartParameter)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002962 Result.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregord3c5d792009-11-17 16:44:22 +00002963 if (IdentifierInfo *II = Sel.getIdentifierInfoForSlot(Idx))
Benjamin Kramer632500c2011-07-26 16:59:25 +00002964 Keyword += II->getName();
Douglas Gregord3c5d792009-11-17 16:44:22 +00002965 Keyword += ":";
Douglas Gregor95887f92010-07-08 23:20:03 +00002966 if (Idx < StartParameter || AllParametersAreInformative)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002967 Result.AddInformativeChunk(Result.getAllocator().CopyString(Keyword));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002968 else
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002969 Result.AddTypedTextChunk(Result.getAllocator().CopyString(Keyword));
Douglas Gregord3c5d792009-11-17 16:44:22 +00002970 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002971
Douglas Gregor1b605f72009-11-19 01:08:35 +00002972 // If we're before the starting parameter, skip the placeholder.
2973 if (Idx < StartParameter)
2974 continue;
Douglas Gregord3c5d792009-11-17 16:44:22 +00002975
2976 std::string Arg;
Douglas Gregorc3425b12015-07-07 06:20:19 +00002977 QualType ParamType = (*P)->getType();
2978 Optional<ArrayRef<QualType>> ObjCSubsts;
2979 if (!CCContext.getBaseType().isNull())
2980 ObjCSubsts = CCContext.getBaseType()->getObjCSubstitutions(Method);
2981
2982 if (ParamType->isBlockPointerType() && !DeclaringEntity)
2983 Arg = FormatFunctionParameter(Policy, *P, true,
2984 /*SuppressBlock=*/false,
2985 ObjCSubsts);
Douglas Gregore90dd002010-08-24 16:15:59 +00002986 else {
Douglas Gregorc3425b12015-07-07 06:20:19 +00002987 if (ObjCSubsts)
2988 ParamType = ParamType.substObjCTypeArgs(Ctx, *ObjCSubsts,
2989 ObjCSubstitutionContext::Parameter);
Douglas Gregor86b42682015-06-19 18:27:52 +00002990 Arg = "(" + formatObjCParamQualifiers((*P)->getObjCDeclQualifier(),
Douglas Gregorc3425b12015-07-07 06:20:19 +00002991 ParamType);
2992 Arg += ParamType.getAsString(Policy) + ")";
Douglas Gregore90dd002010-08-24 16:15:59 +00002993 if (IdentifierInfo *II = (*P)->getIdentifier())
Douglas Gregor981a0c42010-08-29 19:47:46 +00002994 if (DeclaringEntity || AllParametersAreInformative)
Benjamin Kramer632500c2011-07-26 16:59:25 +00002995 Arg += II->getName();
Douglas Gregore90dd002010-08-24 16:15:59 +00002996 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002997
Douglas Gregor400f5972010-08-31 05:13:43 +00002998 if (Method->isVariadic() && (P + 1) == PEnd)
2999 Arg += ", ...";
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003000
Douglas Gregor95887f92010-07-08 23:20:03 +00003001 if (DeclaringEntity)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003002 Result.AddTextChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregor95887f92010-07-08 23:20:03 +00003003 else if (AllParametersAreInformative)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003004 Result.AddInformativeChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregorc8537c52009-11-19 07:41:15 +00003005 else
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003006 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregord3c5d792009-11-17 16:44:22 +00003007 }
3008
Douglas Gregor04c5f972009-12-23 00:21:46 +00003009 if (Method->isVariadic()) {
Douglas Gregor400f5972010-08-31 05:13:43 +00003010 if (Method->param_size() == 0) {
3011 if (DeclaringEntity)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003012 Result.AddTextChunk(", ...");
Douglas Gregor400f5972010-08-31 05:13:43 +00003013 else if (AllParametersAreInformative)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003014 Result.AddInformativeChunk(", ...");
Douglas Gregor400f5972010-08-31 05:13:43 +00003015 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003016 Result.AddPlaceholderChunk(", ...");
Douglas Gregor400f5972010-08-31 05:13:43 +00003017 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003018
Richard Smith20e883e2015-04-29 23:20:19 +00003019 MaybeAddSentinel(PP, Method, Result);
Douglas Gregor04c5f972009-12-23 00:21:46 +00003020 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003021
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003022 return Result.TakeString();
Douglas Gregord3c5d792009-11-17 16:44:22 +00003023 }
3024
Douglas Gregorf09935f2009-12-01 05:55:20 +00003025 if (Qualifier)
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003026 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003027 Ctx, Policy);
Douglas Gregorf09935f2009-12-01 05:55:20 +00003028
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003029 Result.AddTypedTextChunk(
3030 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003031 return Result.TakeString();
Douglas Gregor3545ff42009-09-21 16:56:56 +00003032}
3033
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003034const RawComment *clang::getCompletionComment(const ASTContext &Ctx,
3035 const NamedDecl *ND) {
3036 if (!ND)
3037 return nullptr;
3038 if (auto *RC = Ctx.getRawCommentForAnyRedecl(ND))
3039 return RC;
3040
3041 // Try to find comment from a property for ObjC methods.
3042 const ObjCMethodDecl *M = dyn_cast<ObjCMethodDecl>(ND);
3043 if (!M)
3044 return nullptr;
3045 const ObjCPropertyDecl *PDecl = M->findPropertyDecl();
3046 if (!PDecl)
3047 return nullptr;
3048
3049 return Ctx.getRawCommentForAnyRedecl(PDecl);
3050}
3051
3052const RawComment *clang::getPatternCompletionComment(const ASTContext &Ctx,
3053 const NamedDecl *ND) {
3054 const ObjCMethodDecl *M = dyn_cast_or_null<ObjCMethodDecl>(ND);
3055 if (!M || !M->isPropertyAccessor())
3056 return nullptr;
3057
3058 // Provide code completion comment for self.GetterName where
3059 // GetterName is the getter method for a property with name
3060 // different from the property name (declared via a property
3061 // getter attribute.
3062 const ObjCPropertyDecl *PDecl = M->findPropertyDecl();
3063 if (!PDecl)
3064 return nullptr;
3065 if (PDecl->getGetterName() == M->getSelector() &&
3066 PDecl->getIdentifier() != M->getIdentifier()) {
3067 if (auto *RC = Ctx.getRawCommentForAnyRedecl(M))
3068 return RC;
3069 if (auto *RC = Ctx.getRawCommentForAnyRedecl(PDecl))
3070 return RC;
3071 }
3072 return nullptr;
3073}
3074
3075const RawComment *clang::getParameterComment(
3076 const ASTContext &Ctx,
3077 const CodeCompleteConsumer::OverloadCandidate &Result,
3078 unsigned ArgIndex) {
3079 auto FDecl = Result.getFunction();
3080 if (!FDecl)
3081 return nullptr;
3082 if (ArgIndex < FDecl->getNumParams())
3083 return Ctx.getRawCommentForAnyRedecl(FDecl->getParamDecl(ArgIndex));
3084 return nullptr;
3085}
3086
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003087/// Add function overload parameter chunks to the given code completion
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003088/// string.
3089static void AddOverloadParameterChunks(ASTContext &Context,
3090 const PrintingPolicy &Policy,
3091 const FunctionDecl *Function,
3092 const FunctionProtoType *Prototype,
3093 CodeCompletionBuilder &Result,
3094 unsigned CurrentArg,
3095 unsigned Start = 0,
3096 bool InOptional = false) {
3097 bool FirstParameter = true;
3098 unsigned NumParams = Function ? Function->getNumParams()
3099 : Prototype->getNumParams();
3100
3101 for (unsigned P = Start; P != NumParams; ++P) {
3102 if (Function && Function->getParamDecl(P)->hasDefaultArg() && !InOptional) {
3103 // When we see an optional default argument, put that argument and
3104 // the remaining default arguments into a new, optional string.
3105 CodeCompletionBuilder Opt(Result.getAllocator(),
3106 Result.getCodeCompletionTUInfo());
3107 if (!FirstParameter)
3108 Opt.AddChunk(CodeCompletionString::CK_Comma);
3109 // Optional sections are nested.
3110 AddOverloadParameterChunks(Context, Policy, Function, Prototype, Opt,
3111 CurrentArg, P, /*InOptional=*/true);
3112 Result.AddOptionalChunk(Opt.TakeString());
3113 return;
3114 }
3115
3116 if (FirstParameter)
3117 FirstParameter = false;
3118 else
3119 Result.AddChunk(CodeCompletionString::CK_Comma);
3120
3121 InOptional = false;
3122
3123 // Format the placeholder string.
3124 std::string Placeholder;
Erik Verbruggen11338c52017-07-19 10:45:40 +00003125 if (Function) {
3126 const ParmVarDecl *Param = Function->getParamDecl(P);
3127 Placeholder = FormatFunctionParameter(Policy, Param);
3128 if (Param->hasDefaultArg())
3129 Placeholder += GetDefaultValueString(Param, Context.getSourceManager(), Context.getLangOpts());
3130 } else {
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003131 Placeholder = Prototype->getParamType(P).getAsString(Policy);
Erik Verbruggen11338c52017-07-19 10:45:40 +00003132 }
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003133
3134 if (P == CurrentArg)
3135 Result.AddCurrentParameterChunk(
3136 Result.getAllocator().CopyString(Placeholder));
3137 else
3138 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Placeholder));
3139 }
3140
3141 if (Prototype && Prototype->isVariadic()) {
3142 CodeCompletionBuilder Opt(Result.getAllocator(),
3143 Result.getCodeCompletionTUInfo());
3144 if (!FirstParameter)
3145 Opt.AddChunk(CodeCompletionString::CK_Comma);
3146
3147 if (CurrentArg < NumParams)
3148 Opt.AddPlaceholderChunk("...");
3149 else
3150 Opt.AddCurrentParameterChunk("...");
3151
3152 Result.AddOptionalChunk(Opt.TakeString());
3153 }
3154}
3155
Douglas Gregorf0f51982009-09-23 00:34:09 +00003156CodeCompletionString *
3157CodeCompleteConsumer::OverloadCandidate::CreateSignatureString(
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003158 unsigned CurrentArg, Sema &S,
3159 CodeCompletionAllocator &Allocator,
3160 CodeCompletionTUInfo &CCTUInfo,
3161 bool IncludeBriefComments) const {
Douglas Gregor75acd922011-09-27 23:30:47 +00003162 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
John McCall31168b02011-06-15 23:02:42 +00003163
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003164 // FIXME: Set priority, availability appropriately.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003165 CodeCompletionBuilder Result(Allocator,CCTUInfo, 1, CXAvailability_Available);
Douglas Gregorf0f51982009-09-23 00:34:09 +00003166 FunctionDecl *FDecl = getFunction();
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003167 const FunctionProtoType *Proto
Douglas Gregorf0f51982009-09-23 00:34:09 +00003168 = dyn_cast<FunctionProtoType>(getFunctionType());
3169 if (!FDecl && !Proto) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003170 // Function without a prototype. Just give the return type and a
Douglas Gregorf0f51982009-09-23 00:34:09 +00003171 // highlighted ellipsis.
3172 const FunctionType *FT = getFunctionType();
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003173 Result.AddResultTypeChunk(Result.getAllocator().CopyString(
3174 FT->getReturnType().getAsString(Policy)));
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003175 Result.AddChunk(CodeCompletionString::CK_LeftParen);
3176 Result.AddChunk(CodeCompletionString::CK_CurrentParameter, "...");
3177 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003178 return Result.TakeString();
Douglas Gregorf0f51982009-09-23 00:34:09 +00003179 }
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003180
3181 if (FDecl) {
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003182 if (IncludeBriefComments) {
3183 if (auto RC = getParameterComment(S.getASTContext(), *this, CurrentArg))
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003184 Result.addBriefComment(RC->getBriefText(S.getASTContext()));
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003185 }
Douglas Gregorc3425b12015-07-07 06:20:19 +00003186 AddResultTypeChunk(S.Context, Policy, FDecl, QualType(), Result);
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003187 Result.AddTextChunk(
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003188 Result.getAllocator().CopyString(FDecl->getNameAsString()));
3189 } else {
3190 Result.AddResultTypeChunk(
3191 Result.getAllocator().CopyString(
Alp Toker314cc812014-01-25 16:55:45 +00003192 Proto->getReturnType().getAsString(Policy)));
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003193 }
Alp Toker314cc812014-01-25 16:55:45 +00003194
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003195 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003196 AddOverloadParameterChunks(S.getASTContext(), Policy, FDecl, Proto, Result,
3197 CurrentArg);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003198 Result.AddChunk(CodeCompletionString::CK_RightParen);
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003199
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003200 return Result.TakeString();
Douglas Gregorf0f51982009-09-23 00:34:09 +00003201}
3202
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003203unsigned clang::getMacroUsagePriority(StringRef MacroName,
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00003204 const LangOptions &LangOpts,
Douglas Gregor6e240332010-08-16 16:18:59 +00003205 bool PreferredTypeIsPointer) {
3206 unsigned Priority = CCP_Macro;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003207
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00003208 // Treat the "nil", "Nil" and "NULL" macros as null pointer constants.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003209 if (MacroName.equals("nil") || MacroName.equals("NULL") ||
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00003210 MacroName.equals("Nil")) {
Douglas Gregor6e240332010-08-16 16:18:59 +00003211 Priority = CCP_Constant;
3212 if (PreferredTypeIsPointer)
3213 Priority = Priority / CCF_SimilarTypeMatch;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003214 }
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00003215 // Treat "YES", "NO", "true", and "false" as constants.
3216 else if (MacroName.equals("YES") || MacroName.equals("NO") ||
3217 MacroName.equals("true") || MacroName.equals("false"))
3218 Priority = CCP_Constant;
3219 // Treat "bool" as a type.
3220 else if (MacroName.equals("bool"))
3221 Priority = CCP_Type + (LangOpts.ObjC1? CCD_bool_in_ObjC : 0);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003222
3223
Douglas Gregor6e240332010-08-16 16:18:59 +00003224 return Priority;
3225}
3226
Dmitri Gribenkobdc80de2013-01-11 20:32:41 +00003227CXCursorKind clang::getCursorKindForDecl(const Decl *D) {
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003228 if (!D)
3229 return CXCursor_UnexposedDecl;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003230
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003231 switch (D->getKind()) {
3232 case Decl::Enum: return CXCursor_EnumDecl;
3233 case Decl::EnumConstant: return CXCursor_EnumConstantDecl;
3234 case Decl::Field: return CXCursor_FieldDecl;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003235 case Decl::Function:
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003236 return CXCursor_FunctionDecl;
3237 case Decl::ObjCCategory: return CXCursor_ObjCCategoryDecl;
3238 case Decl::ObjCCategoryImpl: return CXCursor_ObjCCategoryImplDecl;
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003239 case Decl::ObjCImplementation: return CXCursor_ObjCImplementationDecl;
Douglas Gregordeafd0b2011-12-27 22:43:10 +00003240
Argyrios Kyrtzidis3698cef2012-01-24 21:39:26 +00003241 case Decl::ObjCInterface: return CXCursor_ObjCInterfaceDecl;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003242 case Decl::ObjCIvar: return CXCursor_ObjCIvarDecl;
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003243 case Decl::ObjCMethod:
3244 return cast<ObjCMethodDecl>(D)->isInstanceMethod()
3245 ? CXCursor_ObjCInstanceMethodDecl : CXCursor_ObjCClassMethodDecl;
3246 case Decl::CXXMethod: return CXCursor_CXXMethod;
3247 case Decl::CXXConstructor: return CXCursor_Constructor;
3248 case Decl::CXXDestructor: return CXCursor_Destructor;
3249 case Decl::CXXConversion: return CXCursor_ConversionFunction;
3250 case Decl::ObjCProperty: return CXCursor_ObjCPropertyDecl;
Argyrios Kyrtzidis3698cef2012-01-24 21:39:26 +00003251 case Decl::ObjCProtocol: return CXCursor_ObjCProtocolDecl;
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003252 case Decl::ParmVar: return CXCursor_ParmDecl;
3253 case Decl::Typedef: return CXCursor_TypedefDecl;
Richard Smithdda56e42011-04-15 14:24:37 +00003254 case Decl::TypeAlias: return CXCursor_TypeAliasDecl;
Sergey Kalinichev8f3b1872015-11-15 13:48:32 +00003255 case Decl::TypeAliasTemplate: return CXCursor_TypeAliasTemplateDecl;
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003256 case Decl::Var: return CXCursor_VarDecl;
3257 case Decl::Namespace: return CXCursor_Namespace;
3258 case Decl::NamespaceAlias: return CXCursor_NamespaceAlias;
3259 case Decl::TemplateTypeParm: return CXCursor_TemplateTypeParameter;
3260 case Decl::NonTypeTemplateParm:return CXCursor_NonTypeTemplateParameter;
3261 case Decl::TemplateTemplateParm:return CXCursor_TemplateTemplateParameter;
3262 case Decl::FunctionTemplate: return CXCursor_FunctionTemplate;
3263 case Decl::ClassTemplate: return CXCursor_ClassTemplate;
Argyrios Kyrtzidis12afd702011-09-30 17:58:23 +00003264 case Decl::AccessSpec: return CXCursor_CXXAccessSpecifier;
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003265 case Decl::ClassTemplatePartialSpecialization:
3266 return CXCursor_ClassTemplatePartialSpecialization;
3267 case Decl::UsingDirective: return CXCursor_UsingDirective;
Olivier Goffart81978012016-06-09 16:15:55 +00003268 case Decl::StaticAssert: return CXCursor_StaticAssert;
Olivier Goffartd211c642016-11-04 06:29:27 +00003269 case Decl::Friend: return CXCursor_FriendDecl;
Douglas Gregor3e653b32012-04-30 23:41:16 +00003270 case Decl::TranslationUnit: return CXCursor_TranslationUnit;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003271
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003272 case Decl::Using:
3273 case Decl::UnresolvedUsingValue:
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003274 case Decl::UnresolvedUsingTypename:
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003275 return CXCursor_UsingDeclaration;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003276
Douglas Gregor4cd65962011-06-03 23:08:58 +00003277 case Decl::ObjCPropertyImpl:
3278 switch (cast<ObjCPropertyImplDecl>(D)->getPropertyImplementation()) {
3279 case ObjCPropertyImplDecl::Dynamic:
3280 return CXCursor_ObjCDynamicDecl;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003281
Douglas Gregor4cd65962011-06-03 23:08:58 +00003282 case ObjCPropertyImplDecl::Synthesize:
3283 return CXCursor_ObjCSynthesizeDecl;
3284 }
Argyrios Kyrtzidis50e5b1d2012-10-05 00:22:24 +00003285
3286 case Decl::Import:
3287 return CXCursor_ModuleImportDecl;
Douglas Gregor85f3f952015-07-07 03:57:15 +00003288
3289 case Decl::ObjCTypeParam: return CXCursor_TemplateTypeParameter;
3290
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003291 default:
Dmitri Gribenkobdc80de2013-01-11 20:32:41 +00003292 if (const TagDecl *TD = dyn_cast<TagDecl>(D)) {
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003293 switch (TD->getTagKind()) {
Joao Matosdc86f942012-08-31 18:45:21 +00003294 case TTK_Interface: // fall through
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003295 case TTK_Struct: return CXCursor_StructDecl;
3296 case TTK_Class: return CXCursor_ClassDecl;
3297 case TTK_Union: return CXCursor_UnionDecl;
3298 case TTK_Enum: return CXCursor_EnumDecl;
3299 }
3300 }
3301 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003302
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003303 return CXCursor_UnexposedDecl;
3304}
3305
Douglas Gregor55b037b2010-07-08 20:55:51 +00003306static void AddMacroResults(Preprocessor &PP, ResultBuilder &Results,
Eric Liu88de9f62018-09-19 09:34:55 +00003307 bool LoadExternal, bool IncludeUndefined,
Douglas Gregor55b037b2010-07-08 20:55:51 +00003308 bool TargetTypeIsPointer = false) {
John McCall276321a2010-08-25 06:19:51 +00003309 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003310
Douglas Gregorf329c7c2009-10-30 16:50:04 +00003311 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003312
Eric Liu88de9f62018-09-19 09:34:55 +00003313 for (Preprocessor::macro_iterator M = PP.macro_begin(LoadExternal),
3314 MEnd = PP.macro_end(LoadExternal);
Douglas Gregor55b037b2010-07-08 20:55:51 +00003315 M != MEnd; ++M) {
Richard Smith20e883e2015-04-29 23:20:19 +00003316 auto MD = PP.getMacroDefinition(M->first);
3317 if (IncludeUndefined || MD) {
Eric Liud485df12018-09-05 14:59:17 +00003318 MacroInfo *MI = MD.getMacroInfo();
3319 if (MI && MI->isUsedForHeaderGuard())
3320 continue;
Argyrios Kyrtzidis9ef53ce2014-04-09 18:21:23 +00003321
Eric Liud485df12018-09-05 14:59:17 +00003322 Results.AddResult(
3323 Result(M->first, MI,
3324 getMacroUsagePriority(M->first->getName(), PP.getLangOpts(),
3325 TargetTypeIsPointer)));
Argyrios Kyrtzidis9ef53ce2014-04-09 18:21:23 +00003326 }
Douglas Gregor55b037b2010-07-08 20:55:51 +00003327 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003328
Douglas Gregorf329c7c2009-10-30 16:50:04 +00003329 Results.ExitScope();
3330}
3331
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003332static void AddPrettyFunctionResults(const LangOptions &LangOpts,
Douglas Gregorce0e8562010-08-23 21:54:33 +00003333 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00003334 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003335
Douglas Gregorce0e8562010-08-23 21:54:33 +00003336 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003337
Douglas Gregorce0e8562010-08-23 21:54:33 +00003338 Results.AddResult(Result("__PRETTY_FUNCTION__", CCP_Constant));
3339 Results.AddResult(Result("__FUNCTION__", CCP_Constant));
Richard Smith2bf7fdb2013-01-02 11:42:31 +00003340 if (LangOpts.C99 || LangOpts.CPlusPlus11)
Douglas Gregorce0e8562010-08-23 21:54:33 +00003341 Results.AddResult(Result("__func__", CCP_Constant));
3342 Results.ExitScope();
3343}
3344
Daniel Dunbar242ea9a2009-11-13 08:58:20 +00003345static void HandleCodeCompleteResults(Sema *S,
3346 CodeCompleteConsumer *CodeCompleter,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003347 CodeCompletionContext Context,
John McCall276321a2010-08-25 06:19:51 +00003348 CodeCompletionResult *Results,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003349 unsigned NumResults) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00003350 if (CodeCompleter)
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003351 CodeCompleter->ProcessCodeCompleteResults(*S, Context, Results, NumResults);
Douglas Gregor3545ff42009-09-21 16:56:56 +00003352}
3353
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003354static enum CodeCompletionContext::Kind mapCodeCompletionContext(Sema &S,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003355 Sema::ParserCompletionContext PCC) {
3356 switch (PCC) {
John McCallfaf5fb42010-08-26 23:41:50 +00003357 case Sema::PCC_Namespace:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003358 return CodeCompletionContext::CCC_TopLevel;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003359
John McCallfaf5fb42010-08-26 23:41:50 +00003360 case Sema::PCC_Class:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003361 return CodeCompletionContext::CCC_ClassStructUnion;
3362
John McCallfaf5fb42010-08-26 23:41:50 +00003363 case Sema::PCC_ObjCInterface:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003364 return CodeCompletionContext::CCC_ObjCInterface;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003365
John McCallfaf5fb42010-08-26 23:41:50 +00003366 case Sema::PCC_ObjCImplementation:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003367 return CodeCompletionContext::CCC_ObjCImplementation;
3368
John McCallfaf5fb42010-08-26 23:41:50 +00003369 case Sema::PCC_ObjCInstanceVariableList:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003370 return CodeCompletionContext::CCC_ObjCIvarList;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003371
John McCallfaf5fb42010-08-26 23:41:50 +00003372 case Sema::PCC_Template:
3373 case Sema::PCC_MemberTemplate:
Douglas Gregor0ac41382010-09-23 23:01:17 +00003374 if (S.CurContext->isFileContext())
3375 return CodeCompletionContext::CCC_TopLevel;
David Blaikie8a40f702012-01-17 06:56:22 +00003376 if (S.CurContext->isRecord())
Douglas Gregor0ac41382010-09-23 23:01:17 +00003377 return CodeCompletionContext::CCC_ClassStructUnion;
David Blaikie8a40f702012-01-17 06:56:22 +00003378 return CodeCompletionContext::CCC_Other;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003379
John McCallfaf5fb42010-08-26 23:41:50 +00003380 case Sema::PCC_RecoveryInFunction:
Douglas Gregor0ac41382010-09-23 23:01:17 +00003381 return CodeCompletionContext::CCC_Recovery;
Douglas Gregorc769d6e2010-10-18 22:01:46 +00003382
John McCallfaf5fb42010-08-26 23:41:50 +00003383 case Sema::PCC_ForInit:
David Blaikiebbafb8a2012-03-11 07:00:24 +00003384 if (S.getLangOpts().CPlusPlus || S.getLangOpts().C99 ||
3385 S.getLangOpts().ObjC1)
Douglas Gregorc769d6e2010-10-18 22:01:46 +00003386 return CodeCompletionContext::CCC_ParenthesizedExpression;
3387 else
3388 return CodeCompletionContext::CCC_Expression;
3389
3390 case Sema::PCC_Expression:
John McCallfaf5fb42010-08-26 23:41:50 +00003391 case Sema::PCC_Condition:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003392 return CodeCompletionContext::CCC_Expression;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003393
John McCallfaf5fb42010-08-26 23:41:50 +00003394 case Sema::PCC_Statement:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003395 return CodeCompletionContext::CCC_Statement;
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003396
John McCallfaf5fb42010-08-26 23:41:50 +00003397 case Sema::PCC_Type:
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003398 return CodeCompletionContext::CCC_Type;
Douglas Gregor5e35d592010-09-14 23:59:36 +00003399
3400 case Sema::PCC_ParenthesizedExpression:
3401 return CodeCompletionContext::CCC_ParenthesizedExpression;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003402
Douglas Gregor80039242011-02-15 20:33:25 +00003403 case Sema::PCC_LocalDeclarationSpecifiers:
3404 return CodeCompletionContext::CCC_Type;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003405 }
David Blaikie8a40f702012-01-17 06:56:22 +00003406
3407 llvm_unreachable("Invalid ParserCompletionContext!");
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003408}
3409
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003410/// If we're in a C++ virtual member function, add completion results
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003411/// that invoke the functions we override, since it's common to invoke the
Douglas Gregorac322ec2010-08-27 21:18:54 +00003412/// overridden function as well as adding new functionality.
3413///
3414/// \param S The semantic analysis object for which we are generating results.
3415///
3416/// \param InContext This context in which the nested-name-specifier preceding
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003417/// the code-completion point
Douglas Gregorac322ec2010-08-27 21:18:54 +00003418static void MaybeAddOverrideCalls(Sema &S, DeclContext *InContext,
3419 ResultBuilder &Results) {
3420 // Look through blocks.
3421 DeclContext *CurContext = S.CurContext;
3422 while (isa<BlockDecl>(CurContext))
3423 CurContext = CurContext->getParent();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003424
3425
Douglas Gregorac322ec2010-08-27 21:18:54 +00003426 CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(CurContext);
3427 if (!Method || !Method->isVirtual())
3428 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003429
3430 // We need to have names for all of the parameters, if we're going to
Douglas Gregorac322ec2010-08-27 21:18:54 +00003431 // generate a forwarding call.
David Majnemer59f77922016-06-24 04:05:48 +00003432 for (auto P : Method->parameters())
Aaron Ballman43b68be2014-03-07 17:50:17 +00003433 if (!P->getDeclName())
Douglas Gregorac322ec2010-08-27 21:18:54 +00003434 return;
Douglas Gregorac322ec2010-08-27 21:18:54 +00003435
Douglas Gregor75acd922011-09-27 23:30:47 +00003436 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
Benjamin Krameracfa3392017-12-17 23:52:45 +00003437 for (const CXXMethodDecl *Overridden : Method->overridden_methods()) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003438 CodeCompletionBuilder Builder(Results.getAllocator(),
3439 Results.getCodeCompletionTUInfo());
Douglas Gregorac322ec2010-08-27 21:18:54 +00003440 if (Overridden->getCanonicalDecl() == Method->getCanonicalDecl())
3441 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003442
Douglas Gregorac322ec2010-08-27 21:18:54 +00003443 // If we need a nested-name-specifier, add one now.
3444 if (!InContext) {
3445 NestedNameSpecifier *NNS
3446 = getRequiredQualification(S.Context, CurContext,
3447 Overridden->getDeclContext());
3448 if (NNS) {
3449 std::string Str;
3450 llvm::raw_string_ostream OS(Str);
Douglas Gregor75acd922011-09-27 23:30:47 +00003451 NNS->print(OS, Policy);
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003452 Builder.AddTextChunk(Results.getAllocator().CopyString(OS.str()));
Douglas Gregorac322ec2010-08-27 21:18:54 +00003453 }
3454 } else if (!InContext->Equals(Overridden->getDeclContext()))
3455 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003456
3457 Builder.AddTypedTextChunk(Results.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003458 Overridden->getNameAsString()));
3459 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregorac322ec2010-08-27 21:18:54 +00003460 bool FirstParam = true;
David Majnemer59f77922016-06-24 04:05:48 +00003461 for (auto P : Method->parameters()) {
Douglas Gregorac322ec2010-08-27 21:18:54 +00003462 if (FirstParam)
3463 FirstParam = false;
3464 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003465 Builder.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregorac322ec2010-08-27 21:18:54 +00003466
Aaron Ballman43b68be2014-03-07 17:50:17 +00003467 Builder.AddPlaceholderChunk(
3468 Results.getAllocator().CopyString(P->getIdentifier()->getName()));
Douglas Gregorac322ec2010-08-27 21:18:54 +00003469 }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003470 Builder.AddChunk(CodeCompletionString::CK_RightParen);
3471 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregorac322ec2010-08-27 21:18:54 +00003472 CCP_SuperCompletion,
Douglas Gregor78254c82012-03-27 23:34:16 +00003473 CXCursor_CXXMethod,
3474 CXAvailability_Available,
3475 Overridden));
Douglas Gregorac322ec2010-08-27 21:18:54 +00003476 Results.Ignore(Overridden);
3477 }
3478}
3479
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003480void Sema::CodeCompleteModuleImport(SourceLocation ImportLoc,
Douglas Gregor07f43572012-01-29 18:15:03 +00003481 ModuleIdPath Path) {
3482 typedef CodeCompletionResult Result;
3483 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003484 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor07f43572012-01-29 18:15:03 +00003485 CodeCompletionContext::CCC_Other);
3486 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003487
Douglas Gregor07f43572012-01-29 18:15:03 +00003488 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003489 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Douglas Gregor07f43572012-01-29 18:15:03 +00003490 typedef CodeCompletionResult Result;
3491 if (Path.empty()) {
3492 // Enumerate all top-level modules.
Dmitri Gribenkof8579502013-01-12 19:30:44 +00003493 SmallVector<Module *, 8> Modules;
Douglas Gregor07f43572012-01-29 18:15:03 +00003494 PP.getHeaderSearchInfo().collectAllModules(Modules);
3495 for (unsigned I = 0, N = Modules.size(); I != N; ++I) {
3496 Builder.AddTypedTextChunk(
3497 Builder.getAllocator().CopyString(Modules[I]->Name));
3498 Results.AddResult(Result(Builder.TakeString(),
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003499 CCP_Declaration,
Argyrios Kyrtzidis345d05f2013-05-29 18:50:15 +00003500 CXCursor_ModuleImportDecl,
Douglas Gregor07f43572012-01-29 18:15:03 +00003501 Modules[I]->isAvailable()
3502 ? CXAvailability_Available
3503 : CXAvailability_NotAvailable));
3504 }
Daniel Jasper07e6c402013-08-05 20:26:17 +00003505 } else if (getLangOpts().Modules) {
Douglas Gregor07f43572012-01-29 18:15:03 +00003506 // Load the named module.
3507 Module *Mod = PP.getModuleLoader().loadModule(ImportLoc, Path,
3508 Module::AllVisible,
3509 /*IsInclusionDirective=*/false);
3510 // Enumerate submodules.
3511 if (Mod) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003512 for (Module::submodule_iterator Sub = Mod->submodule_begin(),
Douglas Gregor07f43572012-01-29 18:15:03 +00003513 SubEnd = Mod->submodule_end();
3514 Sub != SubEnd; ++Sub) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003515
Douglas Gregor07f43572012-01-29 18:15:03 +00003516 Builder.AddTypedTextChunk(
3517 Builder.getAllocator().CopyString((*Sub)->Name));
3518 Results.AddResult(Result(Builder.TakeString(),
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003519 CCP_Declaration,
Argyrios Kyrtzidis345d05f2013-05-29 18:50:15 +00003520 CXCursor_ModuleImportDecl,
Douglas Gregor07f43572012-01-29 18:15:03 +00003521 (*Sub)->isAvailable()
3522 ? CXAvailability_Available
3523 : CXAvailability_NotAvailable));
3524 }
3525 }
3526 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003527 Results.ExitScope();
Douglas Gregor07f43572012-01-29 18:15:03 +00003528 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
3529 Results.data(),Results.size());
3530}
3531
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003532void Sema::CodeCompleteOrdinaryName(Scope *S,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003533 ParserCompletionContext CompletionContext) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003534 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003535 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00003536 mapCodeCompletionContext(*this, CompletionContext));
Douglas Gregorac322ec2010-08-27 21:18:54 +00003537 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003538
Douglas Gregor504a6ae2010-01-10 23:08:15 +00003539 // Determine how to filter results, e.g., so that the names of
3540 // values (functions, enumerators, function templates, etc.) are
3541 // only allowed where we can have an expression.
3542 switch (CompletionContext) {
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003543 case PCC_Namespace:
3544 case PCC_Class:
3545 case PCC_ObjCInterface:
3546 case PCC_ObjCImplementation:
3547 case PCC_ObjCInstanceVariableList:
3548 case PCC_Template:
3549 case PCC_MemberTemplate:
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003550 case PCC_Type:
Douglas Gregor80039242011-02-15 20:33:25 +00003551 case PCC_LocalDeclarationSpecifiers:
Douglas Gregor504a6ae2010-01-10 23:08:15 +00003552 Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
3553 break;
3554
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003555 case PCC_Statement:
Douglas Gregor5e35d592010-09-14 23:59:36 +00003556 case PCC_ParenthesizedExpression:
Douglas Gregor4d755e82010-08-24 23:58:17 +00003557 case PCC_Expression:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003558 case PCC_ForInit:
3559 case PCC_Condition:
David Blaikiebbafb8a2012-03-11 07:00:24 +00003560 if (WantTypesInContext(CompletionContext, getLangOpts()))
Douglas Gregor70febae2010-05-28 00:49:12 +00003561 Results.setFilter(&ResultBuilder::IsOrdinaryName);
3562 else
3563 Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003564
David Blaikiebbafb8a2012-03-11 07:00:24 +00003565 if (getLangOpts().CPlusPlus)
Craig Topperc3ec1492014-05-26 06:22:03 +00003566 MaybeAddOverrideCalls(*this, /*InContext=*/nullptr, Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00003567 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003568
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003569 case PCC_RecoveryInFunction:
Douglas Gregor6da3db42010-05-25 05:58:43 +00003570 // Unfiltered
3571 break;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00003572 }
3573
Douglas Gregor9be0ed42010-08-26 16:36:48 +00003574 // If we are in a C++ non-static member function, check the qualifiers on
3575 // the member function to filter/prioritize the results list.
3576 if (CXXMethodDecl *CurMethod = dyn_cast<CXXMethodDecl>(CurContext))
3577 if (CurMethod->isInstance())
3578 Results.setObjectTypeQualifiers(
3579 Qualifiers::fromCVRMask(CurMethod->getTypeQualifiers()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003580
Douglas Gregorc580c522010-01-14 01:09:38 +00003581 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00003582 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00003583 CodeCompleter->includeGlobals(),
3584 CodeCompleter->loadExternal());
Douglas Gregor92253692009-12-07 09:54:55 +00003585
Douglas Gregorf98e6a22010-01-13 23:51:12 +00003586 AddOrdinaryNameResults(CompletionContext, S, *this, Results);
Douglas Gregor92253692009-12-07 09:54:55 +00003587 Results.ExitScope();
3588
Douglas Gregorce0e8562010-08-23 21:54:33 +00003589 switch (CompletionContext) {
Douglas Gregor5e35d592010-09-14 23:59:36 +00003590 case PCC_ParenthesizedExpression:
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003591 case PCC_Expression:
3592 case PCC_Statement:
3593 case PCC_RecoveryInFunction:
3594 if (S->getFnParent())
Craig Topper12126262015-11-15 17:27:57 +00003595 AddPrettyFunctionResults(getLangOpts(), Results);
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003596 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003597
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003598 case PCC_Namespace:
3599 case PCC_Class:
3600 case PCC_ObjCInterface:
3601 case PCC_ObjCImplementation:
3602 case PCC_ObjCInstanceVariableList:
3603 case PCC_Template:
3604 case PCC_MemberTemplate:
3605 case PCC_ForInit:
3606 case PCC_Condition:
3607 case PCC_Type:
Douglas Gregor80039242011-02-15 20:33:25 +00003608 case PCC_LocalDeclarationSpecifiers:
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003609 break;
Douglas Gregorce0e8562010-08-23 21:54:33 +00003610 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003611
Douglas Gregor9eb77012009-11-07 00:00:49 +00003612 if (CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00003613 AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003614
Douglas Gregor50832e02010-09-20 22:39:41 +00003615 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003616 Results.data(),Results.size());
Douglas Gregor9d64c5e2009-09-21 20:51:25 +00003617}
3618
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003619static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003620 ParsedType Receiver,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00003621 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00003622 bool AtArgumentExpression,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003623 bool IsSuper,
3624 ResultBuilder &Results);
3625
3626void Sema::CodeCompleteDeclSpec(Scope *S, DeclSpec &DS,
3627 bool AllowNonIdentifiers,
3628 bool AllowNestedNameSpecifiers) {
John McCall276321a2010-08-25 06:19:51 +00003629 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003630 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003631 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00003632 AllowNestedNameSpecifiers
3633 ? CodeCompletionContext::CCC_PotentiallyQualifiedName
3634 : CodeCompletionContext::CCC_Name);
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003635 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003636
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003637 // Type qualifiers can come after names.
3638 Results.AddResult(Result("const"));
3639 Results.AddResult(Result("volatile"));
David Blaikiebbafb8a2012-03-11 07:00:24 +00003640 if (getLangOpts().C99)
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003641 Results.AddResult(Result("restrict"));
3642
David Blaikiebbafb8a2012-03-11 07:00:24 +00003643 if (getLangOpts().CPlusPlus) {
Alex Lorenz8f4d3992017-02-13 23:19:40 +00003644 if (getLangOpts().CPlusPlus11 &&
3645 (DS.getTypeSpecType() == DeclSpec::TST_class ||
3646 DS.getTypeSpecType() == DeclSpec::TST_struct))
3647 Results.AddResult("final");
3648
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003649 if (AllowNonIdentifiers) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003650 Results.AddResult(Result("operator"));
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003651 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003652
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003653 // Add nested-name-specifiers.
3654 if (AllowNestedNameSpecifiers) {
3655 Results.allowNestedNameSpecifiers();
Douglas Gregor0ac41382010-09-23 23:01:17 +00003656 Results.setFilter(&ResultBuilder::IsImpossibleToSatisfy);
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003657 CodeCompletionDeclConsumer Consumer(Results, CurContext);
3658 LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00003659 CodeCompleter->includeGlobals(),
3660 CodeCompleter->loadExternal());
Craig Topperc3ec1492014-05-26 06:22:03 +00003661 Results.setFilter(nullptr);
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003662 }
3663 }
3664 Results.ExitScope();
3665
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003666 // If we're in a context where we might have an expression (rather than a
3667 // declaration), and what we've seen so far is an Objective-C type that could
3668 // be a receiver of a class message, this may be a class message send with
3669 // the initial opening bracket '[' missing. Add appropriate completions.
3670 if (AllowNonIdentifiers && !AllowNestedNameSpecifiers &&
Richard Smithb4a9e862013-04-12 22:46:28 +00003671 DS.getParsedSpecifiers() == DeclSpec::PQ_TypeSpecifier &&
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003672 DS.getTypeSpecType() == DeclSpec::TST_typename &&
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003673 DS.getTypeSpecComplex() == DeclSpec::TSC_unspecified &&
3674 DS.getTypeSpecSign() == DeclSpec::TSS_unspecified &&
Richard Smithb4a9e862013-04-12 22:46:28 +00003675 !DS.isTypeAltiVecVector() &&
3676 S &&
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003677 (S->getFlags() & Scope::DeclScope) != 0 &&
3678 (S->getFlags() & (Scope::ClassScope | Scope::TemplateParamScope |
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003679 Scope::FunctionPrototypeScope |
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003680 Scope::AtCatchScope)) == 0) {
3681 ParsedType T = DS.getRepAsType();
3682 if (!T.get().isNull() && T.get()->isObjCObjectOrInterfaceType())
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00003683 AddClassMessageCompletions(*this, S, T, None, false, false, Results);
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003684 }
3685
Douglas Gregor56ccce02010-08-24 04:59:56 +00003686 // Note that we intentionally suppress macro results here, since we do not
3687 // encourage using macros to produce the names of entities.
3688
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003689 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0ac41382010-09-23 23:01:17 +00003690 Results.getCompletionContext(),
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003691 Results.data(), Results.size());
3692}
3693
Douglas Gregor68762e72010-08-23 21:17:50 +00003694struct Sema::CodeCompleteExpressionData {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003695 CodeCompleteExpressionData(QualType PreferredType = QualType())
Douglas Gregor68762e72010-08-23 21:17:50 +00003696 : PreferredType(PreferredType), IntegralConstantExpression(false),
3697 ObjCCollection(false) { }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003698
Douglas Gregor68762e72010-08-23 21:17:50 +00003699 QualType PreferredType;
3700 bool IntegralConstantExpression;
3701 bool ObjCCollection;
Chris Lattner0e62c1c2011-07-23 10:55:15 +00003702 SmallVector<Decl *, 4> IgnoreDecls;
Douglas Gregor68762e72010-08-23 21:17:50 +00003703};
3704
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003705/// Perform code-completion in an expression context when we know what
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003706/// type we're looking for.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003707void Sema::CodeCompleteExpression(Scope *S,
Douglas Gregor68762e72010-08-23 21:17:50 +00003708 const CodeCompleteExpressionData &Data) {
Eric Liuf5ba09f2018-07-04 10:01:18 +00003709 ResultBuilder Results(
3710 *this, CodeCompleter->getAllocator(),
3711 CodeCompleter->getCodeCompletionTUInfo(),
3712 CodeCompletionContext(CodeCompletionContext::CCC_Expression,
3713 Data.PreferredType));
Douglas Gregor68762e72010-08-23 21:17:50 +00003714 if (Data.ObjCCollection)
3715 Results.setFilter(&ResultBuilder::IsObjCCollection);
3716 else if (Data.IntegralConstantExpression)
Douglas Gregor85b50632010-07-28 21:50:18 +00003717 Results.setFilter(&ResultBuilder::IsIntegralConstantValue);
David Blaikiebbafb8a2012-03-11 07:00:24 +00003718 else if (WantTypesInContext(PCC_Expression, getLangOpts()))
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003719 Results.setFilter(&ResultBuilder::IsOrdinaryName);
3720 else
3721 Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
Douglas Gregor68762e72010-08-23 21:17:50 +00003722
3723 if (!Data.PreferredType.isNull())
3724 Results.setPreferredType(Data.PreferredType.getNonReferenceType());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003725
Douglas Gregor68762e72010-08-23 21:17:50 +00003726 // Ignore any declarations that we were told that we don't care about.
3727 for (unsigned I = 0, N = Data.IgnoreDecls.size(); I != N; ++I)
3728 Results.Ignore(Data.IgnoreDecls[I]);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003729
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003730 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00003731 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00003732 CodeCompleter->includeGlobals(),
3733 CodeCompleter->loadExternal());
3734
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003735 Results.EnterNewScope();
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003736 AddOrdinaryNameResults(PCC_Expression, S, *this, Results);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003737 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003738
Douglas Gregor55b037b2010-07-08 20:55:51 +00003739 bool PreferredTypeIsPointer = false;
Douglas Gregor68762e72010-08-23 21:17:50 +00003740 if (!Data.PreferredType.isNull())
3741 PreferredTypeIsPointer = Data.PreferredType->isAnyPointerType()
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003742 || Data.PreferredType->isMemberPointerType()
Douglas Gregor68762e72010-08-23 21:17:50 +00003743 || Data.PreferredType->isBlockPointerType();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003744
3745 if (S->getFnParent() &&
3746 !Data.ObjCCollection &&
Douglas Gregorce0e8562010-08-23 21:54:33 +00003747 !Data.IntegralConstantExpression)
Craig Topper12126262015-11-15 17:27:57 +00003748 AddPrettyFunctionResults(getLangOpts(), Results);
Douglas Gregorce0e8562010-08-23 21:54:33 +00003749
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003750 if (CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00003751 AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false,
3752 PreferredTypeIsPointer);
Eric Liuf5ba09f2018-07-04 10:01:18 +00003753 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
3754 Results.data(), Results.size());
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003755}
3756
Ilya Biryukov832c4af2018-09-07 14:04:39 +00003757void Sema::CodeCompleteExpression(Scope *S, QualType PreferredType) {
3758 return CodeCompleteExpression(S, CodeCompleteExpressionData(PreferredType));
3759}
3760
Douglas Gregoreda7e542010-09-18 01:28:11 +00003761void Sema::CodeCompletePostfixExpression(Scope *S, ExprResult E) {
3762 if (E.isInvalid())
3763 CodeCompleteOrdinaryName(S, PCC_RecoveryInFunction);
David Blaikiebbafb8a2012-03-11 07:00:24 +00003764 else if (getLangOpts().ObjC1)
Nikola Smiljanic01a75982014-05-29 10:55:11 +00003765 CodeCompleteObjCInstanceMessage(S, E.get(), None, false);
Douglas Gregored0b69d2010-09-15 16:23:04 +00003766}
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003767
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003768/// The set of properties that have already been added, referenced by
Douglas Gregorb888acf2010-12-09 23:01:55 +00003769/// property name.
3770typedef llvm::SmallPtrSet<IdentifierInfo*, 16> AddedPropertiesSet;
3771
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003772/// Retrieve the container definition, if any?
Douglas Gregor9b4f3702012-06-12 13:44:08 +00003773static ObjCContainerDecl *getContainerDef(ObjCContainerDecl *Container) {
3774 if (ObjCInterfaceDecl *Interface = dyn_cast<ObjCInterfaceDecl>(Container)) {
3775 if (Interface->hasDefinition())
3776 return Interface->getDefinition();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003777
Douglas Gregor9b4f3702012-06-12 13:44:08 +00003778 return Interface;
3779 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003780
Douglas Gregor9b4f3702012-06-12 13:44:08 +00003781 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
3782 if (Protocol->hasDefinition())
3783 return Protocol->getDefinition();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003784
Douglas Gregor9b4f3702012-06-12 13:44:08 +00003785 return Protocol;
3786 }
3787 return Container;
3788}
3789
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003790/// Adds a block invocation code completion result for the given block
Alex Lorenzbaef8022016-11-09 13:43:18 +00003791/// declaration \p BD.
3792static void AddObjCBlockCall(ASTContext &Context, const PrintingPolicy &Policy,
3793 CodeCompletionBuilder &Builder,
3794 const NamedDecl *BD,
3795 const FunctionTypeLoc &BlockLoc,
3796 const FunctionProtoTypeLoc &BlockProtoLoc) {
3797 Builder.AddResultTypeChunk(
3798 GetCompletionTypeString(BlockLoc.getReturnLoc().getType(), Context,
3799 Policy, Builder.getAllocator()));
3800
3801 AddTypedNameChunk(Context, Policy, BD, Builder);
3802 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
3803
3804 if (BlockProtoLoc && BlockProtoLoc.getTypePtr()->isVariadic()) {
3805 Builder.AddPlaceholderChunk("...");
3806 } else {
3807 for (unsigned I = 0, N = BlockLoc.getNumParams(); I != N; ++I) {
3808 if (I)
3809 Builder.AddChunk(CodeCompletionString::CK_Comma);
3810
3811 // Format the placeholder string.
3812 std::string PlaceholderStr =
3813 FormatFunctionParameter(Policy, BlockLoc.getParam(I));
3814
3815 if (I == N - 1 && BlockProtoLoc &&
3816 BlockProtoLoc.getTypePtr()->isVariadic())
3817 PlaceholderStr += ", ...";
3818
3819 // Add the placeholder string.
3820 Builder.AddPlaceholderChunk(
3821 Builder.getAllocator().CopyString(PlaceholderStr));
3822 }
3823 }
3824
3825 Builder.AddChunk(CodeCompletionString::CK_RightParen);
3826}
3827
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003828static void AddObjCProperties(
3829 const CodeCompletionContext &CCContext, ObjCContainerDecl *Container,
3830 bool AllowCategories, bool AllowNullaryMethods, DeclContext *CurContext,
3831 AddedPropertiesSet &AddedProperties, ResultBuilder &Results,
3832 bool IsBaseExprStatement = false, bool IsClassProperty = false) {
John McCall276321a2010-08-25 06:19:51 +00003833 typedef CodeCompletionResult Result;
Douglas Gregor9291bad2009-11-18 01:29:26 +00003834
Douglas Gregor9b4f3702012-06-12 13:44:08 +00003835 // Retrieve the definition.
3836 Container = getContainerDef(Container);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003837
Douglas Gregor9291bad2009-11-18 01:29:26 +00003838 // Add properties in this container.
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003839 const auto AddProperty = [&](const ObjCPropertyDecl *P) {
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003840 if (!AddedProperties.insert(P->getIdentifier()).second)
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003841 return;
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003842
Alex Lorenzbaef8022016-11-09 13:43:18 +00003843 // FIXME: Provide block invocation completion for non-statement
3844 // expressions.
3845 if (!P->getType().getTypePtr()->isBlockPointerType() ||
3846 !IsBaseExprStatement) {
3847 Results.MaybeAddResult(Result(P, Results.getBasePriority(P), nullptr),
3848 CurContext);
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003849 return;
Alex Lorenzbaef8022016-11-09 13:43:18 +00003850 }
3851
3852 // Block setter and invocation completion is provided only when we are able
3853 // to find the FunctionProtoTypeLoc with parameter names for the block.
3854 FunctionTypeLoc BlockLoc;
3855 FunctionProtoTypeLoc BlockProtoLoc;
3856 findTypeLocationForBlockDecl(P->getTypeSourceInfo(), BlockLoc,
3857 BlockProtoLoc);
3858 if (!BlockLoc) {
3859 Results.MaybeAddResult(Result(P, Results.getBasePriority(P), nullptr),
3860 CurContext);
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003861 return;
Alex Lorenzbaef8022016-11-09 13:43:18 +00003862 }
3863
3864 // The default completion result for block properties should be the block
3865 // invocation completion when the base expression is a statement.
3866 CodeCompletionBuilder Builder(Results.getAllocator(),
3867 Results.getCodeCompletionTUInfo());
3868 AddObjCBlockCall(Container->getASTContext(),
3869 getCompletionPrintingPolicy(Results.getSema()), Builder, P,
3870 BlockLoc, BlockProtoLoc);
3871 Results.MaybeAddResult(
3872 Result(Builder.TakeString(), P, Results.getBasePriority(P)),
3873 CurContext);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003874
3875 // Provide additional block setter completion iff the base expression is a
Alex Lorenzbaef8022016-11-09 13:43:18 +00003876 // statement and the block property is mutable.
3877 if (!P->isReadOnly()) {
3878 CodeCompletionBuilder Builder(Results.getAllocator(),
3879 Results.getCodeCompletionTUInfo());
3880 AddResultTypeChunk(Container->getASTContext(),
3881 getCompletionPrintingPolicy(Results.getSema()), P,
3882 CCContext.getBaseType(), Builder);
3883 Builder.AddTypedTextChunk(
3884 Results.getAllocator().CopyString(P->getName()));
3885 Builder.AddChunk(CodeCompletionString::CK_Equal);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003886
Alex Lorenzbaef8022016-11-09 13:43:18 +00003887 std::string PlaceholderStr = formatBlockPlaceholder(
3888 getCompletionPrintingPolicy(Results.getSema()), P, BlockLoc,
3889 BlockProtoLoc, /*SuppressBlockName=*/true);
3890 // Add the placeholder string.
3891 Builder.AddPlaceholderChunk(
3892 Builder.getAllocator().CopyString(PlaceholderStr));
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003893
Alex Lorenz6e0f3932017-01-06 12:00:44 +00003894 // When completing blocks properties that return void the default
3895 // property completion result should show up before the setter,
3896 // otherwise the setter completion should show up before the default
3897 // property completion, as we normally want to use the result of the
3898 // call.
Alex Lorenzbaef8022016-11-09 13:43:18 +00003899 Results.MaybeAddResult(
3900 Result(Builder.TakeString(), P,
Alex Lorenz6e0f3932017-01-06 12:00:44 +00003901 Results.getBasePriority(P) +
3902 (BlockLoc.getTypePtr()->getReturnType()->isVoidType()
3903 ? CCD_BlockPropertySetter
3904 : -CCD_BlockPropertySetter)),
Alex Lorenzbaef8022016-11-09 13:43:18 +00003905 CurContext);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003906 }
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003907 };
3908
3909 if (IsClassProperty) {
3910 for (const auto *P : Container->class_properties())
3911 AddProperty(P);
3912 } else {
3913 for (const auto *P : Container->instance_properties())
3914 AddProperty(P);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003915 }
Craig Topperc3ec1492014-05-26 06:22:03 +00003916
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003917 // Add nullary methods or implicit class properties
Douglas Gregor95147142011-05-05 15:50:42 +00003918 if (AllowNullaryMethods) {
3919 ASTContext &Context = Container->getASTContext();
Douglas Gregor75acd922011-09-27 23:30:47 +00003920 PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema());
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003921 // Adds a method result
3922 const auto AddMethod = [&](const ObjCMethodDecl *M) {
3923 IdentifierInfo *Name = M->getSelector().getIdentifierInfoForSlot(0);
3924 if (!Name)
3925 return;
3926 if (!AddedProperties.insert(Name).second)
3927 return;
3928 CodeCompletionBuilder Builder(Results.getAllocator(),
3929 Results.getCodeCompletionTUInfo());
3930 AddResultTypeChunk(Context, Policy, M, CCContext.getBaseType(), Builder);
3931 Builder.AddTypedTextChunk(
3932 Results.getAllocator().CopyString(Name->getName()));
3933 Results.MaybeAddResult(
3934 Result(Builder.TakeString(), M,
3935 CCP_MemberDeclaration + CCD_MethodAsProperty),
3936 CurContext);
3937 };
3938
3939 if (IsClassProperty) {
3940 for (const auto *M : Container->methods()) {
3941 // Gather the class method that can be used as implicit property
3942 // getters. Methods with arguments or methods that return void aren't
3943 // added to the results as they can't be used as a getter.
3944 if (!M->getSelector().isUnarySelector() ||
3945 M->getReturnType()->isVoidType() || M->isInstanceMethod())
3946 continue;
3947 AddMethod(M);
3948 }
3949 } else {
3950 for (auto *M : Container->methods()) {
3951 if (M->getSelector().isUnarySelector())
3952 AddMethod(M);
3953 }
Douglas Gregor95147142011-05-05 15:50:42 +00003954 }
3955 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003956
Douglas Gregor9291bad2009-11-18 01:29:26 +00003957 // Add properties in referenced protocols.
3958 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Aaron Ballman0f6e64d2014-03-13 22:58:06 +00003959 for (auto *P : Protocol->protocols())
Douglas Gregorc3425b12015-07-07 06:20:19 +00003960 AddObjCProperties(CCContext, P, AllowCategories, AllowNullaryMethods,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003961 CurContext, AddedProperties, Results,
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003962 IsBaseExprStatement, IsClassProperty);
Douglas Gregor9291bad2009-11-18 01:29:26 +00003963 } else if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)){
Douglas Gregor5d649882009-11-18 22:32:06 +00003964 if (AllowCategories) {
3965 // Look through categories.
Aaron Ballman15063e12014-03-13 21:35:02 +00003966 for (auto *Cat : IFace->known_categories())
Douglas Gregorc3425b12015-07-07 06:20:19 +00003967 AddObjCProperties(CCContext, Cat, AllowCategories, AllowNullaryMethods,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003968 CurContext, AddedProperties, Results,
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003969 IsBaseExprStatement, IsClassProperty);
Douglas Gregor5d649882009-11-18 22:32:06 +00003970 }
Aaron Ballman15063e12014-03-13 21:35:02 +00003971
Douglas Gregor9291bad2009-11-18 01:29:26 +00003972 // Look through protocols.
Aaron Ballmana9f49e32014-03-13 20:55:22 +00003973 for (auto *I : IFace->all_referenced_protocols())
Douglas Gregorc3425b12015-07-07 06:20:19 +00003974 AddObjCProperties(CCContext, I, AllowCategories, AllowNullaryMethods,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003975 CurContext, AddedProperties, Results,
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003976 IsBaseExprStatement, IsClassProperty);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003977
Douglas Gregor9291bad2009-11-18 01:29:26 +00003978 // Look in the superclass.
3979 if (IFace->getSuperClass())
Douglas Gregorc3425b12015-07-07 06:20:19 +00003980 AddObjCProperties(CCContext, IFace->getSuperClass(), AllowCategories,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003981 AllowNullaryMethods, CurContext, AddedProperties,
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003982 Results, IsBaseExprStatement, IsClassProperty);
Douglas Gregor9291bad2009-11-18 01:29:26 +00003983 } else if (const ObjCCategoryDecl *Category
3984 = dyn_cast<ObjCCategoryDecl>(Container)) {
3985 // Look through protocols.
Aaron Ballman19a41762014-03-14 12:55:57 +00003986 for (auto *P : Category->protocols())
Douglas Gregorc3425b12015-07-07 06:20:19 +00003987 AddObjCProperties(CCContext, P, AllowCategories, AllowNullaryMethods,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003988 CurContext, AddedProperties, Results,
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003989 IsBaseExprStatement, IsClassProperty);
Douglas Gregor9291bad2009-11-18 01:29:26 +00003990 }
3991}
3992
Alex Lorenz0fe0d982017-05-11 13:41:00 +00003993static void AddRecordMembersCompletionResults(Sema &SemaRef,
3994 ResultBuilder &Results, Scope *S,
3995 QualType BaseType,
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00003996 RecordDecl *RD,
3997 Optional<FixItHint> AccessOpFixIt) {
Alex Lorenz0fe0d982017-05-11 13:41:00 +00003998 // Indicate that we are performing a member access, and the cv-qualifiers
3999 // for the base object type.
4000 Results.setObjectTypeQualifiers(BaseType.getQualifiers());
4001
4002 // Access to a C/C++ class, struct, or union.
4003 Results.allowNestedNameSpecifiers();
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004004 std::vector<FixItHint> FixIts;
4005 if (AccessOpFixIt)
4006 FixIts.emplace_back(AccessOpFixIt.getValue());
4007 CodeCompletionDeclConsumer Consumer(Results, SemaRef.CurContext, std::move(FixIts));
Alex Lorenz0fe0d982017-05-11 13:41:00 +00004008 SemaRef.LookupVisibleDecls(RD, Sema::LookupMemberName, Consumer,
Alex Lorenze6afa392017-05-11 13:48:57 +00004009 SemaRef.CodeCompleter->includeGlobals(),
Sam McCallbb2cf632018-01-12 14:51:47 +00004010 /*IncludeDependentBases=*/true,
4011 SemaRef.CodeCompleter->loadExternal());
Alex Lorenz0fe0d982017-05-11 13:41:00 +00004012
4013 if (SemaRef.getLangOpts().CPlusPlus) {
4014 if (!Results.empty()) {
4015 // The "template" keyword can follow "->" or "." in the grammar.
4016 // However, we only want to suggest the template keyword if something
4017 // is dependent.
4018 bool IsDependent = BaseType->isDependentType();
4019 if (!IsDependent) {
4020 for (Scope *DepScope = S; DepScope; DepScope = DepScope->getParent())
4021 if (DeclContext *Ctx = DepScope->getEntity()) {
4022 IsDependent = Ctx->isDependentContext();
4023 break;
4024 }
4025 }
4026
4027 if (IsDependent)
4028 Results.AddResult(CodeCompletionResult("template"));
4029 }
4030 }
4031}
4032
Douglas Gregor1cc88a92012-01-23 15:59:30 +00004033void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base,
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004034 Expr *OtherOpBase,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004035 SourceLocation OpLoc, bool IsArrow,
4036 bool IsBaseExprStatement) {
Douglas Gregor1cc88a92012-01-23 15:59:30 +00004037 if (!Base || !CodeCompleter)
Douglas Gregor2436e712009-09-17 21:32:03 +00004038 return;
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004039
Douglas Gregor1cc88a92012-01-23 15:59:30 +00004040 ExprResult ConvertedBase = PerformMemberExprBaseConversion(Base, IsArrow);
4041 if (ConvertedBase.isInvalid())
4042 return;
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004043 QualType ConvertedBaseType = ConvertedBase.get()->getType();
4044
4045 enum CodeCompletionContext::Kind contextKind;
Douglas Gregor3545ff42009-09-21 16:56:56 +00004046
4047 if (IsArrow) {
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004048 if (const PointerType *Ptr = ConvertedBaseType->getAs<PointerType>())
4049 ConvertedBaseType = Ptr->getPointeeType();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004050 }
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004051
Douglas Gregor21325842011-07-07 16:03:39 +00004052 if (IsArrow) {
4053 contextKind = CodeCompletionContext::CCC_ArrowMemberAccess;
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004054 } else {
4055 if (ConvertedBaseType->isObjCObjectPointerType() ||
4056 ConvertedBaseType->isObjCObjectOrInterfaceType()) {
Douglas Gregor21325842011-07-07 16:03:39 +00004057 contextKind = CodeCompletionContext::CCC_ObjCPropertyAccess;
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004058 } else {
Douglas Gregor21325842011-07-07 16:03:39 +00004059 contextKind = CodeCompletionContext::CCC_DotMemberAccess;
4060 }
4061 }
Douglas Gregorc3425b12015-07-07 06:20:19 +00004062
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004063 CodeCompletionContext CCContext(contextKind, ConvertedBaseType);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004064 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004065 CodeCompleter->getCodeCompletionTUInfo(), CCContext,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004066 &ResultBuilder::IsMember);
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004067
4068 auto DoCompletion = [&](Expr *Base, bool IsArrow, Optional<FixItHint> AccessOpFixIt) -> bool {
4069 if (!Base)
4070 return false;
4071
4072 ExprResult ConvertedBase = PerformMemberExprBaseConversion(Base, IsArrow);
4073 if (ConvertedBase.isInvalid())
4074 return false;
4075 Base = ConvertedBase.get();
4076
4077 QualType BaseType = Base->getType();
4078
4079 if (IsArrow) {
4080 if (const PointerType *Ptr = BaseType->getAs<PointerType>())
4081 BaseType = Ptr->getPointeeType();
4082 else if (BaseType->isObjCObjectPointerType())
4083 /*Do nothing*/;
4084 else
4085 return false;
4086 }
4087
4088 if (const RecordType *Record = BaseType->getAs<RecordType>()) {
4089 AddRecordMembersCompletionResults(*this, Results, S, BaseType,
4090 Record->getDecl(),
4091 std::move(AccessOpFixIt));
4092 } else if (const auto *TST =
4093 BaseType->getAs<TemplateSpecializationType>()) {
4094 TemplateName TN = TST->getTemplateName();
4095 if (const auto *TD =
4096 dyn_cast_or_null<ClassTemplateDecl>(TN.getAsTemplateDecl())) {
4097 CXXRecordDecl *RD = TD->getTemplatedDecl();
4098 AddRecordMembersCompletionResults(*this, Results, S, BaseType, RD,
4099 std::move(AccessOpFixIt));
4100 }
4101 } else if (const auto *ICNT = BaseType->getAs<InjectedClassNameType>()) {
4102 if (auto *RD = ICNT->getDecl())
4103 AddRecordMembersCompletionResults(*this, Results, S, BaseType, RD,
4104 std::move(AccessOpFixIt));
4105 } else if (!IsArrow && BaseType->isObjCObjectPointerType()) {
4106 // Objective-C property reference.
4107 AddedPropertiesSet AddedProperties;
4108
4109 if (const ObjCObjectPointerType *ObjCPtr =
4110 BaseType->getAsObjCInterfacePointerType()) {
4111 // Add property results based on our interface.
4112 assert(ObjCPtr && "Non-NULL pointer guaranteed above!");
4113 AddObjCProperties(CCContext, ObjCPtr->getInterfaceDecl(), true,
4114 /*AllowNullaryMethods=*/true, CurContext,
4115 AddedProperties, Results, IsBaseExprStatement);
4116 }
4117
4118 // Add properties from the protocols in a qualified interface.
4119 for (auto *I : BaseType->getAs<ObjCObjectPointerType>()->quals())
4120 AddObjCProperties(CCContext, I, true, /*AllowNullaryMethods=*/true,
4121 CurContext, AddedProperties, Results,
4122 IsBaseExprStatement);
4123 } else if ((IsArrow && BaseType->isObjCObjectPointerType()) ||
4124 (!IsArrow && BaseType->isObjCObjectType())) {
4125 // Objective-C instance variable access.
4126 ObjCInterfaceDecl *Class = nullptr;
4127 if (const ObjCObjectPointerType *ObjCPtr =
4128 BaseType->getAs<ObjCObjectPointerType>())
4129 Class = ObjCPtr->getInterfaceDecl();
4130 else
4131 Class = BaseType->getAs<ObjCObjectType>()->getInterface();
4132
4133 // Add all ivars from this class and its superclasses.
4134 if (Class) {
4135 CodeCompletionDeclConsumer Consumer(Results, CurContext);
4136 Results.setFilter(&ResultBuilder::IsObjCIvar);
4137 LookupVisibleDecls(
4138 Class, LookupMemberName, Consumer, CodeCompleter->includeGlobals(),
4139 /*IncludeDependentBases=*/false, CodeCompleter->loadExternal());
4140 }
4141 }
4142
4143 // FIXME: How do we cope with isa?
4144 return true;
4145 };
4146
Douglas Gregor9291bad2009-11-18 01:29:26 +00004147 Results.EnterNewScope();
Alex Lorenz06cfa992016-10-12 11:40:15 +00004148
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004149 bool CompletionSucceded = DoCompletion(Base, IsArrow, None);
4150 if (CodeCompleter->includeFixIts()) {
4151 const CharSourceRange OpRange =
4152 CharSourceRange::getTokenRange(OpLoc, OpLoc);
4153 CompletionSucceded |= DoCompletion(
4154 OtherOpBase, !IsArrow,
4155 FixItHint::CreateReplacement(OpRange, IsArrow ? "." : "->"));
Douglas Gregor3545ff42009-09-21 16:56:56 +00004156 }
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004157
Douglas Gregor9291bad2009-11-18 01:29:26 +00004158 Results.ExitScope();
Daniel Dunbar242ea9a2009-11-13 08:58:20 +00004159
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004160 if (!CompletionSucceded)
4161 return;
4162
Daniel Dunbar242ea9a2009-11-13 08:58:20 +00004163 // Hand off the results found for code completion.
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004164 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4165 Results.data(), Results.size());
Douglas Gregor2436e712009-09-17 21:32:03 +00004166}
4167
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004168void Sema::CodeCompleteObjCClassPropertyRefExpr(Scope *S,
4169 IdentifierInfo &ClassName,
4170 SourceLocation ClassNameLoc,
4171 bool IsBaseExprStatement) {
4172 IdentifierInfo *ClassNamePtr = &ClassName;
4173 ObjCInterfaceDecl *IFace = getObjCInterfaceDecl(ClassNamePtr, ClassNameLoc);
4174 if (!IFace)
4175 return;
4176 CodeCompletionContext CCContext(
4177 CodeCompletionContext::CCC_ObjCPropertyAccess);
4178 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4179 CodeCompleter->getCodeCompletionTUInfo(), CCContext,
4180 &ResultBuilder::IsMember);
4181 Results.EnterNewScope();
4182 AddedPropertiesSet AddedProperties;
4183 AddObjCProperties(CCContext, IFace, true,
4184 /*AllowNullaryMethods=*/true, CurContext, AddedProperties,
4185 Results, IsBaseExprStatement,
4186 /*IsClassProperty=*/true);
4187 Results.ExitScope();
4188 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4189 Results.data(), Results.size());
4190}
4191
Faisal Vali090da2d2018-01-01 18:23:28 +00004192void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) {
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004193 if (!CodeCompleter)
4194 return;
Craig Topperc3ec1492014-05-26 06:22:03 +00004195
4196 ResultBuilder::LookupFilter Filter = nullptr;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004197 enum CodeCompletionContext::Kind ContextKind
4198 = CodeCompletionContext::CCC_Other;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004199 switch ((DeclSpec::TST)TagSpec) {
4200 case DeclSpec::TST_enum:
Douglas Gregor3545ff42009-09-21 16:56:56 +00004201 Filter = &ResultBuilder::IsEnum;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004202 ContextKind = CodeCompletionContext::CCC_EnumTag;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004203 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004204
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004205 case DeclSpec::TST_union:
Douglas Gregor3545ff42009-09-21 16:56:56 +00004206 Filter = &ResultBuilder::IsUnion;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004207 ContextKind = CodeCompletionContext::CCC_UnionTag;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004208 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004209
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004210 case DeclSpec::TST_struct:
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004211 case DeclSpec::TST_class:
Joao Matosdc86f942012-08-31 18:45:21 +00004212 case DeclSpec::TST_interface:
Douglas Gregor3545ff42009-09-21 16:56:56 +00004213 Filter = &ResultBuilder::IsClassOrStruct;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004214 ContextKind = CodeCompletionContext::CCC_ClassOrStructTag;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004215 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004216
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004217 default:
David Blaikie83d382b2011-09-23 05:06:16 +00004218 llvm_unreachable("Unknown type specifier kind in CodeCompleteTag");
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004219 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004220
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004221 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4222 CodeCompleter->getCodeCompletionTUInfo(), ContextKind);
Douglas Gregora6e2edc2010-01-14 03:27:13 +00004223 CodeCompletionDeclConsumer Consumer(Results, CurContext);
John McCalle87beb22010-04-23 18:46:30 +00004224
4225 // First pass: look for tags.
4226 Results.setFilter(Filter);
Douglas Gregor39982192010-08-15 06:18:01 +00004227 LookupVisibleDecls(S, LookupTagName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00004228 CodeCompleter->includeGlobals(),
4229 CodeCompleter->loadExternal());
John McCalle87beb22010-04-23 18:46:30 +00004230
Douglas Gregor39982192010-08-15 06:18:01 +00004231 if (CodeCompleter->includeGlobals()) {
4232 // Second pass: look for nested name specifiers.
4233 Results.setFilter(&ResultBuilder::IsNestedNameSpecifier);
Sam McCallbb2cf632018-01-12 14:51:47 +00004234 LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer,
4235 CodeCompleter->includeGlobals(),
4236 CodeCompleter->loadExternal());
Douglas Gregor39982192010-08-15 06:18:01 +00004237 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004238
Douglas Gregor0ac41382010-09-23 23:01:17 +00004239 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004240 Results.data(),Results.size());
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004241}
4242
Alex Lorenz8f4d3992017-02-13 23:19:40 +00004243static void AddTypeQualifierResults(DeclSpec &DS, ResultBuilder &Results,
4244 const LangOptions &LangOpts) {
4245 if (!(DS.getTypeQualifiers() & DeclSpec::TQ_const))
4246 Results.AddResult("const");
4247 if (!(DS.getTypeQualifiers() & DeclSpec::TQ_volatile))
4248 Results.AddResult("volatile");
4249 if (LangOpts.C99 && !(DS.getTypeQualifiers() & DeclSpec::TQ_restrict))
4250 Results.AddResult("restrict");
4251 if (LangOpts.C11 && !(DS.getTypeQualifiers() & DeclSpec::TQ_atomic))
4252 Results.AddResult("_Atomic");
4253 if (LangOpts.MSVCCompat && !(DS.getTypeQualifiers() & DeclSpec::TQ_unaligned))
4254 Results.AddResult("__unaligned");
4255}
4256
Douglas Gregor28c78432010-08-27 17:35:51 +00004257void Sema::CodeCompleteTypeQualifiers(DeclSpec &DS) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004258 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004259 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004260 CodeCompletionContext::CCC_TypeQualifiers);
Douglas Gregor28c78432010-08-27 17:35:51 +00004261 Results.EnterNewScope();
Alex Lorenz8f4d3992017-02-13 23:19:40 +00004262 AddTypeQualifierResults(DS, Results, LangOpts);
Douglas Gregor28c78432010-08-27 17:35:51 +00004263 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004264 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004265 Results.getCompletionContext(),
Douglas Gregor28c78432010-08-27 17:35:51 +00004266 Results.data(), Results.size());
4267}
4268
Alex Lorenz8f4d3992017-02-13 23:19:40 +00004269void Sema::CodeCompleteFunctionQualifiers(DeclSpec &DS, Declarator &D,
4270 const VirtSpecifiers *VS) {
4271 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4272 CodeCompleter->getCodeCompletionTUInfo(),
4273 CodeCompletionContext::CCC_TypeQualifiers);
4274 Results.EnterNewScope();
4275 AddTypeQualifierResults(DS, Results, LangOpts);
4276 if (LangOpts.CPlusPlus11) {
4277 Results.AddResult("noexcept");
Faisal Vali421b2d12017-12-29 05:41:00 +00004278 if (D.getContext() == DeclaratorContext::MemberContext &&
4279 !D.isCtorOrDtor() && !D.isStaticMember()) {
Alex Lorenz8f4d3992017-02-13 23:19:40 +00004280 if (!VS || !VS->isFinalSpecified())
4281 Results.AddResult("final");
4282 if (!VS || !VS->isOverrideSpecified())
4283 Results.AddResult("override");
4284 }
4285 }
4286 Results.ExitScope();
4287 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4288 Results.data(), Results.size());
4289}
4290
Benjamin Kramer72dae622016-02-18 15:30:24 +00004291void Sema::CodeCompleteBracketDeclarator(Scope *S) {
4292 CodeCompleteExpression(S, QualType(getASTContext().getSizeType()));
4293}
4294
Douglas Gregord328d572009-09-21 18:10:23 +00004295void Sema::CodeCompleteCase(Scope *S) {
John McCallaab3e412010-08-25 08:40:02 +00004296 if (getCurFunction()->SwitchStack.empty() || !CodeCompleter)
Douglas Gregord328d572009-09-21 18:10:23 +00004297 return;
John McCall5939b162011-08-06 07:30:58 +00004298
Richard Smithef6c43d2018-07-26 18:41:30 +00004299 SwitchStmt *Switch = getCurFunction()->SwitchStack.back().getPointer();
John McCall5939b162011-08-06 07:30:58 +00004300 QualType type = Switch->getCond()->IgnoreImplicit()->getType();
4301 if (!type->isEnumeralType()) {
4302 CodeCompleteExpressionData Data(type);
Douglas Gregor68762e72010-08-23 21:17:50 +00004303 Data.IntegralConstantExpression = true;
4304 CodeCompleteExpression(S, Data);
Douglas Gregord328d572009-09-21 18:10:23 +00004305 return;
Douglas Gregor85b50632010-07-28 21:50:18 +00004306 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004307
Douglas Gregord328d572009-09-21 18:10:23 +00004308 // Code-complete the cases of a switch statement over an enumeration type
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004309 // by providing the list of
John McCall5939b162011-08-06 07:30:58 +00004310 EnumDecl *Enum = type->castAs<EnumType>()->getDecl();
Douglas Gregor9b4f3702012-06-12 13:44:08 +00004311 if (EnumDecl *Def = Enum->getDefinition())
4312 Enum = Def;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004313
Douglas Gregord328d572009-09-21 18:10:23 +00004314 // Determine which enumerators we have already seen in the switch statement.
4315 // FIXME: Ideally, we would also be able to look *past* the code-completion
4316 // token, in case we are code-completing in the middle of the switch and not
4317 // at the end. However, we aren't able to do so at the moment.
4318 llvm::SmallPtrSet<EnumConstantDecl *, 8> EnumeratorsSeen;
Craig Topperc3ec1492014-05-26 06:22:03 +00004319 NestedNameSpecifier *Qualifier = nullptr;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004320 for (SwitchCase *SC = Switch->getSwitchCaseList(); SC;
Douglas Gregord328d572009-09-21 18:10:23 +00004321 SC = SC->getNextSwitchCase()) {
4322 CaseStmt *Case = dyn_cast<CaseStmt>(SC);
4323 if (!Case)
4324 continue;
4325
4326 Expr *CaseVal = Case->getLHS()->IgnoreParenCasts();
4327 if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CaseVal))
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004328 if (EnumConstantDecl *Enumerator
Douglas Gregord328d572009-09-21 18:10:23 +00004329 = dyn_cast<EnumConstantDecl>(DRE->getDecl())) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004330 // We look into the AST of the case statement to determine which
4331 // enumerator was named. Alternatively, we could compute the value of
Douglas Gregord328d572009-09-21 18:10:23 +00004332 // the integral constant expression, then compare it against the
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004333 // values of each enumerator. However, value-based approach would not
4334 // work as well with C++ templates where enumerators declared within a
Douglas Gregord328d572009-09-21 18:10:23 +00004335 // template are type- and value-dependent.
4336 EnumeratorsSeen.insert(Enumerator);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004337
Douglas Gregorf2510672009-09-21 19:57:38 +00004338 // If this is a qualified-id, keep track of the nested-name-specifier
4339 // so that we can reproduce it as part of code completion, e.g.,
Douglas Gregord328d572009-09-21 18:10:23 +00004340 //
4341 // switch (TagD.getKind()) {
4342 // case TagDecl::TK_enum:
4343 // break;
4344 // case XXX
4345 //
Douglas Gregorf2510672009-09-21 19:57:38 +00004346 // At the XXX, our completions are TagDecl::TK_union,
Douglas Gregord328d572009-09-21 18:10:23 +00004347 // TagDecl::TK_struct, and TagDecl::TK_class, rather than TK_union,
4348 // TK_struct, and TK_class.
Douglas Gregor4bd90e52009-10-23 18:54:35 +00004349 Qualifier = DRE->getQualifier();
Douglas Gregord328d572009-09-21 18:10:23 +00004350 }
4351 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004352
David Blaikiebbafb8a2012-03-11 07:00:24 +00004353 if (getLangOpts().CPlusPlus && !Qualifier && EnumeratorsSeen.empty()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004354 // If there are no prior enumerators in C++, check whether we have to
Douglas Gregorf2510672009-09-21 19:57:38 +00004355 // qualify the names of the enumerators that we suggest, because they
4356 // may not be visible in this scope.
Douglas Gregord3cebdb2012-02-01 05:02:47 +00004357 Qualifier = getRequiredQualification(Context, CurContext, Enum);
Douglas Gregorf2510672009-09-21 19:57:38 +00004358 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004359
Douglas Gregord328d572009-09-21 18:10:23 +00004360 // Add any enumerators that have not yet been mentioned.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004361 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004362 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004363 CodeCompletionContext::CCC_Expression);
Douglas Gregord328d572009-09-21 18:10:23 +00004364 Results.EnterNewScope();
Aaron Ballman23a6dcb2014-03-08 18:45:14 +00004365 for (auto *E : Enum->enumerators()) {
4366 if (EnumeratorsSeen.count(E))
Douglas Gregord328d572009-09-21 18:10:23 +00004367 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004368
Aaron Ballman23a6dcb2014-03-08 18:45:14 +00004369 CodeCompletionResult R(E, CCP_EnumInCase, Qualifier);
Craig Topperc3ec1492014-05-26 06:22:03 +00004370 Results.AddResult(R, CurContext, nullptr, false);
Douglas Gregord328d572009-09-21 18:10:23 +00004371 }
4372 Results.ExitScope();
Douglas Gregor285560922010-04-06 20:02:15 +00004373
Douglas Gregor21325842011-07-07 16:03:39 +00004374 if (CodeCompleter->includeMacros()) {
Eric Liu88de9f62018-09-19 09:34:55 +00004375 AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false);
Douglas Gregor21325842011-07-07 16:03:39 +00004376 }
Eric Liuf5ba09f2018-07-04 10:01:18 +00004377 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4378 Results.data(), Results.size());
Douglas Gregord328d572009-09-21 18:10:23 +00004379}
4380
Robert Wilhelm16e94b92013-08-09 18:02:13 +00004381static bool anyNullArguments(ArrayRef<Expr *> Args) {
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00004382 if (Args.size() && !Args.data())
Douglas Gregor6ed3eb82010-05-30 06:10:08 +00004383 return true;
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00004384
4385 for (unsigned I = 0; I != Args.size(); ++I)
Douglas Gregor6ed3eb82010-05-30 06:10:08 +00004386 if (!Args[I])
4387 return true;
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00004388
Douglas Gregor6ed3eb82010-05-30 06:10:08 +00004389 return false;
4390}
4391
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004392typedef CodeCompleteConsumer::OverloadCandidate ResultCandidate;
4393
Francisco Lopes da Silva8cafefa2015-01-29 05:54:59 +00004394static void mergeCandidatesWithResults(Sema &SemaRef,
4395 SmallVectorImpl<ResultCandidate> &Results,
4396 OverloadCandidateSet &CandidateSet,
4397 SourceLocation Loc) {
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004398 if (!CandidateSet.empty()) {
4399 // Sort the overload candidate set by placing the best overloads first.
4400 std::stable_sort(
4401 CandidateSet.begin(), CandidateSet.end(),
4402 [&](const OverloadCandidate &X, const OverloadCandidate &Y) {
Richard Smith67ef14f2017-09-26 18:37:55 +00004403 return isBetterOverloadCandidate(SemaRef, X, Y, Loc,
4404 CandidateSet.getKind());
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004405 });
4406
4407 // Add the remaining viable overload candidates as code-completion results.
Erik Verbruggen7ec91072017-09-08 10:23:08 +00004408 for (auto &Candidate : CandidateSet) {
4409 if (Candidate.Function && Candidate.Function->isDeleted())
4410 continue;
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004411 if (Candidate.Viable)
4412 Results.push_back(ResultCandidate(Candidate.Function));
Erik Verbruggen7ec91072017-09-08 10:23:08 +00004413 }
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004414 }
4415}
4416
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00004417/// Get the type of the Nth parameter from a given set of overload
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004418/// candidates.
Francisco Lopes da Silva8cafefa2015-01-29 05:54:59 +00004419static QualType getParamType(Sema &SemaRef,
4420 ArrayRef<ResultCandidate> Candidates,
4421 unsigned N) {
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004422
4423 // Given the overloads 'Candidates' for a function call matching all arguments
4424 // up to N, return the type of the Nth parameter if it is the same for all
4425 // overload candidates.
4426 QualType ParamType;
4427 for (auto &Candidate : Candidates) {
4428 if (auto FType = Candidate.getFunctionType())
4429 if (auto Proto = dyn_cast<FunctionProtoType>(FType))
4430 if (N < Proto->getNumParams()) {
4431 if (ParamType.isNull())
4432 ParamType = Proto->getParamType(N);
4433 else if (!SemaRef.Context.hasSameUnqualifiedType(
4434 ParamType.getNonReferenceType(),
4435 Proto->getParamType(N).getNonReferenceType()))
4436 // Otherwise return a default-constructed QualType.
4437 return QualType();
4438 }
4439 }
4440
4441 return ParamType;
4442}
4443
Ilya Biryukov832c4af2018-09-07 14:04:39 +00004444static QualType
4445ProduceSignatureHelp(Sema &SemaRef, Scope *S,
4446 MutableArrayRef<ResultCandidate> Candidates,
4447 unsigned CurrentArg, SourceLocation OpenParLoc) {
4448 if (Candidates.empty())
4449 return QualType();
4450 SemaRef.CodeCompleter->ProcessOverloadCandidates(
4451 SemaRef, CurrentArg, Candidates.data(), Candidates.size(), OpenParLoc);
4452 return getParamType(SemaRef, Candidates, CurrentArg);
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004453}
4454
Ilya Biryukov832c4af2018-09-07 14:04:39 +00004455QualType Sema::ProduceCallSignatureHelp(Scope *S, Expr *Fn,
4456 ArrayRef<Expr *> Args,
4457 SourceLocation OpenParLoc) {
Douglas Gregorcabea402009-09-22 15:41:20 +00004458 if (!CodeCompleter)
Ilya Biryukov832c4af2018-09-07 14:04:39 +00004459 return QualType();
Douglas Gregor3ef59522009-12-11 19:06:04 +00004460
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004461 // FIXME: Provide support for variadic template functions.
Douglas Gregorcabea402009-09-22 15:41:20 +00004462 // Ignore type-dependent call expressions entirely.
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00004463 if (!Fn || Fn->isTypeDependent() || anyNullArguments(Args) ||
4464 Expr::hasAnyTypeDependentArguments(Args)) {
Ilya Biryukov832c4af2018-09-07 14:04:39 +00004465 return QualType();
Douglas Gregor3ef59522009-12-11 19:06:04 +00004466 }
Douglas Gregorcabea402009-09-22 15:41:20 +00004467
John McCall57500772009-12-16 12:17:52 +00004468 // Build an overload candidate set based on the functions we find.
John McCallbc077cf2010-02-08 23:07:23 +00004469 SourceLocation Loc = Fn->getExprLoc();
Richard Smith100b24a2014-04-17 01:52:14 +00004470 OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal);
John McCall57500772009-12-16 12:17:52 +00004471
Chris Lattner0e62c1c2011-07-23 10:55:15 +00004472 SmallVector<ResultCandidate, 8> Results;
Douglas Gregorff59f672010-01-21 15:46:19 +00004473
John McCall57500772009-12-16 12:17:52 +00004474 Expr *NakedFn = Fn->IgnoreParenCasts();
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004475 if (auto ULE = dyn_cast<UnresolvedLookupExpr>(NakedFn))
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00004476 AddOverloadedCallCandidates(ULE, Args, CandidateSet,
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004477 /*PartialOverloading=*/true);
4478 else if (auto UME = dyn_cast<UnresolvedMemberExpr>(NakedFn)) {
4479 TemplateArgumentListInfo TemplateArgsBuffer, *TemplateArgs = nullptr;
4480 if (UME->hasExplicitTemplateArgs()) {
4481 UME->copyTemplateArgumentsInto(TemplateArgsBuffer);
4482 TemplateArgs = &TemplateArgsBuffer;
Douglas Gregorff59f672010-01-21 15:46:19 +00004483 }
Erik Verbruggenf1898cf2017-03-28 07:22:21 +00004484
4485 // Add the base as first argument (use a nullptr if the base is implicit).
4486 SmallVector<Expr *, 12> ArgExprs(
4487 1, UME->isImplicitAccess() ? nullptr : UME->getBase());
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004488 ArgExprs.append(Args.begin(), Args.end());
4489 UnresolvedSet<8> Decls;
4490 Decls.append(UME->decls_begin(), UME->decls_end());
Benjamin Kramere3962ae2017-10-26 08:41:28 +00004491 const bool FirstArgumentIsBase = !UME->isImplicitAccess() && UME->getBase();
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004492 AddFunctionCandidates(Decls, ArgExprs, CandidateSet, TemplateArgs,
4493 /*SuppressUsedConversions=*/false,
Benjamin Kramere3962ae2017-10-26 08:41:28 +00004494 /*PartialOverloading=*/true,
4495 FirstArgumentIsBase);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004496 } else {
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004497 FunctionDecl *FD = nullptr;
4498 if (auto MCE = dyn_cast<MemberExpr>(NakedFn))
4499 FD = dyn_cast<FunctionDecl>(MCE->getMemberDecl());
4500 else if (auto DRE = dyn_cast<DeclRefExpr>(NakedFn))
4501 FD = dyn_cast<FunctionDecl>(DRE->getDecl());
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00004502 if (FD) { // We check whether it's a resolved function declaration.
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00004503 if (!getLangOpts().CPlusPlus ||
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004504 !FD->getType()->getAs<FunctionProtoType>())
4505 Results.push_back(ResultCandidate(FD));
4506 else
4507 AddOverloadCandidate(FD, DeclAccessPair::make(FD, FD->getAccess()),
4508 Args, CandidateSet,
4509 /*SuppressUsedConversions=*/false,
4510 /*PartialOverloading=*/true);
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00004511
4512 } else if (auto DC = NakedFn->getType()->getAsCXXRecordDecl()) {
4513 // If expression's type is CXXRecordDecl, it may overload the function
4514 // call operator, so we check if it does and add them as candidates.
Francisco Lopes da Silvaa349a8a2015-01-25 08:47:59 +00004515 // A complete type is needed to lookup for member function call operators.
Richard Smithdb0ac552015-12-18 22:40:25 +00004516 if (isCompleteType(Loc, NakedFn->getType())) {
Francisco Lopes da Silvaa349a8a2015-01-25 08:47:59 +00004517 DeclarationName OpName = Context.DeclarationNames
4518 .getCXXOperatorName(OO_Call);
4519 LookupResult R(*this, OpName, Loc, LookupOrdinaryName);
4520 LookupQualifiedName(R, DC);
4521 R.suppressDiagnostics();
4522 SmallVector<Expr *, 12> ArgExprs(1, NakedFn);
4523 ArgExprs.append(Args.begin(), Args.end());
4524 AddFunctionCandidates(R.asUnresolvedSet(), ArgExprs, CandidateSet,
4525 /*ExplicitArgs=*/nullptr,
4526 /*SuppressUsedConversions=*/false,
4527 /*PartialOverloading=*/true);
4528 }
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00004529 } else {
4530 // Lastly we check whether expression's type is function pointer or
4531 // function.
4532 QualType T = NakedFn->getType();
4533 if (!T->getPointeeType().isNull())
4534 T = T->getPointeeType();
4535
4536 if (auto FP = T->getAs<FunctionProtoType>()) {
4537 if (!TooManyArguments(FP->getNumParams(), Args.size(),
Francisco Lopes da Silva62a9a4f2015-01-23 13:17:51 +00004538 /*PartialOverloading=*/true) ||
4539 FP->isVariadic())
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00004540 Results.push_back(ResultCandidate(FP));
4541 } else if (auto FT = T->getAs<FunctionType>())
Francisco Lopes da Silva62a9a4f2015-01-23 13:17:51 +00004542 // No prototype and declaration, it may be a K & R style function.
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00004543 Results.push_back(ResultCandidate(FT));
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004544 }
Douglas Gregorcabea402009-09-22 15:41:20 +00004545 }
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004546 mergeCandidatesWithResults(*this, Results, CandidateSet, Loc);
Ilya Biryukov832c4af2018-09-07 14:04:39 +00004547 QualType ParamType =
4548 ProduceSignatureHelp(*this, S, Results, Args.size(), OpenParLoc);
4549 return !CandidateSet.empty() ? ParamType : QualType();
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004550}
4551
Ilya Biryukov832c4af2018-09-07 14:04:39 +00004552QualType Sema::ProduceConstructorSignatureHelp(Scope *S, QualType Type,
4553 SourceLocation Loc,
4554 ArrayRef<Expr *> Args,
4555 SourceLocation OpenParLoc) {
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004556 if (!CodeCompleter)
Ilya Biryukov832c4af2018-09-07 14:04:39 +00004557 return QualType();
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004558
4559 // A complete type is needed to lookup for constructors.
Ilya Biryukovfb9dde72018-05-14 13:50:36 +00004560 CXXRecordDecl *RD =
4561 isCompleteType(Loc, Type) ? Type->getAsCXXRecordDecl() : nullptr;
Ilya Biryukov832c4af2018-09-07 14:04:39 +00004562 if (!RD)
4563 return Type;
Argyrios Kyrtzidisee1d76f2015-03-13 07:39:30 +00004564
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004565 // FIXME: Provide support for member initializers.
4566 // FIXME: Provide support for variadic template constructors.
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004567
4568 OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal);
4569
Argyrios Kyrtzidisee1d76f2015-03-13 07:39:30 +00004570 for (auto C : LookupConstructors(RD)) {
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004571 if (auto FD = dyn_cast<FunctionDecl>(C)) {
4572 AddOverloadCandidate(FD, DeclAccessPair::make(FD, C->getAccess()),
4573 Args, CandidateSet,
4574 /*SuppressUsedConversions=*/false,
4575 /*PartialOverloading=*/true);
4576 } else if (auto FTD = dyn_cast<FunctionTemplateDecl>(C)) {
4577 AddTemplateOverloadCandidate(FTD,
4578 DeclAccessPair::make(FTD, C->getAccess()),
4579 /*ExplicitTemplateArgs=*/nullptr,
4580 Args, CandidateSet,
4581 /*SuppressUsedConversions=*/false,
4582 /*PartialOverloading=*/true);
4583 }
4584 }
4585
4586 SmallVector<ResultCandidate, 8> Results;
4587 mergeCandidatesWithResults(*this, Results, CandidateSet, Loc);
Ilya Biryukov832c4af2018-09-07 14:04:39 +00004588 return ProduceSignatureHelp(*this, S, Results, Args.size(), OpenParLoc);
Douglas Gregorcabea402009-09-22 15:41:20 +00004589}
4590
Kadir Cetinkaya84774c32018-09-11 15:02:18 +00004591QualType Sema::ProduceCtorInitMemberSignatureHelp(
4592 Scope *S, Decl *ConstructorDecl, CXXScopeSpec SS, ParsedType TemplateTypeTy,
4593 ArrayRef<Expr *> ArgExprs, IdentifierInfo *II, SourceLocation OpenParLoc) {
4594 if (!CodeCompleter)
4595 return QualType();
4596
4597 CXXConstructorDecl *Constructor =
4598 dyn_cast<CXXConstructorDecl>(ConstructorDecl);
4599 if (!Constructor)
4600 return QualType();
4601 // FIXME: Add support for Base class constructors as well.
4602 if (ValueDecl *MemberDecl = tryLookupCtorInitMemberDecl(
4603 Constructor->getParent(), SS, TemplateTypeTy, II))
4604 return ProduceConstructorSignatureHelp(getCurScope(), MemberDecl->getType(),
4605 MemberDecl->getLocation(), ArgExprs,
4606 OpenParLoc);
4607 return QualType();
4608}
4609
John McCall48871652010-08-21 09:40:31 +00004610void Sema::CodeCompleteInitializer(Scope *S, Decl *D) {
4611 ValueDecl *VD = dyn_cast_or_null<ValueDecl>(D);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004612 if (!VD) {
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004613 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004614 return;
4615 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004616
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004617 CodeCompleteExpression(S, VD->getType());
4618}
4619
4620void Sema::CodeCompleteReturn(Scope *S) {
4621 QualType ResultType;
4622 if (isa<BlockDecl>(CurContext)) {
4623 if (BlockScopeInfo *BSI = getCurBlock())
4624 ResultType = BSI->ReturnType;
4625 } else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(CurContext))
Alp Toker314cc812014-01-25 16:55:45 +00004626 ResultType = Function->getReturnType();
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004627 else if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(CurContext))
Alp Toker314cc812014-01-25 16:55:45 +00004628 ResultType = Method->getReturnType();
4629
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004630 if (ResultType.isNull())
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004631 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004632 else
4633 CodeCompleteExpression(S, ResultType);
4634}
4635
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004636void Sema::CodeCompleteAfterIf(Scope *S) {
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004637 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004638 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004639 mapCodeCompletionContext(*this, PCC_Statement));
4640 Results.setFilter(&ResultBuilder::IsOrdinaryName);
4641 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004642
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004643 CodeCompletionDeclConsumer Consumer(Results, CurContext);
4644 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00004645 CodeCompleter->includeGlobals(),
4646 CodeCompleter->loadExternal());
4647
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004648 AddOrdinaryNameResults(PCC_Statement, S, *this, Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004649
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004650 // "else" block
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004651 CodeCompletionBuilder Builder(Results.getAllocator(),
4652 Results.getCodeCompletionTUInfo());
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004653 Builder.AddTypedTextChunk("else");
Douglas Gregor3a5d6c22012-02-16 17:49:04 +00004654 if (Results.includeCodePatterns()) {
4655 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4656 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4657 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
4658 Builder.AddPlaceholderChunk("statements");
4659 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
4660 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4661 }
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004662 Results.AddResult(Builder.TakeString());
4663
4664 // "else if" block
4665 Builder.AddTypedTextChunk("else");
4666 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4667 Builder.AddTextChunk("if");
4668 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4669 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00004670 if (getLangOpts().CPlusPlus)
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004671 Builder.AddPlaceholderChunk("condition");
4672 else
4673 Builder.AddPlaceholderChunk("expression");
4674 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor3a5d6c22012-02-16 17:49:04 +00004675 if (Results.includeCodePatterns()) {
4676 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4677 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4678 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
4679 Builder.AddPlaceholderChunk("statements");
4680 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
4681 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4682 }
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004683 Results.AddResult(Builder.TakeString());
4684
4685 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004686
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004687 if (S->getFnParent())
Craig Topper12126262015-11-15 17:27:57 +00004688 AddPrettyFunctionResults(getLangOpts(), Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004689
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004690 if (CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00004691 AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004692
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004693 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4694 Results.data(),Results.size());
4695}
4696
Richard Trieu2bd04012011-09-09 02:00:50 +00004697void Sema::CodeCompleteAssignmentRHS(Scope *S, Expr *LHS) {
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004698 if (LHS)
4699 CodeCompleteExpression(S, static_cast<Expr *>(LHS)->getType());
4700 else
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004701 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004702}
4703
Jeffrey Yasskinc76498d2010-04-08 16:38:48 +00004704void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS,
Douglas Gregor2436e712009-09-17 21:32:03 +00004705 bool EnteringContext) {
Eric Liu06d34022017-12-12 11:35:46 +00004706 if (SS.isEmpty() || !CodeCompleter)
Douglas Gregor2436e712009-09-17 21:32:03 +00004707 return;
Alex Lorenz8a7a4cf2017-06-15 21:40:54 +00004708
Eric Liu06d34022017-12-12 11:35:46 +00004709 // We want to keep the scope specifier even if it's invalid (e.g. the scope
4710 // "a::b::" is not corresponding to any context/namespace in the AST), since
4711 // it can be useful for global code completion which have information about
4712 // contexts/symbols that are not in the AST.
4713 if (SS.isInvalid()) {
4714 CodeCompletionContext CC(CodeCompletionContext::CCC_Name);
4715 CC.setCXXScopeSpecifier(SS);
4716 HandleCodeCompleteResults(this, CodeCompleter, CC, nullptr, 0);
4717 return;
4718 }
Alex Lorenz8a7a4cf2017-06-15 21:40:54 +00004719 // Always pretend to enter a context to ensure that a dependent type
4720 // resolves to a dependent record.
4721 DeclContext *Ctx = computeDeclContext(SS, /*EnteringContext=*/true);
Douglas Gregor3545ff42009-09-21 16:56:56 +00004722 if (!Ctx)
4723 return;
Douglas Gregor800f2f02009-12-11 18:28:39 +00004724
4725 // Try to instantiate any non-dependent declaration contexts before
4726 // we look in them.
John McCall0b66eb32010-05-01 00:40:08 +00004727 if (!isDependentScopeSpecifier(SS) && RequireCompleteDeclContext(SS, Ctx))
Douglas Gregor800f2f02009-12-11 18:28:39 +00004728 return;
4729
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004730 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004731 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004732 CodeCompletionContext::CCC_Name);
Douglas Gregorac322ec2010-08-27 21:18:54 +00004733 Results.EnterNewScope();
Eric Liu06d34022017-12-12 11:35:46 +00004734
Douglas Gregor3545ff42009-09-21 16:56:56 +00004735 // The "template" keyword can follow "::" in the grammar, but only
4736 // put it into the grammar if the nested-name-specifier is dependent.
Aaron Ballman4a979672014-01-03 13:56:08 +00004737 NestedNameSpecifier *NNS = SS.getScopeRep();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004738 if (!Results.empty() && NNS->isDependent())
Douglas Gregor78a21012010-01-14 16:01:26 +00004739 Results.AddResult("template");
Douglas Gregorac322ec2010-08-27 21:18:54 +00004740
4741 // Add calls to overridden virtual functions, if there are any.
4742 //
4743 // FIXME: This isn't wonderful, because we don't know whether we're actually
4744 // in a context that permits expressions. This is a general issue with
4745 // qualified-id completions.
4746 if (!EnteringContext)
4747 MaybeAddOverrideCalls(*this, Ctx, Results);
Eric Liu06d34022017-12-12 11:35:46 +00004748 Results.ExitScope();
4749
Eric Liufead6ae2017-12-13 10:26:49 +00004750 if (CodeCompleter->includeNamespaceLevelDecls() ||
4751 (!Ctx->isNamespace() && !Ctx->isTranslationUnit())) {
4752 CodeCompletionDeclConsumer Consumer(Results, CurContext);
4753 LookupVisibleDecls(Ctx, LookupOrdinaryName, Consumer,
4754 /*IncludeGlobalScope=*/true,
Sam McCallbb2cf632018-01-12 14:51:47 +00004755 /*IncludeDependentBases=*/true,
4756 CodeCompleter->loadExternal());
Eric Liufead6ae2017-12-13 10:26:49 +00004757 }
Douglas Gregorac322ec2010-08-27 21:18:54 +00004758
Eric Liu06d34022017-12-12 11:35:46 +00004759 auto CC = Results.getCompletionContext();
4760 CC.setCXXScopeSpecifier(SS);
4761
4762 HandleCodeCompleteResults(this, CodeCompleter, CC, Results.data(),
4763 Results.size());
Douglas Gregor2436e712009-09-17 21:32:03 +00004764}
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00004765
4766void Sema::CodeCompleteUsing(Scope *S) {
4767 if (!CodeCompleter)
4768 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004769
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004770 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004771 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00004772 CodeCompletionContext::CCC_PotentiallyQualifiedName,
4773 &ResultBuilder::IsNestedNameSpecifier);
Douglas Gregor64b12b52009-09-22 23:31:26 +00004774 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004775
Douglas Gregor3545ff42009-09-21 16:56:56 +00004776 // If we aren't in class scope, we could see the "namespace" keyword.
4777 if (!S->isClassScope())
John McCall276321a2010-08-25 06:19:51 +00004778 Results.AddResult(CodeCompletionResult("namespace"));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004779
4780 // After "using", we can see anything that would start a
Douglas Gregor3545ff42009-09-21 16:56:56 +00004781 // nested-name-specifier.
Douglas Gregora6e2edc2010-01-14 03:27:13 +00004782 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00004783 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00004784 CodeCompleter->includeGlobals(),
4785 CodeCompleter->loadExternal());
Douglas Gregor64b12b52009-09-22 23:31:26 +00004786 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00004787
4788 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4789 Results.data(), Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00004790}
4791
4792void Sema::CodeCompleteUsingDirective(Scope *S) {
4793 if (!CodeCompleter)
4794 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004795
Douglas Gregor3545ff42009-09-21 16:56:56 +00004796 // After "using namespace", we expect to see a namespace name or namespace
4797 // alias.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004798 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004799 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004800 CodeCompletionContext::CCC_Namespace,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004801 &ResultBuilder::IsNamespaceOrAlias);
Douglas Gregor64b12b52009-09-22 23:31:26 +00004802 Results.EnterNewScope();
Douglas Gregora6e2edc2010-01-14 03:27:13 +00004803 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00004804 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00004805 CodeCompleter->includeGlobals(),
4806 CodeCompleter->loadExternal());
Douglas Gregor64b12b52009-09-22 23:31:26 +00004807 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00004808 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4809 Results.data(), Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00004810}
4811
4812void Sema::CodeCompleteNamespaceDecl(Scope *S) {
4813 if (!CodeCompleter)
4814 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004815
Ted Kremenekc37877d2013-10-08 17:08:03 +00004816 DeclContext *Ctx = S->getEntity();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004817 if (!S->getParent())
4818 Ctx = Context.getTranslationUnitDecl();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004819
Douglas Gregor0ac41382010-09-23 23:01:17 +00004820 bool SuppressedGlobalResults
4821 = Ctx && !CodeCompleter->includeGlobals() && isa<TranslationUnitDecl>(Ctx);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004822
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004823 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004824 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00004825 SuppressedGlobalResults
4826 ? CodeCompletionContext::CCC_Namespace
4827 : CodeCompletionContext::CCC_Other,
4828 &ResultBuilder::IsNamespace);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004829
Douglas Gregor0ac41382010-09-23 23:01:17 +00004830 if (Ctx && Ctx->isFileContext() && !SuppressedGlobalResults) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00004831 // We only want to see those namespaces that have already been defined
4832 // within this scope, because its likely that the user is creating an
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004833 // extended namespace declaration. Keep track of the most recent
Douglas Gregor3545ff42009-09-21 16:56:56 +00004834 // definition of each namespace.
4835 std::map<NamespaceDecl *, NamespaceDecl *> OrigToLatest;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004836 for (DeclContext::specific_decl_iterator<NamespaceDecl>
Douglas Gregor3545ff42009-09-21 16:56:56 +00004837 NS(Ctx->decls_begin()), NSEnd(Ctx->decls_end());
4838 NS != NSEnd; ++NS)
David Blaikie40ed2972012-06-06 20:45:41 +00004839 OrigToLatest[NS->getOriginalNamespace()] = *NS;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004840
4841 // Add the most recent definition (or extended definition) of each
Douglas Gregor3545ff42009-09-21 16:56:56 +00004842 // namespace to the list of results.
Douglas Gregor64b12b52009-09-22 23:31:26 +00004843 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004844 for (std::map<NamespaceDecl *, NamespaceDecl *>::iterator
Douglas Gregor78254c82012-03-27 23:34:16 +00004845 NS = OrigToLatest.begin(),
4846 NSEnd = OrigToLatest.end();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004847 NS != NSEnd; ++NS)
Douglas Gregor0a0e2b32013-01-31 04:52:16 +00004848 Results.AddResult(CodeCompletionResult(
Craig Topperc3ec1492014-05-26 06:22:03 +00004849 NS->second, Results.getBasePriority(NS->second),
4850 nullptr),
4851 CurContext, nullptr, false);
Douglas Gregor64b12b52009-09-22 23:31:26 +00004852 Results.ExitScope();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004853 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004854
4855 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004856 Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004857 Results.data(),Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00004858}
4859
4860void Sema::CodeCompleteNamespaceAliasDecl(Scope *S) {
4861 if (!CodeCompleter)
4862 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004863
Douglas Gregor3545ff42009-09-21 16:56:56 +00004864 // After "namespace", we expect to see a namespace or alias.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004865 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004866 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004867 CodeCompletionContext::CCC_Namespace,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004868 &ResultBuilder::IsNamespaceOrAlias);
Douglas Gregora6e2edc2010-01-14 03:27:13 +00004869 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00004870 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00004871 CodeCompleter->includeGlobals(),
4872 CodeCompleter->loadExternal());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004873 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004874 Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004875 Results.data(),Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00004876}
4877
Douglas Gregorc811ede2009-09-18 20:05:18 +00004878void Sema::CodeCompleteOperatorName(Scope *S) {
4879 if (!CodeCompleter)
4880 return;
Douglas Gregor3545ff42009-09-21 16:56:56 +00004881
John McCall276321a2010-08-25 06:19:51 +00004882 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004883 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004884 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004885 CodeCompletionContext::CCC_Type,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004886 &ResultBuilder::IsType);
Douglas Gregor64b12b52009-09-22 23:31:26 +00004887 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004888
Douglas Gregor3545ff42009-09-21 16:56:56 +00004889 // Add the names of overloadable operators.
4890#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
4891 if (std::strcmp(Spelling, "?")) \
Douglas Gregor78a21012010-01-14 16:01:26 +00004892 Results.AddResult(Result(Spelling));
Douglas Gregor3545ff42009-09-21 16:56:56 +00004893#include "clang/Basic/OperatorKinds.def"
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004894
Douglas Gregor3545ff42009-09-21 16:56:56 +00004895 // Add any type names visible from the current scope
Douglas Gregor6ae4c522010-01-14 03:21:49 +00004896 Results.allowNestedNameSpecifiers();
Douglas Gregora6e2edc2010-01-14 03:27:13 +00004897 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00004898 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00004899 CodeCompleter->includeGlobals(),
4900 CodeCompleter->loadExternal());
4901
Douglas Gregor3545ff42009-09-21 16:56:56 +00004902 // Add any type specifiers
David Blaikiebbafb8a2012-03-11 07:00:24 +00004903 AddTypeSpecifierResults(getLangOpts(), Results);
Douglas Gregor64b12b52009-09-22 23:31:26 +00004904 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00004905
4906 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4907 Results.data(), Results.size());
Douglas Gregorc811ede2009-09-18 20:05:18 +00004908}
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00004909
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00004910void Sema::CodeCompleteConstructorInitializer(
4911 Decl *ConstructorD,
4912 ArrayRef <CXXCtorInitializer *> Initializers) {
Benjamin Kramera4f8df02015-07-09 15:31:10 +00004913 if (!ConstructorD)
4914 return;
4915
4916 AdjustDeclIfTemplate(ConstructorD);
4917
4918 CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(ConstructorD);
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004919 if (!Constructor)
4920 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004921
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004922 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004923 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00004924 CodeCompletionContext::CCC_PotentiallyQualifiedName);
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004925 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004926
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004927 // Fill in any already-initialized fields or base classes.
4928 llvm::SmallPtrSet<FieldDecl *, 4> InitializedFields;
4929 llvm::SmallPtrSet<CanQualType, 4> InitializedBases;
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00004930 for (unsigned I = 0, E = Initializers.size(); I != E; ++I) {
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004931 if (Initializers[I]->isBaseInitializer())
4932 InitializedBases.insert(
4933 Context.getCanonicalType(QualType(Initializers[I]->getBaseClass(), 0)));
4934 else
Francois Pichetd583da02010-12-04 09:14:42 +00004935 InitializedFields.insert(cast<FieldDecl>(
4936 Initializers[I]->getAnyMember()));
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004937 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004938
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004939 // Add completions for base classes.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004940 CodeCompletionBuilder Builder(Results.getAllocator(),
4941 Results.getCodeCompletionTUInfo());
Benjamin Kramera4f8df02015-07-09 15:31:10 +00004942 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00004943 bool SawLastInitializer = Initializers.empty();
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004944 CXXRecordDecl *ClassDecl = Constructor->getParent();
Aaron Ballman574705e2014-03-13 15:41:46 +00004945 for (const auto &Base : ClassDecl->bases()) {
David Blaikie82e95a32014-11-19 07:49:47 +00004946 if (!InitializedBases.insert(Context.getCanonicalType(Base.getType()))
4947 .second) {
Douglas Gregor99129ef2010-08-29 19:27:27 +00004948 SawLastInitializer
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004949 = !Initializers.empty() &&
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00004950 Initializers.back()->isBaseInitializer() &&
Aaron Ballman574705e2014-03-13 15:41:46 +00004951 Context.hasSameUnqualifiedType(Base.getType(),
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00004952 QualType(Initializers.back()->getBaseClass(), 0));
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004953 continue;
Douglas Gregor99129ef2010-08-29 19:27:27 +00004954 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004955
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004956 Builder.AddTypedTextChunk(
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00004957 Results.getAllocator().CopyString(
Aaron Ballman574705e2014-03-13 15:41:46 +00004958 Base.getType().getAsString(Policy)));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004959 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4960 Builder.AddPlaceholderChunk("args");
4961 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004962 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor99129ef2010-08-29 19:27:27 +00004963 SawLastInitializer? CCP_NextInitializer
4964 : CCP_MemberDeclaration));
4965 SawLastInitializer = false;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004966 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004967
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004968 // Add completions for virtual base classes.
Aaron Ballman445a9392014-03-13 16:15:17 +00004969 for (const auto &Base : ClassDecl->vbases()) {
David Blaikie82e95a32014-11-19 07:49:47 +00004970 if (!InitializedBases.insert(Context.getCanonicalType(Base.getType()))
4971 .second) {
Douglas Gregor99129ef2010-08-29 19:27:27 +00004972 SawLastInitializer
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004973 = !Initializers.empty() &&
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00004974 Initializers.back()->isBaseInitializer() &&
Aaron Ballman445a9392014-03-13 16:15:17 +00004975 Context.hasSameUnqualifiedType(Base.getType(),
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00004976 QualType(Initializers.back()->getBaseClass(), 0));
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004977 continue;
Douglas Gregor99129ef2010-08-29 19:27:27 +00004978 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004979
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004980 Builder.AddTypedTextChunk(
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00004981 Builder.getAllocator().CopyString(
Aaron Ballman445a9392014-03-13 16:15:17 +00004982 Base.getType().getAsString(Policy)));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004983 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4984 Builder.AddPlaceholderChunk("args");
4985 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004986 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor99129ef2010-08-29 19:27:27 +00004987 SawLastInitializer? CCP_NextInitializer
4988 : CCP_MemberDeclaration));
4989 SawLastInitializer = false;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004990 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004991
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004992 // Add completions for members.
Aaron Ballmane8a8bae2014-03-08 20:12:42 +00004993 for (auto *Field : ClassDecl->fields()) {
David Blaikie82e95a32014-11-19 07:49:47 +00004994 if (!InitializedFields.insert(cast<FieldDecl>(Field->getCanonicalDecl()))
4995 .second) {
Douglas Gregor99129ef2010-08-29 19:27:27 +00004996 SawLastInitializer
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004997 = !Initializers.empty() &&
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00004998 Initializers.back()->isAnyMemberInitializer() &&
Aaron Ballmane8a8bae2014-03-08 20:12:42 +00004999 Initializers.back()->getAnyMember() == Field;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005000 continue;
Douglas Gregor99129ef2010-08-29 19:27:27 +00005001 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005002
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005003 if (!Field->getDeclName())
5004 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005005
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005006 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005007 Field->getIdentifier()->getName()));
5008 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5009 Builder.AddPlaceholderChunk("args");
5010 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005011 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor99129ef2010-08-29 19:27:27 +00005012 SawLastInitializer? CCP_NextInitializer
Douglas Gregorf3af3112010-09-09 21:42:20 +00005013 : CCP_MemberDeclaration,
Douglas Gregor78254c82012-03-27 23:34:16 +00005014 CXCursor_MemberRef,
5015 CXAvailability_Available,
Aaron Ballmane8a8bae2014-03-08 20:12:42 +00005016 Field));
Douglas Gregor99129ef2010-08-29 19:27:27 +00005017 SawLastInitializer = false;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005018 }
5019 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005020
Douglas Gregor0ac41382010-09-23 23:01:17 +00005021 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005022 Results.data(), Results.size());
5023}
5024
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00005025/// Determine whether this scope denotes a namespace.
Douglas Gregord8c61782012-02-15 15:34:24 +00005026static bool isNamespaceScope(Scope *S) {
Ted Kremenekc37877d2013-10-08 17:08:03 +00005027 DeclContext *DC = S->getEntity();
Douglas Gregord8c61782012-02-15 15:34:24 +00005028 if (!DC)
5029 return false;
5030
5031 return DC->isFileContext();
5032}
5033
5034void Sema::CodeCompleteLambdaIntroducer(Scope *S, LambdaIntroducer &Intro,
5035 bool AfterAmpersand) {
5036 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005037 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregord8c61782012-02-15 15:34:24 +00005038 CodeCompletionContext::CCC_Other);
5039 Results.EnterNewScope();
5040
5041 // Note what has already been captured.
5042 llvm::SmallPtrSet<IdentifierInfo *, 4> Known;
5043 bool IncludedThis = false;
Benjamin Kramerf3ca26982014-05-10 16:31:55 +00005044 for (const auto &C : Intro.Captures) {
5045 if (C.Kind == LCK_This) {
Douglas Gregord8c61782012-02-15 15:34:24 +00005046 IncludedThis = true;
5047 continue;
5048 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005049
Benjamin Kramerf3ca26982014-05-10 16:31:55 +00005050 Known.insert(C.Id);
Douglas Gregord8c61782012-02-15 15:34:24 +00005051 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005052
Douglas Gregord8c61782012-02-15 15:34:24 +00005053 // Look for other capturable variables.
5054 for (; S && !isNamespaceScope(S); S = S->getParent()) {
Aaron Ballman35c54952014-03-17 16:55:25 +00005055 for (const auto *D : S->decls()) {
5056 const auto *Var = dyn_cast<VarDecl>(D);
Douglas Gregord8c61782012-02-15 15:34:24 +00005057 if (!Var ||
5058 !Var->hasLocalStorage() ||
5059 Var->hasAttr<BlocksAttr>())
5060 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005061
David Blaikie82e95a32014-11-19 07:49:47 +00005062 if (Known.insert(Var->getIdentifier()).second)
Douglas Gregor0a0e2b32013-01-31 04:52:16 +00005063 Results.AddResult(CodeCompletionResult(Var, CCP_LocalDeclaration),
Craig Topperc3ec1492014-05-26 06:22:03 +00005064 CurContext, nullptr, false);
Douglas Gregord8c61782012-02-15 15:34:24 +00005065 }
5066 }
5067
5068 // Add 'this', if it would be valid.
5069 if (!IncludedThis && !AfterAmpersand && Intro.Default != LCD_ByCopy)
5070 addThisCompletion(*this, Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005071
Douglas Gregord8c61782012-02-15 15:34:24 +00005072 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005073
Douglas Gregord8c61782012-02-15 15:34:24 +00005074 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5075 Results.data(), Results.size());
5076}
5077
James Dennett596e4752012-06-14 03:11:41 +00005078/// Macro that optionally prepends an "@" to the string literal passed in via
5079/// Keyword, depending on whether NeedAt is true or false.
5080#define OBJC_AT_KEYWORD_NAME(NeedAt,Keyword) ((NeedAt)? "@" Keyword : Keyword)
5081
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005082static void AddObjCImplementationResults(const LangOptions &LangOpts,
Douglas Gregorf1934162010-01-13 21:24:21 +00005083 ResultBuilder &Results,
5084 bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005085 typedef CodeCompletionResult Result;
Douglas Gregorf1934162010-01-13 21:24:21 +00005086 // Since we have an implementation, we can end it.
James Dennett596e4752012-06-14 03:11:41 +00005087 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"end")));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005088
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005089 CodeCompletionBuilder Builder(Results.getAllocator(),
5090 Results.getCodeCompletionTUInfo());
Douglas Gregorf1934162010-01-13 21:24:21 +00005091 if (LangOpts.ObjC2) {
5092 // @dynamic
James Dennett596e4752012-06-14 03:11:41 +00005093 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"dynamic"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005094 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5095 Builder.AddPlaceholderChunk("property");
5096 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005097
Douglas Gregorf1934162010-01-13 21:24:21 +00005098 // @synthesize
James Dennett596e4752012-06-14 03:11:41 +00005099 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"synthesize"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005100 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5101 Builder.AddPlaceholderChunk("property");
5102 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005103 }
Douglas Gregorf1934162010-01-13 21:24:21 +00005104}
5105
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005106static void AddObjCInterfaceResults(const LangOptions &LangOpts,
Douglas Gregorf1934162010-01-13 21:24:21 +00005107 ResultBuilder &Results,
5108 bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005109 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005110
Douglas Gregorf1934162010-01-13 21:24:21 +00005111 // Since we have an interface or protocol, we can end it.
James Dennett596e4752012-06-14 03:11:41 +00005112 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"end")));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005113
Douglas Gregorf1934162010-01-13 21:24:21 +00005114 if (LangOpts.ObjC2) {
5115 // @property
James Dennett596e4752012-06-14 03:11:41 +00005116 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"property")));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005117
Douglas Gregorf1934162010-01-13 21:24:21 +00005118 // @required
James Dennett596e4752012-06-14 03:11:41 +00005119 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"required")));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005120
Douglas Gregorf1934162010-01-13 21:24:21 +00005121 // @optional
James Dennett596e4752012-06-14 03:11:41 +00005122 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"optional")));
Douglas Gregorf1934162010-01-13 21:24:21 +00005123 }
5124}
5125
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005126static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005127 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005128 CodeCompletionBuilder Builder(Results.getAllocator(),
5129 Results.getCodeCompletionTUInfo());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005130
Douglas Gregorf1934162010-01-13 21:24:21 +00005131 // @class name ;
James Dennett596e4752012-06-14 03:11:41 +00005132 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"class"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005133 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5134 Builder.AddPlaceholderChunk("name");
5135 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005136
Douglas Gregorf4c33342010-05-28 00:22:41 +00005137 if (Results.includeCodePatterns()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005138 // @interface name
5139 // FIXME: Could introduce the whole pattern, including superclasses and
Douglas Gregorf4c33342010-05-28 00:22:41 +00005140 // such.
James Dennett596e4752012-06-14 03:11:41 +00005141 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"interface"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005142 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5143 Builder.AddPlaceholderChunk("class");
5144 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005145
Douglas Gregorf4c33342010-05-28 00:22:41 +00005146 // @protocol name
James Dennett596e4752012-06-14 03:11:41 +00005147 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"protocol"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005148 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5149 Builder.AddPlaceholderChunk("protocol");
5150 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005151
Douglas Gregorf4c33342010-05-28 00:22:41 +00005152 // @implementation name
James Dennett596e4752012-06-14 03:11:41 +00005153 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"implementation"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005154 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5155 Builder.AddPlaceholderChunk("class");
5156 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00005157 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005158
Douglas Gregorf1934162010-01-13 21:24:21 +00005159 // @compatibility_alias name
James Dennett596e4752012-06-14 03:11:41 +00005160 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"compatibility_alias"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005161 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5162 Builder.AddPlaceholderChunk("alias");
5163 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5164 Builder.AddPlaceholderChunk("class");
5165 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor61e36812013-03-07 23:26:24 +00005166
5167 if (Results.getSema().getLangOpts().Modules) {
5168 // @import name
5169 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "import"));
5170 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5171 Builder.AddPlaceholderChunk("module");
5172 Results.AddResult(Result(Builder.TakeString()));
5173 }
Douglas Gregorf1934162010-01-13 21:24:21 +00005174}
5175
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005176void Sema::CodeCompleteObjCAtDirective(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005177 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005178 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005179 CodeCompletionContext::CCC_Other);
Douglas Gregorf48706c2009-12-07 09:27:33 +00005180 Results.EnterNewScope();
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005181 if (isa<ObjCImplDecl>(CurContext))
David Blaikiebbafb8a2012-03-11 07:00:24 +00005182 AddObjCImplementationResults(getLangOpts(), Results, false);
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005183 else if (CurContext->isObjCContainer())
David Blaikiebbafb8a2012-03-11 07:00:24 +00005184 AddObjCInterfaceResults(getLangOpts(), Results, false);
Douglas Gregorf1934162010-01-13 21:24:21 +00005185 else
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005186 AddObjCTopLevelResults(Results, false);
Douglas Gregorf48706c2009-12-07 09:27:33 +00005187 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005188 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5189 Results.data(), Results.size());
Douglas Gregorf48706c2009-12-07 09:27:33 +00005190}
5191
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005192static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005193 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005194 CodeCompletionBuilder Builder(Results.getAllocator(),
5195 Results.getCodeCompletionTUInfo());
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005196
5197 // @encode ( type-name )
Douglas Gregore5c79d52011-10-18 21:20:17 +00005198 const char *EncodeType = "char[]";
David Blaikiebbafb8a2012-03-11 07:00:24 +00005199 if (Results.getSema().getLangOpts().CPlusPlus ||
5200 Results.getSema().getLangOpts().ConstStrings)
Jordan Rose9da05852012-06-15 18:19:56 +00005201 EncodeType = "const char[]";
Douglas Gregore5c79d52011-10-18 21:20:17 +00005202 Builder.AddResultTypeChunk(EncodeType);
James Dennett596e4752012-06-14 03:11:41 +00005203 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"encode"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005204 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5205 Builder.AddPlaceholderChunk("type-name");
5206 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5207 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005208
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005209 // @protocol ( protocol-name )
Douglas Gregore5c79d52011-10-18 21:20:17 +00005210 Builder.AddResultTypeChunk("Protocol *");
James Dennett596e4752012-06-14 03:11:41 +00005211 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"protocol"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005212 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5213 Builder.AddPlaceholderChunk("protocol-name");
5214 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5215 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005216
5217 // @selector ( selector )
Douglas Gregore5c79d52011-10-18 21:20:17 +00005218 Builder.AddResultTypeChunk("SEL");
James Dennett596e4752012-06-14 03:11:41 +00005219 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"selector"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005220 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5221 Builder.AddPlaceholderChunk("selector");
5222 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5223 Results.AddResult(Result(Builder.TakeString()));
Jordan Rose9da05852012-06-15 18:19:56 +00005224
5225 // @"string"
5226 Builder.AddResultTypeChunk("NSString *");
5227 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"\""));
5228 Builder.AddPlaceholderChunk("string");
5229 Builder.AddTextChunk("\"");
5230 Results.AddResult(Result(Builder.TakeString()));
5231
Douglas Gregor951de302012-07-17 23:24:47 +00005232 // @[objects, ...]
Jordan Rose9da05852012-06-15 18:19:56 +00005233 Builder.AddResultTypeChunk("NSArray *");
James Dennett596e4752012-06-14 03:11:41 +00005234 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"["));
Ted Kremeneke65b0862012-03-06 20:05:56 +00005235 Builder.AddPlaceholderChunk("objects, ...");
Ted Kremeneke65b0862012-03-06 20:05:56 +00005236 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
5237 Results.AddResult(Result(Builder.TakeString()));
5238
Douglas Gregor951de302012-07-17 23:24:47 +00005239 // @{key : object, ...}
Jordan Rose9da05852012-06-15 18:19:56 +00005240 Builder.AddResultTypeChunk("NSDictionary *");
James Dennett596e4752012-06-14 03:11:41 +00005241 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"{"));
Ted Kremeneke65b0862012-03-06 20:05:56 +00005242 Builder.AddPlaceholderChunk("key");
Ted Kremeneke65b0862012-03-06 20:05:56 +00005243 Builder.AddChunk(CodeCompletionString::CK_Colon);
5244 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5245 Builder.AddPlaceholderChunk("object, ...");
Ted Kremeneke65b0862012-03-06 20:05:56 +00005246 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5247 Results.AddResult(Result(Builder.TakeString()));
Jordan Rose9da05852012-06-15 18:19:56 +00005248
Douglas Gregor951de302012-07-17 23:24:47 +00005249 // @(expression)
Jordan Rose9da05852012-06-15 18:19:56 +00005250 Builder.AddResultTypeChunk("id");
5251 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "("));
Jordan Rose9da05852012-06-15 18:19:56 +00005252 Builder.AddPlaceholderChunk("expression");
Jordan Rose9da05852012-06-15 18:19:56 +00005253 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5254 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005255}
5256
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005257static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005258 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005259 CodeCompletionBuilder Builder(Results.getAllocator(),
5260 Results.getCodeCompletionTUInfo());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005261
Douglas Gregorf4c33342010-05-28 00:22:41 +00005262 if (Results.includeCodePatterns()) {
5263 // @try { statements } @catch ( declaration ) { statements } @finally
5264 // { statements }
James Dennett596e4752012-06-14 03:11:41 +00005265 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"try"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005266 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5267 Builder.AddPlaceholderChunk("statements");
5268 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5269 Builder.AddTextChunk("@catch");
5270 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5271 Builder.AddPlaceholderChunk("parameter");
5272 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5273 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5274 Builder.AddPlaceholderChunk("statements");
5275 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5276 Builder.AddTextChunk("@finally");
5277 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5278 Builder.AddPlaceholderChunk("statements");
5279 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5280 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00005281 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005282
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005283 // @throw
James Dennett596e4752012-06-14 03:11:41 +00005284 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"throw"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005285 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5286 Builder.AddPlaceholderChunk("expression");
5287 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005288
Douglas Gregorf4c33342010-05-28 00:22:41 +00005289 if (Results.includeCodePatterns()) {
5290 // @synchronized ( expression ) { statements }
James Dennett596e4752012-06-14 03:11:41 +00005291 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"synchronized"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005292 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5293 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5294 Builder.AddPlaceholderChunk("expression");
5295 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5296 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5297 Builder.AddPlaceholderChunk("statements");
5298 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5299 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00005300 }
Douglas Gregorf1934162010-01-13 21:24:21 +00005301}
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005302
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005303static void AddObjCVisibilityResults(const LangOptions &LangOpts,
Douglas Gregor48d46252010-01-13 21:54:15 +00005304 ResultBuilder &Results,
5305 bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005306 typedef CodeCompletionResult Result;
James Dennett596e4752012-06-14 03:11:41 +00005307 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"private")));
5308 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"protected")));
5309 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"public")));
Douglas Gregor48d46252010-01-13 21:54:15 +00005310 if (LangOpts.ObjC2)
James Dennett596e4752012-06-14 03:11:41 +00005311 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"package")));
Douglas Gregor48d46252010-01-13 21:54:15 +00005312}
5313
5314void Sema::CodeCompleteObjCAtVisibility(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005315 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005316 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005317 CodeCompletionContext::CCC_Other);
Douglas Gregor48d46252010-01-13 21:54:15 +00005318 Results.EnterNewScope();
David Blaikiebbafb8a2012-03-11 07:00:24 +00005319 AddObjCVisibilityResults(getLangOpts(), Results, false);
Douglas Gregor48d46252010-01-13 21:54:15 +00005320 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005321 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5322 Results.data(), Results.size());
Douglas Gregor48d46252010-01-13 21:54:15 +00005323}
5324
5325void Sema::CodeCompleteObjCAtStatement(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005326 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005327 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005328 CodeCompletionContext::CCC_Other);
Douglas Gregorf1934162010-01-13 21:24:21 +00005329 Results.EnterNewScope();
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005330 AddObjCStatementResults(Results, false);
5331 AddObjCExpressionResults(Results, false);
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005332 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005333 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5334 Results.data(), Results.size());
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005335}
5336
5337void Sema::CodeCompleteObjCAtExpression(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005338 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005339 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005340 CodeCompletionContext::CCC_Other);
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005341 Results.EnterNewScope();
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005342 AddObjCExpressionResults(Results, false);
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005343 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005344 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5345 Results.data(), Results.size());
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005346}
5347
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00005348/// Determine whether the addition of the given flag to an Objective-C
Douglas Gregore6078da2009-11-19 00:14:45 +00005349/// property's attributes will cause a conflict.
Bill Wendling44426052012-12-20 19:22:21 +00005350static bool ObjCPropertyFlagConflicts(unsigned Attributes, unsigned NewFlag) {
Douglas Gregore6078da2009-11-19 00:14:45 +00005351 // Check if we've already added this flag.
Bill Wendling44426052012-12-20 19:22:21 +00005352 if (Attributes & NewFlag)
Douglas Gregore6078da2009-11-19 00:14:45 +00005353 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005354
Bill Wendling44426052012-12-20 19:22:21 +00005355 Attributes |= NewFlag;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005356
Douglas Gregore6078da2009-11-19 00:14:45 +00005357 // Check for collisions with "readonly".
Bill Wendling44426052012-12-20 19:22:21 +00005358 if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) &&
5359 (Attributes & ObjCDeclSpec::DQ_PR_readwrite))
Douglas Gregore6078da2009-11-19 00:14:45 +00005360 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005361
Jordan Rose53cb2f32012-08-20 20:01:13 +00005362 // Check for more than one of { assign, copy, retain, strong, weak }.
Bill Wendling44426052012-12-20 19:22:21 +00005363 unsigned AssignCopyRetMask = Attributes & (ObjCDeclSpec::DQ_PR_assign |
John McCall31168b02011-06-15 23:02:42 +00005364 ObjCDeclSpec::DQ_PR_unsafe_unretained |
Douglas Gregore6078da2009-11-19 00:14:45 +00005365 ObjCDeclSpec::DQ_PR_copy |
Jordan Rose53cb2f32012-08-20 20:01:13 +00005366 ObjCDeclSpec::DQ_PR_retain |
5367 ObjCDeclSpec::DQ_PR_strong |
5368 ObjCDeclSpec::DQ_PR_weak);
Douglas Gregore6078da2009-11-19 00:14:45 +00005369 if (AssignCopyRetMask &&
5370 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_assign &&
John McCall31168b02011-06-15 23:02:42 +00005371 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_unsafe_unretained &&
Douglas Gregore6078da2009-11-19 00:14:45 +00005372 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_copy &&
John McCall31168b02011-06-15 23:02:42 +00005373 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_retain &&
Jordan Rose53cb2f32012-08-20 20:01:13 +00005374 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_strong &&
5375 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_weak)
Douglas Gregore6078da2009-11-19 00:14:45 +00005376 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005377
Douglas Gregore6078da2009-11-19 00:14:45 +00005378 return false;
5379}
5380
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005381void Sema::CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS) {
Steve Naroff936354c2009-10-08 21:55:05 +00005382 if (!CodeCompleter)
5383 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005384
Bill Wendling44426052012-12-20 19:22:21 +00005385 unsigned Attributes = ODS.getPropertyAttributes();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005386
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005387 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005388 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005389 CodeCompletionContext::CCC_Other);
Steve Naroff936354c2009-10-08 21:55:05 +00005390 Results.EnterNewScope();
Bill Wendling44426052012-12-20 19:22:21 +00005391 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readonly))
John McCall276321a2010-08-25 06:19:51 +00005392 Results.AddResult(CodeCompletionResult("readonly"));
Bill Wendling44426052012-12-20 19:22:21 +00005393 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_assign))
John McCall276321a2010-08-25 06:19:51 +00005394 Results.AddResult(CodeCompletionResult("assign"));
Bill Wendling44426052012-12-20 19:22:21 +00005395 if (!ObjCPropertyFlagConflicts(Attributes,
John McCall31168b02011-06-15 23:02:42 +00005396 ObjCDeclSpec::DQ_PR_unsafe_unretained))
5397 Results.AddResult(CodeCompletionResult("unsafe_unretained"));
Bill Wendling44426052012-12-20 19:22:21 +00005398 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readwrite))
John McCall276321a2010-08-25 06:19:51 +00005399 Results.AddResult(CodeCompletionResult("readwrite"));
Bill Wendling44426052012-12-20 19:22:21 +00005400 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_retain))
John McCall276321a2010-08-25 06:19:51 +00005401 Results.AddResult(CodeCompletionResult("retain"));
Bill Wendling44426052012-12-20 19:22:21 +00005402 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_strong))
John McCall31168b02011-06-15 23:02:42 +00005403 Results.AddResult(CodeCompletionResult("strong"));
Bill Wendling44426052012-12-20 19:22:21 +00005404 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_copy))
John McCall276321a2010-08-25 06:19:51 +00005405 Results.AddResult(CodeCompletionResult("copy"));
Bill Wendling44426052012-12-20 19:22:21 +00005406 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_nonatomic))
John McCall276321a2010-08-25 06:19:51 +00005407 Results.AddResult(CodeCompletionResult("nonatomic"));
Bill Wendling44426052012-12-20 19:22:21 +00005408 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_atomic))
Fariborz Jahanian1c2d29e2011-06-11 17:14:27 +00005409 Results.AddResult(CodeCompletionResult("atomic"));
Jordan Rose53cb2f32012-08-20 20:01:13 +00005410
5411 // Only suggest "weak" if we're compiling for ARC-with-weak-references or GC.
John McCall460ce582015-10-22 18:38:17 +00005412 if (getLangOpts().ObjCWeak || getLangOpts().getGC() != LangOptions::NonGC)
Bill Wendling44426052012-12-20 19:22:21 +00005413 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_weak))
Jordan Rose53cb2f32012-08-20 20:01:13 +00005414 Results.AddResult(CodeCompletionResult("weak"));
5415
Bill Wendling44426052012-12-20 19:22:21 +00005416 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_setter)) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005417 CodeCompletionBuilder Setter(Results.getAllocator(),
5418 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005419 Setter.AddTypedTextChunk("setter");
Argyrios Kyrtzidis7bbb8812014-02-20 07:55:15 +00005420 Setter.AddTextChunk("=");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005421 Setter.AddPlaceholderChunk("method");
5422 Results.AddResult(CodeCompletionResult(Setter.TakeString()));
Douglas Gregor45f83ee2009-11-19 00:01:57 +00005423 }
Bill Wendling44426052012-12-20 19:22:21 +00005424 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_getter)) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005425 CodeCompletionBuilder Getter(Results.getAllocator(),
5426 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005427 Getter.AddTypedTextChunk("getter");
Argyrios Kyrtzidis7bbb8812014-02-20 07:55:15 +00005428 Getter.AddTextChunk("=");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005429 Getter.AddPlaceholderChunk("method");
5430 Results.AddResult(CodeCompletionResult(Getter.TakeString()));
Douglas Gregor45f83ee2009-11-19 00:01:57 +00005431 }
Douglas Gregor86b42682015-06-19 18:27:52 +00005432 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_nullability)) {
5433 Results.AddResult(CodeCompletionResult("nonnull"));
5434 Results.AddResult(CodeCompletionResult("nullable"));
5435 Results.AddResult(CodeCompletionResult("null_unspecified"));
5436 Results.AddResult(CodeCompletionResult("null_resettable"));
5437 }
Steve Naroff936354c2009-10-08 21:55:05 +00005438 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005439 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5440 Results.data(), Results.size());
Steve Naroff936354c2009-10-08 21:55:05 +00005441}
Steve Naroffeae65032009-11-07 02:08:14 +00005442
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00005443/// Describes the kind of Objective-C method that we want to find
Douglas Gregorc8537c52009-11-19 07:41:15 +00005444/// via code completion.
5445enum ObjCMethodKind {
Dmitri Gribenko4280e5c2012-06-08 23:13:42 +00005446 MK_Any, ///< Any kind of method, provided it means other specified criteria.
5447 MK_ZeroArgSelector, ///< Zero-argument (unary) selector.
5448 MK_OneArgSelector ///< One-argument selector.
Douglas Gregorc8537c52009-11-19 07:41:15 +00005449};
5450
Douglas Gregor67c692c2010-08-26 15:07:07 +00005451static bool isAcceptableObjCSelector(Selector Sel,
5452 ObjCMethodKind WantKind,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005453 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005454 bool AllowSameLength = true) {
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005455 unsigned NumSelIdents = SelIdents.size();
Douglas Gregor67c692c2010-08-26 15:07:07 +00005456 if (NumSelIdents > Sel.getNumArgs())
5457 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005458
Douglas Gregor67c692c2010-08-26 15:07:07 +00005459 switch (WantKind) {
5460 case MK_Any: break;
5461 case MK_ZeroArgSelector: return Sel.isUnarySelector();
5462 case MK_OneArgSelector: return Sel.getNumArgs() == 1;
5463 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005464
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005465 if (!AllowSameLength && NumSelIdents && NumSelIdents == Sel.getNumArgs())
5466 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005467
Douglas Gregor67c692c2010-08-26 15:07:07 +00005468 for (unsigned I = 0; I != NumSelIdents; ++I)
5469 if (SelIdents[I] != Sel.getIdentifierInfoForSlot(I))
5470 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005471
Douglas Gregor67c692c2010-08-26 15:07:07 +00005472 return true;
5473}
5474
Douglas Gregorc8537c52009-11-19 07:41:15 +00005475static bool isAcceptableObjCMethod(ObjCMethodDecl *Method,
5476 ObjCMethodKind WantKind,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005477 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005478 bool AllowSameLength = true) {
Douglas Gregor67c692c2010-08-26 15:07:07 +00005479 return isAcceptableObjCSelector(Method->getSelector(), WantKind, SelIdents,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005480 AllowSameLength);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005481}
Douglas Gregor1154e272010-09-16 16:06:31 +00005482
5483namespace {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005484 /// A set of selectors, which is used to avoid introducing multiple
Douglas Gregor1154e272010-09-16 16:06:31 +00005485 /// completions with the same selector into the result set.
5486 typedef llvm::SmallPtrSet<Selector, 16> VisitedSelectorSet;
5487}
5488
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005489/// Add all of the Objective-C methods in the given Objective-C
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005490/// container to the set of results.
5491///
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005492/// The container will be a class, protocol, category, or implementation of
5493/// any of the above. This mether will recurse to include methods from
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005494/// the superclasses of classes along with their categories, protocols, and
5495/// implementations.
5496///
5497/// \param Container the container in which we'll look to find methods.
5498///
James Dennett596e4752012-06-14 03:11:41 +00005499/// \param WantInstanceMethods Whether to add instance methods (only); if
5500/// false, this routine will add factory methods (only).
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005501///
5502/// \param CurContext the context in which we're performing the lookup that
5503/// finds methods.
5504///
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005505/// \param AllowSameLength Whether we allow a method to be added to the list
5506/// when it has the same number of parameters as we have selector identifiers.
5507///
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005508/// \param Results the structure into which we'll add results.
Alex Lorenz638dbc32017-01-24 14:15:08 +00005509static void AddObjCMethods(ObjCContainerDecl *Container,
5510 bool WantInstanceMethods, ObjCMethodKind WantKind,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005511 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005512 DeclContext *CurContext,
Alex Lorenz638dbc32017-01-24 14:15:08 +00005513 VisitedSelectorSet &Selectors, bool AllowSameLength,
5514 ResultBuilder &Results, bool InOriginalClass = true,
5515 bool IsRootClass = false) {
John McCall276321a2010-08-25 06:19:51 +00005516 typedef CodeCompletionResult Result;
Douglas Gregor9b4f3702012-06-12 13:44:08 +00005517 Container = getContainerDef(Container);
Douglas Gregor41778c32013-01-30 06:58:39 +00005518 ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container);
Alex Lorenz638dbc32017-01-24 14:15:08 +00005519 IsRootClass = IsRootClass || (IFace && !IFace->getSuperClass());
Aaron Ballmanaff18c02014-03-13 19:03:34 +00005520 for (auto *M : Container->methods()) {
Douglas Gregor41778c32013-01-30 06:58:39 +00005521 // The instance methods on the root class can be messaged via the
5522 // metaclass.
5523 if (M->isInstanceMethod() == WantInstanceMethods ||
Alex Lorenz638dbc32017-01-24 14:15:08 +00005524 (IsRootClass && !WantInstanceMethods)) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005525 // Check whether the selector identifiers we've been given are a
Douglas Gregor1b605f72009-11-19 01:08:35 +00005526 // subset of the identifiers for this particular method.
Aaron Ballmanaff18c02014-03-13 19:03:34 +00005527 if (!isAcceptableObjCMethod(M, WantKind, SelIdents, AllowSameLength))
Douglas Gregor1b605f72009-11-19 01:08:35 +00005528 continue;
Douglas Gregorc8537c52009-11-19 07:41:15 +00005529
David Blaikie82e95a32014-11-19 07:49:47 +00005530 if (!Selectors.insert(M->getSelector()).second)
Douglas Gregor1154e272010-09-16 16:06:31 +00005531 continue;
Craig Topperc3ec1492014-05-26 06:22:03 +00005532
5533 Result R = Result(M, Results.getBasePriority(M), nullptr);
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005534 R.StartParameter = SelIdents.size();
Douglas Gregorc8537c52009-11-19 07:41:15 +00005535 R.AllParametersAreInformative = (WantKind != MK_Any);
Douglas Gregor416b5752010-08-25 01:08:01 +00005536 if (!InOriginalClass)
5537 R.Priority += CCD_InBaseClass;
Douglas Gregor1b605f72009-11-19 01:08:35 +00005538 Results.MaybeAddResult(R, CurContext);
5539 }
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005540 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005541
Douglas Gregorf37c9492010-09-16 15:34:59 +00005542 // Visit the protocols of protocols.
5543 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Douglas Gregore6e48b12012-01-01 19:29:29 +00005544 if (Protocol->hasDefinition()) {
5545 const ObjCList<ObjCProtocolDecl> &Protocols
5546 = Protocol->getReferencedProtocols();
5547 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005548 E = Protocols.end();
Douglas Gregore6e48b12012-01-01 19:29:29 +00005549 I != E; ++I)
Alex Lorenz638dbc32017-01-24 14:15:08 +00005550 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, CurContext,
5551 Selectors, AllowSameLength, Results, false, IsRootClass);
Douglas Gregore6e48b12012-01-01 19:29:29 +00005552 }
Douglas Gregorf37c9492010-09-16 15:34:59 +00005553 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005554
Douglas Gregorc0ac7d62011-12-15 05:27:12 +00005555 if (!IFace || !IFace->hasDefinition())
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005556 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005557
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005558 // Add methods in protocols.
Aaron Ballmana49c5062014-03-13 20:29:09 +00005559 for (auto *I : IFace->protocols())
Alex Lorenz638dbc32017-01-24 14:15:08 +00005560 AddObjCMethods(I, WantInstanceMethods, WantKind, SelIdents, CurContext,
5561 Selectors, AllowSameLength, Results, false, IsRootClass);
5562
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005563 // Add methods in categories.
Aaron Ballman15063e12014-03-13 21:35:02 +00005564 for (auto *CatDecl : IFace->known_categories()) {
Douglas Gregor048fbfa2013-01-16 23:00:23 +00005565 AddObjCMethods(CatDecl, WantInstanceMethods, WantKind, SelIdents,
Alex Lorenz638dbc32017-01-24 14:15:08 +00005566 CurContext, Selectors, AllowSameLength, Results,
5567 InOriginalClass, IsRootClass);
5568
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005569 // Add a categories protocol methods.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005570 const ObjCList<ObjCProtocolDecl> &Protocols
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005571 = CatDecl->getReferencedProtocols();
5572 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
5573 E = Protocols.end();
5574 I != E; ++I)
Alex Lorenz638dbc32017-01-24 14:15:08 +00005575 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, CurContext,
5576 Selectors, AllowSameLength, Results, false, IsRootClass);
5577
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005578 // Add methods in category implementations.
5579 if (ObjCCategoryImplDecl *Impl = CatDecl->getImplementation())
Alex Lorenz638dbc32017-01-24 14:15:08 +00005580 AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents, CurContext,
5581 Selectors, AllowSameLength, Results, InOriginalClass,
5582 IsRootClass);
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005583 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005584
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005585 // Add methods in superclass.
Alex Lorenz638dbc32017-01-24 14:15:08 +00005586 // Avoid passing in IsRootClass since root classes won't have super classes.
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005587 if (IFace->getSuperClass())
Alex Lorenz638dbc32017-01-24 14:15:08 +00005588 AddObjCMethods(IFace->getSuperClass(), WantInstanceMethods, WantKind,
5589 SelIdents, CurContext, Selectors, AllowSameLength, Results,
5590 /*IsRootClass=*/false);
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005591
5592 // Add methods in our implementation, if any.
5593 if (ObjCImplementationDecl *Impl = IFace->getImplementation())
Alex Lorenz638dbc32017-01-24 14:15:08 +00005594 AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents, CurContext,
5595 Selectors, AllowSameLength, Results, InOriginalClass,
5596 IsRootClass);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005597}
5598
5599
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005600void Sema::CodeCompleteObjCPropertyGetter(Scope *S) {
Douglas Gregorc8537c52009-11-19 07:41:15 +00005601 // Try to find the interface where getters might live.
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005602 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005603 if (!Class) {
5604 if (ObjCCategoryDecl *Category
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005605 = dyn_cast_or_null<ObjCCategoryDecl>(CurContext))
Douglas Gregorc8537c52009-11-19 07:41:15 +00005606 Class = Category->getClassInterface();
5607
5608 if (!Class)
5609 return;
5610 }
5611
5612 // Find all of the potential getters.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005613 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005614 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005615 CodeCompletionContext::CCC_Other);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005616 Results.EnterNewScope();
5617
Douglas Gregor1154e272010-09-16 16:06:31 +00005618 VisitedSelectorSet Selectors;
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005619 AddObjCMethods(Class, true, MK_ZeroArgSelector, None, CurContext, Selectors,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005620 /*AllowSameLength=*/true, Results);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005621 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005622 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5623 Results.data(), Results.size());
Douglas Gregorc8537c52009-11-19 07:41:15 +00005624}
5625
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005626void Sema::CodeCompleteObjCPropertySetter(Scope *S) {
Douglas Gregorc8537c52009-11-19 07:41:15 +00005627 // Try to find the interface where setters might live.
5628 ObjCInterfaceDecl *Class
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005629 = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005630 if (!Class) {
5631 if (ObjCCategoryDecl *Category
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005632 = dyn_cast_or_null<ObjCCategoryDecl>(CurContext))
Douglas Gregorc8537c52009-11-19 07:41:15 +00005633 Class = Category->getClassInterface();
5634
5635 if (!Class)
5636 return;
5637 }
5638
5639 // Find all of the potential getters.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005640 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005641 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005642 CodeCompletionContext::CCC_Other);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005643 Results.EnterNewScope();
5644
Douglas Gregor1154e272010-09-16 16:06:31 +00005645 VisitedSelectorSet Selectors;
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005646 AddObjCMethods(Class, true, MK_OneArgSelector, None, CurContext,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005647 Selectors, /*AllowSameLength=*/true, Results);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005648
5649 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005650 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5651 Results.data(), Results.size());
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005652}
5653
Douglas Gregorf34a6f02011-02-15 22:19:42 +00005654void Sema::CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS,
5655 bool IsParameter) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005656 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005657 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005658 CodeCompletionContext::CCC_Type);
Douglas Gregor99fa2642010-08-24 01:06:58 +00005659 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005660
Douglas Gregor99fa2642010-08-24 01:06:58 +00005661 // Add context-sensitive, Objective-C parameter-passing keywords.
5662 bool AddedInOut = false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005663 if ((DS.getObjCDeclQualifier() &
Douglas Gregor99fa2642010-08-24 01:06:58 +00005664 (ObjCDeclSpec::DQ_In | ObjCDeclSpec::DQ_Inout)) == 0) {
5665 Results.AddResult("in");
5666 Results.AddResult("inout");
5667 AddedInOut = true;
5668 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005669 if ((DS.getObjCDeclQualifier() &
Douglas Gregor99fa2642010-08-24 01:06:58 +00005670 (ObjCDeclSpec::DQ_Out | ObjCDeclSpec::DQ_Inout)) == 0) {
5671 Results.AddResult("out");
5672 if (!AddedInOut)
5673 Results.AddResult("inout");
5674 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005675 if ((DS.getObjCDeclQualifier() &
Douglas Gregor99fa2642010-08-24 01:06:58 +00005676 (ObjCDeclSpec::DQ_Bycopy | ObjCDeclSpec::DQ_Byref |
5677 ObjCDeclSpec::DQ_Oneway)) == 0) {
5678 Results.AddResult("bycopy");
5679 Results.AddResult("byref");
5680 Results.AddResult("oneway");
5681 }
Douglas Gregor86b42682015-06-19 18:27:52 +00005682 if ((DS.getObjCDeclQualifier() & ObjCDeclSpec::DQ_CSNullability) == 0) {
5683 Results.AddResult("nonnull");
5684 Results.AddResult("nullable");
5685 Results.AddResult("null_unspecified");
5686 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005687
5688 // If we're completing the return type of an Objective-C method and the
Douglas Gregorf34a6f02011-02-15 22:19:42 +00005689 // identifier IBAction refers to a macro, provide a completion item for
5690 // an action, e.g.,
5691 // IBAction)<#selector#>:(id)sender
5692 if (DS.getObjCDeclQualifier() == 0 && !IsParameter &&
Richard Smith20e883e2015-04-29 23:20:19 +00005693 PP.isMacroDefined("IBAction")) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005694 CodeCompletionBuilder Builder(Results.getAllocator(),
5695 Results.getCodeCompletionTUInfo(),
5696 CCP_CodePattern, CXAvailability_Available);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00005697 Builder.AddTypedTextChunk("IBAction");
Benjamin Kramerdb534a42012-03-26 16:57:36 +00005698 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00005699 Builder.AddPlaceholderChunk("selector");
Benjamin Kramerdb534a42012-03-26 16:57:36 +00005700 Builder.AddChunk(CodeCompletionString::CK_Colon);
5701 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00005702 Builder.AddTextChunk("id");
Benjamin Kramerdb534a42012-03-26 16:57:36 +00005703 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00005704 Builder.AddTextChunk("sender");
5705 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
5706 }
Douglas Gregored1f5972013-01-30 07:11:43 +00005707
5708 // If we're completing the return type, provide 'instancetype'.
5709 if (!IsParameter) {
5710 Results.AddResult(CodeCompletionResult("instancetype"));
5711 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005712
Douglas Gregor99fa2642010-08-24 01:06:58 +00005713 // Add various builtin type names and specifiers.
5714 AddOrdinaryNameResults(PCC_Type, S, *this, Results);
5715 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005716
Douglas Gregor99fa2642010-08-24 01:06:58 +00005717 // Add the various type names
5718 Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
5719 CodeCompletionDeclConsumer Consumer(Results, CurContext);
5720 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00005721 CodeCompleter->includeGlobals(),
5722 CodeCompleter->loadExternal());
5723
Douglas Gregor99fa2642010-08-24 01:06:58 +00005724 if (CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00005725 AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false);
Douglas Gregor99fa2642010-08-24 01:06:58 +00005726
Eric Liuf5ba09f2018-07-04 10:01:18 +00005727 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor99fa2642010-08-24 01:06:58 +00005728 Results.data(), Results.size());
5729}
5730
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00005731/// When we have an expression with type "id", we may assume
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005732/// that it has some more-specific class type based on knowledge of
5733/// common uses of Objective-C. This routine returns that class type,
5734/// or NULL if no better result could be determined.
5735static ObjCInterfaceDecl *GetAssumedMessageSendExprType(Expr *E) {
Douglas Gregored0b69d2010-09-15 16:23:04 +00005736 ObjCMessageExpr *Msg = dyn_cast_or_null<ObjCMessageExpr>(E);
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005737 if (!Msg)
Craig Topperc3ec1492014-05-26 06:22:03 +00005738 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005739
5740 Selector Sel = Msg->getSelector();
5741 if (Sel.isNull())
Craig Topperc3ec1492014-05-26 06:22:03 +00005742 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005743
5744 IdentifierInfo *Id = Sel.getIdentifierInfoForSlot(0);
5745 if (!Id)
Craig Topperc3ec1492014-05-26 06:22:03 +00005746 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005747
5748 ObjCMethodDecl *Method = Msg->getMethodDecl();
5749 if (!Method)
Craig Topperc3ec1492014-05-26 06:22:03 +00005750 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005751
5752 // Determine the class that we're sending the message to.
Craig Topperc3ec1492014-05-26 06:22:03 +00005753 ObjCInterfaceDecl *IFace = nullptr;
Douglas Gregor9a129192010-04-21 00:45:42 +00005754 switch (Msg->getReceiverKind()) {
5755 case ObjCMessageExpr::Class:
John McCall8b07ec22010-05-15 11:32:37 +00005756 if (const ObjCObjectType *ObjType
5757 = Msg->getClassReceiver()->getAs<ObjCObjectType>())
5758 IFace = ObjType->getInterface();
Douglas Gregor9a129192010-04-21 00:45:42 +00005759 break;
5760
5761 case ObjCMessageExpr::Instance: {
5762 QualType T = Msg->getInstanceReceiver()->getType();
5763 if (const ObjCObjectPointerType *Ptr = T->getAs<ObjCObjectPointerType>())
5764 IFace = Ptr->getInterfaceDecl();
5765 break;
5766 }
5767
5768 case ObjCMessageExpr::SuperInstance:
5769 case ObjCMessageExpr::SuperClass:
5770 break;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005771 }
5772
5773 if (!IFace)
Craig Topperc3ec1492014-05-26 06:22:03 +00005774 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005775
5776 ObjCInterfaceDecl *Super = IFace->getSuperClass();
5777 if (Method->isInstanceMethod())
5778 return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
5779 .Case("retain", IFace)
John McCall31168b02011-06-15 23:02:42 +00005780 .Case("strong", IFace)
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005781 .Case("autorelease", IFace)
5782 .Case("copy", IFace)
5783 .Case("copyWithZone", IFace)
5784 .Case("mutableCopy", IFace)
5785 .Case("mutableCopyWithZone", IFace)
5786 .Case("awakeFromCoder", IFace)
5787 .Case("replacementObjectFromCoder", IFace)
5788 .Case("class", IFace)
5789 .Case("classForCoder", IFace)
5790 .Case("superclass", Super)
Craig Topperc3ec1492014-05-26 06:22:03 +00005791 .Default(nullptr);
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005792
5793 return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
5794 .Case("new", IFace)
5795 .Case("alloc", IFace)
5796 .Case("allocWithZone", IFace)
5797 .Case("class", IFace)
5798 .Case("superclass", Super)
Craig Topperc3ec1492014-05-26 06:22:03 +00005799 .Default(nullptr);
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005800}
5801
Douglas Gregor6fc04132010-08-27 15:10:57 +00005802// Add a special completion for a message send to "super", which fills in the
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005803// most likely case of forwarding all of our arguments to the superclass
Douglas Gregor6fc04132010-08-27 15:10:57 +00005804// function.
5805///
5806/// \param S The semantic analysis object.
5807///
Dmitri Gribenkoadba9be2012-08-23 17:58:28 +00005808/// \param NeedSuperKeyword Whether we need to prefix this completion with
Douglas Gregor6fc04132010-08-27 15:10:57 +00005809/// the "super" keyword. Otherwise, we just need to provide the arguments.
5810///
5811/// \param SelIdents The identifiers in the selector that have already been
5812/// provided as arguments for a send to "super".
5813///
Douglas Gregor6fc04132010-08-27 15:10:57 +00005814/// \param Results The set of results to augment.
5815///
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005816/// \returns the Objective-C method declaration that would be invoked by
Douglas Gregor6fc04132010-08-27 15:10:57 +00005817/// this "super" completion. If NULL, no completion was added.
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005818static ObjCMethodDecl *AddSuperSendCompletion(
5819 Sema &S, bool NeedSuperKeyword,
5820 ArrayRef<IdentifierInfo *> SelIdents,
5821 ResultBuilder &Results) {
Douglas Gregor6fc04132010-08-27 15:10:57 +00005822 ObjCMethodDecl *CurMethod = S.getCurMethodDecl();
5823 if (!CurMethod)
Craig Topperc3ec1492014-05-26 06:22:03 +00005824 return nullptr;
5825
Douglas Gregor6fc04132010-08-27 15:10:57 +00005826 ObjCInterfaceDecl *Class = CurMethod->getClassInterface();
5827 if (!Class)
Craig Topperc3ec1492014-05-26 06:22:03 +00005828 return nullptr;
5829
Douglas Gregor6fc04132010-08-27 15:10:57 +00005830 // Try to find a superclass method with the same selector.
Craig Topperc3ec1492014-05-26 06:22:03 +00005831 ObjCMethodDecl *SuperMethod = nullptr;
Douglas Gregorb5f1e462011-02-16 00:51:18 +00005832 while ((Class = Class->getSuperClass()) && !SuperMethod) {
5833 // Check in the class
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005834 SuperMethod = Class->getMethod(CurMethod->getSelector(),
Douglas Gregor6fc04132010-08-27 15:10:57 +00005835 CurMethod->isInstanceMethod());
5836
Douglas Gregorb5f1e462011-02-16 00:51:18 +00005837 // Check in categories or class extensions.
5838 if (!SuperMethod) {
Aaron Ballman15063e12014-03-13 21:35:02 +00005839 for (const auto *Cat : Class->known_categories()) {
Douglas Gregor048fbfa2013-01-16 23:00:23 +00005840 if ((SuperMethod = Cat->getMethod(CurMethod->getSelector(),
Douglas Gregorb5f1e462011-02-16 00:51:18 +00005841 CurMethod->isInstanceMethod())))
5842 break;
Douglas Gregor048fbfa2013-01-16 23:00:23 +00005843 }
Douglas Gregorb5f1e462011-02-16 00:51:18 +00005844 }
5845 }
5846
Douglas Gregor6fc04132010-08-27 15:10:57 +00005847 if (!SuperMethod)
Craig Topperc3ec1492014-05-26 06:22:03 +00005848 return nullptr;
5849
Douglas Gregor6fc04132010-08-27 15:10:57 +00005850 // Check whether the superclass method has the same signature.
5851 if (CurMethod->param_size() != SuperMethod->param_size() ||
5852 CurMethod->isVariadic() != SuperMethod->isVariadic())
Craig Topperc3ec1492014-05-26 06:22:03 +00005853 return nullptr;
5854
Douglas Gregor6fc04132010-08-27 15:10:57 +00005855 for (ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin(),
5856 CurPEnd = CurMethod->param_end(),
5857 SuperP = SuperMethod->param_begin();
5858 CurP != CurPEnd; ++CurP, ++SuperP) {
5859 // Make sure the parameter types are compatible.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005860 if (!S.Context.hasSameUnqualifiedType((*CurP)->getType(),
Douglas Gregor6fc04132010-08-27 15:10:57 +00005861 (*SuperP)->getType()))
Craig Topperc3ec1492014-05-26 06:22:03 +00005862 return nullptr;
5863
Douglas Gregor6fc04132010-08-27 15:10:57 +00005864 // Make sure we have a parameter name to forward!
5865 if (!(*CurP)->getIdentifier())
Craig Topperc3ec1492014-05-26 06:22:03 +00005866 return nullptr;
Douglas Gregor6fc04132010-08-27 15:10:57 +00005867 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005868
Douglas Gregor6fc04132010-08-27 15:10:57 +00005869 // We have a superclass method. Now, form the send-to-super completion.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005870 CodeCompletionBuilder Builder(Results.getAllocator(),
5871 Results.getCodeCompletionTUInfo());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005872
Douglas Gregor6fc04132010-08-27 15:10:57 +00005873 // Give this completion a return type.
Douglas Gregorc3425b12015-07-07 06:20:19 +00005874 AddResultTypeChunk(S.Context, getCompletionPrintingPolicy(S), SuperMethod,
5875 Results.getCompletionContext().getBaseType(),
Douglas Gregor75acd922011-09-27 23:30:47 +00005876 Builder);
Douglas Gregor6fc04132010-08-27 15:10:57 +00005877
5878 // If we need the "super" keyword, add it (plus some spacing).
5879 if (NeedSuperKeyword) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005880 Builder.AddTypedTextChunk("super");
5881 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregor6fc04132010-08-27 15:10:57 +00005882 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005883
Douglas Gregor6fc04132010-08-27 15:10:57 +00005884 Selector Sel = CurMethod->getSelector();
5885 if (Sel.isUnarySelector()) {
5886 if (NeedSuperKeyword)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005887 Builder.AddTextChunk(Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00005888 Sel.getNameForSlot(0)));
Douglas Gregor6fc04132010-08-27 15:10:57 +00005889 else
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005890 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00005891 Sel.getNameForSlot(0)));
Douglas Gregor6fc04132010-08-27 15:10:57 +00005892 } else {
5893 ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin();
5894 for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I, ++CurP) {
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005895 if (I > SelIdents.size())
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005896 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005897
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005898 if (I < SelIdents.size())
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005899 Builder.AddInformativeChunk(
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005900 Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00005901 Sel.getNameForSlot(I) + ":"));
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005902 else if (NeedSuperKeyword || I > SelIdents.size()) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005903 Builder.AddTextChunk(
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005904 Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00005905 Sel.getNameForSlot(I) + ":"));
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005906 Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005907 (*CurP)->getIdentifier()->getName()));
Douglas Gregor6fc04132010-08-27 15:10:57 +00005908 } else {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005909 Builder.AddTypedTextChunk(
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005910 Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00005911 Sel.getNameForSlot(I) + ":"));
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005912 Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005913 (*CurP)->getIdentifier()->getName()));
Douglas Gregor6fc04132010-08-27 15:10:57 +00005914 }
5915 }
5916 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005917
Douglas Gregor78254c82012-03-27 23:34:16 +00005918 Results.AddResult(CodeCompletionResult(Builder.TakeString(), SuperMethod,
5919 CCP_SuperCompletion));
Douglas Gregor6fc04132010-08-27 15:10:57 +00005920 return SuperMethod;
5921}
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005922
Douglas Gregora817a192010-05-27 23:06:34 +00005923void Sema::CodeCompleteObjCMessageReceiver(Scope *S) {
John McCall276321a2010-08-25 06:19:51 +00005924 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005925 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005926 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005927 CodeCompletionContext::CCC_ObjCMessageReceiver,
Richard Smith2bf7fdb2013-01-02 11:42:31 +00005928 getLangOpts().CPlusPlus11
Douglas Gregord8c61782012-02-15 15:34:24 +00005929 ? &ResultBuilder::IsObjCMessageReceiverOrLambdaCapture
5930 : &ResultBuilder::IsObjCMessageReceiver);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005931
Douglas Gregora817a192010-05-27 23:06:34 +00005932 CodeCompletionDeclConsumer Consumer(Results, CurContext);
5933 Results.EnterNewScope();
Douglas Gregor39982192010-08-15 06:18:01 +00005934 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00005935 CodeCompleter->includeGlobals(),
5936 CodeCompleter->loadExternal());
5937
Douglas Gregora817a192010-05-27 23:06:34 +00005938 // If we are in an Objective-C method inside a class that has a superclass,
5939 // add "super" as an option.
5940 if (ObjCMethodDecl *Method = getCurMethodDecl())
5941 if (ObjCInterfaceDecl *Iface = Method->getClassInterface())
Douglas Gregor6fc04132010-08-27 15:10:57 +00005942 if (Iface->getSuperClass()) {
Douglas Gregora817a192010-05-27 23:06:34 +00005943 Results.AddResult(Result("super"));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005944
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005945 AddSuperSendCompletion(*this, /*NeedSuperKeyword=*/true, None, Results);
Douglas Gregor6fc04132010-08-27 15:10:57 +00005946 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005947
Richard Smith2bf7fdb2013-01-02 11:42:31 +00005948 if (getLangOpts().CPlusPlus11)
Douglas Gregord8c61782012-02-15 15:34:24 +00005949 addThisCompletion(*this, Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005950
Douglas Gregora817a192010-05-27 23:06:34 +00005951 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005952
Douglas Gregora817a192010-05-27 23:06:34 +00005953 if (CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00005954 AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false);
Douglas Gregor50832e02010-09-20 22:39:41 +00005955 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005956 Results.data(), Results.size());
Douglas Gregora817a192010-05-27 23:06:34 +00005957}
5958
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005959void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005960 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00005961 bool AtArgumentExpression) {
Craig Topperc3ec1492014-05-26 06:22:03 +00005962 ObjCInterfaceDecl *CDecl = nullptr;
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005963 if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
5964 // Figure out which interface we're in.
5965 CDecl = CurMethod->getClassInterface();
5966 if (!CDecl)
5967 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005968
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005969 // Find the superclass of this class.
5970 CDecl = CDecl->getSuperClass();
5971 if (!CDecl)
5972 return;
5973
5974 if (CurMethod->isInstanceMethod()) {
5975 // We are inside an instance method, which means that the message
5976 // send [super ...] is actually calling an instance method on the
Douglas Gregor392a84b2010-10-13 21:24:53 +00005977 // current object.
Craig Topperc3ec1492014-05-26 06:22:03 +00005978 return CodeCompleteObjCInstanceMessage(S, nullptr, SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00005979 AtArgumentExpression,
Douglas Gregor392a84b2010-10-13 21:24:53 +00005980 CDecl);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005981 }
5982
5983 // Fall through to send to the superclass in CDecl.
5984 } else {
5985 // "super" may be the name of a type or variable. Figure out which
5986 // it is.
Argyrios Kyrtzidis3e56dd42013-03-14 22:56:43 +00005987 IdentifierInfo *Super = getSuperIdentifier();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005988 NamedDecl *ND = LookupSingleName(S, Super, SuperLoc,
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005989 LookupOrdinaryName);
5990 if ((CDecl = dyn_cast_or_null<ObjCInterfaceDecl>(ND))) {
5991 // "super" names an interface. Use it.
5992 } else if (TypeDecl *TD = dyn_cast_or_null<TypeDecl>(ND)) {
John McCall8b07ec22010-05-15 11:32:37 +00005993 if (const ObjCObjectType *Iface
5994 = Context.getTypeDeclType(TD)->getAs<ObjCObjectType>())
5995 CDecl = Iface->getInterface();
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005996 } else if (ND && isa<UnresolvedUsingTypenameDecl>(ND)) {
5997 // "super" names an unresolved type; we can't be more specific.
5998 } else {
5999 // Assume that "super" names some kind of value and parse that way.
6000 CXXScopeSpec SS;
Abramo Bagnara7945c982012-01-27 09:46:47 +00006001 SourceLocation TemplateKWLoc;
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006002 UnqualifiedId id;
6003 id.setIdentifier(Super, SuperLoc);
Abramo Bagnara7945c982012-01-27 09:46:47 +00006004 ExprResult SuperExpr = ActOnIdExpression(S, SS, TemplateKWLoc, id,
6005 false, false);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006006 return CodeCompleteObjCInstanceMessage(S, (Expr *)SuperExpr.get(),
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006007 SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006008 AtArgumentExpression);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006009 }
6010
6011 // Fall through
6012 }
6013
John McCallba7bf592010-08-24 05:47:05 +00006014 ParsedType Receiver;
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006015 if (CDecl)
John McCallba7bf592010-08-24 05:47:05 +00006016 Receiver = ParsedType::make(Context.getObjCInterfaceType(CDecl));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006017 return CodeCompleteObjCClassMessage(S, Receiver, SelIdents,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006018 AtArgumentExpression,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006019 /*IsSuper=*/true);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006020}
6021
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006022/// Given a set of code-completion results for the argument of a message
Douglas Gregor74661272010-09-21 00:03:25 +00006023/// send, determine the preferred type (if any) for that argument expression.
6024static QualType getPreferredArgumentTypeForMessageSend(ResultBuilder &Results,
6025 unsigned NumSelIdents) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006026 typedef CodeCompletionResult Result;
Douglas Gregor74661272010-09-21 00:03:25 +00006027 ASTContext &Context = Results.getSema().Context;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006028
Douglas Gregor74661272010-09-21 00:03:25 +00006029 QualType PreferredType;
6030 unsigned BestPriority = CCP_Unlikely * 2;
6031 Result *ResultsData = Results.data();
6032 for (unsigned I = 0, N = Results.size(); I != N; ++I) {
6033 Result &R = ResultsData[I];
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006034 if (R.Kind == Result::RK_Declaration &&
Douglas Gregor74661272010-09-21 00:03:25 +00006035 isa<ObjCMethodDecl>(R.Declaration)) {
6036 if (R.Priority <= BestPriority) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00006037 const ObjCMethodDecl *Method = cast<ObjCMethodDecl>(R.Declaration);
Douglas Gregor74661272010-09-21 00:03:25 +00006038 if (NumSelIdents <= Method->param_size()) {
Alp Toker03376dc2014-07-07 09:02:20 +00006039 QualType MyPreferredType = Method->parameters()[NumSelIdents - 1]
Douglas Gregor74661272010-09-21 00:03:25 +00006040 ->getType();
6041 if (R.Priority < BestPriority || PreferredType.isNull()) {
6042 BestPriority = R.Priority;
6043 PreferredType = MyPreferredType;
6044 } else if (!Context.hasSameUnqualifiedType(PreferredType,
6045 MyPreferredType)) {
6046 PreferredType = QualType();
6047 }
6048 }
6049 }
6050 }
6051 }
6052
6053 return PreferredType;
6054}
6055
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006056static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006057 ParsedType Receiver,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006058 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006059 bool AtArgumentExpression,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006060 bool IsSuper,
6061 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00006062 typedef CodeCompletionResult Result;
Craig Topperc3ec1492014-05-26 06:22:03 +00006063 ObjCInterfaceDecl *CDecl = nullptr;
6064
Douglas Gregor8ce33212009-11-17 17:59:40 +00006065 // If the given name refers to an interface type, retrieve the
6066 // corresponding declaration.
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006067 if (Receiver) {
Craig Topperc3ec1492014-05-26 06:22:03 +00006068 QualType T = SemaRef.GetTypeFromParser(Receiver, nullptr);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006069 if (!T.isNull())
John McCall8b07ec22010-05-15 11:32:37 +00006070 if (const ObjCObjectType *Interface = T->getAs<ObjCObjectType>())
6071 CDecl = Interface->getInterface();
Douglas Gregor8ce33212009-11-17 17:59:40 +00006072 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006073
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006074 // Add all of the factory methods in this Objective-C class, its protocols,
6075 // superclasses, categories, implementation, etc.
Steve Naroffeae65032009-11-07 02:08:14 +00006076 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006077
6078 // If this is a send-to-super, try to add the special "super" send
Douglas Gregor6fc04132010-08-27 15:10:57 +00006079 // completion.
6080 if (IsSuper) {
6081 if (ObjCMethodDecl *SuperMethod
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006082 = AddSuperSendCompletion(SemaRef, false, SelIdents, Results))
Douglas Gregor6fc04132010-08-27 15:10:57 +00006083 Results.Ignore(SuperMethod);
6084 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006085
Douglas Gregorc2cb2e22010-08-27 15:29:55 +00006086 // If we're inside an Objective-C method definition, prefer its selector to
6087 // others.
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006088 if (ObjCMethodDecl *CurMethod = SemaRef.getCurMethodDecl())
Douglas Gregorc2cb2e22010-08-27 15:29:55 +00006089 Results.setPreferredSelector(CurMethod->getSelector());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006090
Douglas Gregor1154e272010-09-16 16:06:31 +00006091 VisitedSelectorSet Selectors;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006092 if (CDecl)
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006093 AddObjCMethods(CDecl, false, MK_Any, SelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00006094 SemaRef.CurContext, Selectors, AtArgumentExpression,
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006095 Results);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006096 else {
Douglas Gregor6285f752010-04-06 16:40:00 +00006097 // We're messaging "id" as a type; provide all class/factory methods.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006098
Douglas Gregord720daf2010-04-06 17:30:22 +00006099 // If we have an external source, load the entire class method
Sebastian Redld44cd6a2010-08-18 23:57:06 +00006100 // pool from the AST file.
Axel Naumanndd433f02012-10-18 19:05:02 +00006101 if (SemaRef.getExternalSource()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006102 for (uint32_t I = 0,
Axel Naumanndd433f02012-10-18 19:05:02 +00006103 N = SemaRef.getExternalSource()->GetNumExternalSelectors();
John McCall75b960e2010-06-01 09:23:16 +00006104 I != N; ++I) {
Axel Naumanndd433f02012-10-18 19:05:02 +00006105 Selector Sel = SemaRef.getExternalSource()->GetExternalSelector(I);
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006106 if (Sel.isNull() || SemaRef.MethodPool.count(Sel))
Douglas Gregord720daf2010-04-06 17:30:22 +00006107 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006108
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006109 SemaRef.ReadMethodPool(Sel);
Douglas Gregord720daf2010-04-06 17:30:22 +00006110 }
6111 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006112
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006113 for (Sema::GlobalMethodPool::iterator M = SemaRef.MethodPool.begin(),
6114 MEnd = SemaRef.MethodPool.end();
Sebastian Redl75d8a322010-08-02 23:18:59 +00006115 M != MEnd; ++M) {
6116 for (ObjCMethodList *MethList = &M->second.second;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006117 MethList && MethList->getMethod();
Argyrios Kyrtzidisd3da6e02013-04-17 00:08:58 +00006118 MethList = MethList->getNext()) {
Nico Weber2e0c8f72014-12-27 03:58:08 +00006119 if (!isAcceptableObjCMethod(MethList->getMethod(), MK_Any, SelIdents))
Douglas Gregor6285f752010-04-06 16:40:00 +00006120 continue;
Craig Topperc3ec1492014-05-26 06:22:03 +00006121
Nico Weber2e0c8f72014-12-27 03:58:08 +00006122 Result R(MethList->getMethod(),
6123 Results.getBasePriority(MethList->getMethod()), nullptr);
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006124 R.StartParameter = SelIdents.size();
Douglas Gregor6285f752010-04-06 16:40:00 +00006125 R.AllParametersAreInformative = false;
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006126 Results.MaybeAddResult(R, SemaRef.CurContext);
Douglas Gregor6285f752010-04-06 16:40:00 +00006127 }
6128 }
6129 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006130
6131 Results.ExitScope();
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006132}
Douglas Gregor6285f752010-04-06 16:40:00 +00006133
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006134void Sema::CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006135 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006136 bool AtArgumentExpression,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006137 bool IsSuper) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006138
Douglas Gregor63745d52011-07-21 01:05:26 +00006139 QualType T = this->GetTypeFromParser(Receiver);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006140
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006141 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006142 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor63745d52011-07-21 01:05:26 +00006143 CodeCompletionContext(CodeCompletionContext::CCC_ObjCClassMessage,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006144 T, SelIdents));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006145
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006146 AddClassMessageCompletions(*this, S, Receiver, SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006147 AtArgumentExpression, IsSuper, Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006148
6149 // If we're actually at the argument expression (rather than prior to the
Douglas Gregor74661272010-09-21 00:03:25 +00006150 // selector), we're actually performing code completion for an expression.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006151 // Determine whether we have a single, best method. If so, we can
Douglas Gregor74661272010-09-21 00:03:25 +00006152 // code-complete the expression using the corresponding parameter type as
6153 // our preferred type, improving completion results.
6154 if (AtArgumentExpression) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006155 QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006156 SelIdents.size());
Douglas Gregor74661272010-09-21 00:03:25 +00006157 if (PreferredType.isNull())
6158 CodeCompleteOrdinaryName(S, PCC_Expression);
6159 else
6160 CodeCompleteExpression(S, PreferredType);
6161 return;
6162 }
6163
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006164 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor63745d52011-07-21 01:05:26 +00006165 Results.getCompletionContext(),
Douglas Gregor6fc04132010-08-27 15:10:57 +00006166 Results.data(), Results.size());
Steve Naroffeae65032009-11-07 02:08:14 +00006167}
6168
Richard Trieu2bd04012011-09-09 02:00:50 +00006169void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006170 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006171 bool AtArgumentExpression,
Douglas Gregor392a84b2010-10-13 21:24:53 +00006172 ObjCInterfaceDecl *Super) {
John McCall276321a2010-08-25 06:19:51 +00006173 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006174
Steve Naroffeae65032009-11-07 02:08:14 +00006175 Expr *RecExpr = static_cast<Expr *>(Receiver);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006176
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006177 // If necessary, apply function/array conversion to the receiver.
6178 // C99 6.7.5.3p[7,8].
John Wiegley01296292011-04-08 18:41:53 +00006179 if (RecExpr) {
6180 ExprResult Conv = DefaultFunctionArrayLvalueConversion(RecExpr);
6181 if (Conv.isInvalid()) // conversion failed. bail.
6182 return;
Nikola Smiljanic01a75982014-05-29 10:55:11 +00006183 RecExpr = Conv.get();
John Wiegley01296292011-04-08 18:41:53 +00006184 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006185 QualType ReceiverType = RecExpr? RecExpr->getType()
Douglas Gregor392a84b2010-10-13 21:24:53 +00006186 : Super? Context.getObjCObjectPointerType(
6187 Context.getObjCInterfaceType(Super))
6188 : Context.getObjCIdType();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006189
Douglas Gregordc520b02010-11-08 21:12:30 +00006190 // If we're messaging an expression with type "id" or "Class", check
6191 // whether we know something special about the receiver that allows
6192 // us to assume a more-specific receiver type.
Anders Carlsson382ba412014-02-28 19:07:22 +00006193 if (ReceiverType->isObjCIdType() || ReceiverType->isObjCClassType()) {
Douglas Gregordc520b02010-11-08 21:12:30 +00006194 if (ObjCInterfaceDecl *IFace = GetAssumedMessageSendExprType(RecExpr)) {
6195 if (ReceiverType->isObjCClassType())
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006196 return CodeCompleteObjCClassMessage(S,
Douglas Gregordc520b02010-11-08 21:12:30 +00006197 ParsedType::make(Context.getObjCInterfaceType(IFace)),
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006198 SelIdents,
Douglas Gregordc520b02010-11-08 21:12:30 +00006199 AtArgumentExpression, Super);
6200
6201 ReceiverType = Context.getObjCObjectPointerType(
6202 Context.getObjCInterfaceType(IFace));
6203 }
Anders Carlsson382ba412014-02-28 19:07:22 +00006204 } else if (RecExpr && getLangOpts().CPlusPlus) {
6205 ExprResult Conv = PerformContextuallyConvertToObjCPointer(RecExpr);
6206 if (Conv.isUsable()) {
Nikola Smiljanic01a75982014-05-29 10:55:11 +00006207 RecExpr = Conv.get();
Anders Carlsson382ba412014-02-28 19:07:22 +00006208 ReceiverType = RecExpr->getType();
6209 }
6210 }
Douglas Gregordc520b02010-11-08 21:12:30 +00006211
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006212 // Build the set of methods we can see.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006213 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006214 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor63745d52011-07-21 01:05:26 +00006215 CodeCompletionContext(CodeCompletionContext::CCC_ObjCInstanceMessage,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006216 ReceiverType, SelIdents));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006217
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006218 Results.EnterNewScope();
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006219
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006220 // If this is a send-to-super, try to add the special "super" send
Douglas Gregor6fc04132010-08-27 15:10:57 +00006221 // completion.
Douglas Gregor392a84b2010-10-13 21:24:53 +00006222 if (Super) {
Douglas Gregor6fc04132010-08-27 15:10:57 +00006223 if (ObjCMethodDecl *SuperMethod
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006224 = AddSuperSendCompletion(*this, false, SelIdents, Results))
Douglas Gregor6fc04132010-08-27 15:10:57 +00006225 Results.Ignore(SuperMethod);
6226 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006227
Douglas Gregorc2cb2e22010-08-27 15:29:55 +00006228 // If we're inside an Objective-C method definition, prefer its selector to
6229 // others.
6230 if (ObjCMethodDecl *CurMethod = getCurMethodDecl())
6231 Results.setPreferredSelector(CurMethod->getSelector());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006232
Douglas Gregor1154e272010-09-16 16:06:31 +00006233 // Keep track of the selectors we've already added.
6234 VisitedSelectorSet Selectors;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006235
Douglas Gregora3329fa2009-11-18 00:06:18 +00006236 // Handle messages to Class. This really isn't a message to an instance
6237 // method, so we treat it the same way we would treat a message send to a
6238 // class method.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006239 if (ReceiverType->isObjCClassType() ||
Douglas Gregora3329fa2009-11-18 00:06:18 +00006240 ReceiverType->isObjCQualifiedClassType()) {
6241 if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
6242 if (ObjCInterfaceDecl *ClassDecl = CurMethod->getClassInterface())
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006243 AddObjCMethods(ClassDecl, false, MK_Any, SelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00006244 CurContext, Selectors, AtArgumentExpression, Results);
Douglas Gregora3329fa2009-11-18 00:06:18 +00006245 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006246 }
Douglas Gregora3329fa2009-11-18 00:06:18 +00006247 // Handle messages to a qualified ID ("id<foo>").
6248 else if (const ObjCObjectPointerType *QualID
6249 = ReceiverType->getAsObjCQualifiedIdType()) {
6250 // Search protocols for instance methods.
Aaron Ballman83731462014-03-17 16:14:00 +00006251 for (auto *I : QualID->quals())
6252 AddObjCMethods(I, true, MK_Any, SelIdents, CurContext,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00006253 Selectors, AtArgumentExpression, Results);
Douglas Gregora3329fa2009-11-18 00:06:18 +00006254 }
6255 // Handle messages to a pointer to interface type.
6256 else if (const ObjCObjectPointerType *IFacePtr
6257 = ReceiverType->getAsObjCInterfacePointerType()) {
6258 // Search the class, its superclasses, etc., for instance methods.
Douglas Gregorc8537c52009-11-19 07:41:15 +00006259 AddObjCMethods(IFacePtr->getInterfaceDecl(), true, MK_Any, SelIdents,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006260 CurContext, Selectors, AtArgumentExpression,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00006261 Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006262
Douglas Gregora3329fa2009-11-18 00:06:18 +00006263 // Search protocols for instance methods.
Aaron Ballman83731462014-03-17 16:14:00 +00006264 for (auto *I : IFacePtr->quals())
6265 AddObjCMethods(I, true, MK_Any, SelIdents, CurContext,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00006266 Selectors, AtArgumentExpression, Results);
Douglas Gregora3329fa2009-11-18 00:06:18 +00006267 }
Douglas Gregor6285f752010-04-06 16:40:00 +00006268 // Handle messages to "id".
6269 else if (ReceiverType->isObjCIdType()) {
Douglas Gregord720daf2010-04-06 17:30:22 +00006270 // We're messaging "id", so provide all instance methods we know
6271 // about as code-completion results.
6272
6273 // If we have an external source, load the entire class method
Sebastian Redld44cd6a2010-08-18 23:57:06 +00006274 // pool from the AST file.
Douglas Gregord720daf2010-04-06 17:30:22 +00006275 if (ExternalSource) {
John McCall75b960e2010-06-01 09:23:16 +00006276 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
6277 I != N; ++I) {
6278 Selector Sel = ExternalSource->GetExternalSelector(I);
Sebastian Redl75d8a322010-08-02 23:18:59 +00006279 if (Sel.isNull() || MethodPool.count(Sel))
Douglas Gregord720daf2010-04-06 17:30:22 +00006280 continue;
6281
Sebastian Redl75d8a322010-08-02 23:18:59 +00006282 ReadMethodPool(Sel);
Douglas Gregord720daf2010-04-06 17:30:22 +00006283 }
6284 }
6285
Sebastian Redl75d8a322010-08-02 23:18:59 +00006286 for (GlobalMethodPool::iterator M = MethodPool.begin(),
6287 MEnd = MethodPool.end();
6288 M != MEnd; ++M) {
6289 for (ObjCMethodList *MethList = &M->second.first;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006290 MethList && MethList->getMethod();
Argyrios Kyrtzidisd3da6e02013-04-17 00:08:58 +00006291 MethList = MethList->getNext()) {
Nico Weber2e0c8f72014-12-27 03:58:08 +00006292 if (!isAcceptableObjCMethod(MethList->getMethod(), MK_Any, SelIdents))
Douglas Gregor6285f752010-04-06 16:40:00 +00006293 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006294
Nico Weber2e0c8f72014-12-27 03:58:08 +00006295 if (!Selectors.insert(MethList->getMethod()->getSelector()).second)
Douglas Gregor1154e272010-09-16 16:06:31 +00006296 continue;
Craig Topperc3ec1492014-05-26 06:22:03 +00006297
Nico Weber2e0c8f72014-12-27 03:58:08 +00006298 Result R(MethList->getMethod(),
6299 Results.getBasePriority(MethList->getMethod()), nullptr);
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006300 R.StartParameter = SelIdents.size();
Douglas Gregor6285f752010-04-06 16:40:00 +00006301 R.AllParametersAreInformative = false;
6302 Results.MaybeAddResult(R, CurContext);
6303 }
6304 }
6305 }
Steve Naroffeae65032009-11-07 02:08:14 +00006306 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006307
6308
6309 // If we're actually at the argument expression (rather than prior to the
Douglas Gregor74661272010-09-21 00:03:25 +00006310 // selector), we're actually performing code completion for an expression.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006311 // Determine whether we have a single, best method. If so, we can
Douglas Gregor74661272010-09-21 00:03:25 +00006312 // code-complete the expression using the corresponding parameter type as
6313 // our preferred type, improving completion results.
6314 if (AtArgumentExpression) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006315 QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006316 SelIdents.size());
Douglas Gregor74661272010-09-21 00:03:25 +00006317 if (PreferredType.isNull())
6318 CodeCompleteOrdinaryName(S, PCC_Expression);
6319 else
6320 CodeCompleteExpression(S, PreferredType);
6321 return;
6322 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006323
6324 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor63745d52011-07-21 01:05:26 +00006325 Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006326 Results.data(),Results.size());
Steve Naroffeae65032009-11-07 02:08:14 +00006327}
Douglas Gregorbaf69612009-11-18 04:19:12 +00006328
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006329void Sema::CodeCompleteObjCForCollection(Scope *S,
Douglas Gregor68762e72010-08-23 21:17:50 +00006330 DeclGroupPtrTy IterationVar) {
6331 CodeCompleteExpressionData Data;
6332 Data.ObjCCollection = true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006333
Douglas Gregor68762e72010-08-23 21:17:50 +00006334 if (IterationVar.getAsOpaquePtr()) {
Serge Pavlov9ddb76e2013-08-27 13:15:56 +00006335 DeclGroupRef DG = IterationVar.get();
Douglas Gregor68762e72010-08-23 21:17:50 +00006336 for (DeclGroupRef::iterator I = DG.begin(), End = DG.end(); I != End; ++I) {
6337 if (*I)
6338 Data.IgnoreDecls.push_back(*I);
6339 }
6340 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006341
Douglas Gregor68762e72010-08-23 21:17:50 +00006342 CodeCompleteExpression(S, Data);
6343}
6344
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006345void Sema::CodeCompleteObjCSelector(Scope *S,
6346 ArrayRef<IdentifierInfo *> SelIdents) {
Douglas Gregor67c692c2010-08-26 15:07:07 +00006347 // If we have an external source, load the entire class method
6348 // pool from the AST file.
6349 if (ExternalSource) {
6350 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
6351 I != N; ++I) {
6352 Selector Sel = ExternalSource->GetExternalSelector(I);
6353 if (Sel.isNull() || MethodPool.count(Sel))
6354 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006355
Douglas Gregor67c692c2010-08-26 15:07:07 +00006356 ReadMethodPool(Sel);
6357 }
6358 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006359
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006360 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006361 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006362 CodeCompletionContext::CCC_SelectorName);
Douglas Gregor67c692c2010-08-26 15:07:07 +00006363 Results.EnterNewScope();
6364 for (GlobalMethodPool::iterator M = MethodPool.begin(),
6365 MEnd = MethodPool.end();
6366 M != MEnd; ++M) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006367
Douglas Gregor67c692c2010-08-26 15:07:07 +00006368 Selector Sel = M->first;
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006369 if (!isAcceptableObjCSelector(Sel, MK_Any, SelIdents))
Douglas Gregor67c692c2010-08-26 15:07:07 +00006370 continue;
6371
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006372 CodeCompletionBuilder Builder(Results.getAllocator(),
6373 Results.getCodeCompletionTUInfo());
Douglas Gregor67c692c2010-08-26 15:07:07 +00006374 if (Sel.isUnarySelector()) {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00006375 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00006376 Sel.getNameForSlot(0)));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006377 Results.AddResult(Builder.TakeString());
Douglas Gregor67c692c2010-08-26 15:07:07 +00006378 continue;
6379 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006380
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00006381 std::string Accumulator;
Douglas Gregor67c692c2010-08-26 15:07:07 +00006382 for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I) {
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006383 if (I == SelIdents.size()) {
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00006384 if (!Accumulator.empty()) {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00006385 Builder.AddInformativeChunk(Builder.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006386 Accumulator));
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00006387 Accumulator.clear();
6388 }
6389 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006390
Benjamin Kramer632500c2011-07-26 16:59:25 +00006391 Accumulator += Sel.getNameForSlot(I);
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00006392 Accumulator += ':';
Douglas Gregor67c692c2010-08-26 15:07:07 +00006393 }
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00006394 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString( Accumulator));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006395 Results.AddResult(Builder.TakeString());
Douglas Gregor67c692c2010-08-26 15:07:07 +00006396 }
6397 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00006398
6399 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor67c692c2010-08-26 15:07:07 +00006400 Results.data(), Results.size());
6401}
6402
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006403/// Add all of the protocol declarations that we find in the given
Douglas Gregorbaf69612009-11-18 04:19:12 +00006404/// (translation unit) context.
6405static void AddProtocolResults(DeclContext *Ctx, DeclContext *CurContext,
Douglas Gregor5b4671c2009-11-18 04:49:41 +00006406 bool OnlyForwardDeclarations,
Douglas Gregorbaf69612009-11-18 04:19:12 +00006407 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00006408 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006409
Aaron Ballman629afae2014-03-07 19:56:05 +00006410 for (const auto *D : Ctx->decls()) {
Douglas Gregorbaf69612009-11-18 04:19:12 +00006411 // Record any protocols we find.
Aaron Ballman629afae2014-03-07 19:56:05 +00006412 if (const auto *Proto = dyn_cast<ObjCProtocolDecl>(D))
Douglas Gregore6e48b12012-01-01 19:29:29 +00006413 if (!OnlyForwardDeclarations || !Proto->hasDefinition())
Craig Topperc3ec1492014-05-26 06:22:03 +00006414 Results.AddResult(Result(Proto, Results.getBasePriority(Proto),nullptr),
6415 CurContext, nullptr, false);
Douglas Gregorbaf69612009-11-18 04:19:12 +00006416 }
6417}
6418
Craig Topper883dd332015-12-24 23:58:11 +00006419void Sema::CodeCompleteObjCProtocolReferences(
6420 ArrayRef<IdentifierLocPair> Protocols) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006421 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006422 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006423 CodeCompletionContext::CCC_ObjCProtocolName);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006424
Chandler Carruthede11632016-11-04 06:06:50 +00006425 if (CodeCompleter->includeGlobals()) {
Douglas Gregora3b23b02010-12-09 21:44:02 +00006426 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006427
Douglas Gregora3b23b02010-12-09 21:44:02 +00006428 // Tell the result set to ignore all of the protocols we have
6429 // already seen.
6430 // FIXME: This doesn't work when caching code-completion results.
Craig Topper883dd332015-12-24 23:58:11 +00006431 for (const IdentifierLocPair &Pair : Protocols)
6432 if (ObjCProtocolDecl *Protocol = LookupProtocol(Pair.first,
6433 Pair.second))
Douglas Gregora3b23b02010-12-09 21:44:02 +00006434 Results.Ignore(Protocol);
Douglas Gregorbaf69612009-11-18 04:19:12 +00006435
Douglas Gregora3b23b02010-12-09 21:44:02 +00006436 // Add all protocols.
6437 AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, false,
6438 Results);
Douglas Gregor5b4671c2009-11-18 04:49:41 +00006439
Douglas Gregora3b23b02010-12-09 21:44:02 +00006440 Results.ExitScope();
6441 }
Eric Liuf5ba09f2018-07-04 10:01:18 +00006442
6443 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6444 Results.data(), Results.size());
Douglas Gregor5b4671c2009-11-18 04:49:41 +00006445}
6446
6447void Sema::CodeCompleteObjCProtocolDecl(Scope *) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006448 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006449 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006450 CodeCompletionContext::CCC_ObjCProtocolName);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006451
Chandler Carruthede11632016-11-04 06:06:50 +00006452 if (CodeCompleter->includeGlobals()) {
Douglas Gregora3b23b02010-12-09 21:44:02 +00006453 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006454
Douglas Gregora3b23b02010-12-09 21:44:02 +00006455 // Add all protocols.
6456 AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, true,
6457 Results);
Douglas Gregorbaf69612009-11-18 04:19:12 +00006458
Douglas Gregora3b23b02010-12-09 21:44:02 +00006459 Results.ExitScope();
6460 }
Eric Liuf5ba09f2018-07-04 10:01:18 +00006461
6462 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6463 Results.data(), Results.size());
Douglas Gregorbaf69612009-11-18 04:19:12 +00006464}
Douglas Gregor49c22a72009-11-18 16:26:39 +00006465
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006466/// Add all of the Objective-C interface declarations that we find in
Douglas Gregor49c22a72009-11-18 16:26:39 +00006467/// the given (translation unit) context.
6468static void AddInterfaceResults(DeclContext *Ctx, DeclContext *CurContext,
6469 bool OnlyForwardDeclarations,
6470 bool OnlyUnimplemented,
6471 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00006472 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006473
Aaron Ballman629afae2014-03-07 19:56:05 +00006474 for (const auto *D : Ctx->decls()) {
Douglas Gregor1c283312010-08-11 12:19:30 +00006475 // Record any interfaces we find.
Aaron Ballman629afae2014-03-07 19:56:05 +00006476 if (const auto *Class = dyn_cast<ObjCInterfaceDecl>(D))
Douglas Gregordc9166c2011-12-15 20:29:51 +00006477 if ((!OnlyForwardDeclarations || !Class->hasDefinition()) &&
Douglas Gregor1c283312010-08-11 12:19:30 +00006478 (!OnlyUnimplemented || !Class->getImplementation()))
Craig Topperc3ec1492014-05-26 06:22:03 +00006479 Results.AddResult(Result(Class, Results.getBasePriority(Class),nullptr),
6480 CurContext, nullptr, false);
Douglas Gregor49c22a72009-11-18 16:26:39 +00006481 }
6482}
6483
Eric Liuf5ba09f2018-07-04 10:01:18 +00006484void Sema::CodeCompleteObjCInterfaceDecl(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006485 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006486 CodeCompleter->getCodeCompletionTUInfo(),
Eric Liuf5ba09f2018-07-04 10:01:18 +00006487 CodeCompletionContext::CCC_ObjCInterfaceName);
Douglas Gregor49c22a72009-11-18 16:26:39 +00006488 Results.EnterNewScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00006489
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006490 if (CodeCompleter->includeGlobals()) {
6491 // Add all classes.
6492 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
6493 false, Results);
6494 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006495
Douglas Gregor49c22a72009-11-18 16:26:39 +00006496 Results.ExitScope();
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006497
Eric Liuf5ba09f2018-07-04 10:01:18 +00006498 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6499 Results.data(), Results.size());
Douglas Gregor49c22a72009-11-18 16:26:39 +00006500}
6501
Douglas Gregorb2ccf012010-04-15 22:33:43 +00006502void Sema::CodeCompleteObjCSuperclass(Scope *S, IdentifierInfo *ClassName,
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006503 SourceLocation ClassNameLoc) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006504 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006505 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006506 CodeCompletionContext::CCC_ObjCInterfaceName);
Douglas Gregor49c22a72009-11-18 16:26:39 +00006507 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006508
Douglas Gregor49c22a72009-11-18 16:26:39 +00006509 // Make sure that we ignore the class we're currently defining.
6510 NamedDecl *CurClass
Douglas Gregorb2ccf012010-04-15 22:33:43 +00006511 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006512 if (CurClass && isa<ObjCInterfaceDecl>(CurClass))
Douglas Gregor49c22a72009-11-18 16:26:39 +00006513 Results.Ignore(CurClass);
6514
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006515 if (CodeCompleter->includeGlobals()) {
6516 // Add all classes.
6517 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
6518 false, Results);
6519 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006520
Douglas Gregor49c22a72009-11-18 16:26:39 +00006521 Results.ExitScope();
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006522
Eric Liuf5ba09f2018-07-04 10:01:18 +00006523 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6524 Results.data(), Results.size());
Douglas Gregor49c22a72009-11-18 16:26:39 +00006525}
6526
Eric Liuf5ba09f2018-07-04 10:01:18 +00006527void Sema::CodeCompleteObjCImplementationDecl(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006528 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006529 CodeCompleter->getCodeCompletionTUInfo(),
Eric Liuf5ba09f2018-07-04 10:01:18 +00006530 CodeCompletionContext::CCC_ObjCImplementation);
Douglas Gregor49c22a72009-11-18 16:26:39 +00006531 Results.EnterNewScope();
6532
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006533 if (CodeCompleter->includeGlobals()) {
6534 // Add all unimplemented classes.
6535 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
6536 true, Results);
6537 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006538
Douglas Gregor49c22a72009-11-18 16:26:39 +00006539 Results.ExitScope();
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006540
Eric Liuf5ba09f2018-07-04 10:01:18 +00006541 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6542 Results.data(), Results.size());
Douglas Gregor49c22a72009-11-18 16:26:39 +00006543}
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006544
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006545void Sema::CodeCompleteObjCInterfaceCategory(Scope *S,
Douglas Gregorb2ccf012010-04-15 22:33:43 +00006546 IdentifierInfo *ClassName,
6547 SourceLocation ClassNameLoc) {
John McCall276321a2010-08-25 06:19:51 +00006548 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006549
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006550 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006551 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor21325842011-07-07 16:03:39 +00006552 CodeCompletionContext::CCC_ObjCCategoryName);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006553
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006554 // Ignore any categories we find that have already been implemented by this
6555 // interface.
6556 llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
6557 NamedDecl *CurClass
Douglas Gregorb2ccf012010-04-15 22:33:43 +00006558 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006559 if (ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass)){
Aaron Ballman3fe486a2014-03-13 21:23:55 +00006560 for (const auto *Cat : Class->visible_categories())
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006561 CategoryNames.insert(Cat->getIdentifier());
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006562 }
6563
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006564 // Add all of the categories we know about.
6565 Results.EnterNewScope();
6566 TranslationUnitDecl *TU = Context.getTranslationUnitDecl();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006567 for (const auto *D : TU->decls())
Aaron Ballman629afae2014-03-07 19:56:05 +00006568 if (const auto *Category = dyn_cast<ObjCCategoryDecl>(D))
David Blaikie82e95a32014-11-19 07:49:47 +00006569 if (CategoryNames.insert(Category->getIdentifier()).second)
Craig Topperc3ec1492014-05-26 06:22:03 +00006570 Results.AddResult(Result(Category, Results.getBasePriority(Category),
6571 nullptr),
6572 CurContext, nullptr, false);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006573 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00006574
6575 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6576 Results.data(), Results.size());
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006577}
6578
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006579void Sema::CodeCompleteObjCImplementationCategory(Scope *S,
Douglas Gregorb2ccf012010-04-15 22:33:43 +00006580 IdentifierInfo *ClassName,
6581 SourceLocation ClassNameLoc) {
John McCall276321a2010-08-25 06:19:51 +00006582 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006583
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006584 // Find the corresponding interface. If we couldn't find the interface, the
6585 // program itself is ill-formed. However, we'll try to be helpful still by
6586 // providing the list of all of the categories we know about.
6587 NamedDecl *CurClass
Douglas Gregorb2ccf012010-04-15 22:33:43 +00006588 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006589 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass);
6590 if (!Class)
Douglas Gregorb2ccf012010-04-15 22:33:43 +00006591 return CodeCompleteObjCInterfaceCategory(S, ClassName, ClassNameLoc);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006592
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006593 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006594 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor21325842011-07-07 16:03:39 +00006595 CodeCompletionContext::CCC_ObjCCategoryName);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006596
6597 // Add all of the categories that have have corresponding interface
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006598 // declarations in this class and any of its superclasses, except for
6599 // already-implemented categories in the class itself.
6600 llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
6601 Results.EnterNewScope();
6602 bool IgnoreImplemented = true;
6603 while (Class) {
Aaron Ballman3fe486a2014-03-13 21:23:55 +00006604 for (const auto *Cat : Class->visible_categories()) {
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006605 if ((!IgnoreImplemented || !Cat->getImplementation()) &&
David Blaikie82e95a32014-11-19 07:49:47 +00006606 CategoryNames.insert(Cat->getIdentifier()).second)
Craig Topperc3ec1492014-05-26 06:22:03 +00006607 Results.AddResult(Result(Cat, Results.getBasePriority(Cat), nullptr),
6608 CurContext, nullptr, false);
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006609 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006610
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006611 Class = Class->getSuperClass();
6612 IgnoreImplemented = false;
6613 }
6614 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00006615
6616 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6617 Results.data(), Results.size());
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006618}
Douglas Gregor5d649882009-11-18 22:32:06 +00006619
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00006620void Sema::CodeCompleteObjCPropertyDefinition(Scope *S) {
Douglas Gregorc3425b12015-07-07 06:20:19 +00006621 CodeCompletionContext CCContext(CodeCompletionContext::CCC_Other);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006622 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006623 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorc3425b12015-07-07 06:20:19 +00006624 CCContext);
Douglas Gregor5d649882009-11-18 22:32:06 +00006625
6626 // Figure out where this @synthesize lives.
6627 ObjCContainerDecl *Container
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00006628 = dyn_cast_or_null<ObjCContainerDecl>(CurContext);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006629 if (!Container ||
6630 (!isa<ObjCImplementationDecl>(Container) &&
Douglas Gregor5d649882009-11-18 22:32:06 +00006631 !isa<ObjCCategoryImplDecl>(Container)))
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006632 return;
Douglas Gregor5d649882009-11-18 22:32:06 +00006633
6634 // Ignore any properties that have already been implemented.
Douglas Gregor9b4f3702012-06-12 13:44:08 +00006635 Container = getContainerDef(Container);
Aaron Ballman629afae2014-03-07 19:56:05 +00006636 for (const auto *D : Container->decls())
6637 if (const auto *PropertyImpl = dyn_cast<ObjCPropertyImplDecl>(D))
Douglas Gregor5d649882009-11-18 22:32:06 +00006638 Results.Ignore(PropertyImpl->getPropertyDecl());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006639
Douglas Gregor5d649882009-11-18 22:32:06 +00006640 // Add any properties that we find.
Douglas Gregorb888acf2010-12-09 23:01:55 +00006641 AddedPropertiesSet AddedProperties;
Douglas Gregor5d649882009-11-18 22:32:06 +00006642 Results.EnterNewScope();
6643 if (ObjCImplementationDecl *ClassImpl
6644 = dyn_cast<ObjCImplementationDecl>(Container))
Douglas Gregorc3425b12015-07-07 06:20:19 +00006645 AddObjCProperties(CCContext, ClassImpl->getClassInterface(), false,
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006646 /*AllowNullaryMethods=*/false, CurContext,
Douglas Gregorb888acf2010-12-09 23:01:55 +00006647 AddedProperties, Results);
Douglas Gregor5d649882009-11-18 22:32:06 +00006648 else
Douglas Gregorc3425b12015-07-07 06:20:19 +00006649 AddObjCProperties(CCContext,
6650 cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl(),
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006651 false, /*AllowNullaryMethods=*/false, CurContext,
Douglas Gregor95147142011-05-05 15:50:42 +00006652 AddedProperties, Results);
Douglas Gregor5d649882009-11-18 22:32:06 +00006653 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00006654
6655 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6656 Results.data(), Results.size());
Douglas Gregor5d649882009-11-18 22:32:06 +00006657}
6658
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006659void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S,
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00006660 IdentifierInfo *PropertyName) {
John McCall276321a2010-08-25 06:19:51 +00006661 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006662 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006663 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006664 CodeCompletionContext::CCC_Other);
Douglas Gregor5d649882009-11-18 22:32:06 +00006665
6666 // Figure out where this @synthesize lives.
6667 ObjCContainerDecl *Container
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00006668 = dyn_cast_or_null<ObjCContainerDecl>(CurContext);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006669 if (!Container ||
6670 (!isa<ObjCImplementationDecl>(Container) &&
Douglas Gregor5d649882009-11-18 22:32:06 +00006671 !isa<ObjCCategoryImplDecl>(Container)))
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006672 return;
6673
Douglas Gregor5d649882009-11-18 22:32:06 +00006674 // Figure out which interface we're looking into.
Craig Topperc3ec1492014-05-26 06:22:03 +00006675 ObjCInterfaceDecl *Class = nullptr;
Douglas Gregor5d649882009-11-18 22:32:06 +00006676 if (ObjCImplementationDecl *ClassImpl
Manman Ren5b786402016-01-28 18:49:28 +00006677 = dyn_cast<ObjCImplementationDecl>(Container))
Douglas Gregor5d649882009-11-18 22:32:06 +00006678 Class = ClassImpl->getClassInterface();
6679 else
6680 Class = cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl()
6681 ->getClassInterface();
6682
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006683 // Determine the type of the property we're synthesizing.
6684 QualType PropertyType = Context.getObjCIdType();
6685 if (Class) {
Manman Ren5b786402016-01-28 18:49:28 +00006686 if (ObjCPropertyDecl *Property = Class->FindPropertyDeclaration(
6687 PropertyName, ObjCPropertyQueryKind::OBJC_PR_query_instance)) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006688 PropertyType
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006689 = Property->getType().getNonReferenceType().getUnqualifiedType();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006690
6691 // Give preference to ivars
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006692 Results.setPreferredType(PropertyType);
6693 }
6694 }
6695
Douglas Gregor5d649882009-11-18 22:32:06 +00006696 // Add all of the instance variables in this class and its superclasses.
6697 Results.EnterNewScope();
Douglas Gregor331faa02011-04-18 14:13:53 +00006698 bool SawSimilarlyNamedIvar = false;
6699 std::string NameWithPrefix;
6700 NameWithPrefix += '_';
Benjamin Kramer632500c2011-07-26 16:59:25 +00006701 NameWithPrefix += PropertyName->getName();
Douglas Gregor331faa02011-04-18 14:13:53 +00006702 std::string NameWithSuffix = PropertyName->getName().str();
6703 NameWithSuffix += '_';
Douglas Gregor5d649882009-11-18 22:32:06 +00006704 for(; Class; Class = Class->getSuperClass()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006705 for (ObjCIvarDecl *Ivar = Class->all_declared_ivar_begin(); Ivar;
Douglas Gregor331faa02011-04-18 14:13:53 +00006706 Ivar = Ivar->getNextIvar()) {
Craig Topperc3ec1492014-05-26 06:22:03 +00006707 Results.AddResult(Result(Ivar, Results.getBasePriority(Ivar), nullptr),
6708 CurContext, nullptr, false);
6709
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006710 // Determine whether we've seen an ivar with a name similar to the
Douglas Gregor331faa02011-04-18 14:13:53 +00006711 // property.
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006712 if ((PropertyName == Ivar->getIdentifier() ||
Douglas Gregor331faa02011-04-18 14:13:53 +00006713 NameWithPrefix == Ivar->getName() ||
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006714 NameWithSuffix == Ivar->getName())) {
Douglas Gregor331faa02011-04-18 14:13:53 +00006715 SawSimilarlyNamedIvar = true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006716
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006717 // Reduce the priority of this result by one, to give it a slight
6718 // advantage over other results whose names don't match so closely.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006719 if (Results.size() &&
6720 Results.data()[Results.size() - 1].Kind
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006721 == CodeCompletionResult::RK_Declaration &&
6722 Results.data()[Results.size() - 1].Declaration == Ivar)
6723 Results.data()[Results.size() - 1].Priority--;
6724 }
Douglas Gregor331faa02011-04-18 14:13:53 +00006725 }
Douglas Gregor5d649882009-11-18 22:32:06 +00006726 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006727
Douglas Gregor331faa02011-04-18 14:13:53 +00006728 if (!SawSimilarlyNamedIvar) {
6729 // Create ivar result _propName, that the user can use to synthesize
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006730 // an ivar of the appropriate type.
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006731 unsigned Priority = CCP_MemberDeclaration + 1;
Douglas Gregor331faa02011-04-18 14:13:53 +00006732 typedef CodeCompletionResult Result;
6733 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006734 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo(),
6735 Priority,CXAvailability_Available);
Douglas Gregor331faa02011-04-18 14:13:53 +00006736
Douglas Gregor75acd922011-09-27 23:30:47 +00006737 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006738 Builder.AddResultTypeChunk(GetCompletionTypeString(PropertyType, Context,
Douglas Gregor75acd922011-09-27 23:30:47 +00006739 Policy, Allocator));
Douglas Gregor331faa02011-04-18 14:13:53 +00006740 Builder.AddTypedTextChunk(Allocator.CopyString(NameWithPrefix));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006741 Results.AddResult(Result(Builder.TakeString(), Priority,
Douglas Gregor331faa02011-04-18 14:13:53 +00006742 CXCursor_ObjCIvarDecl));
6743 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006744
Douglas Gregor5d649882009-11-18 22:32:06 +00006745 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00006746
6747 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6748 Results.data(), Results.size());
Douglas Gregor5d649882009-11-18 22:32:06 +00006749}
Douglas Gregor636a61e2010-04-07 00:21:17 +00006750
Douglas Gregor416b5752010-08-25 01:08:01 +00006751// Mapping from selectors to the methods that implement that selector, along
6752// with the "in original class" flag.
Benjamin Kramereb8c4462013-06-29 17:52:13 +00006753typedef llvm::DenseMap<
6754 Selector, llvm::PointerIntPair<ObjCMethodDecl *, 1, bool> > KnownMethodsMap;
Douglas Gregor636a61e2010-04-07 00:21:17 +00006755
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006756/// Find all of the methods that reside in the given container
Douglas Gregor636a61e2010-04-07 00:21:17 +00006757/// (and its superclasses, protocols, etc.) that meet the given
6758/// criteria. Insert those methods into the map of known methods,
6759/// indexed by selector so they can be easily found.
6760static void FindImplementableMethods(ASTContext &Context,
6761 ObjCContainerDecl *Container,
Alex Lorenzb8740422017-10-24 16:39:37 +00006762 Optional<bool> WantInstanceMethods,
Douglas Gregor636a61e2010-04-07 00:21:17 +00006763 QualType ReturnType,
Douglas Gregor416b5752010-08-25 01:08:01 +00006764 KnownMethodsMap &KnownMethods,
6765 bool InOriginalClass = true) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00006766 if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)) {
Douglas Gregor9b4f3702012-06-12 13:44:08 +00006767 // Make sure we have a definition; that's what we'll walk.
Douglas Gregorc0ac7d62011-12-15 05:27:12 +00006768 if (!IFace->hasDefinition())
6769 return;
Douglas Gregor9b4f3702012-06-12 13:44:08 +00006770
6771 IFace = IFace->getDefinition();
6772 Container = IFace;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006773
Douglas Gregor636a61e2010-04-07 00:21:17 +00006774 const ObjCList<ObjCProtocolDecl> &Protocols
6775 = IFace->getReferencedProtocols();
6776 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006777 E = Protocols.end();
Douglas Gregor636a61e2010-04-07 00:21:17 +00006778 I != E; ++I)
6779 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006780 KnownMethods, InOriginalClass);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006781
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006782 // Add methods from any class extensions and categories.
Aaron Ballman3fe486a2014-03-13 21:23:55 +00006783 for (auto *Cat : IFace->visible_categories()) {
6784 FindImplementableMethods(Context, Cat, WantInstanceMethods, ReturnType,
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006785 KnownMethods, false);
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006786 }
6787
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006788 // Visit the superclass.
6789 if (IFace->getSuperClass())
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006790 FindImplementableMethods(Context, IFace->getSuperClass(),
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006791 WantInstanceMethods, ReturnType,
6792 KnownMethods, false);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006793 }
6794
6795 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(Container)) {
6796 // Recurse into protocols.
6797 const ObjCList<ObjCProtocolDecl> &Protocols
6798 = Category->getReferencedProtocols();
6799 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006800 E = Protocols.end();
Douglas Gregor636a61e2010-04-07 00:21:17 +00006801 I != E; ++I)
6802 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006803 KnownMethods, InOriginalClass);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006804
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006805 // If this category is the original class, jump to the interface.
6806 if (InOriginalClass && Category->getClassInterface())
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006807 FindImplementableMethods(Context, Category->getClassInterface(),
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006808 WantInstanceMethods, ReturnType, KnownMethods,
6809 false);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006810 }
6811
6812 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Douglas Gregor9b4f3702012-06-12 13:44:08 +00006813 // Make sure we have a definition; that's what we'll walk.
6814 if (!Protocol->hasDefinition())
6815 return;
6816 Protocol = Protocol->getDefinition();
6817 Container = Protocol;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006818
Douglas Gregor9b4f3702012-06-12 13:44:08 +00006819 // Recurse into protocols.
6820 const ObjCList<ObjCProtocolDecl> &Protocols
6821 = Protocol->getReferencedProtocols();
6822 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006823 E = Protocols.end();
Douglas Gregor9b4f3702012-06-12 13:44:08 +00006824 I != E; ++I)
6825 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
6826 KnownMethods, false);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006827 }
6828
6829 // Add methods in this container. This operation occurs last because
6830 // we want the methods from this container to override any methods
6831 // we've previously seen with the same selector.
Aaron Ballmanaff18c02014-03-13 19:03:34 +00006832 for (auto *M : Container->methods()) {
Alex Lorenzb8740422017-10-24 16:39:37 +00006833 if (!WantInstanceMethods || M->isInstanceMethod() == *WantInstanceMethods) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00006834 if (!ReturnType.isNull() &&
Alp Toker314cc812014-01-25 16:55:45 +00006835 !Context.hasSameUnqualifiedType(ReturnType, M->getReturnType()))
Douglas Gregor636a61e2010-04-07 00:21:17 +00006836 continue;
6837
Benjamin Kramereb8c4462013-06-29 17:52:13 +00006838 KnownMethods[M->getSelector()] =
Aaron Ballmanaff18c02014-03-13 19:03:34 +00006839 KnownMethodsMap::mapped_type(M, InOriginalClass);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006840 }
6841 }
6842}
6843
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006844/// Add the parenthesized return or parameter type chunk to a code
Douglas Gregor669a25a2011-02-17 00:22:45 +00006845/// completion string.
6846static void AddObjCPassingTypeChunk(QualType Type,
Douglas Gregor29979142012-04-10 18:35:07 +00006847 unsigned ObjCDeclQuals,
Douglas Gregor669a25a2011-02-17 00:22:45 +00006848 ASTContext &Context,
Douglas Gregor75acd922011-09-27 23:30:47 +00006849 const PrintingPolicy &Policy,
Douglas Gregor669a25a2011-02-17 00:22:45 +00006850 CodeCompletionBuilder &Builder) {
6851 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregor86b42682015-06-19 18:27:52 +00006852 std::string Quals = formatObjCParamQualifiers(ObjCDeclQuals, Type);
Douglas Gregor29979142012-04-10 18:35:07 +00006853 if (!Quals.empty())
6854 Builder.AddTextChunk(Builder.getAllocator().CopyString(Quals));
Douglas Gregor75acd922011-09-27 23:30:47 +00006855 Builder.AddTextChunk(GetCompletionTypeString(Type, Context, Policy,
Douglas Gregor669a25a2011-02-17 00:22:45 +00006856 Builder.getAllocator()));
6857 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6858}
6859
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006860/// Determine whether the given class is or inherits from a class by
Douglas Gregor669a25a2011-02-17 00:22:45 +00006861/// the given name.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006862static bool InheritsFromClassNamed(ObjCInterfaceDecl *Class,
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006863 StringRef Name) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006864 if (!Class)
6865 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006866
Douglas Gregor669a25a2011-02-17 00:22:45 +00006867 if (Class->getIdentifier() && Class->getIdentifier()->getName() == Name)
6868 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006869
Douglas Gregor669a25a2011-02-17 00:22:45 +00006870 return InheritsFromClassNamed(Class->getSuperClass(), Name);
6871}
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006872
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006873/// Add code completions for Objective-C Key-Value Coding (KVC) and
Douglas Gregor669a25a2011-02-17 00:22:45 +00006874/// Key-Value Observing (KVO).
6875static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
6876 bool IsInstanceMethod,
6877 QualType ReturnType,
6878 ASTContext &Context,
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006879 VisitedSelectorSet &KnownSelectors,
Douglas Gregor669a25a2011-02-17 00:22:45 +00006880 ResultBuilder &Results) {
6881 IdentifierInfo *PropName = Property->getIdentifier();
6882 if (!PropName || PropName->getLength() == 0)
6883 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006884
Douglas Gregor75acd922011-09-27 23:30:47 +00006885 PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema());
6886
Douglas Gregor669a25a2011-02-17 00:22:45 +00006887 // Builder that will create each code completion.
6888 typedef CodeCompletionResult Result;
6889 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006890 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006891
Douglas Gregor669a25a2011-02-17 00:22:45 +00006892 // The selector table.
6893 SelectorTable &Selectors = Context.Selectors;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006894
Douglas Gregor669a25a2011-02-17 00:22:45 +00006895 // The property name, copied into the code completion allocation region
6896 // on demand.
6897 struct KeyHolder {
6898 CodeCompletionAllocator &Allocator;
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006899 StringRef Key;
Douglas Gregor669a25a2011-02-17 00:22:45 +00006900 const char *CopiedKey;
Craig Topperc3ec1492014-05-26 06:22:03 +00006901
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006902 KeyHolder(CodeCompletionAllocator &Allocator, StringRef Key)
Craig Topperc3ec1492014-05-26 06:22:03 +00006903 : Allocator(Allocator), Key(Key), CopiedKey(nullptr) {}
6904
Douglas Gregor669a25a2011-02-17 00:22:45 +00006905 operator const char *() {
6906 if (CopiedKey)
6907 return CopiedKey;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006908
Douglas Gregor669a25a2011-02-17 00:22:45 +00006909 return CopiedKey = Allocator.CopyString(Key);
6910 }
6911 } Key(Allocator, PropName->getName());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006912
Douglas Gregor669a25a2011-02-17 00:22:45 +00006913 // The uppercased name of the property name.
6914 std::string UpperKey = PropName->getName();
6915 if (!UpperKey.empty())
Jordan Rose4938f272013-02-09 10:09:43 +00006916 UpperKey[0] = toUppercase(UpperKey[0]);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006917
Douglas Gregor669a25a2011-02-17 00:22:45 +00006918 bool ReturnTypeMatchesProperty = ReturnType.isNull() ||
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006919 Context.hasSameUnqualifiedType(ReturnType.getNonReferenceType(),
Douglas Gregor669a25a2011-02-17 00:22:45 +00006920 Property->getType());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006921 bool ReturnTypeMatchesVoid
Douglas Gregor669a25a2011-02-17 00:22:45 +00006922 = ReturnType.isNull() || ReturnType->isVoidType();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006923
Douglas Gregor669a25a2011-02-17 00:22:45 +00006924 // Add the normal accessor -(type)key.
6925 if (IsInstanceMethod &&
David Blaikie82e95a32014-11-19 07:49:47 +00006926 KnownSelectors.insert(Selectors.getNullarySelector(PropName)).second &&
Douglas Gregor669a25a2011-02-17 00:22:45 +00006927 ReturnTypeMatchesProperty && !Property->getGetterMethodDecl()) {
6928 if (ReturnType.isNull())
Douglas Gregor29979142012-04-10 18:35:07 +00006929 AddObjCPassingTypeChunk(Property->getType(), /*Quals=*/0,
6930 Context, Policy, Builder);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006931
Douglas Gregor669a25a2011-02-17 00:22:45 +00006932 Builder.AddTypedTextChunk(Key);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006933 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Douglas Gregor669a25a2011-02-17 00:22:45 +00006934 CXCursor_ObjCInstanceMethodDecl));
6935 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006936
Douglas Gregor669a25a2011-02-17 00:22:45 +00006937 // If we have an integral or boolean property (or the user has provided
6938 // an integral or boolean return type), add the accessor -(type)isKey.
6939 if (IsInstanceMethod &&
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006940 ((!ReturnType.isNull() &&
Douglas Gregor669a25a2011-02-17 00:22:45 +00006941 (ReturnType->isIntegerType() || ReturnType->isBooleanType())) ||
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006942 (ReturnType.isNull() &&
6943 (Property->getType()->isIntegerType() ||
Douglas Gregor669a25a2011-02-17 00:22:45 +00006944 Property->getType()->isBooleanType())))) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006945 std::string SelectorName = (Twine("is") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006946 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00006947 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
6948 .second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006949 if (ReturnType.isNull()) {
6950 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6951 Builder.AddTextChunk("BOOL");
6952 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6953 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006954
Douglas Gregor669a25a2011-02-17 00:22:45 +00006955 Builder.AddTypedTextChunk(
6956 Allocator.CopyString(SelectorId->getName()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006957 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Douglas Gregor669a25a2011-02-17 00:22:45 +00006958 CXCursor_ObjCInstanceMethodDecl));
6959 }
6960 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006961
Douglas Gregor669a25a2011-02-17 00:22:45 +00006962 // Add the normal mutator.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006963 if (IsInstanceMethod && ReturnTypeMatchesVoid &&
Douglas Gregor669a25a2011-02-17 00:22:45 +00006964 !Property->getSetterMethodDecl()) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006965 std::string SelectorName = (Twine("set") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006966 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00006967 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006968 if (ReturnType.isNull()) {
6969 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6970 Builder.AddTextChunk("void");
6971 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6972 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006973
Douglas Gregor669a25a2011-02-17 00:22:45 +00006974 Builder.AddTypedTextChunk(
6975 Allocator.CopyString(SelectorId->getName()));
6976 Builder.AddTypedTextChunk(":");
Douglas Gregor29979142012-04-10 18:35:07 +00006977 AddObjCPassingTypeChunk(Property->getType(), /*Quals=*/0,
6978 Context, Policy, Builder);
Douglas Gregor669a25a2011-02-17 00:22:45 +00006979 Builder.AddTextChunk(Key);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006980 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Douglas Gregor669a25a2011-02-17 00:22:45 +00006981 CXCursor_ObjCInstanceMethodDecl));
6982 }
6983 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006984
Douglas Gregor669a25a2011-02-17 00:22:45 +00006985 // Indexed and unordered accessors
6986 unsigned IndexedGetterPriority = CCP_CodePattern;
6987 unsigned IndexedSetterPriority = CCP_CodePattern;
6988 unsigned UnorderedGetterPriority = CCP_CodePattern;
6989 unsigned UnorderedSetterPriority = CCP_CodePattern;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006990 if (const ObjCObjectPointerType *ObjCPointer
Douglas Gregor669a25a2011-02-17 00:22:45 +00006991 = Property->getType()->getAs<ObjCObjectPointerType>()) {
6992 if (ObjCInterfaceDecl *IFace = ObjCPointer->getInterfaceDecl()) {
6993 // If this interface type is not provably derived from a known
6994 // collection, penalize the corresponding completions.
6995 if (!InheritsFromClassNamed(IFace, "NSMutableArray")) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006996 IndexedSetterPriority += CCD_ProbablyNotObjCCollection;
Douglas Gregor669a25a2011-02-17 00:22:45 +00006997 if (!InheritsFromClassNamed(IFace, "NSArray"))
6998 IndexedGetterPriority += CCD_ProbablyNotObjCCollection;
6999 }
7000
7001 if (!InheritsFromClassNamed(IFace, "NSMutableSet")) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007002 UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;
Douglas Gregor669a25a2011-02-17 00:22:45 +00007003 if (!InheritsFromClassNamed(IFace, "NSSet"))
7004 UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;
7005 }
7006 }
7007 } else {
7008 IndexedGetterPriority += CCD_ProbablyNotObjCCollection;
7009 IndexedSetterPriority += CCD_ProbablyNotObjCCollection;
7010 UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;
7011 UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;
7012 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007013
Douglas Gregor669a25a2011-02-17 00:22:45 +00007014 // Add -(NSUInteger)countOf<key>
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007015 if (IsInstanceMethod &&
Douglas Gregor669a25a2011-02-17 00:22:45 +00007016 (ReturnType.isNull() || ReturnType->isIntegerType())) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007017 std::string SelectorName = (Twine("countOf") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007018 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007019 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
7020 .second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007021 if (ReturnType.isNull()) {
7022 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7023 Builder.AddTextChunk("NSUInteger");
7024 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7025 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007026
Douglas Gregor669a25a2011-02-17 00:22:45 +00007027 Builder.AddTypedTextChunk(
7028 Allocator.CopyString(SelectorId->getName()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007029 Results.AddResult(Result(Builder.TakeString(),
7030 std::min(IndexedGetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007031 UnorderedGetterPriority),
7032 CXCursor_ObjCInstanceMethodDecl));
7033 }
7034 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007035
Douglas Gregor669a25a2011-02-17 00:22:45 +00007036 // Indexed getters
7037 // Add -(id)objectInKeyAtIndex:(NSUInteger)index
7038 if (IsInstanceMethod &&
7039 (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007040 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007041 = (Twine("objectIn") + UpperKey + "AtIndex").str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007042 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007043 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007044 if (ReturnType.isNull()) {
7045 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7046 Builder.AddTextChunk("id");
7047 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7048 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007049
Douglas Gregor669a25a2011-02-17 00:22:45 +00007050 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7051 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7052 Builder.AddTextChunk("NSUInteger");
7053 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7054 Builder.AddTextChunk("index");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007055 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007056 CXCursor_ObjCInstanceMethodDecl));
7057 }
7058 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007059
Douglas Gregor669a25a2011-02-17 00:22:45 +00007060 // Add -(NSArray *)keyAtIndexes:(NSIndexSet *)indexes
7061 if (IsInstanceMethod &&
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007062 (ReturnType.isNull() ||
Douglas Gregor669a25a2011-02-17 00:22:45 +00007063 (ReturnType->isObjCObjectPointerType() &&
7064 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
7065 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
7066 ->getName() == "NSArray"))) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007067 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007068 = (Twine(Property->getName()) + "AtIndexes").str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007069 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007070 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007071 if (ReturnType.isNull()) {
7072 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7073 Builder.AddTextChunk("NSArray *");
7074 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7075 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007076
Douglas Gregor669a25a2011-02-17 00:22:45 +00007077 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7078 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7079 Builder.AddTextChunk("NSIndexSet *");
7080 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7081 Builder.AddTextChunk("indexes");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007082 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007083 CXCursor_ObjCInstanceMethodDecl));
7084 }
7085 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007086
Douglas Gregor669a25a2011-02-17 00:22:45 +00007087 // Add -(void)getKey:(type **)buffer range:(NSRange)inRange
7088 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007089 std::string SelectorName = (Twine("get") + UpperKey).str();
Douglas Gregor669a25a2011-02-17 00:22:45 +00007090 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007091 &Context.Idents.get(SelectorName),
Douglas Gregor669a25a2011-02-17 00:22:45 +00007092 &Context.Idents.get("range")
7093 };
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007094
David Blaikie82e95a32014-11-19 07:49:47 +00007095 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007096 if (ReturnType.isNull()) {
7097 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7098 Builder.AddTextChunk("void");
7099 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7100 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007101
Douglas Gregor669a25a2011-02-17 00:22:45 +00007102 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7103 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7104 Builder.AddPlaceholderChunk("object-type");
7105 Builder.AddTextChunk(" **");
7106 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7107 Builder.AddTextChunk("buffer");
7108 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7109 Builder.AddTypedTextChunk("range:");
7110 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7111 Builder.AddTextChunk("NSRange");
7112 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7113 Builder.AddTextChunk("inRange");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007114 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007115 CXCursor_ObjCInstanceMethodDecl));
7116 }
7117 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007118
Douglas Gregor669a25a2011-02-17 00:22:45 +00007119 // Mutable indexed accessors
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007120
Douglas Gregor669a25a2011-02-17 00:22:45 +00007121 // - (void)insertObject:(type *)object inKeyAtIndex:(NSUInteger)index
7122 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007123 std::string SelectorName = (Twine("in") + UpperKey + "AtIndex").str();
Douglas Gregor669a25a2011-02-17 00:22:45 +00007124 IdentifierInfo *SelectorIds[2] = {
7125 &Context.Idents.get("insertObject"),
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007126 &Context.Idents.get(SelectorName)
Douglas Gregor669a25a2011-02-17 00:22:45 +00007127 };
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007128
David Blaikie82e95a32014-11-19 07:49:47 +00007129 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007130 if (ReturnType.isNull()) {
7131 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7132 Builder.AddTextChunk("void");
7133 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7134 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007135
Douglas Gregor669a25a2011-02-17 00:22:45 +00007136 Builder.AddTypedTextChunk("insertObject:");
7137 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7138 Builder.AddPlaceholderChunk("object-type");
7139 Builder.AddTextChunk(" *");
7140 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7141 Builder.AddTextChunk("object");
7142 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7143 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7144 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7145 Builder.AddPlaceholderChunk("NSUInteger");
7146 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7147 Builder.AddTextChunk("index");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007148 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007149 CXCursor_ObjCInstanceMethodDecl));
7150 }
7151 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007152
Douglas Gregor669a25a2011-02-17 00:22:45 +00007153 // - (void)insertKey:(NSArray *)array atIndexes:(NSIndexSet *)indexes
7154 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007155 std::string SelectorName = (Twine("insert") + UpperKey).str();
Douglas Gregor669a25a2011-02-17 00:22:45 +00007156 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007157 &Context.Idents.get(SelectorName),
Douglas Gregor669a25a2011-02-17 00:22:45 +00007158 &Context.Idents.get("atIndexes")
7159 };
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007160
David Blaikie82e95a32014-11-19 07:49:47 +00007161 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007162 if (ReturnType.isNull()) {
7163 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7164 Builder.AddTextChunk("void");
7165 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7166 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007167
Douglas Gregor669a25a2011-02-17 00:22:45 +00007168 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7169 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7170 Builder.AddTextChunk("NSArray *");
7171 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7172 Builder.AddTextChunk("array");
7173 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7174 Builder.AddTypedTextChunk("atIndexes:");
7175 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7176 Builder.AddPlaceholderChunk("NSIndexSet *");
7177 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7178 Builder.AddTextChunk("indexes");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007179 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007180 CXCursor_ObjCInstanceMethodDecl));
7181 }
7182 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007183
Douglas Gregor669a25a2011-02-17 00:22:45 +00007184 // -(void)removeObjectFromKeyAtIndex:(NSUInteger)index
7185 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007186 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007187 = (Twine("removeObjectFrom") + UpperKey + "AtIndex").str();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007188 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007189 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007190 if (ReturnType.isNull()) {
7191 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7192 Builder.AddTextChunk("void");
7193 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7194 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007195
Douglas Gregor669a25a2011-02-17 00:22:45 +00007196 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7197 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7198 Builder.AddTextChunk("NSUInteger");
7199 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7200 Builder.AddTextChunk("index");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007201 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007202 CXCursor_ObjCInstanceMethodDecl));
7203 }
7204 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007205
Douglas Gregor669a25a2011-02-17 00:22:45 +00007206 // -(void)removeKeyAtIndexes:(NSIndexSet *)indexes
7207 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007208 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007209 = (Twine("remove") + UpperKey + "AtIndexes").str();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007210 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007211 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007212 if (ReturnType.isNull()) {
7213 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7214 Builder.AddTextChunk("void");
7215 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7216 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007217
Douglas Gregor669a25a2011-02-17 00:22:45 +00007218 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7219 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7220 Builder.AddTextChunk("NSIndexSet *");
7221 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7222 Builder.AddTextChunk("indexes");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007223 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007224 CXCursor_ObjCInstanceMethodDecl));
7225 }
7226 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007227
Douglas Gregor669a25a2011-02-17 00:22:45 +00007228 // - (void)replaceObjectInKeyAtIndex:(NSUInteger)index withObject:(id)object
7229 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007230 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007231 = (Twine("replaceObjectIn") + UpperKey + "AtIndex").str();
Douglas Gregor669a25a2011-02-17 00:22:45 +00007232 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007233 &Context.Idents.get(SelectorName),
Douglas Gregor669a25a2011-02-17 00:22:45 +00007234 &Context.Idents.get("withObject")
7235 };
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007236
David Blaikie82e95a32014-11-19 07:49:47 +00007237 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007238 if (ReturnType.isNull()) {
7239 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7240 Builder.AddTextChunk("void");
7241 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7242 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007243
Douglas Gregor669a25a2011-02-17 00:22:45 +00007244 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7245 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7246 Builder.AddPlaceholderChunk("NSUInteger");
7247 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7248 Builder.AddTextChunk("index");
7249 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7250 Builder.AddTypedTextChunk("withObject:");
7251 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7252 Builder.AddTextChunk("id");
7253 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7254 Builder.AddTextChunk("object");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007255 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007256 CXCursor_ObjCInstanceMethodDecl));
7257 }
7258 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007259
Douglas Gregor669a25a2011-02-17 00:22:45 +00007260 // - (void)replaceKeyAtIndexes:(NSIndexSet *)indexes withKey:(NSArray *)array
7261 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007262 std::string SelectorName1
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007263 = (Twine("replace") + UpperKey + "AtIndexes").str();
7264 std::string SelectorName2 = (Twine("with") + UpperKey).str();
Douglas Gregor669a25a2011-02-17 00:22:45 +00007265 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007266 &Context.Idents.get(SelectorName1),
7267 &Context.Idents.get(SelectorName2)
Douglas Gregor669a25a2011-02-17 00:22:45 +00007268 };
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007269
David Blaikie82e95a32014-11-19 07:49:47 +00007270 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007271 if (ReturnType.isNull()) {
7272 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7273 Builder.AddTextChunk("void");
7274 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7275 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007276
Douglas Gregor669a25a2011-02-17 00:22:45 +00007277 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName1 + ":"));
7278 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7279 Builder.AddPlaceholderChunk("NSIndexSet *");
7280 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7281 Builder.AddTextChunk("indexes");
7282 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7283 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName2 + ":"));
7284 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7285 Builder.AddTextChunk("NSArray *");
7286 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7287 Builder.AddTextChunk("array");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007288 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007289 CXCursor_ObjCInstanceMethodDecl));
7290 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007291 }
7292
Douglas Gregor669a25a2011-02-17 00:22:45 +00007293 // Unordered getters
7294 // - (NSEnumerator *)enumeratorOfKey
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007295 if (IsInstanceMethod &&
7296 (ReturnType.isNull() ||
Douglas Gregor669a25a2011-02-17 00:22:45 +00007297 (ReturnType->isObjCObjectPointerType() &&
7298 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
7299 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
7300 ->getName() == "NSEnumerator"))) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007301 std::string SelectorName = (Twine("enumeratorOf") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007302 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007303 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
7304 .second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007305 if (ReturnType.isNull()) {
7306 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7307 Builder.AddTextChunk("NSEnumerator *");
7308 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7309 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007310
Douglas Gregor669a25a2011-02-17 00:22:45 +00007311 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007312 Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007313 CXCursor_ObjCInstanceMethodDecl));
7314 }
7315 }
7316
7317 // - (type *)memberOfKey:(type *)object
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007318 if (IsInstanceMethod &&
Douglas Gregor669a25a2011-02-17 00:22:45 +00007319 (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007320 std::string SelectorName = (Twine("memberOf") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19: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.AddPlaceholderChunk("object-type");
7326 Builder.AddTextChunk(" *");
7327 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7328 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007329
Douglas Gregor669a25a2011-02-17 00:22:45 +00007330 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7331 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7332 if (ReturnType.isNull()) {
7333 Builder.AddPlaceholderChunk("object-type");
7334 Builder.AddTextChunk(" *");
7335 } else {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007336 Builder.AddTextChunk(GetCompletionTypeString(ReturnType, Context,
Douglas Gregor75acd922011-09-27 23:30:47 +00007337 Policy,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007338 Builder.getAllocator()));
7339 }
7340 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7341 Builder.AddTextChunk("object");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007342 Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007343 CXCursor_ObjCInstanceMethodDecl));
7344 }
7345 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007346
Douglas Gregor669a25a2011-02-17 00:22:45 +00007347 // Mutable unordered accessors
7348 // - (void)addKeyObject:(type *)object
7349 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007350 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007351 = (Twine("add") + UpperKey + Twine("Object")).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007352 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007353 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007354 if (ReturnType.isNull()) {
7355 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7356 Builder.AddTextChunk("void");
7357 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7358 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007359
Douglas Gregor669a25a2011-02-17 00:22:45 +00007360 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7361 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7362 Builder.AddPlaceholderChunk("object-type");
7363 Builder.AddTextChunk(" *");
7364 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7365 Builder.AddTextChunk("object");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007366 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007367 CXCursor_ObjCInstanceMethodDecl));
7368 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007369 }
Douglas Gregor669a25a2011-02-17 00:22:45 +00007370
7371 // - (void)addKey:(NSSet *)objects
7372 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007373 std::string SelectorName = (Twine("add") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007374 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007375 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007376 if (ReturnType.isNull()) {
7377 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7378 Builder.AddTextChunk("void");
7379 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7380 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007381
Douglas Gregor669a25a2011-02-17 00:22:45 +00007382 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7383 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7384 Builder.AddTextChunk("NSSet *");
7385 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7386 Builder.AddTextChunk("objects");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007387 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007388 CXCursor_ObjCInstanceMethodDecl));
7389 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007390 }
7391
Douglas Gregor669a25a2011-02-17 00:22:45 +00007392 // - (void)removeKeyObject:(type *)object
7393 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007394 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007395 = (Twine("remove") + UpperKey + Twine("Object")).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007396 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007397 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007398 if (ReturnType.isNull()) {
7399 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7400 Builder.AddTextChunk("void");
7401 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7402 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007403
Douglas Gregor669a25a2011-02-17 00:22:45 +00007404 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7405 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7406 Builder.AddPlaceholderChunk("object-type");
7407 Builder.AddTextChunk(" *");
7408 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7409 Builder.AddTextChunk("object");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007410 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007411 CXCursor_ObjCInstanceMethodDecl));
7412 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007413 }
7414
Douglas Gregor669a25a2011-02-17 00:22:45 +00007415 // - (void)removeKey:(NSSet *)objects
7416 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007417 std::string SelectorName = (Twine("remove") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007418 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007419 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007420 if (ReturnType.isNull()) {
7421 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7422 Builder.AddTextChunk("void");
7423 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7424 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007425
Douglas Gregor669a25a2011-02-17 00:22:45 +00007426 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7427 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7428 Builder.AddTextChunk("NSSet *");
7429 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7430 Builder.AddTextChunk("objects");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007431 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007432 CXCursor_ObjCInstanceMethodDecl));
7433 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007434 }
Douglas Gregor669a25a2011-02-17 00:22:45 +00007435
7436 // - (void)intersectKey:(NSSet *)objects
7437 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007438 std::string SelectorName = (Twine("intersect") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007439 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007440 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007441 if (ReturnType.isNull()) {
7442 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7443 Builder.AddTextChunk("void");
7444 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7445 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007446
Douglas Gregor669a25a2011-02-17 00:22:45 +00007447 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7448 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7449 Builder.AddTextChunk("NSSet *");
7450 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7451 Builder.AddTextChunk("objects");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007452 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007453 CXCursor_ObjCInstanceMethodDecl));
7454 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007455 }
7456
Douglas Gregor669a25a2011-02-17 00:22:45 +00007457 // Key-Value Observing
7458 // + (NSSet *)keyPathsForValuesAffectingKey
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007459 if (!IsInstanceMethod &&
7460 (ReturnType.isNull() ||
Douglas Gregor669a25a2011-02-17 00:22:45 +00007461 (ReturnType->isObjCObjectPointerType() &&
7462 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
7463 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
7464 ->getName() == "NSSet"))) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007465 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007466 = (Twine("keyPathsForValuesAffecting") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007467 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007468 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
7469 .second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007470 if (ReturnType.isNull()) {
7471 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Alex Lorenz71ecb072016-12-08 16:49:05 +00007472 Builder.AddTextChunk("NSSet<NSString *> *");
Douglas Gregor669a25a2011-02-17 00:22:45 +00007473 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7474 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007475
Douglas Gregor669a25a2011-02-17 00:22:45 +00007476 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007477 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Douglas Gregor857bcda2011-06-02 04:02:27 +00007478 CXCursor_ObjCClassMethodDecl));
7479 }
7480 }
7481
7482 // + (BOOL)automaticallyNotifiesObserversForKey
7483 if (!IsInstanceMethod &&
7484 (ReturnType.isNull() ||
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007485 ReturnType->isIntegerType() ||
Douglas Gregor857bcda2011-06-02 04:02:27 +00007486 ReturnType->isBooleanType())) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007487 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007488 = (Twine("automaticallyNotifiesObserversOf") + UpperKey).str();
Douglas Gregor857bcda2011-06-02 04:02:27 +00007489 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007490 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
7491 .second) {
Douglas Gregor857bcda2011-06-02 04:02:27 +00007492 if (ReturnType.isNull()) {
7493 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7494 Builder.AddTextChunk("BOOL");
7495 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7496 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007497
Douglas Gregor857bcda2011-06-02 04:02:27 +00007498 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007499 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Douglas Gregor857bcda2011-06-02 04:02:27 +00007500 CXCursor_ObjCClassMethodDecl));
Douglas Gregor669a25a2011-02-17 00:22:45 +00007501 }
7502 }
7503}
7504
Alex Lorenzb8740422017-10-24 16:39:37 +00007505void Sema::CodeCompleteObjCMethodDecl(Scope *S, Optional<bool> IsInstanceMethod,
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00007506 ParsedType ReturnTy) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00007507 // Determine the return type of the method we're declaring, if
7508 // provided.
7509 QualType ReturnType = GetTypeFromParser(ReturnTy);
Craig Topperc3ec1492014-05-26 06:22:03 +00007510 Decl *IDecl = nullptr;
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00007511 if (CurContext->isObjCContainer()) {
7512 ObjCContainerDecl *OCD = dyn_cast<ObjCContainerDecl>(CurContext);
George Burgess IV00f70bd2018-03-01 05:43:23 +00007513 IDecl = OCD;
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00007514 }
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007515 // Determine where we should start searching for methods.
Craig Topperc3ec1492014-05-26 06:22:03 +00007516 ObjCContainerDecl *SearchDecl = nullptr;
Douglas Gregor636a61e2010-04-07 00:21:17 +00007517 bool IsInImplementation = false;
John McCall48871652010-08-21 09:40:31 +00007518 if (Decl *D = IDecl) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00007519 if (ObjCImplementationDecl *Impl = dyn_cast<ObjCImplementationDecl>(D)) {
7520 SearchDecl = Impl->getClassInterface();
Douglas Gregor636a61e2010-04-07 00:21:17 +00007521 IsInImplementation = true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007522 } else if (ObjCCategoryImplDecl *CatImpl
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007523 = dyn_cast<ObjCCategoryImplDecl>(D)) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00007524 SearchDecl = CatImpl->getCategoryDecl();
Douglas Gregor636a61e2010-04-07 00:21:17 +00007525 IsInImplementation = true;
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007526 } else
Douglas Gregor636a61e2010-04-07 00:21:17 +00007527 SearchDecl = dyn_cast<ObjCContainerDecl>(D);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007528 }
7529
7530 if (!SearchDecl && S) {
Ted Kremenekc37877d2013-10-08 17:08:03 +00007531 if (DeclContext *DC = S->getEntity())
Douglas Gregor636a61e2010-04-07 00:21:17 +00007532 SearchDecl = dyn_cast<ObjCContainerDecl>(DC);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007533 }
7534
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007535 if (!SearchDecl) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007536 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00007537 CodeCompletionContext::CCC_Other,
Craig Topperc3ec1492014-05-26 06:22:03 +00007538 nullptr, 0);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007539 return;
7540 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007541
Douglas Gregor636a61e2010-04-07 00:21:17 +00007542 // Find all of the methods that we could declare/implement here.
7543 KnownMethodsMap KnownMethods;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007544 FindImplementableMethods(Context, SearchDecl, IsInstanceMethod,
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007545 ReturnType, KnownMethods);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007546
Douglas Gregor636a61e2010-04-07 00:21:17 +00007547 // Add declarations or definitions for each of the known methods.
John McCall276321a2010-08-25 06:19:51 +00007548 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007549 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007550 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007551 CodeCompletionContext::CCC_Other);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007552 Results.EnterNewScope();
Douglas Gregor75acd922011-09-27 23:30:47 +00007553 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007554 for (KnownMethodsMap::iterator M = KnownMethods.begin(),
Douglas Gregor636a61e2010-04-07 00:21:17 +00007555 MEnd = KnownMethods.end();
7556 M != MEnd; ++M) {
Benjamin Kramereb8c4462013-06-29 17:52:13 +00007557 ObjCMethodDecl *Method = M->second.getPointer();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007558 CodeCompletionBuilder Builder(Results.getAllocator(),
7559 Results.getCodeCompletionTUInfo());
Alex Lorenzb8740422017-10-24 16:39:37 +00007560
7561 // Add the '-'/'+' prefix if it wasn't provided yet.
7562 if (!IsInstanceMethod) {
7563 Builder.AddTextChunk(Method->isInstanceMethod() ? "-" : "+");
7564 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7565 }
7566
Douglas Gregor636a61e2010-04-07 00:21:17 +00007567 // If the result type was not already provided, add it to the
7568 // pattern as (type).
Argyrios Kyrtzidisf0917ab2015-07-24 17:00:19 +00007569 if (ReturnType.isNull()) {
7570 QualType ResTy = Method->getSendResultType().stripObjCKindOfType(Context);
7571 AttributedType::stripOuterNullability(ResTy);
7572 AddObjCPassingTypeChunk(ResTy,
Alp Toker314cc812014-01-25 16:55:45 +00007573 Method->getObjCDeclQualifier(), Context, Policy,
7574 Builder);
Argyrios Kyrtzidisf0917ab2015-07-24 17:00:19 +00007575 }
Douglas Gregor636a61e2010-04-07 00:21:17 +00007576
7577 Selector Sel = Method->getSelector();
7578
7579 // Add the first part of the selector to the pattern.
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00007580 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00007581 Sel.getNameForSlot(0)));
Douglas Gregor636a61e2010-04-07 00:21:17 +00007582
7583 // Add parameters to the pattern.
7584 unsigned I = 0;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007585 for (ObjCMethodDecl::param_iterator P = Method->param_begin(),
Douglas Gregor636a61e2010-04-07 00:21:17 +00007586 PEnd = Method->param_end();
7587 P != PEnd; (void)++P, ++I) {
7588 // Add the part of the selector name.
7589 if (I == 0)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007590 Builder.AddTypedTextChunk(":");
Douglas Gregor636a61e2010-04-07 00:21:17 +00007591 else if (I < Sel.getNumArgs()) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007592 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7593 Builder.AddTypedTextChunk(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00007594 Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":"));
Douglas Gregor636a61e2010-04-07 00:21:17 +00007595 } else
7596 break;
7597
7598 // Add the parameter type.
Douglas Gregor86b42682015-06-19 18:27:52 +00007599 QualType ParamType;
7600 if ((*P)->getObjCDeclQualifier() & Decl::OBJC_TQ_CSNullability)
7601 ParamType = (*P)->getType();
7602 else
7603 ParamType = (*P)->getOriginalType();
Douglas Gregor9b7b3e92015-07-07 06:20:27 +00007604 ParamType = ParamType.substObjCTypeArgs(Context, {},
7605 ObjCSubstitutionContext::Parameter);
Argyrios Kyrtzidisf0917ab2015-07-24 17:00:19 +00007606 AttributedType::stripOuterNullability(ParamType);
Douglas Gregor86b42682015-06-19 18:27:52 +00007607 AddObjCPassingTypeChunk(ParamType,
Douglas Gregor29979142012-04-10 18:35:07 +00007608 (*P)->getObjCDeclQualifier(),
7609 Context, Policy,
Douglas Gregor75acd922011-09-27 23:30:47 +00007610 Builder);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007611
Douglas Gregor636a61e2010-04-07 00:21:17 +00007612 if (IdentifierInfo *Id = (*P)->getIdentifier())
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007613 Builder.AddTextChunk(Builder.getAllocator().CopyString( Id->getName()));
Douglas Gregor636a61e2010-04-07 00:21:17 +00007614 }
7615
7616 if (Method->isVariadic()) {
7617 if (Method->param_size() > 0)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007618 Builder.AddChunk(CodeCompletionString::CK_Comma);
7619 Builder.AddTextChunk("...");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007620 }
Douglas Gregor636a61e2010-04-07 00:21:17 +00007621
Douglas Gregord37c59d2010-05-28 00:57:46 +00007622 if (IsInImplementation && Results.includeCodePatterns()) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00007623 // We will be defining the method here, so add a compound statement.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007624 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7625 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
7626 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
Alp Toker314cc812014-01-25 16:55:45 +00007627 if (!Method->getReturnType()->isVoidType()) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00007628 // If the result type is not void, add a return clause.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007629 Builder.AddTextChunk("return");
7630 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7631 Builder.AddPlaceholderChunk("expression");
7632 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007633 } else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007634 Builder.AddPlaceholderChunk("statements");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007635
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007636 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
7637 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007638 }
7639
Douglas Gregor416b5752010-08-25 01:08:01 +00007640 unsigned Priority = CCP_CodePattern;
Benjamin Kramereb8c4462013-06-29 17:52:13 +00007641 if (!M->second.getInt())
Douglas Gregor416b5752010-08-25 01:08:01 +00007642 Priority += CCD_InBaseClass;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007643
Douglas Gregor78254c82012-03-27 23:34:16 +00007644 Results.AddResult(Result(Builder.TakeString(), Method, Priority));
Douglas Gregor636a61e2010-04-07 00:21:17 +00007645 }
7646
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007647 // Add Key-Value-Coding and Key-Value-Observing accessor methods for all of
Douglas Gregor669a25a2011-02-17 00:22:45 +00007648 // the properties in this class and its categories.
David Blaikiebbafb8a2012-03-11 07:00:24 +00007649 if (Context.getLangOpts().ObjC2) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007650 SmallVector<ObjCContainerDecl *, 4> Containers;
Douglas Gregor669a25a2011-02-17 00:22:45 +00007651 Containers.push_back(SearchDecl);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007652
Douglas Gregord4a8ced2011-05-04 23:50:46 +00007653 VisitedSelectorSet KnownSelectors;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007654 for (KnownMethodsMap::iterator M = KnownMethods.begin(),
Douglas Gregord4a8ced2011-05-04 23:50:46 +00007655 MEnd = KnownMethods.end();
7656 M != MEnd; ++M)
7657 KnownSelectors.insert(M->first);
7658
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007659
Douglas Gregor669a25a2011-02-17 00:22:45 +00007660 ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(SearchDecl);
7661 if (!IFace)
7662 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(SearchDecl))
7663 IFace = Category->getClassInterface();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007664
Aaron Ballman3fe486a2014-03-13 21:23:55 +00007665 if (IFace)
7666 for (auto *Cat : IFace->visible_categories())
7667 Containers.push_back(Cat);
Alex Lorenzb8740422017-10-24 16:39:37 +00007668
7669 if (IsInstanceMethod) {
7670 for (unsigned I = 0, N = Containers.size(); I != N; ++I)
7671 for (auto *P : Containers[I]->instance_properties())
7672 AddObjCKeyValueCompletions(P, *IsInstanceMethod, ReturnType, Context,
7673 KnownSelectors, Results);
7674 }
Douglas Gregor669a25a2011-02-17 00:22:45 +00007675 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007676
Douglas Gregor636a61e2010-04-07 00:21:17 +00007677 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00007678
7679 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
7680 Results.data(), Results.size());
Douglas Gregor636a61e2010-04-07 00:21:17 +00007681}
Douglas Gregor95887f92010-07-08 23:20:03 +00007682
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007683void Sema::CodeCompleteObjCMethodDeclSelector(Scope *S,
Douglas Gregor95887f92010-07-08 23:20:03 +00007684 bool IsInstanceMethod,
Douglas Gregor45879692010-07-08 23:37:41 +00007685 bool AtParameterName,
John McCallba7bf592010-08-24 05:47:05 +00007686 ParsedType ReturnTy,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00007687 ArrayRef<IdentifierInfo *> SelIdents) {
Douglas Gregor95887f92010-07-08 23:20:03 +00007688 // If we have an external source, load the entire class method
Sebastian Redld44cd6a2010-08-18 23:57:06 +00007689 // pool from the AST file.
Douglas Gregor95887f92010-07-08 23:20:03 +00007690 if (ExternalSource) {
7691 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
7692 I != N; ++I) {
7693 Selector Sel = ExternalSource->GetExternalSelector(I);
Sebastian Redl75d8a322010-08-02 23:18:59 +00007694 if (Sel.isNull() || MethodPool.count(Sel))
Douglas Gregor95887f92010-07-08 23:20:03 +00007695 continue;
Sebastian Redl75d8a322010-08-02 23:18:59 +00007696
7697 ReadMethodPool(Sel);
Douglas Gregor95887f92010-07-08 23:20:03 +00007698 }
7699 }
7700
7701 // Build the set of methods we can see.
John McCall276321a2010-08-25 06:19:51 +00007702 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007703 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007704 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007705 CodeCompletionContext::CCC_Other);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007706
Douglas Gregor95887f92010-07-08 23:20:03 +00007707 if (ReturnTy)
7708 Results.setPreferredType(GetTypeFromParser(ReturnTy).getNonReferenceType());
Sebastian Redl75d8a322010-08-02 23:18:59 +00007709
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007710 Results.EnterNewScope();
Sebastian Redl75d8a322010-08-02 23:18:59 +00007711 for (GlobalMethodPool::iterator M = MethodPool.begin(),
7712 MEnd = MethodPool.end();
7713 M != MEnd; ++M) {
7714 for (ObjCMethodList *MethList = IsInstanceMethod ? &M->second.first :
7715 &M->second.second;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007716 MethList && MethList->getMethod();
Argyrios Kyrtzidisd3da6e02013-04-17 00:08:58 +00007717 MethList = MethList->getNext()) {
Nico Weber2e0c8f72014-12-27 03:58:08 +00007718 if (!isAcceptableObjCMethod(MethList->getMethod(), MK_Any, SelIdents))
Douglas Gregor95887f92010-07-08 23:20:03 +00007719 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007720
Douglas Gregor45879692010-07-08 23:37:41 +00007721 if (AtParameterName) {
7722 // Suggest parameter names we've seen before.
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00007723 unsigned NumSelIdents = SelIdents.size();
Nico Weber2e0c8f72014-12-27 03:58:08 +00007724 if (NumSelIdents &&
7725 NumSelIdents <= MethList->getMethod()->param_size()) {
7726 ParmVarDecl *Param =
7727 MethList->getMethod()->parameters()[NumSelIdents - 1];
Douglas Gregor45879692010-07-08 23:37:41 +00007728 if (Param->getIdentifier()) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007729 CodeCompletionBuilder Builder(Results.getAllocator(),
7730 Results.getCodeCompletionTUInfo());
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00007731 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007732 Param->getIdentifier()->getName()));
7733 Results.AddResult(Builder.TakeString());
Douglas Gregor45879692010-07-08 23:37:41 +00007734 }
7735 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007736
Douglas Gregor45879692010-07-08 23:37:41 +00007737 continue;
7738 }
Craig Topperc3ec1492014-05-26 06:22:03 +00007739
Nico Weber2e0c8f72014-12-27 03:58:08 +00007740 Result R(MethList->getMethod(),
7741 Results.getBasePriority(MethList->getMethod()), nullptr);
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00007742 R.StartParameter = SelIdents.size();
Douglas Gregor95887f92010-07-08 23:20:03 +00007743 R.AllParametersAreInformative = false;
7744 R.DeclaringEntity = true;
7745 Results.MaybeAddResult(R, CurContext);
7746 }
7747 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007748
Douglas Gregor95887f92010-07-08 23:20:03 +00007749 Results.ExitScope();
Alex Lorenz847fda12017-01-03 11:56:40 +00007750
7751 if (!AtParameterName && !SelIdents.empty() &&
7752 SelIdents.front()->getName().startswith("init")) {
7753 for (const auto &M : PP.macros()) {
7754 if (M.first->getName() != "NS_DESIGNATED_INITIALIZER")
7755 continue;
7756 Results.EnterNewScope();
7757 CodeCompletionBuilder Builder(Results.getAllocator(),
7758 Results.getCodeCompletionTUInfo());
7759 Builder.AddTypedTextChunk(
7760 Builder.getAllocator().CopyString(M.first->getName()));
7761 Results.AddResult(CodeCompletionResult(Builder.TakeString(), CCP_Macro,
7762 CXCursor_MacroDefinition));
7763 Results.ExitScope();
7764 }
7765 }
7766
Eric Liuf5ba09f2018-07-04 10:01:18 +00007767 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
7768 Results.data(), Results.size());
Douglas Gregor95887f92010-07-08 23:20:03 +00007769}
Douglas Gregorb14904c2010-08-13 22:48:40 +00007770
Douglas Gregorec00a262010-08-24 22:20:20 +00007771void Sema::CodeCompletePreprocessorDirective(bool InConditional) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007772 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007773 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00007774 CodeCompletionContext::CCC_PreprocessorDirective);
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007775 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007776
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007777 // #if <condition>
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007778 CodeCompletionBuilder Builder(Results.getAllocator(),
7779 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007780 Builder.AddTypedTextChunk("if");
7781 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7782 Builder.AddPlaceholderChunk("condition");
7783 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007784
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007785 // #ifdef <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007786 Builder.AddTypedTextChunk("ifdef");
7787 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7788 Builder.AddPlaceholderChunk("macro");
7789 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007790
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007791 // #ifndef <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007792 Builder.AddTypedTextChunk("ifndef");
7793 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7794 Builder.AddPlaceholderChunk("macro");
7795 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007796
7797 if (InConditional) {
7798 // #elif <condition>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007799 Builder.AddTypedTextChunk("elif");
7800 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7801 Builder.AddPlaceholderChunk("condition");
7802 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007803
7804 // #else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007805 Builder.AddTypedTextChunk("else");
7806 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007807
7808 // #endif
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007809 Builder.AddTypedTextChunk("endif");
7810 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007811 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007812
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007813 // #include "header"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007814 Builder.AddTypedTextChunk("include");
7815 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7816 Builder.AddTextChunk("\"");
7817 Builder.AddPlaceholderChunk("header");
7818 Builder.AddTextChunk("\"");
7819 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007820
7821 // #include <header>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007822 Builder.AddTypedTextChunk("include");
7823 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7824 Builder.AddTextChunk("<");
7825 Builder.AddPlaceholderChunk("header");
7826 Builder.AddTextChunk(">");
7827 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007828
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007829 // #define <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007830 Builder.AddTypedTextChunk("define");
7831 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7832 Builder.AddPlaceholderChunk("macro");
7833 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007834
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007835 // #define <macro>(<args>)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007836 Builder.AddTypedTextChunk("define");
7837 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7838 Builder.AddPlaceholderChunk("macro");
7839 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7840 Builder.AddPlaceholderChunk("args");
7841 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7842 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007843
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007844 // #undef <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007845 Builder.AddTypedTextChunk("undef");
7846 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7847 Builder.AddPlaceholderChunk("macro");
7848 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007849
7850 // #line <number>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007851 Builder.AddTypedTextChunk("line");
7852 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7853 Builder.AddPlaceholderChunk("number");
7854 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007855
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007856 // #line <number> "filename"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007857 Builder.AddTypedTextChunk("line");
7858 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7859 Builder.AddPlaceholderChunk("number");
7860 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7861 Builder.AddTextChunk("\"");
7862 Builder.AddPlaceholderChunk("filename");
7863 Builder.AddTextChunk("\"");
7864 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007865
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007866 // #error <message>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007867 Builder.AddTypedTextChunk("error");
7868 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7869 Builder.AddPlaceholderChunk("message");
7870 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007871
7872 // #pragma <arguments>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007873 Builder.AddTypedTextChunk("pragma");
7874 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7875 Builder.AddPlaceholderChunk("arguments");
7876 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007877
David Blaikiebbafb8a2012-03-11 07:00:24 +00007878 if (getLangOpts().ObjC1) {
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007879 // #import "header"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007880 Builder.AddTypedTextChunk("import");
7881 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7882 Builder.AddTextChunk("\"");
7883 Builder.AddPlaceholderChunk("header");
7884 Builder.AddTextChunk("\"");
7885 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007886
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007887 // #import <header>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007888 Builder.AddTypedTextChunk("import");
7889 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7890 Builder.AddTextChunk("<");
7891 Builder.AddPlaceholderChunk("header");
7892 Builder.AddTextChunk(">");
7893 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007894 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007895
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007896 // #include_next "header"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007897 Builder.AddTypedTextChunk("include_next");
7898 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7899 Builder.AddTextChunk("\"");
7900 Builder.AddPlaceholderChunk("header");
7901 Builder.AddTextChunk("\"");
7902 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007903
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007904 // #include_next <header>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007905 Builder.AddTypedTextChunk("include_next");
7906 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7907 Builder.AddTextChunk("<");
7908 Builder.AddPlaceholderChunk("header");
7909 Builder.AddTextChunk(">");
7910 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007911
7912 // #warning <message>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007913 Builder.AddTypedTextChunk("warning");
7914 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7915 Builder.AddPlaceholderChunk("message");
7916 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007917
7918 // Note: #ident and #sccs are such crazy anachronisms that we don't provide
7919 // completions for them. And __include_macros is a Clang-internal extension
7920 // that we don't want to encourage anyone to use.
7921
7922 // FIXME: we don't support #assert or #unassert, so don't suggest them.
7923 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00007924
7925 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007926 Results.data(), Results.size());
7927}
7928
7929void Sema::CodeCompleteInPreprocessorConditionalExclusion(Scope *S) {
Douglas Gregorec00a262010-08-24 22:20:20 +00007930 CodeCompleteOrdinaryName(S,
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007931 S->getFnParent()? Sema::PCC_RecoveryInFunction
John McCallfaf5fb42010-08-26 23:41:50 +00007932 : Sema::PCC_Namespace);
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007933}
7934
Douglas Gregorec00a262010-08-24 22:20:20 +00007935void Sema::CodeCompletePreprocessorMacroName(bool IsDefinition) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007936 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007937 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00007938 IsDefinition? CodeCompletionContext::CCC_MacroName
7939 : CodeCompletionContext::CCC_MacroNameUse);
Douglas Gregor12785102010-08-24 20:21:13 +00007940 if (!IsDefinition && (!CodeCompleter || CodeCompleter->includeMacros())) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007941 // Add just the names of macros, not their arguments.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007942 CodeCompletionBuilder Builder(Results.getAllocator(),
7943 Results.getCodeCompletionTUInfo());
Douglas Gregor12785102010-08-24 20:21:13 +00007944 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007945 for (Preprocessor::macro_iterator M = PP.macro_begin(),
Douglas Gregor12785102010-08-24 20:21:13 +00007946 MEnd = PP.macro_end();
7947 M != MEnd; ++M) {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00007948 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007949 M->first->getName()));
Argyrios Kyrtzidis5c8b1cd2012-09-27 00:24:09 +00007950 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
7951 CCP_CodePattern,
7952 CXCursor_MacroDefinition));
Douglas Gregor12785102010-08-24 20:21:13 +00007953 }
7954 Results.ExitScope();
7955 } else if (IsDefinition) {
7956 // FIXME: Can we detect when the user just wrote an include guard above?
7957 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007958
Douglas Gregor0ac41382010-09-23 23:01:17 +00007959 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007960 Results.data(), Results.size());
Douglas Gregor12785102010-08-24 20:21:13 +00007961}
7962
Douglas Gregorec00a262010-08-24 22:20:20 +00007963void Sema::CodeCompletePreprocessorExpression() {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007964 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007965 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00007966 CodeCompletionContext::CCC_PreprocessorExpression);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007967
Douglas Gregorec00a262010-08-24 22:20:20 +00007968 if (!CodeCompleter || CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00007969 AddMacroResults(PP, Results,
7970 CodeCompleter ? CodeCompleter->loadExternal() : false,
7971 true);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007972
Douglas Gregorec00a262010-08-24 22:20:20 +00007973 // defined (<macro>)
7974 Results.EnterNewScope();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007975 CodeCompletionBuilder Builder(Results.getAllocator(),
7976 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007977 Builder.AddTypedTextChunk("defined");
7978 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7979 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7980 Builder.AddPlaceholderChunk("macro");
7981 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7982 Results.AddResult(Builder.TakeString());
Douglas Gregorec00a262010-08-24 22:20:20 +00007983 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00007984
7985 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
7986 Results.data(), Results.size());
Douglas Gregorec00a262010-08-24 22:20:20 +00007987}
7988
7989void Sema::CodeCompletePreprocessorMacroArgument(Scope *S,
7990 IdentifierInfo *Macro,
7991 MacroInfo *MacroInfo,
7992 unsigned Argument) {
7993 // FIXME: In the future, we could provide "overload" results, much like we
7994 // do for function calls.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007995
Argyrios Kyrtzidis75f6cd22011-08-18 19:41:28 +00007996 // Now just ignore this. There will be another code-completion callback
7997 // for the expanded tokens.
Douglas Gregorec00a262010-08-24 22:20:20 +00007998}
7999
Sam McCall3d8051a2018-09-18 08:40:41 +00008000// This handles completion inside an #include filename, e.g. #include <foo/ba
8001// We look for the directory "foo" under each directory on the include path,
8002// list its files, and reassemble the appropriate #include.
8003void Sema::CodeCompleteIncludedFile(llvm::StringRef Dir, bool Angled) {
8004 // RelDir should use /, but unescaped \ is possible on windows!
8005 // Our completions will normalize to / for simplicity, this case is rare.
8006 std::string RelDir = llvm::sys::path::convert_to_slash(Dir);
8007 // We need the native slashes for the actual file system interactions.
8008 SmallString<128> NativeRelDir = StringRef(RelDir);
8009 llvm::sys::path::native(NativeRelDir);
8010 auto FS = getSourceManager().getFileManager().getVirtualFileSystem();
8011
8012 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
8013 CodeCompleter->getCodeCompletionTUInfo(),
8014 CodeCompletionContext::CCC_IncludedFile);
8015 llvm::DenseSet<StringRef> SeenResults; // To deduplicate results.
8016
8017 // Helper: adds one file or directory completion result.
8018 auto AddCompletion = [&](StringRef Filename, bool IsDirectory) {
8019 SmallString<64> TypedChunk = Filename;
8020 // Directory completion is up to the slash, e.g. <sys/
8021 TypedChunk.push_back(IsDirectory ? '/' : Angled ? '>' : '"');
8022 auto R = SeenResults.insert(TypedChunk);
8023 if (R.second) { // New completion
8024 const char *InternedTyped = Results.getAllocator().CopyString(TypedChunk);
8025 *R.first = InternedTyped; // Avoid dangling StringRef.
8026 CodeCompletionBuilder Builder(CodeCompleter->getAllocator(),
8027 CodeCompleter->getCodeCompletionTUInfo());
8028 Builder.AddTypedTextChunk(InternedTyped);
8029 // The result is a "Pattern", which is pretty opaque.
8030 // We may want to include the real filename to allow smart ranking.
8031 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
8032 }
8033 };
8034
8035 // Helper: scans IncludeDir for nice files, and adds results for each.
8036 auto AddFilesFromIncludeDir = [&](StringRef IncludeDir, bool IsSystem) {
8037 llvm::SmallString<128> Dir = IncludeDir;
8038 if (!NativeRelDir.empty())
8039 llvm::sys::path::append(Dir, NativeRelDir);
8040
8041 std::error_code EC;
8042 unsigned Count = 0;
8043 for (auto It = FS->dir_begin(Dir, EC);
8044 !EC && It != vfs::directory_iterator(); It.increment(EC)) {
8045 if (++Count == 2500) // If we happen to hit a huge directory,
8046 break; // bail out early so we're not too slow.
8047 StringRef Filename = llvm::sys::path::filename(It->path());
8048 switch (It->type()) {
8049 case llvm::sys::fs::file_type::directory_file:
8050 AddCompletion(Filename, /*IsDirectory=*/true);
8051 break;
8052 case llvm::sys::fs::file_type::regular_file:
8053 // Only files that really look like headers. (Except in system dirs).
8054 if (!IsSystem) {
8055 // Header extensions from Types.def, which we can't depend on here.
8056 if (!(Filename.endswith_lower(".h") ||
8057 Filename.endswith_lower(".hh") ||
8058 Filename.endswith_lower(".hpp") ||
8059 Filename.endswith_lower(".inc")))
8060 break;
8061 }
8062 AddCompletion(Filename, /*IsDirectory=*/false);
8063 break;
8064 default:
8065 break;
8066 }
8067 }
8068 };
8069
8070 // Helper: adds results relative to IncludeDir, if possible.
8071 auto AddFilesFromDirLookup = [&](const DirectoryLookup &IncludeDir,
8072 bool IsSystem) {
8073 llvm::SmallString<128> Dir;
8074 switch (IncludeDir.getLookupType()) {
8075 case DirectoryLookup::LT_HeaderMap:
8076 // header maps are not (currently) enumerable.
8077 break;
8078 case DirectoryLookup::LT_NormalDir:
8079 AddFilesFromIncludeDir(IncludeDir.getDir()->getName(), IsSystem);
8080 break;
8081 case DirectoryLookup::LT_Framework:
8082 AddFilesFromIncludeDir(IncludeDir.getFrameworkDir()->getName(), IsSystem);
8083 break;
8084 }
8085 };
8086
8087 // Finally with all our helpers, we can scan the include path.
8088 // Do this in standard order so deduplication keeps the right file.
8089 // (In case we decide to add more details to the results later).
8090 const auto &S = PP.getHeaderSearchInfo();
8091 using llvm::make_range;
8092 if (!Angled) {
8093 // The current directory is on the include path for "quoted" includes.
8094 auto *CurFile = PP.getCurrentFileLexer()->getFileEntry();
8095 if (CurFile && CurFile->getDir())
8096 AddFilesFromIncludeDir(CurFile->getDir()->getName(), false);
8097 for (const auto &D : make_range(S.quoted_dir_begin(), S.quoted_dir_end()))
8098 AddFilesFromDirLookup(D, false);
8099 }
8100 for (const auto &D : make_range(S.angled_dir_begin(), S.angled_dir_end()))
8101 AddFilesFromDirLookup(D, true);
8102 for (const auto &D : make_range(S.system_dir_begin(), S.system_dir_end()))
8103 AddFilesFromDirLookup(D, true);
8104
8105 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
8106 Results.data(), Results.size());
8107}
8108
Douglas Gregor11583702010-08-25 17:04:25 +00008109void Sema::CodeCompleteNaturalLanguage() {
Douglas Gregor11583702010-08-25 17:04:25 +00008110 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregorea736372010-08-25 17:10:00 +00008111 CodeCompletionContext::CCC_NaturalLanguage,
Craig Topperc3ec1492014-05-26 06:22:03 +00008112 nullptr, 0);
Douglas Gregor11583702010-08-25 17:04:25 +00008113}
8114
Alex Lorenzf7f6f822017-05-09 16:05:04 +00008115void Sema::CodeCompleteAvailabilityPlatformName() {
8116 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
8117 CodeCompleter->getCodeCompletionTUInfo(),
8118 CodeCompletionContext::CCC_Other);
8119 Results.EnterNewScope();
8120 static const char *Platforms[] = {"macOS", "iOS", "watchOS", "tvOS"};
8121 for (const char *Platform : llvm::makeArrayRef(Platforms)) {
8122 Results.AddResult(CodeCompletionResult(Platform));
8123 Results.AddResult(CodeCompletionResult(Results.getAllocator().CopyString(
8124 Twine(Platform) + "ApplicationExtension")));
8125 }
8126 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00008127 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
8128 Results.data(), Results.size());
Alex Lorenzf7f6f822017-05-09 16:05:04 +00008129}
8130
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00008131void Sema::GatherGlobalCodeCompletions(CodeCompletionAllocator &Allocator,
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008132 CodeCompletionTUInfo &CCTUInfo,
Chris Lattner0e62c1c2011-07-23 10:55:15 +00008133 SmallVectorImpl<CodeCompletionResult> &Results) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008134 ResultBuilder Builder(*this, Allocator, CCTUInfo,
8135 CodeCompletionContext::CCC_Recovery);
Douglas Gregor39982192010-08-15 06:18:01 +00008136 if (!CodeCompleter || CodeCompleter->includeGlobals()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008137 CodeCompletionDeclConsumer Consumer(Builder,
Douglas Gregor39982192010-08-15 06:18:01 +00008138 Context.getTranslationUnitDecl());
Sam McCallbb2cf632018-01-12 14:51:47 +00008139 LookupVisibleDecls(Context.getTranslationUnitDecl(), LookupAnyName,
8140 Consumer,
8141 !CodeCompleter || CodeCompleter->loadExternal());
Douglas Gregor39982192010-08-15 06:18:01 +00008142 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008143
Douglas Gregorb14904c2010-08-13 22:48:40 +00008144 if (!CodeCompleter || CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00008145 AddMacroResults(PP, Builder,
8146 CodeCompleter ? CodeCompleter->loadExternal() : false,
8147 true);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008148
Douglas Gregorb14904c2010-08-13 22:48:40 +00008149 Results.clear();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008150 Results.insert(Results.end(),
Douglas Gregorb14904c2010-08-13 22:48:40 +00008151 Builder.data(), Builder.data() + Builder.size());
8152}