blob: 11544fb64e9e21a66baf13bb0116c43c353f7394 [file] [log] [blame]
Douglas Gregor2436e712009-09-17 21:32:03 +00001//===---------------- SemaCodeComplete.cpp - Code Completion ----*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file defines the code-completion semantic actions.
11//
12//===----------------------------------------------------------------------===//
Eric Liub91e0812018-10-02 10:29:00 +000013#include "clang/AST/Decl.h"
Ilya Biryukov4e7a6fe2017-09-22 19:07:37 +000014#include "clang/AST/DeclCXX.h"
John McCallde6836a2010-08-24 07:21:54 +000015#include "clang/AST/DeclObjC.h"
Douglas Gregorf2510672009-09-21 19:57:38 +000016#include "clang/AST/ExprCXX.h"
Douglas Gregor8ce33212009-11-17 17:59:40 +000017#include "clang/AST/ExprObjC.h"
Ilya Biryukovb5da91c2017-11-08 10:39:09 +000018#include "clang/AST/QualTypeNames.h"
Jordan Rose4938f272013-02-09 10:09:43 +000019#include "clang/Basic/CharInfo.h"
Douglas Gregor07f43572012-01-29 18:15:03 +000020#include "clang/Lex/HeaderSearch.h"
Douglas Gregorf329c7c2009-10-30 16:50:04 +000021#include "clang/Lex/MacroInfo.h"
22#include "clang/Lex/Preprocessor.h"
Chandler Carruth3a022472012-12-04 09:13:33 +000023#include "clang/Sema/CodeCompleteConsumer.h"
Chandler Carruth3a022472012-12-04 09:13:33 +000024#include "clang/Sema/Lookup.h"
25#include "clang/Sema/Overload.h"
26#include "clang/Sema/Scope.h"
27#include "clang/Sema/ScopeInfo.h"
Ilya Biryukov4e7a6fe2017-09-22 19:07:37 +000028#include "clang/Sema/SemaInternal.h"
Douglas Gregor1154e272010-09-16 16:06:31 +000029#include "llvm/ADT/DenseSet.h"
Benjamin Kramere0513cb2012-01-30 16:17:39 +000030#include "llvm/ADT/SmallBitVector.h"
Douglas Gregor3545ff42009-09-21 16:56:56 +000031#include "llvm/ADT/SmallPtrSet.h"
Benjamin Kramer49038022012-02-04 13:45:25 +000032#include "llvm/ADT/SmallString.h"
Douglas Gregore6688e62009-09-28 03:51:44 +000033#include "llvm/ADT/StringExtras.h"
Douglas Gregor9d2ddb22010-04-06 19:22:33 +000034#include "llvm/ADT/StringSwitch.h"
Douglas Gregor67c692c2010-08-26 15:07:07 +000035#include "llvm/ADT/Twine.h"
Sam McCall3d8051a2018-09-18 08:40:41 +000036#include "llvm/ADT/iterator_range.h"
37#include "llvm/Support/Path.h"
Douglas Gregor3545ff42009-09-21 16:56:56 +000038#include <list>
39#include <map>
40#include <vector>
Douglas Gregor2436e712009-09-17 21:32:03 +000041
42using namespace clang;
John McCallaab3e412010-08-25 08:40:02 +000043using namespace sema;
Douglas Gregor2436e712009-09-17 21:32:03 +000044
Douglas Gregor3545ff42009-09-21 16:56:56 +000045namespace {
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000046 /// A container of code-completion results.
Douglas Gregor3545ff42009-09-21 16:56:56 +000047 class ResultBuilder {
48 public:
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000049 /// The type of a name-lookup filter, which can be provided to the
Douglas Gregor3545ff42009-09-21 16:56:56 +000050 /// name-lookup routines to specify which declarations should be included in
51 /// the result set (when it returns true) and which declarations should be
52 /// filtered out (returns false).
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +000053 typedef bool (ResultBuilder::*LookupFilter)(const NamedDecl *) const;
Ivan Donchevskii13d90542017-10-27 11:05:40 +000054
John McCall276321a2010-08-25 06:19:51 +000055 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +000056
Douglas Gregor3545ff42009-09-21 16:56:56 +000057 private:
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000058 /// The actual results we have found.
Douglas Gregor3545ff42009-09-21 16:56:56 +000059 std::vector<Result> Results;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +000060
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000061 /// A record of all of the declarations we have found and placed
Douglas Gregor3545ff42009-09-21 16:56:56 +000062 /// into the result set, used to ensure that no declaration ever gets into
63 /// the result set twice.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +000064 llvm::SmallPtrSet<const Decl*, 16> AllDeclsFound;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +000065
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +000066 typedef std::pair<const NamedDecl *, unsigned> DeclIndexPair;
Douglas Gregor05e7ca32009-12-06 20:23:50 +000067
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000068 /// An entry in the shadow map, which is optimized to store
Douglas Gregor05e7ca32009-12-06 20:23:50 +000069 /// a single (declaration, index) mapping (the common case) but
70 /// can also store a list of (declaration, index) mappings.
71 class ShadowMapEntry {
Chris Lattner0e62c1c2011-07-23 10:55:15 +000072 typedef SmallVector<DeclIndexPair, 4> DeclIndexPairVector;
Douglas Gregor05e7ca32009-12-06 20:23:50 +000073
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000074 /// Contains either the solitary NamedDecl * or a vector
Douglas Gregor05e7ca32009-12-06 20:23:50 +000075 /// of (declaration, index) pairs.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +000076 llvm::PointerUnion<const NamedDecl *, DeclIndexPairVector*> DeclOrVector;
Douglas Gregor05e7ca32009-12-06 20:23:50 +000077
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000078 /// When the entry contains a single declaration, this is
Douglas Gregor05e7ca32009-12-06 20:23:50 +000079 /// the index associated with that entry.
80 unsigned SingleDeclIndex;
81
82 public:
83 ShadowMapEntry() : DeclOrVector(), SingleDeclIndex(0) { }
84
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +000085 void Add(const NamedDecl *ND, unsigned Index) {
Douglas Gregor05e7ca32009-12-06 20:23:50 +000086 if (DeclOrVector.isNull()) {
87 // 0 - > 1 elements: just set the single element information.
88 DeclOrVector = ND;
89 SingleDeclIndex = Index;
90 return;
91 }
92
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +000093 if (const NamedDecl *PrevND =
94 DeclOrVector.dyn_cast<const NamedDecl *>()) {
Douglas Gregor05e7ca32009-12-06 20:23:50 +000095 // 1 -> 2 elements: create the vector of results and push in the
96 // existing declaration.
97 DeclIndexPairVector *Vec = new DeclIndexPairVector;
98 Vec->push_back(DeclIndexPair(PrevND, SingleDeclIndex));
99 DeclOrVector = Vec;
100 }
101
102 // Add the new element to the end of the vector.
103 DeclOrVector.get<DeclIndexPairVector*>()->push_back(
104 DeclIndexPair(ND, Index));
105 }
106
107 void Destroy() {
108 if (DeclIndexPairVector *Vec
109 = DeclOrVector.dyn_cast<DeclIndexPairVector *>()) {
110 delete Vec;
Craig Topperc3ec1492014-05-26 06:22:03 +0000111 DeclOrVector = ((NamedDecl *)nullptr);
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000112 }
113 }
114
115 // Iteration.
116 class iterator;
117 iterator begin() const;
118 iterator end() const;
119 };
120
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000121 /// A mapping from declaration names to the declarations that have
Douglas Gregor3545ff42009-09-21 16:56:56 +0000122 /// this name within a particular scope and their index within the list of
123 /// results.
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000124 typedef llvm::DenseMap<DeclarationName, ShadowMapEntry> ShadowMap;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000125
126 /// The semantic analysis object for which results are being
Douglas Gregor3545ff42009-09-21 16:56:56 +0000127 /// produced.
128 Sema &SemaRef;
Douglas Gregorb278aaf2011-02-01 19:23:04 +0000129
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000130 /// The allocator used to allocate new code-completion strings.
Douglas Gregorbcbf46c2011-02-01 22:57:45 +0000131 CodeCompletionAllocator &Allocator;
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +0000132
133 CodeCompletionTUInfo &CCTUInfo;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000134
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000135 /// If non-NULL, a filter function used to remove any code-completion
Douglas Gregor3545ff42009-09-21 16:56:56 +0000136 /// results that are not desirable.
137 LookupFilter Filter;
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000138
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000139 /// Whether we should allow declarations as
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000140 /// nested-name-specifiers that would otherwise be filtered out.
141 bool AllowNestedNameSpecifiers;
142
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000143 /// If set, the type that we would prefer our resulting value
Douglas Gregor7aa6b222010-05-30 01:49:25 +0000144 /// declarations to have.
145 ///
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000146 /// Closely matching the preferred type gives a boost to a result's
Douglas Gregor7aa6b222010-05-30 01:49:25 +0000147 /// priority.
148 CanQualType PreferredType;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000149
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000150 /// A list of shadow maps, which is used to model name hiding at
Douglas Gregor3545ff42009-09-21 16:56:56 +0000151 /// different levels of, e.g., the inheritance hierarchy.
152 std::list<ShadowMap> ShadowMaps;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000153
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000154 /// If we're potentially referring to a C++ member function, the set
Douglas Gregor9be0ed42010-08-26 16:36:48 +0000155 /// of qualifiers applied to the object type.
156 Qualifiers ObjectTypeQualifiers;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000157
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000158 /// Whether the \p ObjectTypeQualifiers field is active.
Douglas Gregor9be0ed42010-08-26 16:36:48 +0000159 bool HasObjectTypeQualifiers;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000160
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000161 /// The selector that we prefer.
Douglas Gregorc2cb2e22010-08-27 15:29:55 +0000162 Selector PreferredSelector;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000163
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000164 /// The completion context in which we are gathering results.
Douglas Gregor50832e02010-09-20 22:39:41 +0000165 CodeCompletionContext CompletionContext;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000166
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000167 /// If we are in an instance method definition, the \@implementation
Douglas Gregor05fcf842010-11-02 20:36:02 +0000168 /// object.
169 ObjCImplementationDecl *ObjCImplementation;
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000170
Douglas Gregor50832e02010-09-20 22:39:41 +0000171 void AdjustResultPriorityForDecl(Result &R);
Douglas Gregor95887f92010-07-08 23:20:03 +0000172
Douglas Gregor0212fd72010-09-21 16:06:22 +0000173 void MaybeAddConstructorResults(Result R);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000174
Douglas Gregor3545ff42009-09-21 16:56:56 +0000175 public:
Douglas Gregorbcbf46c2011-02-01 22:57:45 +0000176 explicit ResultBuilder(Sema &SemaRef, CodeCompletionAllocator &Allocator,
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +0000177 CodeCompletionTUInfo &CCTUInfo,
Douglas Gregor0ac41382010-09-23 23:01:17 +0000178 const CodeCompletionContext &CompletionContext,
Craig Topperc3ec1492014-05-26 06:22:03 +0000179 LookupFilter Filter = nullptr)
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +0000180 : SemaRef(SemaRef), Allocator(Allocator), CCTUInfo(CCTUInfo),
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000181 Filter(Filter),
182 AllowNestedNameSpecifiers(false), HasObjectTypeQualifiers(false),
Douglas Gregor05fcf842010-11-02 20:36:02 +0000183 CompletionContext(CompletionContext),
Craig Topperc3ec1492014-05-26 06:22:03 +0000184 ObjCImplementation(nullptr)
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000185 {
186 // If this is an Objective-C instance method definition, dig out the
Douglas Gregor05fcf842010-11-02 20:36:02 +0000187 // corresponding implementation.
188 switch (CompletionContext.getKind()) {
189 case CodeCompletionContext::CCC_Expression:
190 case CodeCompletionContext::CCC_ObjCMessageReceiver:
191 case CodeCompletionContext::CCC_ParenthesizedExpression:
192 case CodeCompletionContext::CCC_Statement:
193 case CodeCompletionContext::CCC_Recovery:
194 if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl())
195 if (Method->isInstanceMethod())
196 if (ObjCInterfaceDecl *Interface = Method->getClassInterface())
197 ObjCImplementation = Interface->getImplementation();
198 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000199
Douglas Gregor05fcf842010-11-02 20:36:02 +0000200 default:
201 break;
202 }
203 }
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000204
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000205 /// Determine the priority for a reference to the given declaration.
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000206 unsigned getBasePriority(const NamedDecl *D);
207
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000208 /// Whether we should include code patterns in the completion
Douglas Gregorf64acca2010-05-25 21:41:55 +0000209 /// results.
210 bool includeCodePatterns() const {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000211 return SemaRef.CodeCompleter &&
Douglas Gregorac322ec2010-08-27 21:18:54 +0000212 SemaRef.CodeCompleter->includeCodePatterns();
Douglas Gregorf64acca2010-05-25 21:41:55 +0000213 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000214
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000215 /// Set the filter used for code-completion results.
Douglas Gregor3545ff42009-09-21 16:56:56 +0000216 void setFilter(LookupFilter Filter) {
217 this->Filter = Filter;
218 }
Craig Topperc3ec1492014-05-26 06:22:03 +0000219
220 Result *data() { return Results.empty()? nullptr : &Results.front(); }
Douglas Gregor3545ff42009-09-21 16:56:56 +0000221 unsigned size() const { return Results.size(); }
222 bool empty() const { return Results.empty(); }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000223
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000224 /// Specify the preferred type.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000225 void setPreferredType(QualType T) {
226 PreferredType = SemaRef.Context.getCanonicalType(T);
Douglas Gregor7aa6b222010-05-30 01:49:25 +0000227 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000228
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000229 /// Set the cv-qualifiers on the object type, for us in filtering
Douglas Gregor9be0ed42010-08-26 16:36:48 +0000230 /// calls to member functions.
231 ///
232 /// When there are qualifiers in this set, they will be used to filter
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000233 /// out member functions that aren't available (because there will be a
Douglas Gregor9be0ed42010-08-26 16:36:48 +0000234 /// cv-qualifier mismatch) or prefer functions with an exact qualifier
235 /// match.
236 void setObjectTypeQualifiers(Qualifiers Quals) {
237 ObjectTypeQualifiers = Quals;
238 HasObjectTypeQualifiers = true;
239 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000240
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000241 /// Set the preferred selector.
Douglas Gregorc2cb2e22010-08-27 15:29:55 +0000242 ///
243 /// When an Objective-C method declaration result is added, and that
244 /// method's selector matches this preferred selector, we give that method
245 /// a slight priority boost.
246 void setPreferredSelector(Selector Sel) {
247 PreferredSelector = Sel;
248 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000249
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000250 /// Retrieve the code-completion context for which results are
Douglas Gregor50832e02010-09-20 22:39:41 +0000251 /// being collected.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000252 const CodeCompletionContext &getCompletionContext() const {
253 return CompletionContext;
Douglas Gregor50832e02010-09-20 22:39:41 +0000254 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000255
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000256 /// Specify whether nested-name-specifiers are allowed.
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000257 void allowNestedNameSpecifiers(bool Allow = true) {
258 AllowNestedNameSpecifiers = Allow;
259 }
260
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000261 /// Return the semantic analysis object for which we are collecting
Douglas Gregor74661272010-09-21 00:03:25 +0000262 /// code completion results.
263 Sema &getSema() const { return SemaRef; }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000264
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000265 /// Retrieve the allocator used to allocate code completion strings.
Douglas Gregorbcbf46c2011-02-01 22:57:45 +0000266 CodeCompletionAllocator &getAllocator() const { return Allocator; }
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +0000267
268 CodeCompletionTUInfo &getCodeCompletionTUInfo() const { return CCTUInfo; }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000269
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000270 /// Determine whether the given declaration is at all interesting
Douglas Gregor7c208612010-01-14 00:20:49 +0000271 /// as a code-completion result.
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000272 ///
273 /// \param ND the declaration that we are inspecting.
274 ///
275 /// \param AsNestedNameSpecifier will be set true if this declaration is
276 /// only interesting when it is a nested-name-specifier.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000277 bool isInterestingDecl(const NamedDecl *ND,
278 bool &AsNestedNameSpecifier) const;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000279
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000280 /// Check whether the result is hidden by the Hiding declaration.
Douglas Gregore0717ab2010-01-14 00:41:07 +0000281 ///
282 /// \returns true if the result is hidden and cannot be found, false if
283 /// the hidden result could still be found. When false, \p R may be
284 /// modified to describe how the result can be found (e.g., via extra
285 /// qualification).
286 bool CheckHiddenResult(Result &R, DeclContext *CurContext,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000287 const NamedDecl *Hiding);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000288
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000289 /// Add a new result to this result set (if it isn't already in one
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000290 /// of the shadow maps), or replace an existing result (for, e.g., a
Douglas Gregor3545ff42009-09-21 16:56:56 +0000291 /// redeclaration).
Douglas Gregor2af2f672009-09-21 20:12:40 +0000292 ///
Douglas Gregord8c61782012-02-15 15:34:24 +0000293 /// \param R the result to add (if it is unique).
Douglas Gregor2af2f672009-09-21 20:12:40 +0000294 ///
Douglas Gregord8c61782012-02-15 15:34:24 +0000295 /// \param CurContext the context in which this result will be named.
Craig Topperc3ec1492014-05-26 06:22:03 +0000296 void MaybeAddResult(Result R, DeclContext *CurContext = nullptr);
297
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000298 /// Add a new result to this result set, where we already know
Yaron Keren8fbe43982014-11-14 18:33:42 +0000299 /// the hiding declaration (if any).
Douglas Gregorc580c522010-01-14 01:09:38 +0000300 ///
301 /// \param R the result to add (if it is unique).
302 ///
303 /// \param CurContext the context in which this result will be named.
304 ///
305 /// \param Hiding the declaration that hides the result.
Douglas Gregor09bbc652010-01-14 15:47:35 +0000306 ///
307 /// \param InBaseClass whether the result was found in a base
308 /// class of the searched context.
309 void AddResult(Result R, DeclContext *CurContext, NamedDecl *Hiding,
310 bool InBaseClass);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000311
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000312 /// Add a new non-declaration result to this result set.
Douglas Gregor78a21012010-01-14 16:01:26 +0000313 void AddResult(Result R);
314
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000315 /// Enter into a new scope.
Douglas Gregor3545ff42009-09-21 16:56:56 +0000316 void EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000317
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000318 /// Exit from the current scope.
Douglas Gregor3545ff42009-09-21 16:56:56 +0000319 void ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000320
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000321 /// Ignore this declaration, if it is seen again.
Dmitri Gribenko6cfb1532013-02-14 13:53:30 +0000322 void Ignore(const Decl *D) { AllDeclsFound.insert(D->getCanonicalDecl()); }
Douglas Gregorbaf69612009-11-18 04:19:12 +0000323
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000324 /// Add a visited context.
Haojian Wu10d95c52018-01-17 14:29:25 +0000325 void addVisitedContext(DeclContext *Ctx) {
326 CompletionContext.addVisitedContext(Ctx);
327 }
328
Douglas Gregor3545ff42009-09-21 16:56:56 +0000329 /// \name Name lookup predicates
330 ///
331 /// These predicates can be passed to the name lookup functions to filter the
332 /// results of name lookup. All of the predicates have the same type, so that
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000333 ///
Douglas Gregor3545ff42009-09-21 16:56:56 +0000334 //@{
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000335 bool IsOrdinaryName(const NamedDecl *ND) const;
336 bool IsOrdinaryNonTypeName(const NamedDecl *ND) const;
337 bool IsIntegralConstantValue(const NamedDecl *ND) const;
338 bool IsOrdinaryNonValueName(const NamedDecl *ND) const;
339 bool IsNestedNameSpecifier(const NamedDecl *ND) const;
340 bool IsEnum(const NamedDecl *ND) const;
341 bool IsClassOrStruct(const NamedDecl *ND) const;
342 bool IsUnion(const NamedDecl *ND) const;
343 bool IsNamespace(const NamedDecl *ND) const;
344 bool IsNamespaceOrAlias(const NamedDecl *ND) const;
345 bool IsType(const NamedDecl *ND) const;
346 bool IsMember(const NamedDecl *ND) const;
347 bool IsObjCIvar(const NamedDecl *ND) const;
348 bool IsObjCMessageReceiver(const NamedDecl *ND) const;
349 bool IsObjCMessageReceiverOrLambdaCapture(const NamedDecl *ND) const;
350 bool IsObjCCollection(const NamedDecl *ND) const;
351 bool IsImpossibleToSatisfy(const NamedDecl *ND) const;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000352 //@}
353 };
Alexander Kornienkoab9db512015-06-22 23:07:51 +0000354}
Douglas Gregor3545ff42009-09-21 16:56:56 +0000355
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000356class ResultBuilder::ShadowMapEntry::iterator {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000357 llvm::PointerUnion<const NamedDecl *, const DeclIndexPair *> DeclOrIterator;
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000358 unsigned SingleDeclIndex;
359
360public:
361 typedef DeclIndexPair value_type;
362 typedef value_type reference;
363 typedef std::ptrdiff_t difference_type;
364 typedef std::input_iterator_tag iterator_category;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000365
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000366 class pointer {
367 DeclIndexPair Value;
368
369 public:
370 pointer(const DeclIndexPair &Value) : Value(Value) { }
371
372 const DeclIndexPair *operator->() const {
373 return &Value;
374 }
375 };
Craig Topperc3ec1492014-05-26 06:22:03 +0000376
377 iterator() : DeclOrIterator((NamedDecl *)nullptr), SingleDeclIndex(0) {}
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000378
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000379 iterator(const NamedDecl *SingleDecl, unsigned Index)
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000380 : DeclOrIterator(SingleDecl), SingleDeclIndex(Index) { }
381
382 iterator(const DeclIndexPair *Iterator)
383 : DeclOrIterator(Iterator), SingleDeclIndex(0) { }
384
385 iterator &operator++() {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000386 if (DeclOrIterator.is<const NamedDecl *>()) {
Craig Topperc3ec1492014-05-26 06:22:03 +0000387 DeclOrIterator = (NamedDecl *)nullptr;
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000388 SingleDeclIndex = 0;
389 return *this;
390 }
391
392 const DeclIndexPair *I = DeclOrIterator.get<const DeclIndexPair*>();
393 ++I;
394 DeclOrIterator = I;
395 return *this;
396 }
397
Chris Lattner9795b392010-09-04 18:12:20 +0000398 /*iterator operator++(int) {
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000399 iterator tmp(*this);
400 ++(*this);
401 return tmp;
Chris Lattner9795b392010-09-04 18:12:20 +0000402 }*/
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000403
404 reference operator*() const {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000405 if (const NamedDecl *ND = DeclOrIterator.dyn_cast<const NamedDecl *>())
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000406 return reference(ND, SingleDeclIndex);
407
Douglas Gregor94bb5e82009-12-06 21:27:58 +0000408 return *DeclOrIterator.get<const DeclIndexPair*>();
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000409 }
410
411 pointer operator->() const {
412 return pointer(**this);
413 }
414
415 friend bool operator==(const iterator &X, const iterator &Y) {
Douglas Gregor94bb5e82009-12-06 21:27:58 +0000416 return X.DeclOrIterator.getOpaqueValue()
417 == Y.DeclOrIterator.getOpaqueValue() &&
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000418 X.SingleDeclIndex == Y.SingleDeclIndex;
419 }
420
421 friend bool operator!=(const iterator &X, const iterator &Y) {
Douglas Gregor94bb5e82009-12-06 21:27:58 +0000422 return !(X == Y);
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000423 }
424};
425
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000426ResultBuilder::ShadowMapEntry::iterator
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000427ResultBuilder::ShadowMapEntry::begin() const {
428 if (DeclOrVector.isNull())
429 return iterator();
430
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000431 if (const NamedDecl *ND = DeclOrVector.dyn_cast<const NamedDecl *>())
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000432 return iterator(ND, SingleDeclIndex);
433
434 return iterator(DeclOrVector.get<DeclIndexPairVector *>()->begin());
435}
436
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000437ResultBuilder::ShadowMapEntry::iterator
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000438ResultBuilder::ShadowMapEntry::end() const {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000439 if (DeclOrVector.is<const NamedDecl *>() || DeclOrVector.isNull())
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000440 return iterator();
441
442 return iterator(DeclOrVector.get<DeclIndexPairVector *>()->end());
443}
444
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000445/// Compute the qualification required to get from the current context
Douglas Gregor2af2f672009-09-21 20:12:40 +0000446/// (\p CurContext) to the target context (\p TargetContext).
447///
448/// \param Context the AST context in which the qualification will be used.
449///
450/// \param CurContext the context where an entity is being named, which is
451/// typically based on the current scope.
452///
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000453/// \param TargetContext the context in which the named entity actually
Douglas Gregor2af2f672009-09-21 20:12:40 +0000454/// resides.
455///
456/// \returns a nested name specifier that refers into the target context, or
457/// NULL if no qualification is needed.
458static NestedNameSpecifier *
459getRequiredQualification(ASTContext &Context,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000460 const DeclContext *CurContext,
461 const DeclContext *TargetContext) {
462 SmallVector<const DeclContext *, 4> TargetParents;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000463
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000464 for (const DeclContext *CommonAncestor = TargetContext;
Douglas Gregor2af2f672009-09-21 20:12:40 +0000465 CommonAncestor && !CommonAncestor->Encloses(CurContext);
466 CommonAncestor = CommonAncestor->getLookupParent()) {
467 if (CommonAncestor->isTransparentContext() ||
468 CommonAncestor->isFunctionOrMethod())
469 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000470
Douglas Gregor2af2f672009-09-21 20:12:40 +0000471 TargetParents.push_back(CommonAncestor);
472 }
Craig Topperc3ec1492014-05-26 06:22:03 +0000473
474 NestedNameSpecifier *Result = nullptr;
Douglas Gregor2af2f672009-09-21 20:12:40 +0000475 while (!TargetParents.empty()) {
Robert Wilhelm25284cc2013-08-23 16:11:15 +0000476 const DeclContext *Parent = TargetParents.pop_back_val();
477
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000478 if (const NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Parent)) {
Douglas Gregor68762e72010-08-23 21:17:50 +0000479 if (!Namespace->getIdentifier())
480 continue;
481
Douglas Gregor2af2f672009-09-21 20:12:40 +0000482 Result = NestedNameSpecifier::Create(Context, Result, Namespace);
Douglas Gregor68762e72010-08-23 21:17:50 +0000483 }
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000484 else if (const TagDecl *TD = dyn_cast<TagDecl>(Parent))
Douglas Gregor2af2f672009-09-21 20:12:40 +0000485 Result = NestedNameSpecifier::Create(Context, Result,
486 false,
487 Context.getTypeDeclType(TD).getTypePtr());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000488 }
Douglas Gregor2af2f672009-09-21 20:12:40 +0000489 return Result;
490}
491
Alp Toker034bbd52014-06-30 01:33:53 +0000492/// Determine whether \p Id is a name reserved for the implementation (C99
493/// 7.1.3, C++ [lib.global.names]).
Argyrios Kyrtzidis5d8006d2016-07-01 01:17:02 +0000494static bool isReservedName(const IdentifierInfo *Id,
495 bool doubleUnderscoreOnly = false) {
Alp Toker034bbd52014-06-30 01:33:53 +0000496 if (Id->getLength() < 2)
497 return false;
498 const char *Name = Id->getNameStart();
499 return Name[0] == '_' &&
Argyrios Kyrtzidis5d8006d2016-07-01 01:17:02 +0000500 (Name[1] == '_' || (Name[1] >= 'A' && Name[1] <= 'Z' &&
501 !doubleUnderscoreOnly));
502}
503
504// Some declarations have reserved names that we don't want to ever show.
505// Filter out names reserved for the implementation if they come from a
506// system header.
507static bool shouldIgnoreDueToReservedName(const NamedDecl *ND, Sema &SemaRef) {
508 const IdentifierInfo *Id = ND->getIdentifier();
509 if (!Id)
510 return false;
511
512 // Ignore reserved names for compiler provided decls.
513 if (isReservedName(Id) && ND->getLocation().isInvalid())
514 return true;
515
516 // For system headers ignore only double-underscore names.
517 // This allows for system headers providing private symbols with a single
518 // underscore.
519 if (isReservedName(Id, /*doubleUnderscoreOnly=*/true) &&
520 SemaRef.SourceMgr.isInSystemHeader(
521 SemaRef.SourceMgr.getSpellingLoc(ND->getLocation())))
522 return true;
523
524 return false;
Alp Toker034bbd52014-06-30 01:33:53 +0000525}
526
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000527bool ResultBuilder::isInterestingDecl(const NamedDecl *ND,
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000528 bool &AsNestedNameSpecifier) const {
529 AsNestedNameSpecifier = false;
530
Richard Smithf2005d32015-12-29 23:34:32 +0000531 auto *Named = ND;
Douglas Gregor7c208612010-01-14 00:20:49 +0000532 ND = ND->getUnderlyingDecl();
Douglas Gregor58acf322009-10-09 22:16:47 +0000533
534 // Skip unnamed entities.
Douglas Gregor7c208612010-01-14 00:20:49 +0000535 if (!ND->getDeclName())
536 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000537
Douglas Gregor3545ff42009-09-21 16:56:56 +0000538 // Friend declarations and declarations introduced due to friends are never
539 // added as results.
Richard Smith6eece292015-01-15 02:27:20 +0000540 if (ND->getFriendObjectKind() == Decl::FOK_Undeclared)
Douglas Gregor7c208612010-01-14 00:20:49 +0000541 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000542
Douglas Gregor99fe2ad2009-12-11 17:31:05 +0000543 // Class template (partial) specializations are never added as results.
Douglas Gregor7c208612010-01-14 00:20:49 +0000544 if (isa<ClassTemplateSpecializationDecl>(ND) ||
545 isa<ClassTemplatePartialSpecializationDecl>(ND))
546 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000547
Douglas Gregor99fe2ad2009-12-11 17:31:05 +0000548 // Using declarations themselves are never added as results.
Douglas Gregor7c208612010-01-14 00:20:49 +0000549 if (isa<UsingDecl>(ND))
550 return false;
Argyrios Kyrtzidis5d8006d2016-07-01 01:17:02 +0000551
552 if (shouldIgnoreDueToReservedName(ND, SemaRef))
553 return false;
Douglas Gregor2927c0c2010-11-09 03:59:40 +0000554
Douglas Gregor59cab552010-08-16 23:05:20 +0000555 if (Filter == &ResultBuilder::IsNestedNameSpecifier ||
Richard Smithf2005d32015-12-29 23:34:32 +0000556 (isa<NamespaceDecl>(ND) &&
Douglas Gregor59cab552010-08-16 23:05:20 +0000557 Filter != &ResultBuilder::IsNamespace &&
Douglas Gregor0ac41382010-09-23 23:01:17 +0000558 Filter != &ResultBuilder::IsNamespaceOrAlias &&
Craig Topperc3ec1492014-05-26 06:22:03 +0000559 Filter != nullptr))
Douglas Gregor59cab552010-08-16 23:05:20 +0000560 AsNestedNameSpecifier = true;
561
Douglas Gregor3545ff42009-09-21 16:56:56 +0000562 // Filter out any unwanted results.
Richard Smithf2005d32015-12-29 23:34:32 +0000563 if (Filter && !(this->*Filter)(Named)) {
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000564 // Check whether it is interesting as a nested-name-specifier.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000565 if (AllowNestedNameSpecifiers && SemaRef.getLangOpts().CPlusPlus &&
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000566 IsNestedNameSpecifier(ND) &&
567 (Filter != &ResultBuilder::IsMember ||
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000568 (isa<CXXRecordDecl>(ND) &&
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000569 cast<CXXRecordDecl>(ND)->isInjectedClassName()))) {
570 AsNestedNameSpecifier = true;
571 return true;
572 }
573
Douglas Gregor7c208612010-01-14 00:20:49 +0000574 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000575 }
Douglas Gregor7c208612010-01-14 00:20:49 +0000576 // ... then it must be interesting!
577 return true;
578}
579
Douglas Gregore0717ab2010-01-14 00:41:07 +0000580bool ResultBuilder::CheckHiddenResult(Result &R, DeclContext *CurContext,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000581 const NamedDecl *Hiding) {
Douglas Gregore0717ab2010-01-14 00:41:07 +0000582 // In C, there is no way to refer to a hidden name.
583 // FIXME: This isn't true; we can find a tag name hidden by an ordinary
584 // name if we introduce the tag type.
David Blaikiebbafb8a2012-03-11 07:00:24 +0000585 if (!SemaRef.getLangOpts().CPlusPlus)
Douglas Gregore0717ab2010-01-14 00:41:07 +0000586 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000587
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000588 const DeclContext *HiddenCtx =
589 R.Declaration->getDeclContext()->getRedeclContext();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000590
Douglas Gregore0717ab2010-01-14 00:41:07 +0000591 // There is no way to qualify a name declared in a function or method.
592 if (HiddenCtx->isFunctionOrMethod())
593 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000594
Sebastian Redl50c68252010-08-31 00:36:30 +0000595 if (HiddenCtx == Hiding->getDeclContext()->getRedeclContext())
Douglas Gregore0717ab2010-01-14 00:41:07 +0000596 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000597
Douglas Gregore0717ab2010-01-14 00:41:07 +0000598 // We can refer to the result with the appropriate qualification. Do it.
599 R.Hidden = true;
600 R.QualifierIsInformative = false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000601
Douglas Gregore0717ab2010-01-14 00:41:07 +0000602 if (!R.Qualifier)
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000603 R.Qualifier = getRequiredQualification(SemaRef.Context,
604 CurContext,
Douglas Gregore0717ab2010-01-14 00:41:07 +0000605 R.Declaration->getDeclContext());
606 return false;
607}
608
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000609/// A simplified classification of types used to determine whether two
Douglas Gregor95887f92010-07-08 23:20:03 +0000610/// types are "similar enough" when adjusting priorities.
Douglas Gregor6e240332010-08-16 16:18:59 +0000611SimplifiedTypeClass clang::getSimplifiedTypeClass(CanQualType T) {
Douglas Gregor95887f92010-07-08 23:20:03 +0000612 switch (T->getTypeClass()) {
613 case Type::Builtin:
614 switch (cast<BuiltinType>(T)->getKind()) {
615 case BuiltinType::Void:
616 return STC_Void;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000617
Douglas Gregor95887f92010-07-08 23:20:03 +0000618 case BuiltinType::NullPtr:
619 return STC_Pointer;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000620
Douglas Gregor95887f92010-07-08 23:20:03 +0000621 case BuiltinType::Overload:
622 case BuiltinType::Dependent:
Douglas Gregor95887f92010-07-08 23:20:03 +0000623 return STC_Other;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000624
Douglas Gregor95887f92010-07-08 23:20:03 +0000625 case BuiltinType::ObjCId:
626 case BuiltinType::ObjCClass:
627 case BuiltinType::ObjCSel:
628 return STC_ObjectiveC;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000629
Douglas Gregor95887f92010-07-08 23:20:03 +0000630 default:
631 return STC_Arithmetic;
632 }
David Blaikie8a40f702012-01-17 06:56:22 +0000633
Douglas Gregor95887f92010-07-08 23:20:03 +0000634 case Type::Complex:
635 return STC_Arithmetic;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000636
Douglas Gregor95887f92010-07-08 23:20:03 +0000637 case Type::Pointer:
638 return STC_Pointer;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000639
Douglas Gregor95887f92010-07-08 23:20:03 +0000640 case Type::BlockPointer:
641 return STC_Block;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000642
Douglas Gregor95887f92010-07-08 23:20:03 +0000643 case Type::LValueReference:
644 case Type::RValueReference:
645 return getSimplifiedTypeClass(T->getAs<ReferenceType>()->getPointeeType());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000646
Douglas Gregor95887f92010-07-08 23:20:03 +0000647 case Type::ConstantArray:
648 case Type::IncompleteArray:
649 case Type::VariableArray:
650 case Type::DependentSizedArray:
651 return STC_Array;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000652
Douglas Gregor95887f92010-07-08 23:20:03 +0000653 case Type::DependentSizedExtVector:
654 case Type::Vector:
655 case Type::ExtVector:
656 return STC_Arithmetic;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000657
Douglas Gregor95887f92010-07-08 23:20:03 +0000658 case Type::FunctionProto:
659 case Type::FunctionNoProto:
660 return STC_Function;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000661
Douglas Gregor95887f92010-07-08 23:20:03 +0000662 case Type::Record:
663 return STC_Record;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000664
Douglas Gregor95887f92010-07-08 23:20:03 +0000665 case Type::Enum:
666 return STC_Arithmetic;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000667
Douglas Gregor95887f92010-07-08 23:20:03 +0000668 case Type::ObjCObject:
669 case Type::ObjCInterface:
670 case Type::ObjCObjectPointer:
671 return STC_ObjectiveC;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000672
Douglas Gregor95887f92010-07-08 23:20:03 +0000673 default:
674 return STC_Other;
675 }
676}
677
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000678/// Get the type that a given expression will have if this declaration
Douglas Gregor95887f92010-07-08 23:20:03 +0000679/// is used as an expression in its "typical" code-completion form.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000680QualType clang::getDeclUsageType(ASTContext &C, const NamedDecl *ND) {
George Burgess IV00f70bd2018-03-01 05:43:23 +0000681 ND = ND->getUnderlyingDecl();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000682
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000683 if (const TypeDecl *Type = dyn_cast<TypeDecl>(ND))
Douglas Gregor95887f92010-07-08 23:20:03 +0000684 return C.getTypeDeclType(Type);
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000685 if (const ObjCInterfaceDecl *Iface = dyn_cast<ObjCInterfaceDecl>(ND))
Douglas Gregor95887f92010-07-08 23:20:03 +0000686 return C.getObjCInterfaceType(Iface);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000687
Douglas Gregor95887f92010-07-08 23:20:03 +0000688 QualType T;
Alp Tokera2794f92014-01-22 07:29:52 +0000689 if (const FunctionDecl *Function = ND->getAsFunction())
Douglas Gregor603d81b2010-07-13 08:18:22 +0000690 T = Function->getCallResultType();
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000691 else if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND))
Douglas Gregor603d81b2010-07-13 08:18:22 +0000692 T = Method->getSendResultType();
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000693 else if (const EnumConstantDecl *Enumerator = dyn_cast<EnumConstantDecl>(ND))
Douglas Gregor95887f92010-07-08 23:20:03 +0000694 T = C.getTypeDeclType(cast<EnumDecl>(Enumerator->getDeclContext()));
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000695 else if (const ObjCPropertyDecl *Property = dyn_cast<ObjCPropertyDecl>(ND))
Douglas Gregor95887f92010-07-08 23:20:03 +0000696 T = Property->getType();
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000697 else if (const ValueDecl *Value = dyn_cast<ValueDecl>(ND))
Douglas Gregor95887f92010-07-08 23:20:03 +0000698 T = Value->getType();
699 else
700 return QualType();
Douglas Gregoraf670a82011-04-14 20:33:34 +0000701
702 // Dig through references, function pointers, and block pointers to
703 // get down to the likely type of an expression when the entity is
704 // used.
705 do {
706 if (const ReferenceType *Ref = T->getAs<ReferenceType>()) {
707 T = Ref->getPointeeType();
708 continue;
709 }
710
711 if (const PointerType *Pointer = T->getAs<PointerType>()) {
712 if (Pointer->getPointeeType()->isFunctionType()) {
713 T = Pointer->getPointeeType();
714 continue;
715 }
716
717 break;
718 }
719
720 if (const BlockPointerType *Block = T->getAs<BlockPointerType>()) {
721 T = Block->getPointeeType();
722 continue;
723 }
724
725 if (const FunctionType *Function = T->getAs<FunctionType>()) {
Alp Toker314cc812014-01-25 16:55:45 +0000726 T = Function->getReturnType();
Douglas Gregoraf670a82011-04-14 20:33:34 +0000727 continue;
728 }
729
730 break;
731 } while (true);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000732
Douglas Gregoraf670a82011-04-14 20:33:34 +0000733 return T;
Douglas Gregor95887f92010-07-08 23:20:03 +0000734}
735
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000736unsigned ResultBuilder::getBasePriority(const NamedDecl *ND) {
737 if (!ND)
738 return CCP_Unlikely;
739
740 // Context-based decisions.
Richard Smith541b38b2013-09-20 01:15:31 +0000741 const DeclContext *LexicalDC = ND->getLexicalDeclContext();
742 if (LexicalDC->isFunctionOrMethod()) {
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000743 // _cmd is relatively rare
744 if (const ImplicitParamDecl *ImplicitParam =
745 dyn_cast<ImplicitParamDecl>(ND))
746 if (ImplicitParam->getIdentifier() &&
747 ImplicitParam->getIdentifier()->isStr("_cmd"))
748 return CCP_ObjC_cmd;
749
750 return CCP_LocalDeclaration;
751 }
Richard Smith541b38b2013-09-20 01:15:31 +0000752
753 const DeclContext *DC = ND->getDeclContext()->getRedeclContext();
Ilya Biryukov4e7a6fe2017-09-22 19:07:37 +0000754 if (DC->isRecord() || isa<ObjCContainerDecl>(DC)) {
755 // Explicit destructor calls are very rare.
756 if (isa<CXXDestructorDecl>(ND))
757 return CCP_Unlikely;
758 // Explicit operator and conversion function calls are also very rare.
759 auto DeclNameKind = ND->getDeclName().getNameKind();
760 if (DeclNameKind == DeclarationName::CXXOperatorName ||
761 DeclNameKind == DeclarationName::CXXLiteralOperatorName ||
762 DeclNameKind == DeclarationName::CXXConversionFunctionName)
763 return CCP_Unlikely;
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000764 return CCP_MemberDeclaration;
Ilya Biryukov4e7a6fe2017-09-22 19:07:37 +0000765 }
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000766
767 // Content-based decisions.
768 if (isa<EnumConstantDecl>(ND))
769 return CCP_Constant;
770
Douglas Gregor52e0de42013-01-31 05:03:46 +0000771 // Use CCP_Type for type declarations unless we're in a statement, Objective-C
772 // message receiver, or parenthesized expression context. There, it's as
773 // likely that the user will want to write a type as other declarations.
774 if ((isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND)) &&
775 !(CompletionContext.getKind() == CodeCompletionContext::CCC_Statement ||
776 CompletionContext.getKind()
777 == CodeCompletionContext::CCC_ObjCMessageReceiver ||
778 CompletionContext.getKind()
779 == CodeCompletionContext::CCC_ParenthesizedExpression))
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000780 return CCP_Type;
781
782 return CCP_Declaration;
783}
784
Douglas Gregor50832e02010-09-20 22:39:41 +0000785void ResultBuilder::AdjustResultPriorityForDecl(Result &R) {
786 // If this is an Objective-C method declaration whose selector matches our
787 // preferred selector, give it a priority boost.
788 if (!PreferredSelector.isNull())
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000789 if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(R.Declaration))
Douglas Gregor50832e02010-09-20 22:39:41 +0000790 if (PreferredSelector == Method->getSelector())
791 R.Priority += CCD_SelectorMatch;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000792
Douglas Gregor50832e02010-09-20 22:39:41 +0000793 // If we have a preferred type, adjust the priority for results with exactly-
794 // matching or nearly-matching types.
795 if (!PreferredType.isNull()) {
796 QualType T = getDeclUsageType(SemaRef.Context, R.Declaration);
797 if (!T.isNull()) {
798 CanQualType TC = SemaRef.Context.getCanonicalType(T);
799 // Check for exactly-matching types (modulo qualifiers).
800 if (SemaRef.Context.hasSameUnqualifiedType(PreferredType, TC))
801 R.Priority /= CCF_ExactTypeMatch;
802 // Check for nearly-matching types, based on classification of each.
803 else if ((getSimplifiedTypeClass(PreferredType)
Douglas Gregor95887f92010-07-08 23:20:03 +0000804 == getSimplifiedTypeClass(TC)) &&
Douglas Gregor50832e02010-09-20 22:39:41 +0000805 !(PreferredType->isEnumeralType() && TC->isEnumeralType()))
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000806 R.Priority /= CCF_SimilarTypeMatch;
Douglas Gregor50832e02010-09-20 22:39:41 +0000807 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000808 }
Douglas Gregor95887f92010-07-08 23:20:03 +0000809}
810
Douglas Gregor0212fd72010-09-21 16:06:22 +0000811void ResultBuilder::MaybeAddConstructorResults(Result R) {
David Blaikiebbafb8a2012-03-11 07:00:24 +0000812 if (!SemaRef.getLangOpts().CPlusPlus || !R.Declaration ||
Douglas Gregor0212fd72010-09-21 16:06:22 +0000813 !CompletionContext.wantConstructorResults())
814 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000815
Douglas Gregor0212fd72010-09-21 16:06:22 +0000816 ASTContext &Context = SemaRef.Context;
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000817 const NamedDecl *D = R.Declaration;
Craig Topperc3ec1492014-05-26 06:22:03 +0000818 const CXXRecordDecl *Record = nullptr;
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000819 if (const ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(D))
Douglas Gregor0212fd72010-09-21 16:06:22 +0000820 Record = ClassTemplate->getTemplatedDecl();
821 else if ((Record = dyn_cast<CXXRecordDecl>(D))) {
822 // Skip specializations and partial specializations.
823 if (isa<ClassTemplateSpecializationDecl>(Record))
824 return;
825 } else {
826 // There are no constructors here.
827 return;
828 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000829
Douglas Gregor0212fd72010-09-21 16:06:22 +0000830 Record = Record->getDefinition();
831 if (!Record)
832 return;
833
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000834
Douglas Gregor0212fd72010-09-21 16:06:22 +0000835 QualType RecordTy = Context.getTypeDeclType(Record);
836 DeclarationName ConstructorName
837 = Context.DeclarationNames.getCXXConstructorName(
838 Context.getCanonicalType(RecordTy));
Richard Smithcf4bdde2015-02-21 02:45:19 +0000839 DeclContext::lookup_result Ctors = Record->lookup(ConstructorName);
840 for (DeclContext::lookup_iterator I = Ctors.begin(),
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000841 E = Ctors.end();
842 I != E; ++I) {
David Blaikieff7d47a2012-12-19 00:45:41 +0000843 R.Declaration = *I;
Douglas Gregor0212fd72010-09-21 16:06:22 +0000844 R.CursorKind = getCursorKindForDecl(R.Declaration);
845 Results.push_back(R);
846 }
847}
848
Sam McCall63c59722018-01-22 20:44:47 +0000849static bool isConstructor(const Decl *ND) {
850 if (const auto *Tmpl = dyn_cast<FunctionTemplateDecl>(ND))
851 ND = Tmpl->getTemplatedDecl();
852 return isa<CXXConstructorDecl>(ND);
853}
854
Douglas Gregor7c208612010-01-14 00:20:49 +0000855void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) {
856 assert(!ShadowMaps.empty() && "Must enter into a results scope");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000857
Douglas Gregor7c208612010-01-14 00:20:49 +0000858 if (R.Kind != Result::RK_Declaration) {
859 // For non-declaration results, just add the result.
860 Results.push_back(R);
861 return;
862 }
863
864 // Look through using declarations.
Kirill Bobyrev47d7f522018-07-11 14:49:49 +0000865 if (const UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(R.Declaration)) {
866 CodeCompletionResult Result(Using->getTargetDecl(),
867 getBasePriority(Using->getTargetDecl()),
868 R.Qualifier);
869 Result.ShadowDecl = Using;
870 MaybeAddResult(Result, CurContext);
Douglas Gregor7c208612010-01-14 00:20:49 +0000871 return;
872 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000873
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000874 const Decl *CanonDecl = R.Declaration->getCanonicalDecl();
Douglas Gregor7c208612010-01-14 00:20:49 +0000875 unsigned IDNS = CanonDecl->getIdentifierNamespace();
876
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000877 bool AsNestedNameSpecifier = false;
878 if (!isInterestingDecl(R.Declaration, AsNestedNameSpecifier))
Douglas Gregor7c208612010-01-14 00:20:49 +0000879 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000880
Douglas Gregor0212fd72010-09-21 16:06:22 +0000881 // C++ constructors are never found by name lookup.
Sam McCall63c59722018-01-22 20:44:47 +0000882 if (isConstructor(R.Declaration))
Douglas Gregor0212fd72010-09-21 16:06:22 +0000883 return;
884
Douglas Gregor3545ff42009-09-21 16:56:56 +0000885 ShadowMap &SMap = ShadowMaps.back();
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000886 ShadowMapEntry::iterator I, IEnd;
887 ShadowMap::iterator NamePos = SMap.find(R.Declaration->getDeclName());
888 if (NamePos != SMap.end()) {
889 I = NamePos->second.begin();
890 IEnd = NamePos->second.end();
891 }
892
893 for (; I != IEnd; ++I) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000894 const NamedDecl *ND = I->first;
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000895 unsigned Index = I->second;
Douglas Gregor3545ff42009-09-21 16:56:56 +0000896 if (ND->getCanonicalDecl() == CanonDecl) {
897 // This is a redeclaration. Always pick the newer declaration.
Douglas Gregor3545ff42009-09-21 16:56:56 +0000898 Results[Index].Declaration = R.Declaration;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000899
Douglas Gregor3545ff42009-09-21 16:56:56 +0000900 // We're done.
901 return;
902 }
903 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000904
Douglas Gregor3545ff42009-09-21 16:56:56 +0000905 // This is a new declaration in this scope. However, check whether this
906 // declaration name is hidden by a similarly-named declaration in an outer
907 // scope.
908 std::list<ShadowMap>::iterator SM, SMEnd = ShadowMaps.end();
909 --SMEnd;
910 for (SM = ShadowMaps.begin(); SM != SMEnd; ++SM) {
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000911 ShadowMapEntry::iterator I, IEnd;
912 ShadowMap::iterator NamePos = SM->find(R.Declaration->getDeclName());
913 if (NamePos != SM->end()) {
914 I = NamePos->second.begin();
915 IEnd = NamePos->second.end();
916 }
917 for (; I != IEnd; ++I) {
Douglas Gregor3545ff42009-09-21 16:56:56 +0000918 // A tag declaration does not hide a non-tag declaration.
John McCalle87beb22010-04-23 18:46:30 +0000919 if (I->first->hasTagIdentifierNamespace() &&
Richard Smith541b38b2013-09-20 01:15:31 +0000920 (IDNS & (Decl::IDNS_Member | Decl::IDNS_Ordinary |
921 Decl::IDNS_LocalExtern | Decl::IDNS_ObjCProtocol)))
Douglas Gregor3545ff42009-09-21 16:56:56 +0000922 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000923
Douglas Gregor3545ff42009-09-21 16:56:56 +0000924 // Protocols are in distinct namespaces from everything else.
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000925 if (((I->first->getIdentifierNamespace() & Decl::IDNS_ObjCProtocol)
Douglas Gregor3545ff42009-09-21 16:56:56 +0000926 || (IDNS & Decl::IDNS_ObjCProtocol)) &&
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000927 I->first->getIdentifierNamespace() != IDNS)
Douglas Gregor3545ff42009-09-21 16:56:56 +0000928 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000929
Douglas Gregor3545ff42009-09-21 16:56:56 +0000930 // The newly-added result is hidden by an entry in the shadow map.
Douglas Gregore0717ab2010-01-14 00:41:07 +0000931 if (CheckHiddenResult(R, CurContext, I->first))
Douglas Gregor3545ff42009-09-21 16:56:56 +0000932 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000933
Douglas Gregor3545ff42009-09-21 16:56:56 +0000934 break;
935 }
936 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000937
Douglas Gregor3545ff42009-09-21 16:56:56 +0000938 // Make sure that any given declaration only shows up in the result set once.
David Blaikie82e95a32014-11-19 07:49:47 +0000939 if (!AllDeclsFound.insert(CanonDecl).second)
Douglas Gregor3545ff42009-09-21 16:56:56 +0000940 return;
Douglas Gregorc2cb2e22010-08-27 15:29:55 +0000941
Douglas Gregore412a5a2009-09-23 22:26:46 +0000942 // If the filter is for nested-name-specifiers, then this result starts a
943 // nested-name-specifier.
Douglas Gregora2db7932010-05-26 22:00:08 +0000944 if (AsNestedNameSpecifier) {
Douglas Gregore412a5a2009-09-23 22:26:46 +0000945 R.StartsNestedNameSpecifier = true;
Douglas Gregora2db7932010-05-26 22:00:08 +0000946 R.Priority = CCP_NestedNameSpecifier;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000947 } else
Douglas Gregor50832e02010-09-20 22:39:41 +0000948 AdjustResultPriorityForDecl(R);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000949
Douglas Gregor5bf52692009-09-22 23:15:58 +0000950 // If this result is supposed to have an informative qualifier, add one.
Douglas Gregore412a5a2009-09-23 22:26:46 +0000951 if (R.QualifierIsInformative && !R.Qualifier &&
952 !R.StartsNestedNameSpecifier) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000953 const DeclContext *Ctx = R.Declaration->getDeclContext();
954 if (const NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Ctx))
Craig Topperc3ec1492014-05-26 06:22:03 +0000955 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, nullptr,
956 Namespace);
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000957 else if (const TagDecl *Tag = dyn_cast<TagDecl>(Ctx))
Craig Topperc3ec1492014-05-26 06:22:03 +0000958 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, nullptr,
959 false, SemaRef.Context.getTypeDeclType(Tag).getTypePtr());
Douglas Gregor5bf52692009-09-22 23:15:58 +0000960 else
961 R.QualifierIsInformative = false;
962 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000963
Douglas Gregor3545ff42009-09-21 16:56:56 +0000964 // Insert this result into the set of results and into the current shadow
965 // map.
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000966 SMap[R.Declaration->getDeclName()].Add(R.Declaration, Results.size());
Douglas Gregor3545ff42009-09-21 16:56:56 +0000967 Results.push_back(R);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000968
Douglas Gregor0212fd72010-09-21 16:06:22 +0000969 if (!AsNestedNameSpecifier)
970 MaybeAddConstructorResults(R);
Douglas Gregor3545ff42009-09-21 16:56:56 +0000971}
972
Eric Liu4a7cd632018-10-24 12:57:27 +0000973static void setInBaseClass(ResultBuilder::Result &R) {
974 R.Priority += CCD_InBaseClass;
975 R.InBaseClass = true;
976}
977
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000978void ResultBuilder::AddResult(Result R, DeclContext *CurContext,
Douglas Gregor09bbc652010-01-14 15:47:35 +0000979 NamedDecl *Hiding, bool InBaseClass = false) {
Douglas Gregor78a21012010-01-14 16:01:26 +0000980 if (R.Kind != Result::RK_Declaration) {
981 // For non-declaration results, just add the result.
982 Results.push_back(R);
983 return;
984 }
985
Douglas Gregorc580c522010-01-14 01:09:38 +0000986 // Look through using declarations.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000987 if (const UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(R.Declaration)) {
Kirill Bobyrev47d7f522018-07-11 14:49:49 +0000988 CodeCompletionResult Result(Using->getTargetDecl(),
989 getBasePriority(Using->getTargetDecl()),
990 R.Qualifier);
991 Result.ShadowDecl = Using;
992 AddResult(Result, CurContext, Hiding);
Douglas Gregorc580c522010-01-14 01:09:38 +0000993 return;
994 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000995
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000996 bool AsNestedNameSpecifier = false;
997 if (!isInterestingDecl(R.Declaration, AsNestedNameSpecifier))
Douglas Gregorc580c522010-01-14 01:09:38 +0000998 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000999
Douglas Gregor0212fd72010-09-21 16:06:22 +00001000 // C++ constructors are never found by name lookup.
Sam McCall63c59722018-01-22 20:44:47 +00001001 if (isConstructor(R.Declaration))
Douglas Gregor0212fd72010-09-21 16:06:22 +00001002 return;
1003
Douglas Gregorc580c522010-01-14 01:09:38 +00001004 if (Hiding && CheckHiddenResult(R, CurContext, Hiding))
1005 return;
Nick Lewyckyc3921482012-04-03 21:44:08 +00001006
Douglas Gregorc580c522010-01-14 01:09:38 +00001007 // Make sure that any given declaration only shows up in the result set once.
David Blaikie82e95a32014-11-19 07:49:47 +00001008 if (!AllDeclsFound.insert(R.Declaration->getCanonicalDecl()).second)
Douglas Gregorc580c522010-01-14 01:09:38 +00001009 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001010
Douglas Gregorc580c522010-01-14 01:09:38 +00001011 // If the filter is for nested-name-specifiers, then this result starts a
1012 // nested-name-specifier.
Douglas Gregora2db7932010-05-26 22:00:08 +00001013 if (AsNestedNameSpecifier) {
Douglas Gregorc580c522010-01-14 01:09:38 +00001014 R.StartsNestedNameSpecifier = true;
Douglas Gregora2db7932010-05-26 22:00:08 +00001015 R.Priority = CCP_NestedNameSpecifier;
Kirill Bobyrev47d7f522018-07-11 14:49:49 +00001016 } else if (Filter == &ResultBuilder::IsMember && !R.Qualifier &&
1017 InBaseClass &&
1018 isa<CXXRecordDecl>(
1019 R.Declaration->getDeclContext()->getRedeclContext()))
Douglas Gregor09bbc652010-01-14 15:47:35 +00001020 R.QualifierIsInformative = true;
1021
Douglas Gregorc580c522010-01-14 01:09:38 +00001022 // If this result is supposed to have an informative qualifier, add one.
1023 if (R.QualifierIsInformative && !R.Qualifier &&
1024 !R.StartsNestedNameSpecifier) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001025 const DeclContext *Ctx = R.Declaration->getDeclContext();
1026 if (const NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Ctx))
Craig Topperc3ec1492014-05-26 06:22:03 +00001027 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, nullptr,
1028 Namespace);
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001029 else if (const TagDecl *Tag = dyn_cast<TagDecl>(Ctx))
Craig Topperc3ec1492014-05-26 06:22:03 +00001030 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, nullptr, false,
Douglas Gregor6ae4c522010-01-14 03:21:49 +00001031 SemaRef.Context.getTypeDeclType(Tag).getTypePtr());
Douglas Gregorc580c522010-01-14 01:09:38 +00001032 else
1033 R.QualifierIsInformative = false;
1034 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001035
Douglas Gregora2db7932010-05-26 22:00:08 +00001036 // Adjust the priority if this result comes from a base class.
1037 if (InBaseClass)
Eric Liu4a7cd632018-10-24 12:57:27 +00001038 setInBaseClass(R);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001039
Douglas Gregor50832e02010-09-20 22:39:41 +00001040 AdjustResultPriorityForDecl(R);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001041
Douglas Gregor9be0ed42010-08-26 16:36:48 +00001042 if (HasObjectTypeQualifiers)
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001043 if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(R.Declaration))
Douglas Gregor9be0ed42010-08-26 16:36:48 +00001044 if (Method->isInstance()) {
1045 Qualifiers MethodQuals
1046 = Qualifiers::fromCVRMask(Method->getTypeQualifiers());
1047 if (ObjectTypeQualifiers == MethodQuals)
1048 R.Priority += CCD_ObjectQualifierMatch;
1049 else if (ObjectTypeQualifiers - MethodQuals) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001050 // The method cannot be invoked, because doing so would drop
Douglas Gregor9be0ed42010-08-26 16:36:48 +00001051 // qualifiers.
1052 return;
1053 }
1054 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001055
Douglas Gregorc580c522010-01-14 01:09:38 +00001056 // Insert this result into the set of results.
1057 Results.push_back(R);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001058
Douglas Gregor0212fd72010-09-21 16:06:22 +00001059 if (!AsNestedNameSpecifier)
1060 MaybeAddConstructorResults(R);
Douglas Gregorc580c522010-01-14 01:09:38 +00001061}
1062
Douglas Gregor78a21012010-01-14 16:01:26 +00001063void ResultBuilder::AddResult(Result R) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001064 assert(R.Kind != Result::RK_Declaration &&
Douglas Gregor78a21012010-01-14 16:01:26 +00001065 "Declaration results need more context");
1066 Results.push_back(R);
1067}
1068
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001069/// Enter into a new scope.
Benjamin Kramer3204b152015-05-29 19:42:19 +00001070void ResultBuilder::EnterNewScope() { ShadowMaps.emplace_back(); }
Douglas Gregor3545ff42009-09-21 16:56:56 +00001071
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001072/// Exit from the current scope.
Douglas Gregor3545ff42009-09-21 16:56:56 +00001073void ResultBuilder::ExitScope() {
Douglas Gregor05e7ca32009-12-06 20:23:50 +00001074 for (ShadowMap::iterator E = ShadowMaps.back().begin(),
1075 EEnd = ShadowMaps.back().end();
1076 E != EEnd;
1077 ++E)
1078 E->second.Destroy();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001079
Douglas Gregor3545ff42009-09-21 16:56:56 +00001080 ShadowMaps.pop_back();
1081}
1082
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001083/// Determines whether this given declaration will be found by
Douglas Gregor9d64c5e2009-09-21 20:51:25 +00001084/// ordinary name lookup.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001085bool ResultBuilder::IsOrdinaryName(const NamedDecl *ND) const {
George Burgess IV00f70bd2018-03-01 05:43:23 +00001086 ND = ND->getUnderlyingDecl();
Douglas Gregor70febae2010-05-28 00:49:12 +00001087
Richard Smith541b38b2013-09-20 01:15:31 +00001088 // If name lookup finds a local extern declaration, then we are in a
1089 // context where it behaves like an ordinary name.
1090 unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_LocalExtern;
David Blaikiebbafb8a2012-03-11 07:00:24 +00001091 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregor9858ed52010-06-15 20:26:51 +00001092 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member;
Erik Pilkingtonfa983902018-10-30 20:31:30 +00001093 else if (SemaRef.getLangOpts().ObjC) {
Douglas Gregor05fcf842010-11-02 20:36:02 +00001094 if (isa<ObjCIvarDecl>(ND))
1095 return true;
Douglas Gregor05fcf842010-11-02 20:36:02 +00001096 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001097
Douglas Gregor9d64c5e2009-09-21 20:51:25 +00001098 return ND->getIdentifierNamespace() & IDNS;
1099}
1100
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001101/// Determines whether this given declaration will be found by
Douglas Gregor70febae2010-05-28 00:49:12 +00001102/// ordinary name lookup but is not a type name.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001103bool ResultBuilder::IsOrdinaryNonTypeName(const NamedDecl *ND) const {
George Burgess IV00f70bd2018-03-01 05:43:23 +00001104 ND = ND->getUnderlyingDecl();
Alex Lorenzf3df1f72017-11-14 01:46:24 +00001105 if (isa<TypeDecl>(ND))
Douglas Gregor70febae2010-05-28 00:49:12 +00001106 return false;
Alex Lorenzf3df1f72017-11-14 01:46:24 +00001107 // Objective-C interfaces names are not filtered by this method because they
1108 // can be used in a class property expression. We can still filter out
1109 // @class declarations though.
1110 if (const auto *ID = dyn_cast<ObjCInterfaceDecl>(ND)) {
1111 if (!ID->getDefinition())
1112 return false;
1113 }
1114
Richard Smith541b38b2013-09-20 01:15:31 +00001115 unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_LocalExtern;
David Blaikiebbafb8a2012-03-11 07:00:24 +00001116 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregor9858ed52010-06-15 20:26:51 +00001117 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member;
Erik Pilkingtonfa983902018-10-30 20:31:30 +00001118 else if (SemaRef.getLangOpts().ObjC) {
Douglas Gregor05fcf842010-11-02 20:36:02 +00001119 if (isa<ObjCIvarDecl>(ND))
1120 return true;
Douglas Gregor05fcf842010-11-02 20:36:02 +00001121 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001122
Douglas Gregor70febae2010-05-28 00:49:12 +00001123 return ND->getIdentifierNamespace() & IDNS;
1124}
1125
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001126bool ResultBuilder::IsIntegralConstantValue(const NamedDecl *ND) const {
Douglas Gregor85b50632010-07-28 21:50:18 +00001127 if (!IsOrdinaryNonTypeName(ND))
1128 return 0;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001129
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001130 if (const ValueDecl *VD = dyn_cast<ValueDecl>(ND->getUnderlyingDecl()))
Douglas Gregor85b50632010-07-28 21:50:18 +00001131 if (VD->getType()->isIntegralOrEnumerationType())
1132 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001133
Douglas Gregor85b50632010-07-28 21:50:18 +00001134 return false;
1135}
1136
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001137/// Determines whether this given declaration will be found by
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001138/// ordinary name lookup.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001139bool ResultBuilder::IsOrdinaryNonValueName(const NamedDecl *ND) const {
George Burgess IV00f70bd2018-03-01 05:43:23 +00001140 ND = ND->getUnderlyingDecl();
Douglas Gregor70febae2010-05-28 00:49:12 +00001141
Richard Smith541b38b2013-09-20 01:15:31 +00001142 unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_LocalExtern;
David Blaikiebbafb8a2012-03-11 07:00:24 +00001143 if (SemaRef.getLangOpts().CPlusPlus)
John McCalle87beb22010-04-23 18:46:30 +00001144 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001145
1146 return (ND->getIdentifierNamespace() & IDNS) &&
1147 !isa<ValueDecl>(ND) && !isa<FunctionTemplateDecl>(ND) &&
Douglas Gregor70febae2010-05-28 00:49:12 +00001148 !isa<ObjCPropertyDecl>(ND);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001149}
1150
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001151/// Determines whether the given declaration is suitable as the
Douglas Gregor3545ff42009-09-21 16:56:56 +00001152/// start of a C++ nested-name-specifier, e.g., a class or namespace.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001153bool ResultBuilder::IsNestedNameSpecifier(const NamedDecl *ND) const {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001154 // Allow us to find class templates, too.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001155 if (const ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
Douglas Gregor3545ff42009-09-21 16:56:56 +00001156 ND = ClassTemplate->getTemplatedDecl();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001157
Douglas Gregor3545ff42009-09-21 16:56:56 +00001158 return SemaRef.isAcceptableNestedNameSpecifier(ND);
1159}
1160
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001161/// Determines whether the given declaration is an enumeration.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001162bool ResultBuilder::IsEnum(const NamedDecl *ND) const {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001163 return isa<EnumDecl>(ND);
1164}
1165
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001166/// Determines whether the given declaration is a class or struct.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001167bool ResultBuilder::IsClassOrStruct(const NamedDecl *ND) const {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001168 // Allow us to find class templates, too.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001169 if (const ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
Douglas Gregor3545ff42009-09-21 16:56:56 +00001170 ND = ClassTemplate->getTemplatedDecl();
Joao Matosdc86f942012-08-31 18:45:21 +00001171
1172 // For purposes of this check, interfaces match too.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001173 if (const RecordDecl *RD = dyn_cast<RecordDecl>(ND))
Abramo Bagnara6150c882010-05-11 21:36:43 +00001174 return RD->getTagKind() == TTK_Class ||
Joao Matosdc86f942012-08-31 18:45:21 +00001175 RD->getTagKind() == TTK_Struct ||
1176 RD->getTagKind() == TTK_Interface;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001177
Douglas Gregor3545ff42009-09-21 16:56:56 +00001178 return false;
1179}
1180
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001181/// Determines whether the given declaration is a union.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001182bool ResultBuilder::IsUnion(const NamedDecl *ND) const {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001183 // Allow us to find class templates, too.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001184 if (const ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
Douglas Gregor3545ff42009-09-21 16:56:56 +00001185 ND = ClassTemplate->getTemplatedDecl();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001186
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001187 if (const RecordDecl *RD = dyn_cast<RecordDecl>(ND))
Abramo Bagnara6150c882010-05-11 21:36:43 +00001188 return RD->getTagKind() == TTK_Union;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001189
Douglas Gregor3545ff42009-09-21 16:56:56 +00001190 return false;
1191}
1192
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001193/// Determines whether the given declaration is a namespace.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001194bool ResultBuilder::IsNamespace(const NamedDecl *ND) const {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001195 return isa<NamespaceDecl>(ND);
1196}
1197
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001198/// Determines whether the given declaration is a namespace or
Douglas Gregor3545ff42009-09-21 16:56:56 +00001199/// namespace alias.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001200bool ResultBuilder::IsNamespaceOrAlias(const NamedDecl *ND) const {
Richard Smithf2005d32015-12-29 23:34:32 +00001201 return isa<NamespaceDecl>(ND->getUnderlyingDecl());
Douglas Gregor3545ff42009-09-21 16:56:56 +00001202}
1203
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001204/// Determines whether the given declaration is a type.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001205bool ResultBuilder::IsType(const NamedDecl *ND) const {
Richard Smithf2005d32015-12-29 23:34:32 +00001206 ND = ND->getUnderlyingDecl();
Douglas Gregor99fa2642010-08-24 01:06:58 +00001207 return isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND);
Douglas Gregor3545ff42009-09-21 16:56:56 +00001208}
1209
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001210/// Determines which members of a class should be visible via
Douglas Gregor99fe2ad2009-12-11 17:31:05 +00001211/// "." or "->". Only value declarations, nested name specifiers, and
1212/// using declarations thereof should show up.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001213bool ResultBuilder::IsMember(const NamedDecl *ND) const {
Richard Smithf2005d32015-12-29 23:34:32 +00001214 ND = ND->getUnderlyingDecl();
Douglas Gregor70788392009-12-11 18:14:22 +00001215 return isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND) ||
Richard Smithf2005d32015-12-29 23:34:32 +00001216 isa<ObjCPropertyDecl>(ND);
Douglas Gregore412a5a2009-09-23 22:26:46 +00001217}
1218
Douglas Gregora817a192010-05-27 23:06:34 +00001219static bool isObjCReceiverType(ASTContext &C, QualType T) {
1220 T = C.getCanonicalType(T);
1221 switch (T->getTypeClass()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001222 case Type::ObjCObject:
Douglas Gregora817a192010-05-27 23:06:34 +00001223 case Type::ObjCInterface:
1224 case Type::ObjCObjectPointer:
1225 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001226
Douglas Gregora817a192010-05-27 23:06:34 +00001227 case Type::Builtin:
1228 switch (cast<BuiltinType>(T)->getKind()) {
1229 case BuiltinType::ObjCId:
1230 case BuiltinType::ObjCClass:
1231 case BuiltinType::ObjCSel:
1232 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001233
Douglas Gregora817a192010-05-27 23:06:34 +00001234 default:
1235 break;
1236 }
1237 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001238
Douglas Gregora817a192010-05-27 23:06:34 +00001239 default:
1240 break;
1241 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001242
David Blaikiebbafb8a2012-03-11 07:00:24 +00001243 if (!C.getLangOpts().CPlusPlus)
Douglas Gregora817a192010-05-27 23:06:34 +00001244 return false;
1245
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001246 // FIXME: We could perform more analysis here to determine whether a
Douglas Gregora817a192010-05-27 23:06:34 +00001247 // particular class type has any conversions to Objective-C types. For now,
1248 // just accept all class types.
1249 return T->isDependentType() || T->isRecordType();
1250}
1251
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001252bool ResultBuilder::IsObjCMessageReceiver(const NamedDecl *ND) const {
Douglas Gregora817a192010-05-27 23:06:34 +00001253 QualType T = getDeclUsageType(SemaRef.Context, ND);
1254 if (T.isNull())
1255 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001256
Douglas Gregora817a192010-05-27 23:06:34 +00001257 T = SemaRef.Context.getBaseElementType(T);
1258 return isObjCReceiverType(SemaRef.Context, T);
1259}
1260
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001261bool ResultBuilder::IsObjCMessageReceiverOrLambdaCapture(const NamedDecl *ND) const {
Douglas Gregord8c61782012-02-15 15:34:24 +00001262 if (IsObjCMessageReceiver(ND))
1263 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001264
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001265 const VarDecl *Var = dyn_cast<VarDecl>(ND);
Douglas Gregord8c61782012-02-15 15:34:24 +00001266 if (!Var)
1267 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001268
Douglas Gregord8c61782012-02-15 15:34:24 +00001269 return Var->hasLocalStorage() && !Var->hasAttr<BlocksAttr>();
1270}
1271
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001272bool ResultBuilder::IsObjCCollection(const NamedDecl *ND) const {
David Blaikiebbafb8a2012-03-11 07:00:24 +00001273 if ((SemaRef.getLangOpts().CPlusPlus && !IsOrdinaryName(ND)) ||
1274 (!SemaRef.getLangOpts().CPlusPlus && !IsOrdinaryNonTypeName(ND)))
Douglas Gregor68762e72010-08-23 21:17:50 +00001275 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001276
Douglas Gregor68762e72010-08-23 21:17:50 +00001277 QualType T = getDeclUsageType(SemaRef.Context, ND);
1278 if (T.isNull())
1279 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001280
Douglas Gregor68762e72010-08-23 21:17:50 +00001281 T = SemaRef.Context.getBaseElementType(T);
1282 return T->isObjCObjectType() || T->isObjCObjectPointerType() ||
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001283 T->isObjCIdType() ||
David Blaikiebbafb8a2012-03-11 07:00:24 +00001284 (SemaRef.getLangOpts().CPlusPlus && T->isRecordType());
Douglas Gregor68762e72010-08-23 21:17:50 +00001285}
Douglas Gregora817a192010-05-27 23:06:34 +00001286
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001287bool ResultBuilder::IsImpossibleToSatisfy(const NamedDecl *ND) const {
Douglas Gregor0ac41382010-09-23 23:01:17 +00001288 return false;
1289}
1290
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001291/// Determines whether the given declaration is an Objective-C
Douglas Gregor2b8162b2010-01-14 16:08:12 +00001292/// instance variable.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001293bool ResultBuilder::IsObjCIvar(const NamedDecl *ND) const {
Douglas Gregor2b8162b2010-01-14 16:08:12 +00001294 return isa<ObjCIvarDecl>(ND);
1295}
1296
Douglas Gregorc580c522010-01-14 01:09:38 +00001297namespace {
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001298 /// Visible declaration consumer that adds a code-completion result
Douglas Gregorc580c522010-01-14 01:09:38 +00001299 /// for each visible declaration.
1300 class CodeCompletionDeclConsumer : public VisibleDeclConsumer {
1301 ResultBuilder &Results;
1302 DeclContext *CurContext;
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00001303 std::vector<FixItHint> FixIts;
Eric Liub91e0812018-10-02 10:29:00 +00001304 // This is set to the record where the search starts, if this is a record
1305 // member completion.
1306 RecordDecl *MemberCompletionRecord = nullptr;
Haojian Wu10d95c52018-01-17 14:29:25 +00001307
Douglas Gregorc580c522010-01-14 01:09:38 +00001308 public:
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00001309 CodeCompletionDeclConsumer(
1310 ResultBuilder &Results, DeclContext *CurContext,
Eric Liub91e0812018-10-02 10:29:00 +00001311 std::vector<FixItHint> FixIts = std::vector<FixItHint>(),
1312 RecordDecl *MemberCompletionRecord = nullptr)
1313 : Results(Results), CurContext(CurContext), FixIts(std::move(FixIts)),
1314 MemberCompletionRecord(MemberCompletionRecord) {}
Craig Toppere14c0f82014-03-12 04:55:44 +00001315
1316 void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx,
1317 bool InBaseClass) override {
Erik Verbruggen2e657ff2011-10-06 07:27:49 +00001318 bool Accessible = true;
Eric Liub91e0812018-10-02 10:29:00 +00001319 if (Ctx) {
1320 // Set the actual accessing context (i.e. naming class) to the record
1321 // context where the search starts. When `InBaseClass` is true, `Ctx`
1322 // will be the base class, which is not the actual naming class.
1323 DeclContext *AccessingCtx =
1324 MemberCompletionRecord ? MemberCompletionRecord : Ctx;
1325 Accessible = Results.getSema().IsSimplyAccessible(ND, AccessingCtx);
1326 }
Craig Topperc3ec1492014-05-26 06:22:03 +00001327 ResultBuilder::Result Result(ND, Results.getBasePriority(ND), nullptr,
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00001328 false, Accessible, FixIts);
Erik Verbruggen2e657ff2011-10-06 07:27:49 +00001329 Results.AddResult(Result, CurContext, Hiding, InBaseClass);
Douglas Gregorc580c522010-01-14 01:09:38 +00001330 }
Haojian Wu10d95c52018-01-17 14:29:25 +00001331
1332 void EnteredContext(DeclContext* Ctx) override {
1333 Results.addVisitedContext(Ctx);
1334 }
Douglas Gregorc580c522010-01-14 01:09:38 +00001335 };
Alexander Kornienkoab9db512015-06-22 23:07:51 +00001336}
Douglas Gregorc580c522010-01-14 01:09:38 +00001337
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001338/// Add type specifiers for the current language as keyword results.
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001339static void AddTypeSpecifierResults(const LangOptions &LangOpts,
Douglas Gregor3545ff42009-09-21 16:56:56 +00001340 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00001341 typedef CodeCompletionResult Result;
Douglas Gregora2db7932010-05-26 22:00:08 +00001342 Results.AddResult(Result("short", CCP_Type));
1343 Results.AddResult(Result("long", CCP_Type));
1344 Results.AddResult(Result("signed", CCP_Type));
1345 Results.AddResult(Result("unsigned", CCP_Type));
1346 Results.AddResult(Result("void", CCP_Type));
1347 Results.AddResult(Result("char", CCP_Type));
1348 Results.AddResult(Result("int", CCP_Type));
1349 Results.AddResult(Result("float", CCP_Type));
1350 Results.AddResult(Result("double", CCP_Type));
1351 Results.AddResult(Result("enum", CCP_Type));
1352 Results.AddResult(Result("struct", CCP_Type));
1353 Results.AddResult(Result("union", CCP_Type));
1354 Results.AddResult(Result("const", CCP_Type));
1355 Results.AddResult(Result("volatile", CCP_Type));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001356
Douglas Gregor3545ff42009-09-21 16:56:56 +00001357 if (LangOpts.C99) {
1358 // C99-specific
Douglas Gregora2db7932010-05-26 22:00:08 +00001359 Results.AddResult(Result("_Complex", CCP_Type));
1360 Results.AddResult(Result("_Imaginary", CCP_Type));
1361 Results.AddResult(Result("_Bool", CCP_Type));
1362 Results.AddResult(Result("restrict", CCP_Type));
Douglas Gregor3545ff42009-09-21 16:56:56 +00001363 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001364
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00001365 CodeCompletionBuilder Builder(Results.getAllocator(),
1366 Results.getCodeCompletionTUInfo());
Douglas Gregor3545ff42009-09-21 16:56:56 +00001367 if (LangOpts.CPlusPlus) {
1368 // C++-specific
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001369 Results.AddResult(Result("bool", CCP_Type +
Erik Pilkingtonfa983902018-10-30 20:31:30 +00001370 (LangOpts.ObjC ? CCD_bool_in_ObjC : 0)));
Douglas Gregora2db7932010-05-26 22:00:08 +00001371 Results.AddResult(Result("class", CCP_Type));
1372 Results.AddResult(Result("wchar_t", CCP_Type));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001373
Douglas Gregorf4c33342010-05-28 00:22:41 +00001374 // typename qualified-id
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001375 Builder.AddTypedTextChunk("typename");
1376 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1377 Builder.AddPlaceholderChunk("qualifier");
1378 Builder.AddTextChunk("::");
1379 Builder.AddPlaceholderChunk("name");
1380 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001381
Richard Smith2bf7fdb2013-01-02 11:42:31 +00001382 if (LangOpts.CPlusPlus11) {
Douglas Gregora2db7932010-05-26 22:00:08 +00001383 Results.AddResult(Result("auto", CCP_Type));
1384 Results.AddResult(Result("char16_t", CCP_Type));
1385 Results.AddResult(Result("char32_t", CCP_Type));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001386
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001387 Builder.AddTypedTextChunk("decltype");
1388 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1389 Builder.AddPlaceholderChunk("expression");
1390 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1391 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor3545ff42009-09-21 16:56:56 +00001392 }
Alex Lorenz46eed9d2017-02-13 23:35:59 +00001393 } else
1394 Results.AddResult(Result("__auto_type", CCP_Type));
1395
Richard Smith7b301e22018-05-24 21:51:52 +00001396 // GNU keywords
1397 if (LangOpts.GNUKeywords) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001398 // FIXME: Enable when we actually support decimal floating point.
Douglas Gregor78a21012010-01-14 16:01:26 +00001399 // Results.AddResult(Result("_Decimal32"));
1400 // Results.AddResult(Result("_Decimal64"));
1401 // Results.AddResult(Result("_Decimal128"));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001402
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001403 Builder.AddTypedTextChunk("typeof");
1404 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1405 Builder.AddPlaceholderChunk("expression");
1406 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00001407
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001408 Builder.AddTypedTextChunk("typeof");
1409 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1410 Builder.AddPlaceholderChunk("type");
1411 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1412 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor3545ff42009-09-21 16:56:56 +00001413 }
Douglas Gregor86b42682015-06-19 18:27:52 +00001414
1415 // Nullability
Douglas Gregoraea7afd2015-06-24 22:02:08 +00001416 Results.AddResult(Result("_Nonnull", CCP_Type));
1417 Results.AddResult(Result("_Null_unspecified", CCP_Type));
1418 Results.AddResult(Result("_Nullable", CCP_Type));
Douglas Gregor3545ff42009-09-21 16:56:56 +00001419}
1420
John McCallfaf5fb42010-08-26 23:41:50 +00001421static void AddStorageSpecifiers(Sema::ParserCompletionContext CCC,
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001422 const LangOptions &LangOpts,
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001423 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00001424 typedef CodeCompletionResult Result;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001425 // Note: we don't suggest either "auto" or "register", because both
1426 // are pointless as storage specifiers. Elsewhere, we suggest "auto"
1427 // in C++0x as a type specifier.
Douglas Gregor78a21012010-01-14 16:01:26 +00001428 Results.AddResult(Result("extern"));
1429 Results.AddResult(Result("static"));
Alex Lorenz8f4d3992017-02-13 23:19:40 +00001430
1431 if (LangOpts.CPlusPlus11) {
1432 CodeCompletionAllocator &Allocator = Results.getAllocator();
1433 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
1434
1435 // alignas
1436 Builder.AddTypedTextChunk("alignas");
1437 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1438 Builder.AddPlaceholderChunk("expression");
1439 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1440 Results.AddResult(Result(Builder.TakeString()));
1441
1442 Results.AddResult(Result("constexpr"));
1443 Results.AddResult(Result("thread_local"));
1444 }
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001445}
1446
John McCallfaf5fb42010-08-26 23:41:50 +00001447static void AddFunctionSpecifiers(Sema::ParserCompletionContext CCC,
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001448 const LangOptions &LangOpts,
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001449 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00001450 typedef CodeCompletionResult Result;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001451 switch (CCC) {
John McCallfaf5fb42010-08-26 23:41:50 +00001452 case Sema::PCC_Class:
1453 case Sema::PCC_MemberTemplate:
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001454 if (LangOpts.CPlusPlus) {
Douglas Gregor78a21012010-01-14 16:01:26 +00001455 Results.AddResult(Result("explicit"));
1456 Results.AddResult(Result("friend"));
1457 Results.AddResult(Result("mutable"));
1458 Results.AddResult(Result("virtual"));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001459 }
Adrian Prantlf3b3ccd2017-12-19 22:06:11 +00001460 LLVM_FALLTHROUGH;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001461
John McCallfaf5fb42010-08-26 23:41:50 +00001462 case Sema::PCC_ObjCInterface:
1463 case Sema::PCC_ObjCImplementation:
1464 case Sema::PCC_Namespace:
1465 case Sema::PCC_Template:
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001466 if (LangOpts.CPlusPlus || LangOpts.C99)
Douglas Gregor78a21012010-01-14 16:01:26 +00001467 Results.AddResult(Result("inline"));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001468 break;
1469
John McCallfaf5fb42010-08-26 23:41:50 +00001470 case Sema::PCC_ObjCInstanceVariableList:
1471 case Sema::PCC_Expression:
1472 case Sema::PCC_Statement:
1473 case Sema::PCC_ForInit:
1474 case Sema::PCC_Condition:
1475 case Sema::PCC_RecoveryInFunction:
1476 case Sema::PCC_Type:
Douglas Gregor5e35d592010-09-14 23:59:36 +00001477 case Sema::PCC_ParenthesizedExpression:
Douglas Gregor80039242011-02-15 20:33:25 +00001478 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001479 break;
1480 }
1481}
1482
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001483static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt);
1484static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt);
1485static void AddObjCVisibilityResults(const LangOptions &LangOpts,
Douglas Gregor48d46252010-01-13 21:54:15 +00001486 ResultBuilder &Results,
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001487 bool NeedAt);
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001488static void AddObjCImplementationResults(const LangOptions &LangOpts,
Douglas Gregorf1934162010-01-13 21:24:21 +00001489 ResultBuilder &Results,
1490 bool NeedAt);
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001491static void AddObjCInterfaceResults(const LangOptions &LangOpts,
Douglas Gregorf1934162010-01-13 21:24:21 +00001492 ResultBuilder &Results,
1493 bool NeedAt);
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001494static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt);
Douglas Gregorf1934162010-01-13 21:24:21 +00001495
Douglas Gregorf4c33342010-05-28 00:22:41 +00001496static void AddTypedefResult(ResultBuilder &Results) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00001497 CodeCompletionBuilder Builder(Results.getAllocator(),
1498 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001499 Builder.AddTypedTextChunk("typedef");
1500 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1501 Builder.AddPlaceholderChunk("type");
1502 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1503 Builder.AddPlaceholderChunk("name");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001504 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00001505}
1506
John McCallfaf5fb42010-08-26 23:41:50 +00001507static bool WantTypesInContext(Sema::ParserCompletionContext CCC,
Douglas Gregor70febae2010-05-28 00:49:12 +00001508 const LangOptions &LangOpts) {
Douglas Gregor70febae2010-05-28 00:49:12 +00001509 switch (CCC) {
John McCallfaf5fb42010-08-26 23:41:50 +00001510 case Sema::PCC_Namespace:
1511 case Sema::PCC_Class:
1512 case Sema::PCC_ObjCInstanceVariableList:
1513 case Sema::PCC_Template:
1514 case Sema::PCC_MemberTemplate:
1515 case Sema::PCC_Statement:
1516 case Sema::PCC_RecoveryInFunction:
1517 case Sema::PCC_Type:
Douglas Gregor5e35d592010-09-14 23:59:36 +00001518 case Sema::PCC_ParenthesizedExpression:
Douglas Gregor80039242011-02-15 20:33:25 +00001519 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregor70febae2010-05-28 00:49:12 +00001520 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001521
John McCallfaf5fb42010-08-26 23:41:50 +00001522 case Sema::PCC_Expression:
1523 case Sema::PCC_Condition:
Douglas Gregor5e35d592010-09-14 23:59:36 +00001524 return LangOpts.CPlusPlus;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001525
Douglas Gregor5e35d592010-09-14 23:59:36 +00001526 case Sema::PCC_ObjCInterface:
1527 case Sema::PCC_ObjCImplementation:
Douglas Gregor70febae2010-05-28 00:49:12 +00001528 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001529
John McCallfaf5fb42010-08-26 23:41:50 +00001530 case Sema::PCC_ForInit:
Erik Pilkingtonfa983902018-10-30 20:31:30 +00001531 return LangOpts.CPlusPlus || LangOpts.ObjC || LangOpts.C99;
Douglas Gregor70febae2010-05-28 00:49:12 +00001532 }
David Blaikie8a40f702012-01-17 06:56:22 +00001533
1534 llvm_unreachable("Invalid ParserCompletionContext!");
Douglas Gregor70febae2010-05-28 00:49:12 +00001535}
1536
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00001537static PrintingPolicy getCompletionPrintingPolicy(const ASTContext &Context,
1538 const Preprocessor &PP) {
1539 PrintingPolicy Policy = Sema::getPrintingPolicy(Context, PP);
Douglas Gregore5c79d52011-10-18 21:20:17 +00001540 Policy.AnonymousTagLocations = false;
1541 Policy.SuppressStrongLifetime = true;
Douglas Gregor2e10cf92011-11-03 00:16:13 +00001542 Policy.SuppressUnwrittenScope = true;
Ilya Biryukovb5da91c2017-11-08 10:39:09 +00001543 Policy.SuppressScope = true;
Douglas Gregore5c79d52011-10-18 21:20:17 +00001544 return Policy;
1545}
1546
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001547/// Retrieve a printing policy suitable for code completion.
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00001548static PrintingPolicy getCompletionPrintingPolicy(Sema &S) {
1549 return getCompletionPrintingPolicy(S.Context, S.PP);
1550}
1551
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001552/// Retrieve the string representation of the given type as a string
Douglas Gregore5c79d52011-10-18 21:20:17 +00001553/// that has the appropriate lifetime for code completion.
1554///
1555/// This routine provides a fast path where we provide constant strings for
1556/// common type names.
1557static const char *GetCompletionTypeString(QualType T,
1558 ASTContext &Context,
1559 const PrintingPolicy &Policy,
1560 CodeCompletionAllocator &Allocator) {
1561 if (!T.getLocalQualifiers()) {
1562 // Built-in type names are constant strings.
1563 if (const BuiltinType *BT = dyn_cast<BuiltinType>(T))
Argyrios Kyrtzidisbbff3da2012-05-05 04:20:28 +00001564 return BT->getNameAsCString(Policy);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001565
Douglas Gregore5c79d52011-10-18 21:20:17 +00001566 // Anonymous tag types are constant strings.
1567 if (const TagType *TagT = dyn_cast<TagType>(T))
1568 if (TagDecl *Tag = TagT->getDecl())
John McCall5ea95772013-03-09 00:54:27 +00001569 if (!Tag->hasNameForLinkage()) {
Douglas Gregore5c79d52011-10-18 21:20:17 +00001570 switch (Tag->getTagKind()) {
1571 case TTK_Struct: return "struct <anonymous>";
Joao Matosdc86f942012-08-31 18:45:21 +00001572 case TTK_Interface: return "__interface <anonymous>";
1573 case TTK_Class: return "class <anonymous>";
Douglas Gregore5c79d52011-10-18 21:20:17 +00001574 case TTK_Union: return "union <anonymous>";
1575 case TTK_Enum: return "enum <anonymous>";
1576 }
1577 }
1578 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001579
Douglas Gregore5c79d52011-10-18 21:20:17 +00001580 // Slow path: format the type as a string.
1581 std::string Result;
1582 T.getAsStringInternal(Result, Policy);
1583 return Allocator.CopyString(Result);
1584}
1585
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001586/// Add a completion for "this", if we're in a member function.
Douglas Gregord8c61782012-02-15 15:34:24 +00001587static void addThisCompletion(Sema &S, ResultBuilder &Results) {
1588 QualType ThisTy = S.getCurrentThisType();
1589 if (ThisTy.isNull())
1590 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001591
Douglas Gregord8c61782012-02-15 15:34:24 +00001592 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00001593 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Douglas Gregord8c61782012-02-15 15:34:24 +00001594 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001595 Builder.AddResultTypeChunk(GetCompletionTypeString(ThisTy,
1596 S.Context,
Douglas Gregord8c61782012-02-15 15:34:24 +00001597 Policy,
1598 Allocator));
1599 Builder.AddTypedTextChunk("this");
Joao Matosdc86f942012-08-31 18:45:21 +00001600 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
Douglas Gregord8c61782012-02-15 15:34:24 +00001601}
1602
Alex Lorenz8f4d3992017-02-13 23:19:40 +00001603static void AddStaticAssertResult(CodeCompletionBuilder &Builder,
1604 ResultBuilder &Results,
1605 const LangOptions &LangOpts) {
1606 if (!LangOpts.CPlusPlus11)
1607 return;
1608
1609 Builder.AddTypedTextChunk("static_assert");
1610 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1611 Builder.AddPlaceholderChunk("expression");
1612 Builder.AddChunk(CodeCompletionString::CK_Comma);
1613 Builder.AddPlaceholderChunk("message");
1614 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1615 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
1616}
1617
Kadir Cetinkayaae45d0a42018-10-02 09:42:31 +00001618namespace {
1619void printOverrideString(llvm::raw_ostream &OS, CodeCompletionString *CCS) {
1620 for (const auto &C : *CCS) {
1621 if (C.Kind == CodeCompletionString::CK_Optional)
1622 printOverrideString(OS, C.Optional);
1623 else
1624 OS << C.Text;
1625 // Add a space after return type.
1626 if (C.Kind == CodeCompletionString::CK_ResultType)
1627 OS << ' ';
1628 }
1629}
1630} // namespace
1631
1632static void AddOverrideResults(ResultBuilder &Results,
1633 const CodeCompletionContext &CCContext,
1634 CodeCompletionBuilder &Builder) {
1635 Sema &S = Results.getSema();
1636 const auto *CR = llvm::dyn_cast<CXXRecordDecl>(S.CurContext);
1637 // If not inside a class/struct/union return empty.
1638 if (!CR)
1639 return;
1640 // First store overrides within current class.
1641 // These are stored by name to make querying fast in the later step.
1642 llvm::StringMap<std::vector<FunctionDecl *>> Overrides;
1643 for (auto *Method : CR->methods()) {
1644 if (!Method->isVirtual() || !Method->getIdentifier())
1645 continue;
1646 Overrides[Method->getName()].push_back(Method);
1647 }
1648
1649 for (const auto &Base : CR->bases()) {
1650 const auto *BR = Base.getType().getTypePtr()->getAsCXXRecordDecl();
1651 if (!BR)
1652 continue;
1653 for (auto *Method : BR->methods()) {
1654 if (!Method->isVirtual() || !Method->getIdentifier())
1655 continue;
1656 const auto it = Overrides.find(Method->getName());
1657 bool IsOverriden = false;
1658 if (it != Overrides.end()) {
1659 for (auto *MD : it->second) {
1660 // If the method in current body is not an overload of this virtual
1661 // function, then it overrides this one.
1662 if (!S.IsOverload(MD, Method, false)) {
1663 IsOverriden = true;
1664 break;
1665 }
1666 }
1667 }
1668 if (!IsOverriden) {
1669 // Generates a new CodeCompletionResult by taking this function and
1670 // converting it into an override declaration with only one chunk in the
1671 // final CodeCompletionString as a TypedTextChunk.
1672 std::string OverrideSignature;
1673 llvm::raw_string_ostream OS(OverrideSignature);
1674 CodeCompletionResult CCR(Method, 0);
1675 PrintingPolicy Policy =
1676 getCompletionPrintingPolicy(S.getASTContext(), S.getPreprocessor());
1677 auto *CCS = CCR.createCodeCompletionStringForOverride(
1678 S.getPreprocessor(), S.getASTContext(), Builder,
1679 /*IncludeBriefComments=*/false, CCContext, Policy);
1680 Results.AddResult(CodeCompletionResult(CCS, Method, CCP_CodePattern));
1681 }
1682 }
1683 }
1684}
1685
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001686/// Add language constructs that show up for "ordinary" names.
John McCallfaf5fb42010-08-26 23:41:50 +00001687static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001688 Scope *S,
1689 Sema &SemaRef,
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001690 ResultBuilder &Results) {
Douglas Gregore5c79d52011-10-18 21:20:17 +00001691 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00001692 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001693
John McCall276321a2010-08-25 06:19:51 +00001694 typedef CodeCompletionResult Result;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001695 switch (CCC) {
John McCallfaf5fb42010-08-26 23:41:50 +00001696 case Sema::PCC_Namespace:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001697 if (SemaRef.getLangOpts().CPlusPlus) {
Douglas Gregorf4c33342010-05-28 00:22:41 +00001698 if (Results.includeCodePatterns()) {
1699 // namespace <identifier> { declarations }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001700 Builder.AddTypedTextChunk("namespace");
1701 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1702 Builder.AddPlaceholderChunk("identifier");
1703 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1704 Builder.AddPlaceholderChunk("declarations");
1705 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1706 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1707 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00001708 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001709
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001710 // namespace identifier = identifier ;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001711 Builder.AddTypedTextChunk("namespace");
1712 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1713 Builder.AddPlaceholderChunk("name");
1714 Builder.AddChunk(CodeCompletionString::CK_Equal);
1715 Builder.AddPlaceholderChunk("namespace");
1716 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001717
1718 // Using directives
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001719 Builder.AddTypedTextChunk("using");
1720 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1721 Builder.AddTextChunk("namespace");
1722 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1723 Builder.AddPlaceholderChunk("identifier");
1724 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001725
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001726 // asm(string-literal)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001727 Builder.AddTypedTextChunk("asm");
1728 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1729 Builder.AddPlaceholderChunk("string-literal");
1730 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1731 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001732
Douglas Gregorf4c33342010-05-28 00:22:41 +00001733 if (Results.includeCodePatterns()) {
1734 // Explicit template instantiation
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001735 Builder.AddTypedTextChunk("template");
1736 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1737 Builder.AddPlaceholderChunk("declaration");
1738 Results.AddResult(Result(Builder.TakeString()));
Eric Liub87c6eb2018-10-15 12:37:23 +00001739 } else {
1740 Results.AddResult(Result("template", CodeCompletionResult::RK_Keyword));
Douglas Gregorf4c33342010-05-28 00:22:41 +00001741 }
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001742 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001743
Erik Pilkingtonfa983902018-10-30 20:31:30 +00001744 if (SemaRef.getLangOpts().ObjC)
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001745 AddObjCTopLevelResults(Results, true);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001746
Douglas Gregorf4c33342010-05-28 00:22:41 +00001747 AddTypedefResult(Results);
Adrian Prantlf3b3ccd2017-12-19 22:06:11 +00001748 LLVM_FALLTHROUGH;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001749
John McCallfaf5fb42010-08-26 23:41:50 +00001750 case Sema::PCC_Class:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001751 if (SemaRef.getLangOpts().CPlusPlus) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001752 // Using declaration
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001753 Builder.AddTypedTextChunk("using");
1754 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1755 Builder.AddPlaceholderChunk("qualifier");
1756 Builder.AddTextChunk("::");
1757 Builder.AddPlaceholderChunk("name");
1758 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001759
Douglas Gregorf4c33342010-05-28 00:22:41 +00001760 // using typename qualifier::name (only in a dependent context)
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001761 if (SemaRef.CurContext->isDependentContext()) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001762 Builder.AddTypedTextChunk("using");
1763 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1764 Builder.AddTextChunk("typename");
1765 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1766 Builder.AddPlaceholderChunk("qualifier");
1767 Builder.AddTextChunk("::");
1768 Builder.AddPlaceholderChunk("name");
1769 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001770 }
1771
Alex Lorenz8f4d3992017-02-13 23:19:40 +00001772 AddStaticAssertResult(Builder, Results, SemaRef.getLangOpts());
1773
John McCallfaf5fb42010-08-26 23:41:50 +00001774 if (CCC == Sema::PCC_Class) {
Douglas Gregorf4c33342010-05-28 00:22:41 +00001775 AddTypedefResult(Results);
1776
Erik Verbruggen6524c052017-10-24 13:46:58 +00001777 bool IsNotInheritanceScope =
1778 !(S->getFlags() & Scope::ClassInheritanceScope);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001779 // public:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001780 Builder.AddTypedTextChunk("public");
Erik Verbruggen6524c052017-10-24 13:46:58 +00001781 if (IsNotInheritanceScope && Results.includeCodePatterns())
Douglas Gregor9489cdf2012-04-10 17:56:28 +00001782 Builder.AddChunk(CodeCompletionString::CK_Colon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001783 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001784
1785 // protected:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001786 Builder.AddTypedTextChunk("protected");
Erik Verbruggen6524c052017-10-24 13:46:58 +00001787 if (IsNotInheritanceScope && Results.includeCodePatterns())
Douglas Gregor9489cdf2012-04-10 17:56:28 +00001788 Builder.AddChunk(CodeCompletionString::CK_Colon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001789 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001790
1791 // private:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001792 Builder.AddTypedTextChunk("private");
Erik Verbruggen6524c052017-10-24 13:46:58 +00001793 if (IsNotInheritanceScope && Results.includeCodePatterns())
Douglas Gregor9489cdf2012-04-10 17:56:28 +00001794 Builder.AddChunk(CodeCompletionString::CK_Colon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001795 Results.AddResult(Result(Builder.TakeString()));
Kadir Cetinkayaae45d0a42018-10-02 09:42:31 +00001796
1797 // FIXME: This adds override results only if we are at the first word of
1798 // the declaration/definition. Also call this from other sides to have
1799 // more use-cases.
1800 AddOverrideResults(Results, CodeCompletionContext::CCC_ClassStructUnion,
1801 Builder);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001802 }
1803 }
Adrian Prantlf3b3ccd2017-12-19 22:06:11 +00001804 LLVM_FALLTHROUGH;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001805
John McCallfaf5fb42010-08-26 23:41:50 +00001806 case Sema::PCC_Template:
1807 case Sema::PCC_MemberTemplate:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001808 if (SemaRef.getLangOpts().CPlusPlus && Results.includeCodePatterns()) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001809 // template < parameters >
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001810 Builder.AddTypedTextChunk("template");
1811 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1812 Builder.AddPlaceholderChunk("parameters");
1813 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1814 Results.AddResult(Result(Builder.TakeString()));
Eric Liub87c6eb2018-10-15 12:37:23 +00001815 } else {
1816 Results.AddResult(Result("template", CodeCompletionResult::RK_Keyword));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001817 }
1818
David Blaikiebbafb8a2012-03-11 07:00:24 +00001819 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
1820 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001821 break;
1822
John McCallfaf5fb42010-08-26 23:41:50 +00001823 case Sema::PCC_ObjCInterface:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001824 AddObjCInterfaceResults(SemaRef.getLangOpts(), Results, true);
1825 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
1826 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregorf1934162010-01-13 21:24:21 +00001827 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001828
John McCallfaf5fb42010-08-26 23:41:50 +00001829 case Sema::PCC_ObjCImplementation:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001830 AddObjCImplementationResults(SemaRef.getLangOpts(), Results, true);
1831 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
1832 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregorf1934162010-01-13 21:24:21 +00001833 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001834
John McCallfaf5fb42010-08-26 23:41:50 +00001835 case Sema::PCC_ObjCInstanceVariableList:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001836 AddObjCVisibilityResults(SemaRef.getLangOpts(), Results, true);
Douglas Gregor48d46252010-01-13 21:54:15 +00001837 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001838
John McCallfaf5fb42010-08-26 23:41:50 +00001839 case Sema::PCC_RecoveryInFunction:
1840 case Sema::PCC_Statement: {
Douglas Gregorf4c33342010-05-28 00:22:41 +00001841 AddTypedefResult(Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001842
David Blaikiebbafb8a2012-03-11 07:00:24 +00001843 if (SemaRef.getLangOpts().CPlusPlus && Results.includeCodePatterns() &&
1844 SemaRef.getLangOpts().CXXExceptions) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001845 Builder.AddTypedTextChunk("try");
1846 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1847 Builder.AddPlaceholderChunk("statements");
1848 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1849 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1850 Builder.AddTextChunk("catch");
1851 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1852 Builder.AddPlaceholderChunk("declaration");
1853 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1854 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1855 Builder.AddPlaceholderChunk("statements");
1856 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1857 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1858 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001859 }
Erik Pilkingtonfa983902018-10-30 20:31:30 +00001860 if (SemaRef.getLangOpts().ObjC)
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001861 AddObjCStatementResults(Results, true);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001862
Douglas Gregorf64acca2010-05-25 21:41:55 +00001863 if (Results.includeCodePatterns()) {
1864 // if (condition) { statements }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001865 Builder.AddTypedTextChunk("if");
1866 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00001867 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001868 Builder.AddPlaceholderChunk("condition");
Douglas Gregorf64acca2010-05-25 21:41:55 +00001869 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001870 Builder.AddPlaceholderChunk("expression");
1871 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1872 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1873 Builder.AddPlaceholderChunk("statements");
1874 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1875 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1876 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001877
Douglas Gregorf64acca2010-05-25 21:41:55 +00001878 // switch (condition) { }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001879 Builder.AddTypedTextChunk("switch");
1880 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00001881 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001882 Builder.AddPlaceholderChunk("condition");
Douglas Gregorf64acca2010-05-25 21:41:55 +00001883 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001884 Builder.AddPlaceholderChunk("expression");
1885 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1886 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1887 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1888 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1889 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf64acca2010-05-25 21:41:55 +00001890 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001891
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001892 // Switch-specific statements.
Sam McCallaeb4b3e2018-10-10 10:51:48 +00001893 if (SemaRef.getCurFunction() &&
1894 !SemaRef.getCurFunction()->SwitchStack.empty()) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001895 // case expression:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001896 Builder.AddTypedTextChunk("case");
1897 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1898 Builder.AddPlaceholderChunk("expression");
1899 Builder.AddChunk(CodeCompletionString::CK_Colon);
1900 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001901
1902 // default:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001903 Builder.AddTypedTextChunk("default");
1904 Builder.AddChunk(CodeCompletionString::CK_Colon);
1905 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001906 }
1907
Douglas Gregorf64acca2010-05-25 21:41:55 +00001908 if (Results.includeCodePatterns()) {
1909 /// while (condition) { statements }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001910 Builder.AddTypedTextChunk("while");
1911 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00001912 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001913 Builder.AddPlaceholderChunk("condition");
Douglas Gregorf64acca2010-05-25 21:41:55 +00001914 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001915 Builder.AddPlaceholderChunk("expression");
1916 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1917 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1918 Builder.AddPlaceholderChunk("statements");
1919 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1920 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1921 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf64acca2010-05-25 21:41:55 +00001922
1923 // do { statements } while ( expression );
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001924 Builder.AddTypedTextChunk("do");
1925 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1926 Builder.AddPlaceholderChunk("statements");
1927 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1928 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1929 Builder.AddTextChunk("while");
1930 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1931 Builder.AddPlaceholderChunk("expression");
1932 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1933 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001934
Douglas Gregorf64acca2010-05-25 21:41:55 +00001935 // for ( for-init-statement ; condition ; expression ) { statements }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001936 Builder.AddTypedTextChunk("for");
1937 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00001938 if (SemaRef.getLangOpts().CPlusPlus || SemaRef.getLangOpts().C99)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001939 Builder.AddPlaceholderChunk("init-statement");
Douglas Gregorf64acca2010-05-25 21:41:55 +00001940 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001941 Builder.AddPlaceholderChunk("init-expression");
1942 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
1943 Builder.AddPlaceholderChunk("condition");
1944 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
1945 Builder.AddPlaceholderChunk("inc-expression");
1946 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1947 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1948 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1949 Builder.AddPlaceholderChunk("statements");
1950 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1951 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1952 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf64acca2010-05-25 21:41:55 +00001953 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001954
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001955 if (S->getContinueParent()) {
1956 // continue ;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001957 Builder.AddTypedTextChunk("continue");
1958 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001959 }
1960
1961 if (S->getBreakParent()) {
1962 // break ;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001963 Builder.AddTypedTextChunk("break");
1964 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001965 }
1966
1967 // "return expression ;" or "return ;", depending on whether we
1968 // know the function is void or not.
1969 bool isVoid = false;
1970 if (FunctionDecl *Function = dyn_cast<FunctionDecl>(SemaRef.CurContext))
Alp Toker314cc812014-01-25 16:55:45 +00001971 isVoid = Function->getReturnType()->isVoidType();
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001972 else if (ObjCMethodDecl *Method
1973 = dyn_cast<ObjCMethodDecl>(SemaRef.CurContext))
Alp Toker314cc812014-01-25 16:55:45 +00001974 isVoid = Method->getReturnType()->isVoidType();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001975 else if (SemaRef.getCurBlock() &&
Douglas Gregor9a28e842010-03-01 23:15:13 +00001976 !SemaRef.getCurBlock()->ReturnType.isNull())
1977 isVoid = SemaRef.getCurBlock()->ReturnType->isVoidType();
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001978 Builder.AddTypedTextChunk("return");
Douglas Gregor44272ca2010-02-18 04:06:48 +00001979 if (!isVoid) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001980 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1981 Builder.AddPlaceholderChunk("expression");
Douglas Gregor44272ca2010-02-18 04:06:48 +00001982 }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001983 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001984
Douglas Gregorf4c33342010-05-28 00:22:41 +00001985 // goto identifier ;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001986 Builder.AddTypedTextChunk("goto");
1987 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1988 Builder.AddPlaceholderChunk("label");
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 // Using directives
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001992 Builder.AddTypedTextChunk("using");
1993 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1994 Builder.AddTextChunk("namespace");
1995 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1996 Builder.AddPlaceholderChunk("identifier");
1997 Results.AddResult(Result(Builder.TakeString()));
Alex Lorenz8f4d3992017-02-13 23:19:40 +00001998
1999 AddStaticAssertResult(Builder, Results, SemaRef.getLangOpts());
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002000 }
Galina Kistanovabe3ba9da2017-06-07 06:31:55 +00002001 LLVM_FALLTHROUGH;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002002
2003 // Fall through (for statement expressions).
John McCallfaf5fb42010-08-26 23:41:50 +00002004 case Sema::PCC_ForInit:
2005 case Sema::PCC_Condition:
David Blaikiebbafb8a2012-03-11 07:00:24 +00002006 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002007 // Fall through: conditions and statements can have expressions.
Galina Kistanova33399112017-06-03 06:35:06 +00002008 LLVM_FALLTHROUGH;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002009
Douglas Gregor5e35d592010-09-14 23:59:36 +00002010 case Sema::PCC_ParenthesizedExpression:
David Blaikiebbafb8a2012-03-11 07:00:24 +00002011 if (SemaRef.getLangOpts().ObjCAutoRefCount &&
John McCall31168b02011-06-15 23:02:42 +00002012 CCC == Sema::PCC_ParenthesizedExpression) {
2013 // (__bridge <type>)<expression>
2014 Builder.AddTypedTextChunk("__bridge");
2015 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2016 Builder.AddPlaceholderChunk("type");
2017 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2018 Builder.AddPlaceholderChunk("expression");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002019 Results.AddResult(Result(Builder.TakeString()));
John McCall31168b02011-06-15 23:02:42 +00002020
2021 // (__bridge_transfer <Objective-C type>)<expression>
2022 Builder.AddTypedTextChunk("__bridge_transfer");
2023 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2024 Builder.AddPlaceholderChunk("Objective-C type");
2025 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2026 Builder.AddPlaceholderChunk("expression");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002027 Results.AddResult(Result(Builder.TakeString()));
John McCall31168b02011-06-15 23:02:42 +00002028
2029 // (__bridge_retained <CF type>)<expression>
2030 Builder.AddTypedTextChunk("__bridge_retained");
2031 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2032 Builder.AddPlaceholderChunk("CF type");
2033 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2034 Builder.AddPlaceholderChunk("expression");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002035 Results.AddResult(Result(Builder.TakeString()));
John McCall31168b02011-06-15 23:02:42 +00002036 }
2037 // Fall through
Galina Kistanova33399112017-06-03 06:35:06 +00002038 LLVM_FALLTHROUGH;
John McCall31168b02011-06-15 23:02:42 +00002039
John McCallfaf5fb42010-08-26 23:41:50 +00002040 case Sema::PCC_Expression: {
David Blaikiebbafb8a2012-03-11 07:00:24 +00002041 if (SemaRef.getLangOpts().CPlusPlus) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002042 // 'this', if we're in a non-static member function.
Douglas Gregord8c61782012-02-15 15:34:24 +00002043 addThisCompletion(SemaRef, Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002044
Douglas Gregore5c79d52011-10-18 21:20:17 +00002045 // true
2046 Builder.AddResultTypeChunk("bool");
2047 Builder.AddTypedTextChunk("true");
2048 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002049
Douglas Gregore5c79d52011-10-18 21:20:17 +00002050 // false
2051 Builder.AddResultTypeChunk("bool");
2052 Builder.AddTypedTextChunk("false");
2053 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002054
David Blaikiebbafb8a2012-03-11 07:00:24 +00002055 if (SemaRef.getLangOpts().RTTI) {
Douglas Gregorc05f6572011-04-12 02:47:21 +00002056 // dynamic_cast < type-id > ( expression )
2057 Builder.AddTypedTextChunk("dynamic_cast");
2058 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
2059 Builder.AddPlaceholderChunk("type");
2060 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
2061 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2062 Builder.AddPlaceholderChunk("expression");
2063 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002064 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc05f6572011-04-12 02:47:21 +00002065 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002066
Douglas Gregorf4c33342010-05-28 00:22:41 +00002067 // static_cast < type-id > ( expression )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002068 Builder.AddTypedTextChunk("static_cast");
2069 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
2070 Builder.AddPlaceholderChunk("type");
2071 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
2072 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2073 Builder.AddPlaceholderChunk("expression");
2074 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002075 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002076
Douglas Gregorf4c33342010-05-28 00:22:41 +00002077 // reinterpret_cast < type-id > ( expression )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002078 Builder.AddTypedTextChunk("reinterpret_cast");
2079 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
2080 Builder.AddPlaceholderChunk("type");
2081 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
2082 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2083 Builder.AddPlaceholderChunk("expression");
2084 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002085 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002086
Douglas Gregorf4c33342010-05-28 00:22:41 +00002087 // const_cast < type-id > ( expression )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002088 Builder.AddTypedTextChunk("const_cast");
2089 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
2090 Builder.AddPlaceholderChunk("type");
2091 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
2092 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2093 Builder.AddPlaceholderChunk("expression");
2094 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002095 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002096
David Blaikiebbafb8a2012-03-11 07:00:24 +00002097 if (SemaRef.getLangOpts().RTTI) {
Douglas Gregorc05f6572011-04-12 02:47:21 +00002098 // typeid ( expression-or-type )
Douglas Gregore5c79d52011-10-18 21:20:17 +00002099 Builder.AddResultTypeChunk("std::type_info");
Douglas Gregorc05f6572011-04-12 02:47:21 +00002100 Builder.AddTypedTextChunk("typeid");
2101 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2102 Builder.AddPlaceholderChunk("expression-or-type");
2103 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002104 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc05f6572011-04-12 02:47:21 +00002105 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002106
Douglas Gregorf4c33342010-05-28 00:22:41 +00002107 // new T ( ... )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002108 Builder.AddTypedTextChunk("new");
2109 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2110 Builder.AddPlaceholderChunk("type");
2111 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2112 Builder.AddPlaceholderChunk("expressions");
2113 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002114 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002115
Douglas Gregorf4c33342010-05-28 00:22:41 +00002116 // new T [ ] ( ... )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002117 Builder.AddTypedTextChunk("new");
2118 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2119 Builder.AddPlaceholderChunk("type");
2120 Builder.AddChunk(CodeCompletionString::CK_LeftBracket);
2121 Builder.AddPlaceholderChunk("size");
2122 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
2123 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2124 Builder.AddPlaceholderChunk("expressions");
2125 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002126 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002127
Douglas Gregorf4c33342010-05-28 00:22:41 +00002128 // delete expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00002129 Builder.AddResultTypeChunk("void");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002130 Builder.AddTypedTextChunk("delete");
2131 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2132 Builder.AddPlaceholderChunk("expression");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002133 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002134
Douglas Gregorf4c33342010-05-28 00:22:41 +00002135 // delete [] expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00002136 Builder.AddResultTypeChunk("void");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002137 Builder.AddTypedTextChunk("delete");
2138 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2139 Builder.AddChunk(CodeCompletionString::CK_LeftBracket);
2140 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
2141 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2142 Builder.AddPlaceholderChunk("expression");
2143 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002144
David Blaikiebbafb8a2012-03-11 07:00:24 +00002145 if (SemaRef.getLangOpts().CXXExceptions) {
Douglas Gregorc05f6572011-04-12 02:47:21 +00002146 // throw expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00002147 Builder.AddResultTypeChunk("void");
Douglas Gregorc05f6572011-04-12 02:47:21 +00002148 Builder.AddTypedTextChunk("throw");
2149 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2150 Builder.AddPlaceholderChunk("expression");
2151 Results.AddResult(Result(Builder.TakeString()));
2152 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002153
Douglas Gregora2db7932010-05-26 22:00:08 +00002154 // FIXME: Rethrow?
Douglas Gregor4205fef2011-10-18 16:29:03 +00002155
Richard Smith2bf7fdb2013-01-02 11:42:31 +00002156 if (SemaRef.getLangOpts().CPlusPlus11) {
Douglas Gregor4205fef2011-10-18 16:29:03 +00002157 // nullptr
Douglas Gregore5c79d52011-10-18 21:20:17 +00002158 Builder.AddResultTypeChunk("std::nullptr_t");
Douglas Gregor4205fef2011-10-18 16:29:03 +00002159 Builder.AddTypedTextChunk("nullptr");
2160 Results.AddResult(Result(Builder.TakeString()));
2161
2162 // alignof
Douglas Gregore5c79d52011-10-18 21:20:17 +00002163 Builder.AddResultTypeChunk("size_t");
Douglas Gregor4205fef2011-10-18 16:29:03 +00002164 Builder.AddTypedTextChunk("alignof");
2165 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2166 Builder.AddPlaceholderChunk("type");
2167 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2168 Results.AddResult(Result(Builder.TakeString()));
2169
2170 // noexcept
Douglas Gregore5c79d52011-10-18 21:20:17 +00002171 Builder.AddResultTypeChunk("bool");
Douglas Gregor4205fef2011-10-18 16:29:03 +00002172 Builder.AddTypedTextChunk("noexcept");
2173 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2174 Builder.AddPlaceholderChunk("expression");
2175 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2176 Results.AddResult(Result(Builder.TakeString()));
2177
2178 // sizeof... expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00002179 Builder.AddResultTypeChunk("size_t");
Douglas Gregor4205fef2011-10-18 16:29:03 +00002180 Builder.AddTypedTextChunk("sizeof...");
2181 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2182 Builder.AddPlaceholderChunk("parameter-pack");
2183 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2184 Results.AddResult(Result(Builder.TakeString()));
2185 }
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002186 }
2187
Erik Pilkingtonfa983902018-10-30 20:31:30 +00002188 if (SemaRef.getLangOpts().ObjC) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002189 // Add "super", if we're in an Objective-C class with a superclass.
Ted Kremenek305a0a72010-05-31 21:43:10 +00002190 if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl()) {
2191 // The interface can be NULL.
2192 if (ObjCInterfaceDecl *ID = Method->getClassInterface())
Douglas Gregore5c79d52011-10-18 21:20:17 +00002193 if (ID->getSuperClass()) {
2194 std::string SuperType;
2195 SuperType = ID->getSuperClass()->getNameAsString();
2196 if (Method->isInstanceMethod())
2197 SuperType += " *";
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002198
Douglas Gregore5c79d52011-10-18 21:20:17 +00002199 Builder.AddResultTypeChunk(Allocator.CopyString(SuperType));
2200 Builder.AddTypedTextChunk("super");
2201 Results.AddResult(Result(Builder.TakeString()));
2202 }
Ted Kremenek305a0a72010-05-31 21:43:10 +00002203 }
2204
Douglas Gregorf98e6a22010-01-13 23:51:12 +00002205 AddObjCExpressionResults(Results, true);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002206 }
2207
Jordan Rose58d54722012-06-30 21:33:57 +00002208 if (SemaRef.getLangOpts().C11) {
2209 // _Alignof
2210 Builder.AddResultTypeChunk("size_t");
Richard Smith20e883e2015-04-29 23:20:19 +00002211 if (SemaRef.PP.isMacroDefined("alignof"))
Jordan Rose58d54722012-06-30 21:33:57 +00002212 Builder.AddTypedTextChunk("alignof");
2213 else
2214 Builder.AddTypedTextChunk("_Alignof");
2215 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2216 Builder.AddPlaceholderChunk("type");
2217 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2218 Results.AddResult(Result(Builder.TakeString()));
2219 }
2220
Douglas Gregorf4c33342010-05-28 00:22:41 +00002221 // sizeof expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00002222 Builder.AddResultTypeChunk("size_t");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002223 Builder.AddTypedTextChunk("sizeof");
2224 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2225 Builder.AddPlaceholderChunk("expression-or-type");
2226 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2227 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002228 break;
2229 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002230
John McCallfaf5fb42010-08-26 23:41:50 +00002231 case Sema::PCC_Type:
Douglas Gregor80039242011-02-15 20:33:25 +00002232 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregor99fa2642010-08-24 01:06:58 +00002233 break;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002234 }
2235
David Blaikiebbafb8a2012-03-11 07:00:24 +00002236 if (WantTypesInContext(CCC, SemaRef.getLangOpts()))
2237 AddTypeSpecifierResults(SemaRef.getLangOpts(), Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002238
David Blaikiebbafb8a2012-03-11 07:00:24 +00002239 if (SemaRef.getLangOpts().CPlusPlus && CCC != Sema::PCC_Type)
Douglas Gregor78a21012010-01-14 16:01:26 +00002240 Results.AddResult(Result("operator"));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002241}
2242
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002243/// If the given declaration has an associated type, add it as a result
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002244/// type chunk.
2245static void AddResultTypeChunk(ASTContext &Context,
Douglas Gregor75acd922011-09-27 23:30:47 +00002246 const PrintingPolicy &Policy,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002247 const NamedDecl *ND,
Douglas Gregorc3425b12015-07-07 06:20:19 +00002248 QualType BaseType,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002249 CodeCompletionBuilder &Result) {
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002250 if (!ND)
2251 return;
Douglas Gregor0212fd72010-09-21 16:06:22 +00002252
2253 // Skip constructors and conversion functions, which have their return types
2254 // built into their names.
Sam McCall63c59722018-01-22 20:44:47 +00002255 if (isConstructor(ND) || isa<CXXConversionDecl>(ND))
Douglas Gregor0212fd72010-09-21 16:06:22 +00002256 return;
2257
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002258 // Determine the type of the declaration (if it has a type).
Alp Tokera2794f92014-01-22 07:29:52 +00002259 QualType T;
2260 if (const FunctionDecl *Function = ND->getAsFunction())
Alp Toker314cc812014-01-25 16:55:45 +00002261 T = Function->getReturnType();
Douglas Gregorc3425b12015-07-07 06:20:19 +00002262 else if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND)) {
2263 if (!BaseType.isNull())
2264 T = Method->getSendResultType(BaseType);
2265 else
2266 T = Method->getReturnType();
Ilya Biryukovb5da91c2017-11-08 10:39:09 +00002267 } else if (const EnumConstantDecl *Enumerator = dyn_cast<EnumConstantDecl>(ND)) {
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002268 T = Context.getTypeDeclType(cast<TypeDecl>(Enumerator->getDeclContext()));
Ilya Biryukovb5da91c2017-11-08 10:39:09 +00002269 T = clang::TypeName::getFullyQualifiedType(T, Context);
2270 } else if (isa<UnresolvedUsingValueDecl>(ND)) {
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002271 /* Do nothing: ignore unresolved using declarations*/
Douglas Gregorc3425b12015-07-07 06:20:19 +00002272 } else if (const ObjCIvarDecl *Ivar = dyn_cast<ObjCIvarDecl>(ND)) {
2273 if (!BaseType.isNull())
2274 T = Ivar->getUsageType(BaseType);
2275 else
2276 T = Ivar->getType();
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002277 } else if (const ValueDecl *Value = dyn_cast<ValueDecl>(ND)) {
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002278 T = Value->getType();
Douglas Gregorc3425b12015-07-07 06:20:19 +00002279 } else if (const ObjCPropertyDecl *Property = dyn_cast<ObjCPropertyDecl>(ND)) {
2280 if (!BaseType.isNull())
2281 T = Property->getUsageType(BaseType);
2282 else
2283 T = Property->getType();
2284 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002285
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002286 if (T.isNull() || Context.hasSameType(T, Context.DependentTy))
2287 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002288
Douglas Gregor75acd922011-09-27 23:30:47 +00002289 Result.AddResultTypeChunk(GetCompletionTypeString(T, Context, Policy,
Douglas Gregor304f9b02011-02-01 21:15:40 +00002290 Result.getAllocator()));
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002291}
2292
Richard Smith20e883e2015-04-29 23:20:19 +00002293static void MaybeAddSentinel(Preprocessor &PP,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002294 const NamedDecl *FunctionOrMethod,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002295 CodeCompletionBuilder &Result) {
Douglas Gregordbb71db2010-08-23 23:51:41 +00002296 if (SentinelAttr *Sentinel = FunctionOrMethod->getAttr<SentinelAttr>())
2297 if (Sentinel->getSentinel() == 0) {
Erik Pilkingtonfa983902018-10-30 20:31:30 +00002298 if (PP.getLangOpts().ObjC && PP.isMacroDefined("nil"))
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002299 Result.AddTextChunk(", nil");
Richard Smith20e883e2015-04-29 23:20:19 +00002300 else if (PP.isMacroDefined("NULL"))
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002301 Result.AddTextChunk(", NULL");
Douglas Gregordbb71db2010-08-23 23:51:41 +00002302 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002303 Result.AddTextChunk(", (void*)0");
Douglas Gregordbb71db2010-08-23 23:51:41 +00002304 }
2305}
2306
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002307static std::string formatObjCParamQualifiers(unsigned ObjCQuals,
Douglas Gregor86b42682015-06-19 18:27:52 +00002308 QualType &Type) {
Douglas Gregor8f08d742011-07-30 07:55:26 +00002309 std::string Result;
2310 if (ObjCQuals & Decl::OBJC_TQ_In)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002311 Result += "in ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002312 else if (ObjCQuals & Decl::OBJC_TQ_Inout)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002313 Result += "inout ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002314 else if (ObjCQuals & Decl::OBJC_TQ_Out)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002315 Result += "out ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002316 if (ObjCQuals & Decl::OBJC_TQ_Bycopy)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002317 Result += "bycopy ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002318 else if (ObjCQuals & Decl::OBJC_TQ_Byref)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002319 Result += "byref ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002320 if (ObjCQuals & Decl::OBJC_TQ_Oneway)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002321 Result += "oneway ";
Douglas Gregor86b42682015-06-19 18:27:52 +00002322 if (ObjCQuals & Decl::OBJC_TQ_CSNullability) {
2323 if (auto nullability = AttributedType::stripOuterNullability(Type)) {
2324 switch (*nullability) {
2325 case NullabilityKind::NonNull:
2326 Result += "nonnull ";
2327 break;
2328
2329 case NullabilityKind::Nullable:
2330 Result += "nullable ";
2331 break;
2332
2333 case NullabilityKind::Unspecified:
2334 Result += "null_unspecified ";
2335 break;
2336 }
2337 }
2338 }
Douglas Gregor8f08d742011-07-30 07:55:26 +00002339 return Result;
2340}
2341
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002342/// Tries to find the most appropriate type location for an Objective-C
Alex Lorenza1951202016-10-18 10:35:27 +00002343/// block placeholder.
2344///
2345/// This function ignores things like typedefs and qualifiers in order to
2346/// present the most relevant and accurate block placeholders in code completion
2347/// results.
2348static void findTypeLocationForBlockDecl(const TypeSourceInfo *TSInfo,
2349 FunctionTypeLoc &Block,
2350 FunctionProtoTypeLoc &BlockProto,
2351 bool SuppressBlock = false) {
2352 if (!TSInfo)
2353 return;
2354 TypeLoc TL = TSInfo->getTypeLoc().getUnqualifiedLoc();
2355 while (true) {
2356 // Look through typedefs.
2357 if (!SuppressBlock) {
2358 if (TypedefTypeLoc TypedefTL = TL.getAs<TypedefTypeLoc>()) {
2359 if (TypeSourceInfo *InnerTSInfo =
2360 TypedefTL.getTypedefNameDecl()->getTypeSourceInfo()) {
2361 TL = InnerTSInfo->getTypeLoc().getUnqualifiedLoc();
2362 continue;
2363 }
2364 }
2365
2366 // Look through qualified types
2367 if (QualifiedTypeLoc QualifiedTL = TL.getAs<QualifiedTypeLoc>()) {
2368 TL = QualifiedTL.getUnqualifiedLoc();
2369 continue;
2370 }
2371
2372 if (AttributedTypeLoc AttrTL = TL.getAs<AttributedTypeLoc>()) {
2373 TL = AttrTL.getModifiedLoc();
2374 continue;
2375 }
2376 }
2377
2378 // Try to get the function prototype behind the block pointer type,
2379 // then we're done.
2380 if (BlockPointerTypeLoc BlockPtr = TL.getAs<BlockPointerTypeLoc>()) {
2381 TL = BlockPtr.getPointeeLoc().IgnoreParens();
2382 Block = TL.getAs<FunctionTypeLoc>();
2383 BlockProto = TL.getAs<FunctionProtoTypeLoc>();
2384 }
2385 break;
2386 }
2387}
2388
Alex Lorenz920ae142016-10-18 10:38:58 +00002389static std::string
2390formatBlockPlaceholder(const PrintingPolicy &Policy, const NamedDecl *BlockDecl,
2391 FunctionTypeLoc &Block, FunctionProtoTypeLoc &BlockProto,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002392 bool SuppressBlockName = false,
Alex Lorenz920ae142016-10-18 10:38:58 +00002393 bool SuppressBlock = false,
2394 Optional<ArrayRef<QualType>> ObjCSubsts = None);
2395
Richard Smith20e883e2015-04-29 23:20:19 +00002396static std::string FormatFunctionParameter(const PrintingPolicy &Policy,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002397 const ParmVarDecl *Param,
Douglas Gregord793e7c2011-10-18 04:23:19 +00002398 bool SuppressName = false,
Douglas Gregorc3425b12015-07-07 06:20:19 +00002399 bool SuppressBlock = false,
2400 Optional<ArrayRef<QualType>> ObjCSubsts = None) {
Douglas Gregore90dd002010-08-24 16:15:59 +00002401 bool ObjCMethodParam = isa<ObjCMethodDecl>(Param->getDeclContext());
2402 if (Param->getType()->isDependentType() ||
2403 !Param->getType()->isBlockPointerType()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002404 // The argument for a dependent or non-block parameter is a placeholder
Douglas Gregore90dd002010-08-24 16:15:59 +00002405 // containing that parameter's type.
2406 std::string Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002407
Douglas Gregor981a0c42010-08-29 19:47:46 +00002408 if (Param->getIdentifier() && !ObjCMethodParam && !SuppressName)
Douglas Gregore90dd002010-08-24 16:15:59 +00002409 Result = Param->getIdentifier()->getName();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002410
Douglas Gregor86b42682015-06-19 18:27:52 +00002411 QualType Type = Param->getType();
Douglas Gregorc3425b12015-07-07 06:20:19 +00002412 if (ObjCSubsts)
2413 Type = Type.substObjCTypeArgs(Param->getASTContext(), *ObjCSubsts,
2414 ObjCSubstitutionContext::Parameter);
Douglas Gregore90dd002010-08-24 16:15:59 +00002415 if (ObjCMethodParam) {
Douglas Gregor86b42682015-06-19 18:27:52 +00002416 Result = "(" + formatObjCParamQualifiers(Param->getObjCDeclQualifier(),
2417 Type);
2418 Result += Type.getAsString(Policy) + ")";
Douglas Gregor981a0c42010-08-29 19:47:46 +00002419 if (Param->getIdentifier() && !SuppressName)
Douglas Gregore90dd002010-08-24 16:15:59 +00002420 Result += Param->getIdentifier()->getName();
Douglas Gregor86b42682015-06-19 18:27:52 +00002421 } else {
2422 Type.getAsStringInternal(Result, Policy);
Douglas Gregore90dd002010-08-24 16:15:59 +00002423 }
2424 return Result;
2425 }
Alex Lorenza1951202016-10-18 10:35:27 +00002426
Douglas Gregore90dd002010-08-24 16:15:59 +00002427 // The argument for a block pointer parameter is a block literal with
2428 // the appropriate type.
David Blaikie6adc78e2013-02-18 22:06:02 +00002429 FunctionTypeLoc Block;
2430 FunctionProtoTypeLoc BlockProto;
Alex Lorenza1951202016-10-18 10:35:27 +00002431 findTypeLocationForBlockDecl(Param->getTypeSourceInfo(), Block, BlockProto,
2432 SuppressBlock);
Alex Lorenz6bf4a582017-03-13 15:43:42 +00002433 // Try to retrieve the block type information from the property if this is a
2434 // parameter in a setter.
2435 if (!Block && ObjCMethodParam &&
2436 cast<ObjCMethodDecl>(Param->getDeclContext())->isPropertyAccessor()) {
2437 if (const auto *PD = cast<ObjCMethodDecl>(Param->getDeclContext())
2438 ->findPropertyDecl(/*CheckOverrides=*/false))
2439 findTypeLocationForBlockDecl(PD->getTypeSourceInfo(), Block, BlockProto,
2440 SuppressBlock);
2441 }
Douglas Gregore90dd002010-08-24 16:15:59 +00002442
2443 if (!Block) {
2444 // We were unable to find a FunctionProtoTypeLoc with parameter names
2445 // for the block; just use the parameter type as a placeholder.
2446 std::string Result;
Douglas Gregord793e7c2011-10-18 04:23:19 +00002447 if (!ObjCMethodParam && Param->getIdentifier())
2448 Result = Param->getIdentifier()->getName();
2449
Douglas Gregor86b42682015-06-19 18:27:52 +00002450 QualType Type = Param->getType().getUnqualifiedType();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002451
Douglas Gregore90dd002010-08-24 16:15:59 +00002452 if (ObjCMethodParam) {
Alex Lorenz01bcfc12016-11-23 16:28:34 +00002453 Result = Type.getAsString(Policy);
2454 std::string Quals =
2455 formatObjCParamQualifiers(Param->getObjCDeclQualifier(), Type);
2456 if (!Quals.empty())
2457 Result = "(" + Quals + " " + Result + ")";
2458 if (Result.back() != ')')
2459 Result += " ";
Douglas Gregore90dd002010-08-24 16:15:59 +00002460 if (Param->getIdentifier())
2461 Result += Param->getIdentifier()->getName();
Douglas Gregor86b42682015-06-19 18:27:52 +00002462 } else {
2463 Type.getAsStringInternal(Result, Policy);
Douglas Gregore90dd002010-08-24 16:15:59 +00002464 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002465
Douglas Gregore90dd002010-08-24 16:15:59 +00002466 return Result;
2467 }
Alex Lorenz01bcfc12016-11-23 16:28:34 +00002468
Douglas Gregore90dd002010-08-24 16:15:59 +00002469 // We have the function prototype behind the block pointer type, as it was
2470 // written in the source.
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002471 return formatBlockPlaceholder(Policy, Param, Block, BlockProto,
2472 /*SuppressBlockName=*/false, SuppressBlock,
Alex Lorenz920ae142016-10-18 10:38:58 +00002473 ObjCSubsts);
2474}
2475
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002476/// Returns a placeholder string that corresponds to an Objective-C block
Alex Lorenz920ae142016-10-18 10:38:58 +00002477/// declaration.
2478///
2479/// \param BlockDecl A declaration with an Objective-C block type.
2480///
2481/// \param Block The most relevant type location for that block type.
2482///
Alexander Kornienko2a8c18d2018-04-06 15:14:32 +00002483/// \param SuppressBlockName Determines whether or not the name of the block
Alex Lorenz920ae142016-10-18 10:38:58 +00002484/// declaration is included in the resulting string.
2485static std::string
2486formatBlockPlaceholder(const PrintingPolicy &Policy, const NamedDecl *BlockDecl,
2487 FunctionTypeLoc &Block, FunctionProtoTypeLoc &BlockProto,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002488 bool SuppressBlockName, bool SuppressBlock,
Alex Lorenz920ae142016-10-18 10:38:58 +00002489 Optional<ArrayRef<QualType>> ObjCSubsts) {
Douglas Gregor67da50e2010-09-08 22:47:51 +00002490 std::string Result;
Alp Toker314cc812014-01-25 16:55:45 +00002491 QualType ResultType = Block.getTypePtr()->getReturnType();
Douglas Gregorc3425b12015-07-07 06:20:19 +00002492 if (ObjCSubsts)
Alex Lorenz920ae142016-10-18 10:38:58 +00002493 ResultType =
2494 ResultType.substObjCTypeArgs(BlockDecl->getASTContext(), *ObjCSubsts,
2495 ObjCSubstitutionContext::Result);
Douglas Gregord793e7c2011-10-18 04:23:19 +00002496 if (!ResultType->isVoidType() || SuppressBlock)
John McCall31168b02011-06-15 23:02:42 +00002497 ResultType.getAsStringInternal(Result, Policy);
Douglas Gregord793e7c2011-10-18 04:23:19 +00002498
2499 // Format the parameter list.
2500 std::string Params;
Alp Tokerb3fd5cf2014-01-21 00:32:38 +00002501 if (!BlockProto || Block.getNumParams() == 0) {
David Blaikie6adc78e2013-02-18 22:06:02 +00002502 if (BlockProto && BlockProto.getTypePtr()->isVariadic())
Douglas Gregord793e7c2011-10-18 04:23:19 +00002503 Params = "(...)";
Douglas Gregoraf25cfa2010-10-02 23:49:58 +00002504 else
Douglas Gregord793e7c2011-10-18 04:23:19 +00002505 Params = "(void)";
Douglas Gregor67da50e2010-09-08 22:47:51 +00002506 } else {
Douglas Gregord793e7c2011-10-18 04:23:19 +00002507 Params += "(";
Alp Tokerb3fd5cf2014-01-21 00:32:38 +00002508 for (unsigned I = 0, N = Block.getNumParams(); I != N; ++I) {
Douglas Gregor67da50e2010-09-08 22:47:51 +00002509 if (I)
Douglas Gregord793e7c2011-10-18 04:23:19 +00002510 Params += ", ";
Richard Smith20e883e2015-04-29 23:20:19 +00002511 Params += FormatFunctionParameter(Policy, Block.getParam(I),
Alp Tokerb3fd5cf2014-01-21 00:32:38 +00002512 /*SuppressName=*/false,
Alex Lorenz920ae142016-10-18 10:38:58 +00002513 /*SuppressBlock=*/true, ObjCSubsts);
Alp Tokerb3fd5cf2014-01-21 00:32:38 +00002514
David Blaikie6adc78e2013-02-18 22:06:02 +00002515 if (I == N - 1 && BlockProto.getTypePtr()->isVariadic())
Douglas Gregord793e7c2011-10-18 04:23:19 +00002516 Params += ", ...";
Douglas Gregor67da50e2010-09-08 22:47:51 +00002517 }
Douglas Gregord793e7c2011-10-18 04:23:19 +00002518 Params += ")";
Douglas Gregor400f5972010-08-31 05:13:43 +00002519 }
Alex Lorenz920ae142016-10-18 10:38:58 +00002520
Douglas Gregord793e7c2011-10-18 04:23:19 +00002521 if (SuppressBlock) {
2522 // Format as a parameter.
2523 Result = Result + " (^";
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002524 if (!SuppressBlockName && BlockDecl->getIdentifier())
Alex Lorenz920ae142016-10-18 10:38:58 +00002525 Result += BlockDecl->getIdentifier()->getName();
Douglas Gregord793e7c2011-10-18 04:23:19 +00002526 Result += ")";
2527 Result += Params;
2528 } else {
2529 // Format as a block literal argument.
2530 Result = '^' + Result;
2531 Result += Params;
Alex Lorenz920ae142016-10-18 10:38:58 +00002532
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002533 if (!SuppressBlockName && BlockDecl->getIdentifier())
Alex Lorenz920ae142016-10-18 10:38:58 +00002534 Result += BlockDecl->getIdentifier()->getName();
Douglas Gregord793e7c2011-10-18 04:23:19 +00002535 }
Alex Lorenz920ae142016-10-18 10:38:58 +00002536
Douglas Gregore90dd002010-08-24 16:15:59 +00002537 return Result;
2538}
2539
Erik Verbruggen11338c52017-07-19 10:45:40 +00002540static std::string GetDefaultValueString(const ParmVarDecl *Param,
2541 const SourceManager &SM,
2542 const LangOptions &LangOpts) {
Ilya Biryukovb6d1ec82017-07-21 09:24:00 +00002543 const SourceRange SrcRange = Param->getDefaultArgRange();
Erik Verbruggen11338c52017-07-19 10:45:40 +00002544 CharSourceRange CharSrcRange = CharSourceRange::getTokenRange(SrcRange);
2545 bool Invalid = CharSrcRange.isInvalid();
2546 if (Invalid)
2547 return "";
2548 StringRef srcText = Lexer::getSourceText(CharSrcRange, SM, LangOpts, &Invalid);
2549 if (Invalid)
2550 return "";
2551
2552 if (srcText.empty() || srcText == "=") {
2553 // Lexer can't determine the value.
2554 // This happens if the code is incorrect (for example class is forward declared).
2555 return "";
2556 }
Erik Verbruggen797980e2017-07-19 11:15:36 +00002557 std::string DefValue(srcText.str());
Erik Verbruggen11338c52017-07-19 10:45:40 +00002558 // FIXME: remove this check if the Lexer::getSourceText value is fixed and
2559 // this value always has (or always does not have) '=' in front of it
2560 if (DefValue.at(0) != '=') {
2561 // If we don't have '=' in front of value.
2562 // Lexer returns built-in types values without '=' and user-defined types values with it.
2563 return " = " + DefValue;
2564 }
2565 return " " + DefValue;
2566}
2567
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002568/// Add function parameter chunks to the given code completion string.
Richard Smith20e883e2015-04-29 23:20:19 +00002569static void AddFunctionParameterChunks(Preprocessor &PP,
Douglas Gregor75acd922011-09-27 23:30:47 +00002570 const PrintingPolicy &Policy,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002571 const FunctionDecl *Function,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002572 CodeCompletionBuilder &Result,
2573 unsigned Start = 0,
2574 bool InOptional = false) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002575 bool FirstParameter = true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002576
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002577 for (unsigned P = Start, N = Function->getNumParams(); P != N; ++P) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002578 const ParmVarDecl *Param = Function->getParamDecl(P);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002579
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002580 if (Param->hasDefaultArg() && !InOptional) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002581 // When we see an optional default argument, put that argument and
2582 // the remaining default arguments into a new, optional string.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00002583 CodeCompletionBuilder Opt(Result.getAllocator(),
2584 Result.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002585 if (!FirstParameter)
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002586 Opt.AddChunk(CodeCompletionString::CK_Comma);
Richard Smith20e883e2015-04-29 23:20:19 +00002587 AddFunctionParameterChunks(PP, Policy, Function, Opt, P, true);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002588 Result.AddOptionalChunk(Opt.TakeString());
2589 break;
Douglas Gregor3545ff42009-09-21 16:56:56 +00002590 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002591
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002592 if (FirstParameter)
2593 FirstParameter = false;
2594 else
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002595 Result.AddChunk(CodeCompletionString::CK_Comma);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002596
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002597 InOptional = false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002598
Douglas Gregor3545ff42009-09-21 16:56:56 +00002599 // Format the placeholder string.
Richard Smith20e883e2015-04-29 23:20:19 +00002600 std::string PlaceholderStr = FormatFunctionParameter(Policy, Param);
Erik Verbruggen11338c52017-07-19 10:45:40 +00002601 if (Param->hasDefaultArg())
2602 PlaceholderStr += GetDefaultValueString(Param, PP.getSourceManager(), PP.getLangOpts());
Richard Smith20e883e2015-04-29 23:20:19 +00002603
Douglas Gregor400f5972010-08-31 05:13:43 +00002604 if (Function->isVariadic() && P == N - 1)
2605 PlaceholderStr += ", ...";
2606
Douglas Gregor3545ff42009-09-21 16:56:56 +00002607 // Add the placeholder string.
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002608 Result.AddPlaceholderChunk(
2609 Result.getAllocator().CopyString(PlaceholderStr));
Douglas Gregor3545ff42009-09-21 16:56:56 +00002610 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002611
2612 if (const FunctionProtoType *Proto
Douglas Gregorba449032009-09-22 21:42:17 +00002613 = Function->getType()->getAs<FunctionProtoType>())
Douglas Gregordbb71db2010-08-23 23:51:41 +00002614 if (Proto->isVariadic()) {
Alp Toker9cacbab2014-01-20 20:26:09 +00002615 if (Proto->getNumParams() == 0)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002616 Result.AddPlaceholderChunk("...");
Douglas Gregordbb71db2010-08-23 23:51:41 +00002617
Richard Smith20e883e2015-04-29 23:20:19 +00002618 MaybeAddSentinel(PP, Function, Result);
Douglas Gregordbb71db2010-08-23 23:51:41 +00002619 }
Douglas Gregor3545ff42009-09-21 16:56:56 +00002620}
2621
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002622/// Add template parameter chunks to the given code completion string.
Douglas Gregor3545ff42009-09-21 16:56:56 +00002623static void AddTemplateParameterChunks(ASTContext &Context,
Douglas Gregor75acd922011-09-27 23:30:47 +00002624 const PrintingPolicy &Policy,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002625 const TemplateDecl *Template,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002626 CodeCompletionBuilder &Result,
2627 unsigned MaxParameters = 0,
2628 unsigned Start = 0,
2629 bool InDefaultArg = false) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002630 bool FirstParameter = true;
Richard Smith6eece292015-01-15 02:27:20 +00002631
2632 // Prefer to take the template parameter names from the first declaration of
2633 // the template.
2634 Template = cast<TemplateDecl>(Template->getCanonicalDecl());
2635
Douglas Gregor3545ff42009-09-21 16:56:56 +00002636 TemplateParameterList *Params = Template->getTemplateParameters();
2637 TemplateParameterList::iterator PEnd = Params->end();
2638 if (MaxParameters)
2639 PEnd = Params->begin() + MaxParameters;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002640 for (TemplateParameterList::iterator P = Params->begin() + Start;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002641 P != PEnd; ++P) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002642 bool HasDefaultArg = false;
2643 std::string PlaceholderStr;
2644 if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*P)) {
2645 if (TTP->wasDeclaredWithTypename())
2646 PlaceholderStr = "typename";
2647 else
2648 PlaceholderStr = "class";
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002649
Douglas Gregor3545ff42009-09-21 16:56:56 +00002650 if (TTP->getIdentifier()) {
2651 PlaceholderStr += ' ';
2652 PlaceholderStr += TTP->getIdentifier()->getName();
2653 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002654
Douglas Gregor3545ff42009-09-21 16:56:56 +00002655 HasDefaultArg = TTP->hasDefaultArgument();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002656 } else if (NonTypeTemplateParmDecl *NTTP
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002657 = dyn_cast<NonTypeTemplateParmDecl>(*P)) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002658 if (NTTP->getIdentifier())
2659 PlaceholderStr = NTTP->getIdentifier()->getName();
John McCall31168b02011-06-15 23:02:42 +00002660 NTTP->getType().getAsStringInternal(PlaceholderStr, Policy);
Douglas Gregor3545ff42009-09-21 16:56:56 +00002661 HasDefaultArg = NTTP->hasDefaultArgument();
2662 } else {
2663 assert(isa<TemplateTemplateParmDecl>(*P));
2664 TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*P);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002665
Douglas Gregor3545ff42009-09-21 16:56:56 +00002666 // Since putting the template argument list into the placeholder would
2667 // be very, very long, we just use an abbreviation.
2668 PlaceholderStr = "template<...> class";
2669 if (TTP->getIdentifier()) {
2670 PlaceholderStr += ' ';
2671 PlaceholderStr += TTP->getIdentifier()->getName();
2672 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002673
Douglas Gregor3545ff42009-09-21 16:56:56 +00002674 HasDefaultArg = TTP->hasDefaultArgument();
2675 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002676
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002677 if (HasDefaultArg && !InDefaultArg) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002678 // When we see an optional default argument, put that argument and
2679 // the remaining default arguments into a new, optional string.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00002680 CodeCompletionBuilder Opt(Result.getAllocator(),
2681 Result.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002682 if (!FirstParameter)
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002683 Opt.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor75acd922011-09-27 23:30:47 +00002684 AddTemplateParameterChunks(Context, Policy, Template, Opt, MaxParameters,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002685 P - Params->begin(), true);
2686 Result.AddOptionalChunk(Opt.TakeString());
2687 break;
Douglas Gregor3545ff42009-09-21 16:56:56 +00002688 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002689
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002690 InDefaultArg = false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002691
Douglas Gregor3545ff42009-09-21 16:56:56 +00002692 if (FirstParameter)
2693 FirstParameter = false;
2694 else
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002695 Result.AddChunk(CodeCompletionString::CK_Comma);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002696
Douglas Gregor3545ff42009-09-21 16:56:56 +00002697 // Add the placeholder string.
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002698 Result.AddPlaceholderChunk(
2699 Result.getAllocator().CopyString(PlaceholderStr));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002700 }
Douglas Gregor3545ff42009-09-21 16:56:56 +00002701}
2702
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002703/// Add a qualifier to the given code-completion string, if the
Douglas Gregorf2510672009-09-21 19:57:38 +00002704/// provided nested-name-specifier is non-NULL.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002705static void
2706AddQualifierToCompletionString(CodeCompletionBuilder &Result,
2707 NestedNameSpecifier *Qualifier,
Douglas Gregor0f622362009-12-11 18:44:16 +00002708 bool QualifierIsInformative,
Douglas Gregor75acd922011-09-27 23:30:47 +00002709 ASTContext &Context,
2710 const PrintingPolicy &Policy) {
Douglas Gregorf2510672009-09-21 19:57:38 +00002711 if (!Qualifier)
2712 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002713
Douglas Gregorf2510672009-09-21 19:57:38 +00002714 std::string PrintedNNS;
2715 {
2716 llvm::raw_string_ostream OS(PrintedNNS);
Douglas Gregor75acd922011-09-27 23:30:47 +00002717 Qualifier->print(OS, Policy);
Douglas Gregorf2510672009-09-21 19:57:38 +00002718 }
Douglas Gregor5bf52692009-09-22 23:15:58 +00002719 if (QualifierIsInformative)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002720 Result.AddInformativeChunk(Result.getAllocator().CopyString(PrintedNNS));
Douglas Gregor5bf52692009-09-22 23:15:58 +00002721 else
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002722 Result.AddTextChunk(Result.getAllocator().CopyString(PrintedNNS));
Douglas Gregorf2510672009-09-21 19:57:38 +00002723}
2724
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002725static void
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002726AddFunctionTypeQualsToCompletionString(CodeCompletionBuilder &Result,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002727 const FunctionDecl *Function) {
Douglas Gregor0f622362009-12-11 18:44:16 +00002728 const FunctionProtoType *Proto
2729 = Function->getType()->getAs<FunctionProtoType>();
2730 if (!Proto || !Proto->getTypeQuals())
2731 return;
2732
Douglas Gregor304f9b02011-02-01 21:15:40 +00002733 // FIXME: Add ref-qualifier!
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002734
Douglas Gregor304f9b02011-02-01 21:15:40 +00002735 // Handle single qualifiers without copying
2736 if (Proto->getTypeQuals() == Qualifiers::Const) {
2737 Result.AddInformativeChunk(" const");
2738 return;
2739 }
2740
2741 if (Proto->getTypeQuals() == Qualifiers::Volatile) {
2742 Result.AddInformativeChunk(" volatile");
2743 return;
2744 }
2745
2746 if (Proto->getTypeQuals() == Qualifiers::Restrict) {
2747 Result.AddInformativeChunk(" restrict");
2748 return;
2749 }
2750
2751 // Handle multiple qualifiers.
Douglas Gregor0f622362009-12-11 18:44:16 +00002752 std::string QualsStr;
David Blaikief5697e52012-08-10 00:55:35 +00002753 if (Proto->isConst())
Douglas Gregor0f622362009-12-11 18:44:16 +00002754 QualsStr += " const";
David Blaikief5697e52012-08-10 00:55:35 +00002755 if (Proto->isVolatile())
Douglas Gregor0f622362009-12-11 18:44:16 +00002756 QualsStr += " volatile";
David Blaikief5697e52012-08-10 00:55:35 +00002757 if (Proto->isRestrict())
Douglas Gregor0f622362009-12-11 18:44:16 +00002758 QualsStr += " restrict";
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002759 Result.AddInformativeChunk(Result.getAllocator().CopyString(QualsStr));
Douglas Gregor0f622362009-12-11 18:44:16 +00002760}
2761
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002762/// Add the name of the given declaration
Douglas Gregor75acd922011-09-27 23:30:47 +00002763static void AddTypedNameChunk(ASTContext &Context, const PrintingPolicy &Policy,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002764 const NamedDecl *ND,
2765 CodeCompletionBuilder &Result) {
Douglas Gregor0212fd72010-09-21 16:06:22 +00002766 DeclarationName Name = ND->getDeclName();
2767 if (!Name)
2768 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002769
Douglas Gregor0212fd72010-09-21 16:06:22 +00002770 switch (Name.getNameKind()) {
Douglas Gregor304f9b02011-02-01 21:15:40 +00002771 case DeclarationName::CXXOperatorName: {
Craig Topperc3ec1492014-05-26 06:22:03 +00002772 const char *OperatorName = nullptr;
Douglas Gregor304f9b02011-02-01 21:15:40 +00002773 switch (Name.getCXXOverloadedOperator()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002774 case OO_None:
Douglas Gregor304f9b02011-02-01 21:15:40 +00002775 case OO_Conditional:
2776 case NUM_OVERLOADED_OPERATORS:
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002777 OperatorName = "operator";
Douglas Gregor304f9b02011-02-01 21:15:40 +00002778 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002779
Douglas Gregor304f9b02011-02-01 21:15:40 +00002780#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
2781 case OO_##Name: OperatorName = "operator" Spelling; break;
2782#define OVERLOADED_OPERATOR_MULTI(Name,Spelling,Unary,Binary,MemberOnly)
2783#include "clang/Basic/OperatorKinds.def"
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002784
Douglas Gregor304f9b02011-02-01 21:15:40 +00002785 case OO_New: OperatorName = "operator new"; break;
2786 case OO_Delete: OperatorName = "operator delete"; break;
2787 case OO_Array_New: OperatorName = "operator new[]"; break;
2788 case OO_Array_Delete: OperatorName = "operator delete[]"; break;
2789 case OO_Call: OperatorName = "operator()"; break;
2790 case OO_Subscript: OperatorName = "operator[]"; break;
2791 }
2792 Result.AddTypedTextChunk(OperatorName);
2793 break;
2794 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002795
Douglas Gregor0212fd72010-09-21 16:06:22 +00002796 case DeclarationName::Identifier:
2797 case DeclarationName::CXXConversionFunctionName:
Douglas Gregor0212fd72010-09-21 16:06:22 +00002798 case DeclarationName::CXXDestructorName:
2799 case DeclarationName::CXXLiteralOperatorName:
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002800 Result.AddTypedTextChunk(
2801 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor0212fd72010-09-21 16:06:22 +00002802 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002803
Richard Smith35845152017-02-07 01:37:30 +00002804 case DeclarationName::CXXDeductionGuideName:
Douglas Gregor0212fd72010-09-21 16:06:22 +00002805 case DeclarationName::CXXUsingDirective:
2806 case DeclarationName::ObjCZeroArgSelector:
2807 case DeclarationName::ObjCOneArgSelector:
2808 case DeclarationName::ObjCMultiArgSelector:
2809 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002810
Douglas Gregor0212fd72010-09-21 16:06:22 +00002811 case DeclarationName::CXXConstructorName: {
Craig Topperc3ec1492014-05-26 06:22:03 +00002812 CXXRecordDecl *Record = nullptr;
Douglas Gregor0212fd72010-09-21 16:06:22 +00002813 QualType Ty = Name.getCXXNameType();
2814 if (const RecordType *RecordTy = Ty->getAs<RecordType>())
2815 Record = cast<CXXRecordDecl>(RecordTy->getDecl());
2816 else if (const InjectedClassNameType *InjectedTy
2817 = Ty->getAs<InjectedClassNameType>())
2818 Record = InjectedTy->getDecl();
2819 else {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002820 Result.AddTypedTextChunk(
2821 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor0212fd72010-09-21 16:06:22 +00002822 break;
2823 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002824
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002825 Result.AddTypedTextChunk(
2826 Result.getAllocator().CopyString(Record->getNameAsString()));
Douglas Gregor0212fd72010-09-21 16:06:22 +00002827 if (ClassTemplateDecl *Template = Record->getDescribedClassTemplate()) {
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002828 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Douglas Gregor75acd922011-09-27 23:30:47 +00002829 AddTemplateParameterChunks(Context, Policy, Template, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002830 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregor0212fd72010-09-21 16:06:22 +00002831 }
2832 break;
2833 }
2834 }
2835}
2836
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002837CodeCompletionString *CodeCompletionResult::CreateCodeCompletionString(Sema &S,
Douglas Gregorc3425b12015-07-07 06:20:19 +00002838 const CodeCompletionContext &CCContext,
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00002839 CodeCompletionAllocator &Allocator,
Dmitri Gribenko3292d062012-07-02 17:35:10 +00002840 CodeCompletionTUInfo &CCTUInfo,
2841 bool IncludeBriefComments) {
Douglas Gregorc3425b12015-07-07 06:20:19 +00002842 return CreateCodeCompletionString(S.Context, S.PP, CCContext, Allocator,
2843 CCTUInfo, IncludeBriefComments);
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002844}
2845
Eric Liu00f43c92018-07-06 09:43:57 +00002846CodeCompletionString *CodeCompletionResult::CreateCodeCompletionStringForMacro(
2847 Preprocessor &PP, CodeCompletionAllocator &Allocator,
2848 CodeCompletionTUInfo &CCTUInfo) {
2849 assert(Kind == RK_Macro);
2850 CodeCompletionBuilder Result(Allocator, CCTUInfo, Priority, Availability);
2851 const MacroInfo *MI = PP.getMacroInfo(Macro);
2852 Result.AddTypedTextChunk(Result.getAllocator().CopyString(Macro->getName()));
2853
2854 if (!MI || !MI->isFunctionLike())
2855 return Result.TakeString();
2856
2857 // Format a function-like macro with placeholders for the arguments.
2858 Result.AddChunk(CodeCompletionString::CK_LeftParen);
2859 MacroInfo::param_iterator A = MI->param_begin(), AEnd = MI->param_end();
2860
2861 // C99 variadic macros add __VA_ARGS__ at the end. Skip it.
2862 if (MI->isC99Varargs()) {
2863 --AEnd;
2864
2865 if (A == AEnd) {
2866 Result.AddPlaceholderChunk("...");
2867 }
2868 }
2869
2870 for (MacroInfo::param_iterator A = MI->param_begin(); A != AEnd; ++A) {
2871 if (A != MI->param_begin())
2872 Result.AddChunk(CodeCompletionString::CK_Comma);
2873
2874 if (MI->isVariadic() && (A + 1) == AEnd) {
2875 SmallString<32> Arg = (*A)->getName();
2876 if (MI->isC99Varargs())
2877 Arg += ", ...";
2878 else
2879 Arg += "...";
2880 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg));
2881 break;
2882 }
2883
2884 // Non-variadic macros are simple.
2885 Result.AddPlaceholderChunk(
2886 Result.getAllocator().CopyString((*A)->getName()));
2887 }
2888 Result.AddChunk(CodeCompletionString::CK_RightParen);
2889 return Result.TakeString();
2890}
2891
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002892/// If possible, create a new code completion string for the given
Douglas Gregor3545ff42009-09-21 16:56:56 +00002893/// result.
2894///
2895/// \returns Either a new, heap-allocated code completion string describing
2896/// how to use this result, or NULL to indicate that the string or name of the
2897/// result is all that is needed.
2898CodeCompletionString *
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002899CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx,
2900 Preprocessor &PP,
Douglas Gregorc3425b12015-07-07 06:20:19 +00002901 const CodeCompletionContext &CCContext,
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00002902 CodeCompletionAllocator &Allocator,
Dmitri Gribenko3292d062012-07-02 17:35:10 +00002903 CodeCompletionTUInfo &CCTUInfo,
2904 bool IncludeBriefComments) {
Eric Liu00f43c92018-07-06 09:43:57 +00002905 if (Kind == RK_Macro)
2906 return CreateCodeCompletionStringForMacro(PP, Allocator, CCTUInfo);
2907
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00002908 CodeCompletionBuilder Result(Allocator, CCTUInfo, Priority, Availability);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002909
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002910 PrintingPolicy Policy = getCompletionPrintingPolicy(Ctx, PP);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002911 if (Kind == RK_Pattern) {
2912 Pattern->Priority = Priority;
2913 Pattern->Availability = Availability;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002914
Douglas Gregor78254c82012-03-27 23:34:16 +00002915 if (Declaration) {
2916 Result.addParentContext(Declaration->getDeclContext());
Douglas Gregor78254c82012-03-27 23:34:16 +00002917 Pattern->ParentName = Result.getParentName();
Ilya Biryukova3f955b2018-05-16 12:30:01 +00002918 if (const RawComment *RC =
2919 getPatternCompletionComment(Ctx, Declaration)) {
2920 Result.addBriefComment(RC->getBriefText(Ctx));
2921 Pattern->BriefComment = Result.getBriefComment();
2922 }
Douglas Gregor78254c82012-03-27 23:34:16 +00002923 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002924
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002925 return Pattern;
2926 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002927
Douglas Gregorf09935f2009-12-01 05:55:20 +00002928 if (Kind == RK_Keyword) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002929 Result.AddTypedTextChunk(Keyword);
2930 return Result.TakeString();
Douglas Gregorf09935f2009-12-01 05:55:20 +00002931 }
Douglas Gregorf64acca2010-05-25 21:41:55 +00002932 assert(Kind == RK_Declaration && "Missed a result kind?");
Kadir Cetinkayaae45d0a42018-10-02 09:42:31 +00002933 return createCodeCompletionStringForDecl(PP, Ctx, Result, IncludeBriefComments,
2934 CCContext, Policy);
2935}
2936
2937CodeCompletionString *
2938CodeCompletionResult::createCodeCompletionStringForOverride(
2939 Preprocessor &PP, ASTContext &Ctx, CodeCompletionBuilder &Result,
2940 bool IncludeBriefComments, const CodeCompletionContext &CCContext,
2941 PrintingPolicy &Policy) {
2942 std::string OverrideSignature;
2943 llvm::raw_string_ostream OS(OverrideSignature);
2944 auto *CCS = createCodeCompletionStringForDecl(PP, Ctx, Result,
2945 /*IncludeBriefComments=*/false,
2946 CCContext, Policy);
2947 printOverrideString(OS, CCS);
2948 OS << " override";
2949 Result.AddTypedTextChunk(Result.getAllocator().CopyString(OS.str()));
2950 return Result.TakeString();
2951}
2952
2953CodeCompletionString *CodeCompletionResult::createCodeCompletionStringForDecl(
2954 Preprocessor &PP, ASTContext &Ctx, CodeCompletionBuilder &Result,
2955 bool IncludeBriefComments, const CodeCompletionContext &CCContext,
2956 PrintingPolicy &Policy) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002957 const NamedDecl *ND = Declaration;
Douglas Gregor78254c82012-03-27 23:34:16 +00002958 Result.addParentContext(ND->getDeclContext());
Dmitri Gribenko3292d062012-07-02 17:35:10 +00002959
2960 if (IncludeBriefComments) {
2961 // Add documentation comment, if it exists.
Ilya Biryukova3f955b2018-05-16 12:30:01 +00002962 if (const RawComment *RC = getCompletionComment(Ctx, Declaration)) {
Dmitri Gribenko3292d062012-07-02 17:35:10 +00002963 Result.addBriefComment(RC->getBriefText(Ctx));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002964 }
Dmitri Gribenko3292d062012-07-02 17:35:10 +00002965 }
2966
Douglas Gregor9eb77012009-11-07 00:00:49 +00002967 if (StartsNestedNameSpecifier) {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002968 Result.AddTypedTextChunk(
2969 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002970 Result.AddTextChunk("::");
2971 return Result.TakeString();
Douglas Gregor9eb77012009-11-07 00:00:49 +00002972 }
Erik Verbruggen98ea7f62011-10-14 15:31:08 +00002973
Aaron Ballmanbe22bcb2014-03-10 17:08:28 +00002974 for (const auto *I : ND->specific_attrs<AnnotateAttr>())
2975 Result.AddAnnotation(Result.getAllocator().CopyString(I->getAnnotation()));
Aaron Ballmanb97112e2014-03-08 22:19:01 +00002976
Douglas Gregorc3425b12015-07-07 06:20:19 +00002977 AddResultTypeChunk(Ctx, Policy, ND, CCContext.getBaseType(), Result);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002978
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002979 if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(ND)) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002980 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002981 Ctx, Policy);
2982 AddTypedNameChunk(Ctx, Policy, ND, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002983 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Richard Smith20e883e2015-04-29 23:20:19 +00002984 AddFunctionParameterChunks(PP, Policy, Function, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002985 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor0f622362009-12-11 18:44:16 +00002986 AddFunctionTypeQualsToCompletionString(Result, Function);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002987 return Result.TakeString();
Douglas Gregor3545ff42009-09-21 16:56:56 +00002988 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002989
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002990 if (const FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND)) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002991 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002992 Ctx, Policy);
Douglas Gregor3545ff42009-09-21 16:56:56 +00002993 FunctionDecl *Function = FunTmpl->getTemplatedDecl();
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002994 AddTypedNameChunk(Ctx, Policy, Function, Result);
Douglas Gregor0212fd72010-09-21 16:06:22 +00002995
Douglas Gregor3545ff42009-09-21 16:56:56 +00002996 // Figure out which template parameters are deduced (or have default
2997 // arguments).
Benjamin Kramere0513cb2012-01-30 16:17:39 +00002998 llvm::SmallBitVector Deduced;
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002999 Sema::MarkDeducedTemplateParameters(Ctx, FunTmpl, Deduced);
Douglas Gregor3545ff42009-09-21 16:56:56 +00003000 unsigned LastDeducibleArgument;
3001 for (LastDeducibleArgument = Deduced.size(); LastDeducibleArgument > 0;
3002 --LastDeducibleArgument) {
3003 if (!Deduced[LastDeducibleArgument - 1]) {
3004 // C++0x: Figure out if the template argument has a default. If so,
3005 // the user doesn't need to type this argument.
3006 // FIXME: We need to abstract template parameters better!
3007 bool HasDefaultArg = false;
3008 NamedDecl *Param = FunTmpl->getTemplateParameters()->getParam(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003009 LastDeducibleArgument - 1);
Douglas Gregor3545ff42009-09-21 16:56:56 +00003010 if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param))
3011 HasDefaultArg = TTP->hasDefaultArgument();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003012 else if (NonTypeTemplateParmDecl *NTTP
Douglas Gregor3545ff42009-09-21 16:56:56 +00003013 = dyn_cast<NonTypeTemplateParmDecl>(Param))
3014 HasDefaultArg = NTTP->hasDefaultArgument();
3015 else {
3016 assert(isa<TemplateTemplateParmDecl>(Param));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003017 HasDefaultArg
Douglas Gregor9eb77012009-11-07 00:00:49 +00003018 = cast<TemplateTemplateParmDecl>(Param)->hasDefaultArgument();
Douglas Gregor3545ff42009-09-21 16:56:56 +00003019 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003020
Douglas Gregor3545ff42009-09-21 16:56:56 +00003021 if (!HasDefaultArg)
3022 break;
3023 }
3024 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003025
Douglas Gregor3545ff42009-09-21 16:56:56 +00003026 if (LastDeducibleArgument) {
3027 // Some of the function template arguments cannot be deduced from a
3028 // function call, so we introduce an explicit template argument list
3029 // containing all of the arguments up to the first deducible argument.
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003030 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003031 AddTemplateParameterChunks(Ctx, Policy, FunTmpl, Result,
Douglas Gregor3545ff42009-09-21 16:56:56 +00003032 LastDeducibleArgument);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003033 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregor3545ff42009-09-21 16:56:56 +00003034 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003035
Douglas Gregor3545ff42009-09-21 16:56:56 +00003036 // Add the function parameters
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003037 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Richard Smith20e883e2015-04-29 23:20:19 +00003038 AddFunctionParameterChunks(PP, Policy, Function, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003039 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor0f622362009-12-11 18:44:16 +00003040 AddFunctionTypeQualsToCompletionString(Result, Function);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003041 return Result.TakeString();
Douglas Gregor3545ff42009-09-21 16:56:56 +00003042 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003043
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00003044 if (const TemplateDecl *Template = dyn_cast<TemplateDecl>(ND)) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003045 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003046 Ctx, Policy);
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003047 Result.AddTypedTextChunk(
3048 Result.getAllocator().CopyString(Template->getNameAsString()));
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003049 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003050 AddTemplateParameterChunks(Ctx, Policy, Template, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003051 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003052 return Result.TakeString();
Douglas Gregor3545ff42009-09-21 16:56:56 +00003053 }
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00003054 if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND)) {
Douglas Gregord3c5d792009-11-17 16:44:22 +00003055 Selector Sel = Method->getSelector();
3056 if (Sel.isUnarySelector()) {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003057 Result.AddTypedTextChunk(Result.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00003058 Sel.getNameForSlot(0)));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003059 return Result.TakeString();
Douglas Gregord3c5d792009-11-17 16:44:22 +00003060 }
3061
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00003062 std::string SelName = Sel.getNameForSlot(0).str();
Douglas Gregor1b605f72009-11-19 01:08:35 +00003063 SelName += ':';
3064 if (StartParameter == 0)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003065 Result.AddTypedTextChunk(Result.getAllocator().CopyString(SelName));
Douglas Gregor1b605f72009-11-19 01:08:35 +00003066 else {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003067 Result.AddInformativeChunk(Result.getAllocator().CopyString(SelName));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003068
Douglas Gregor1b605f72009-11-19 01:08:35 +00003069 // If there is only one parameter, and we're past it, add an empty
3070 // typed-text chunk since there is nothing to type.
3071 if (Method->param_size() == 1)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003072 Result.AddTypedTextChunk("");
Douglas Gregor1b605f72009-11-19 01:08:35 +00003073 }
Douglas Gregord3c5d792009-11-17 16:44:22 +00003074 unsigned Idx = 0;
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00003075 for (ObjCMethodDecl::param_const_iterator P = Method->param_begin(),
3076 PEnd = Method->param_end();
Douglas Gregord3c5d792009-11-17 16:44:22 +00003077 P != PEnd; (void)++P, ++Idx) {
3078 if (Idx > 0) {
Douglas Gregor1b605f72009-11-19 01:08:35 +00003079 std::string Keyword;
3080 if (Idx > StartParameter)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003081 Result.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregord3c5d792009-11-17 16:44:22 +00003082 if (IdentifierInfo *II = Sel.getIdentifierInfoForSlot(Idx))
Benjamin Kramer632500c2011-07-26 16:59:25 +00003083 Keyword += II->getName();
Douglas Gregord3c5d792009-11-17 16:44:22 +00003084 Keyword += ":";
Douglas Gregor95887f92010-07-08 23:20:03 +00003085 if (Idx < StartParameter || AllParametersAreInformative)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003086 Result.AddInformativeChunk(Result.getAllocator().CopyString(Keyword));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003087 else
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003088 Result.AddTypedTextChunk(Result.getAllocator().CopyString(Keyword));
Douglas Gregord3c5d792009-11-17 16:44:22 +00003089 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003090
Douglas Gregor1b605f72009-11-19 01:08:35 +00003091 // If we're before the starting parameter, skip the placeholder.
3092 if (Idx < StartParameter)
3093 continue;
Douglas Gregord3c5d792009-11-17 16:44:22 +00003094
3095 std::string Arg;
Douglas Gregorc3425b12015-07-07 06:20:19 +00003096 QualType ParamType = (*P)->getType();
3097 Optional<ArrayRef<QualType>> ObjCSubsts;
3098 if (!CCContext.getBaseType().isNull())
3099 ObjCSubsts = CCContext.getBaseType()->getObjCSubstitutions(Method);
3100
3101 if (ParamType->isBlockPointerType() && !DeclaringEntity)
3102 Arg = FormatFunctionParameter(Policy, *P, true,
3103 /*SuppressBlock=*/false,
3104 ObjCSubsts);
Douglas Gregore90dd002010-08-24 16:15:59 +00003105 else {
Douglas Gregorc3425b12015-07-07 06:20:19 +00003106 if (ObjCSubsts)
3107 ParamType = ParamType.substObjCTypeArgs(Ctx, *ObjCSubsts,
3108 ObjCSubstitutionContext::Parameter);
Douglas Gregor86b42682015-06-19 18:27:52 +00003109 Arg = "(" + formatObjCParamQualifiers((*P)->getObjCDeclQualifier(),
Douglas Gregorc3425b12015-07-07 06:20:19 +00003110 ParamType);
3111 Arg += ParamType.getAsString(Policy) + ")";
Douglas Gregore90dd002010-08-24 16:15:59 +00003112 if (IdentifierInfo *II = (*P)->getIdentifier())
Douglas Gregor981a0c42010-08-29 19:47:46 +00003113 if (DeclaringEntity || AllParametersAreInformative)
Benjamin Kramer632500c2011-07-26 16:59:25 +00003114 Arg += II->getName();
Douglas Gregore90dd002010-08-24 16:15:59 +00003115 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003116
Douglas Gregor400f5972010-08-31 05:13:43 +00003117 if (Method->isVariadic() && (P + 1) == PEnd)
3118 Arg += ", ...";
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003119
Douglas Gregor95887f92010-07-08 23:20:03 +00003120 if (DeclaringEntity)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003121 Result.AddTextChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregor95887f92010-07-08 23:20:03 +00003122 else if (AllParametersAreInformative)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003123 Result.AddInformativeChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregorc8537c52009-11-19 07:41:15 +00003124 else
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003125 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregord3c5d792009-11-17 16:44:22 +00003126 }
3127
Douglas Gregor04c5f972009-12-23 00:21:46 +00003128 if (Method->isVariadic()) {
Douglas Gregor400f5972010-08-31 05:13:43 +00003129 if (Method->param_size() == 0) {
3130 if (DeclaringEntity)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003131 Result.AddTextChunk(", ...");
Douglas Gregor400f5972010-08-31 05:13:43 +00003132 else if (AllParametersAreInformative)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003133 Result.AddInformativeChunk(", ...");
Douglas Gregor400f5972010-08-31 05:13:43 +00003134 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003135 Result.AddPlaceholderChunk(", ...");
Douglas Gregor400f5972010-08-31 05:13:43 +00003136 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003137
Richard Smith20e883e2015-04-29 23:20:19 +00003138 MaybeAddSentinel(PP, Method, Result);
Douglas Gregor04c5f972009-12-23 00:21:46 +00003139 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003140
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003141 return Result.TakeString();
Douglas Gregord3c5d792009-11-17 16:44:22 +00003142 }
3143
Douglas Gregorf09935f2009-12-01 05:55:20 +00003144 if (Qualifier)
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003145 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003146 Ctx, Policy);
Douglas Gregorf09935f2009-12-01 05:55:20 +00003147
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003148 Result.AddTypedTextChunk(
Kadir Cetinkayaae45d0a42018-10-02 09:42:31 +00003149 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003150 return Result.TakeString();
Douglas Gregor3545ff42009-09-21 16:56:56 +00003151}
3152
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003153const RawComment *clang::getCompletionComment(const ASTContext &Ctx,
3154 const NamedDecl *ND) {
3155 if (!ND)
3156 return nullptr;
3157 if (auto *RC = Ctx.getRawCommentForAnyRedecl(ND))
3158 return RC;
3159
3160 // Try to find comment from a property for ObjC methods.
3161 const ObjCMethodDecl *M = dyn_cast<ObjCMethodDecl>(ND);
3162 if (!M)
3163 return nullptr;
3164 const ObjCPropertyDecl *PDecl = M->findPropertyDecl();
3165 if (!PDecl)
3166 return nullptr;
3167
3168 return Ctx.getRawCommentForAnyRedecl(PDecl);
3169}
3170
3171const RawComment *clang::getPatternCompletionComment(const ASTContext &Ctx,
3172 const NamedDecl *ND) {
3173 const ObjCMethodDecl *M = dyn_cast_or_null<ObjCMethodDecl>(ND);
3174 if (!M || !M->isPropertyAccessor())
3175 return nullptr;
3176
3177 // Provide code completion comment for self.GetterName where
3178 // GetterName is the getter method for a property with name
3179 // different from the property name (declared via a property
3180 // getter attribute.
3181 const ObjCPropertyDecl *PDecl = M->findPropertyDecl();
3182 if (!PDecl)
3183 return nullptr;
3184 if (PDecl->getGetterName() == M->getSelector() &&
3185 PDecl->getIdentifier() != M->getIdentifier()) {
3186 if (auto *RC = Ctx.getRawCommentForAnyRedecl(M))
3187 return RC;
3188 if (auto *RC = Ctx.getRawCommentForAnyRedecl(PDecl))
3189 return RC;
3190 }
3191 return nullptr;
3192}
3193
3194const RawComment *clang::getParameterComment(
3195 const ASTContext &Ctx,
3196 const CodeCompleteConsumer::OverloadCandidate &Result,
3197 unsigned ArgIndex) {
3198 auto FDecl = Result.getFunction();
3199 if (!FDecl)
3200 return nullptr;
3201 if (ArgIndex < FDecl->getNumParams())
3202 return Ctx.getRawCommentForAnyRedecl(FDecl->getParamDecl(ArgIndex));
3203 return nullptr;
3204}
3205
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003206/// Add function overload parameter chunks to the given code completion
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003207/// string.
3208static void AddOverloadParameterChunks(ASTContext &Context,
3209 const PrintingPolicy &Policy,
3210 const FunctionDecl *Function,
3211 const FunctionProtoType *Prototype,
3212 CodeCompletionBuilder &Result,
3213 unsigned CurrentArg,
3214 unsigned Start = 0,
3215 bool InOptional = false) {
3216 bool FirstParameter = true;
3217 unsigned NumParams = Function ? Function->getNumParams()
3218 : Prototype->getNumParams();
3219
3220 for (unsigned P = Start; P != NumParams; ++P) {
3221 if (Function && Function->getParamDecl(P)->hasDefaultArg() && !InOptional) {
3222 // When we see an optional default argument, put that argument and
3223 // the remaining default arguments into a new, optional string.
3224 CodeCompletionBuilder Opt(Result.getAllocator(),
3225 Result.getCodeCompletionTUInfo());
3226 if (!FirstParameter)
3227 Opt.AddChunk(CodeCompletionString::CK_Comma);
3228 // Optional sections are nested.
3229 AddOverloadParameterChunks(Context, Policy, Function, Prototype, Opt,
3230 CurrentArg, P, /*InOptional=*/true);
3231 Result.AddOptionalChunk(Opt.TakeString());
3232 return;
3233 }
3234
3235 if (FirstParameter)
3236 FirstParameter = false;
3237 else
3238 Result.AddChunk(CodeCompletionString::CK_Comma);
3239
3240 InOptional = false;
3241
3242 // Format the placeholder string.
3243 std::string Placeholder;
Erik Verbruggen11338c52017-07-19 10:45:40 +00003244 if (Function) {
3245 const ParmVarDecl *Param = Function->getParamDecl(P);
3246 Placeholder = FormatFunctionParameter(Policy, Param);
3247 if (Param->hasDefaultArg())
3248 Placeholder += GetDefaultValueString(Param, Context.getSourceManager(), Context.getLangOpts());
3249 } else {
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003250 Placeholder = Prototype->getParamType(P).getAsString(Policy);
Erik Verbruggen11338c52017-07-19 10:45:40 +00003251 }
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003252
3253 if (P == CurrentArg)
3254 Result.AddCurrentParameterChunk(
3255 Result.getAllocator().CopyString(Placeholder));
3256 else
3257 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Placeholder));
3258 }
3259
3260 if (Prototype && Prototype->isVariadic()) {
3261 CodeCompletionBuilder Opt(Result.getAllocator(),
3262 Result.getCodeCompletionTUInfo());
3263 if (!FirstParameter)
3264 Opt.AddChunk(CodeCompletionString::CK_Comma);
3265
3266 if (CurrentArg < NumParams)
3267 Opt.AddPlaceholderChunk("...");
3268 else
3269 Opt.AddCurrentParameterChunk("...");
3270
3271 Result.AddOptionalChunk(Opt.TakeString());
3272 }
3273}
3274
Douglas Gregorf0f51982009-09-23 00:34:09 +00003275CodeCompletionString *
3276CodeCompleteConsumer::OverloadCandidate::CreateSignatureString(
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003277 unsigned CurrentArg, Sema &S,
3278 CodeCompletionAllocator &Allocator,
3279 CodeCompletionTUInfo &CCTUInfo,
3280 bool IncludeBriefComments) const {
Douglas Gregor75acd922011-09-27 23:30:47 +00003281 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
John McCall31168b02011-06-15 23:02:42 +00003282
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003283 // FIXME: Set priority, availability appropriately.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003284 CodeCompletionBuilder Result(Allocator,CCTUInfo, 1, CXAvailability_Available);
Douglas Gregorf0f51982009-09-23 00:34:09 +00003285 FunctionDecl *FDecl = getFunction();
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003286 const FunctionProtoType *Proto
Douglas Gregorf0f51982009-09-23 00:34:09 +00003287 = dyn_cast<FunctionProtoType>(getFunctionType());
3288 if (!FDecl && !Proto) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003289 // Function without a prototype. Just give the return type and a
Douglas Gregorf0f51982009-09-23 00:34:09 +00003290 // highlighted ellipsis.
3291 const FunctionType *FT = getFunctionType();
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003292 Result.AddResultTypeChunk(Result.getAllocator().CopyString(
3293 FT->getReturnType().getAsString(Policy)));
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003294 Result.AddChunk(CodeCompletionString::CK_LeftParen);
3295 Result.AddChunk(CodeCompletionString::CK_CurrentParameter, "...");
3296 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003297 return Result.TakeString();
Douglas Gregorf0f51982009-09-23 00:34:09 +00003298 }
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003299
3300 if (FDecl) {
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003301 if (IncludeBriefComments) {
3302 if (auto RC = getParameterComment(S.getASTContext(), *this, CurrentArg))
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003303 Result.addBriefComment(RC->getBriefText(S.getASTContext()));
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003304 }
Douglas Gregorc3425b12015-07-07 06:20:19 +00003305 AddResultTypeChunk(S.Context, Policy, FDecl, QualType(), Result);
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003306 Result.AddTextChunk(
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003307 Result.getAllocator().CopyString(FDecl->getNameAsString()));
3308 } else {
3309 Result.AddResultTypeChunk(
3310 Result.getAllocator().CopyString(
Alp Toker314cc812014-01-25 16:55:45 +00003311 Proto->getReturnType().getAsString(Policy)));
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003312 }
Alp Toker314cc812014-01-25 16:55:45 +00003313
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003314 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003315 AddOverloadParameterChunks(S.getASTContext(), Policy, FDecl, Proto, Result,
3316 CurrentArg);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003317 Result.AddChunk(CodeCompletionString::CK_RightParen);
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003318
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003319 return Result.TakeString();
Douglas Gregorf0f51982009-09-23 00:34:09 +00003320}
3321
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003322unsigned clang::getMacroUsagePriority(StringRef MacroName,
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00003323 const LangOptions &LangOpts,
Douglas Gregor6e240332010-08-16 16:18:59 +00003324 bool PreferredTypeIsPointer) {
3325 unsigned Priority = CCP_Macro;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003326
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00003327 // Treat the "nil", "Nil" and "NULL" macros as null pointer constants.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003328 if (MacroName.equals("nil") || MacroName.equals("NULL") ||
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00003329 MacroName.equals("Nil")) {
Douglas Gregor6e240332010-08-16 16:18:59 +00003330 Priority = CCP_Constant;
3331 if (PreferredTypeIsPointer)
3332 Priority = Priority / CCF_SimilarTypeMatch;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003333 }
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00003334 // Treat "YES", "NO", "true", and "false" as constants.
3335 else if (MacroName.equals("YES") || MacroName.equals("NO") ||
3336 MacroName.equals("true") || MacroName.equals("false"))
3337 Priority = CCP_Constant;
3338 // Treat "bool" as a type.
3339 else if (MacroName.equals("bool"))
Erik Pilkingtonfa983902018-10-30 20:31:30 +00003340 Priority = CCP_Type + (LangOpts.ObjC ? CCD_bool_in_ObjC : 0);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003341
3342
Douglas Gregor6e240332010-08-16 16:18:59 +00003343 return Priority;
3344}
3345
Dmitri Gribenkobdc80de2013-01-11 20:32:41 +00003346CXCursorKind clang::getCursorKindForDecl(const Decl *D) {
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003347 if (!D)
3348 return CXCursor_UnexposedDecl;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003349
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003350 switch (D->getKind()) {
3351 case Decl::Enum: return CXCursor_EnumDecl;
3352 case Decl::EnumConstant: return CXCursor_EnumConstantDecl;
3353 case Decl::Field: return CXCursor_FieldDecl;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003354 case Decl::Function:
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003355 return CXCursor_FunctionDecl;
3356 case Decl::ObjCCategory: return CXCursor_ObjCCategoryDecl;
3357 case Decl::ObjCCategoryImpl: return CXCursor_ObjCCategoryImplDecl;
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003358 case Decl::ObjCImplementation: return CXCursor_ObjCImplementationDecl;
Douglas Gregordeafd0b2011-12-27 22:43:10 +00003359
Argyrios Kyrtzidis3698cef2012-01-24 21:39:26 +00003360 case Decl::ObjCInterface: return CXCursor_ObjCInterfaceDecl;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003361 case Decl::ObjCIvar: return CXCursor_ObjCIvarDecl;
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003362 case Decl::ObjCMethod:
3363 return cast<ObjCMethodDecl>(D)->isInstanceMethod()
3364 ? CXCursor_ObjCInstanceMethodDecl : CXCursor_ObjCClassMethodDecl;
3365 case Decl::CXXMethod: return CXCursor_CXXMethod;
3366 case Decl::CXXConstructor: return CXCursor_Constructor;
3367 case Decl::CXXDestructor: return CXCursor_Destructor;
3368 case Decl::CXXConversion: return CXCursor_ConversionFunction;
3369 case Decl::ObjCProperty: return CXCursor_ObjCPropertyDecl;
Argyrios Kyrtzidis3698cef2012-01-24 21:39:26 +00003370 case Decl::ObjCProtocol: return CXCursor_ObjCProtocolDecl;
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003371 case Decl::ParmVar: return CXCursor_ParmDecl;
3372 case Decl::Typedef: return CXCursor_TypedefDecl;
Richard Smithdda56e42011-04-15 14:24:37 +00003373 case Decl::TypeAlias: return CXCursor_TypeAliasDecl;
Sergey Kalinichev8f3b1872015-11-15 13:48:32 +00003374 case Decl::TypeAliasTemplate: return CXCursor_TypeAliasTemplateDecl;
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003375 case Decl::Var: return CXCursor_VarDecl;
3376 case Decl::Namespace: return CXCursor_Namespace;
3377 case Decl::NamespaceAlias: return CXCursor_NamespaceAlias;
3378 case Decl::TemplateTypeParm: return CXCursor_TemplateTypeParameter;
3379 case Decl::NonTypeTemplateParm:return CXCursor_NonTypeTemplateParameter;
3380 case Decl::TemplateTemplateParm:return CXCursor_TemplateTemplateParameter;
3381 case Decl::FunctionTemplate: return CXCursor_FunctionTemplate;
3382 case Decl::ClassTemplate: return CXCursor_ClassTemplate;
Argyrios Kyrtzidis12afd702011-09-30 17:58:23 +00003383 case Decl::AccessSpec: return CXCursor_CXXAccessSpecifier;
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003384 case Decl::ClassTemplatePartialSpecialization:
3385 return CXCursor_ClassTemplatePartialSpecialization;
3386 case Decl::UsingDirective: return CXCursor_UsingDirective;
Olivier Goffart81978012016-06-09 16:15:55 +00003387 case Decl::StaticAssert: return CXCursor_StaticAssert;
Olivier Goffartd211c642016-11-04 06:29:27 +00003388 case Decl::Friend: return CXCursor_FriendDecl;
Douglas Gregor3e653b32012-04-30 23:41:16 +00003389 case Decl::TranslationUnit: return CXCursor_TranslationUnit;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003390
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003391 case Decl::Using:
3392 case Decl::UnresolvedUsingValue:
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003393 case Decl::UnresolvedUsingTypename:
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003394 return CXCursor_UsingDeclaration;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003395
Douglas Gregor4cd65962011-06-03 23:08:58 +00003396 case Decl::ObjCPropertyImpl:
3397 switch (cast<ObjCPropertyImplDecl>(D)->getPropertyImplementation()) {
3398 case ObjCPropertyImplDecl::Dynamic:
3399 return CXCursor_ObjCDynamicDecl;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003400
Douglas Gregor4cd65962011-06-03 23:08:58 +00003401 case ObjCPropertyImplDecl::Synthesize:
3402 return CXCursor_ObjCSynthesizeDecl;
3403 }
Argyrios Kyrtzidis50e5b1d2012-10-05 00:22:24 +00003404
3405 case Decl::Import:
3406 return CXCursor_ModuleImportDecl;
Douglas Gregor85f3f952015-07-07 03:57:15 +00003407
3408 case Decl::ObjCTypeParam: return CXCursor_TemplateTypeParameter;
3409
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003410 default:
Dmitri Gribenkobdc80de2013-01-11 20:32:41 +00003411 if (const TagDecl *TD = dyn_cast<TagDecl>(D)) {
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003412 switch (TD->getTagKind()) {
Joao Matosdc86f942012-08-31 18:45:21 +00003413 case TTK_Interface: // fall through
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003414 case TTK_Struct: return CXCursor_StructDecl;
3415 case TTK_Class: return CXCursor_ClassDecl;
3416 case TTK_Union: return CXCursor_UnionDecl;
3417 case TTK_Enum: return CXCursor_EnumDecl;
3418 }
3419 }
3420 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003421
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003422 return CXCursor_UnexposedDecl;
3423}
3424
Douglas Gregor55b037b2010-07-08 20:55:51 +00003425static void AddMacroResults(Preprocessor &PP, ResultBuilder &Results,
Eric Liu88de9f62018-09-19 09:34:55 +00003426 bool LoadExternal, bool IncludeUndefined,
Douglas Gregor55b037b2010-07-08 20:55:51 +00003427 bool TargetTypeIsPointer = false) {
John McCall276321a2010-08-25 06:19:51 +00003428 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003429
Douglas Gregorf329c7c2009-10-30 16:50:04 +00003430 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003431
Eric Liu88de9f62018-09-19 09:34:55 +00003432 for (Preprocessor::macro_iterator M = PP.macro_begin(LoadExternal),
3433 MEnd = PP.macro_end(LoadExternal);
Douglas Gregor55b037b2010-07-08 20:55:51 +00003434 M != MEnd; ++M) {
Richard Smith20e883e2015-04-29 23:20:19 +00003435 auto MD = PP.getMacroDefinition(M->first);
3436 if (IncludeUndefined || MD) {
Eric Liud485df12018-09-05 14:59:17 +00003437 MacroInfo *MI = MD.getMacroInfo();
3438 if (MI && MI->isUsedForHeaderGuard())
3439 continue;
Argyrios Kyrtzidis9ef53ce2014-04-09 18:21:23 +00003440
Eric Liud485df12018-09-05 14:59:17 +00003441 Results.AddResult(
3442 Result(M->first, MI,
3443 getMacroUsagePriority(M->first->getName(), PP.getLangOpts(),
3444 TargetTypeIsPointer)));
Argyrios Kyrtzidis9ef53ce2014-04-09 18:21:23 +00003445 }
Douglas Gregor55b037b2010-07-08 20:55:51 +00003446 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003447
Douglas Gregorf329c7c2009-10-30 16:50:04 +00003448 Results.ExitScope();
3449}
3450
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003451static void AddPrettyFunctionResults(const LangOptions &LangOpts,
Douglas Gregorce0e8562010-08-23 21:54:33 +00003452 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00003453 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003454
Douglas Gregorce0e8562010-08-23 21:54:33 +00003455 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003456
Douglas Gregorce0e8562010-08-23 21:54:33 +00003457 Results.AddResult(Result("__PRETTY_FUNCTION__", CCP_Constant));
3458 Results.AddResult(Result("__FUNCTION__", CCP_Constant));
Richard Smith2bf7fdb2013-01-02 11:42:31 +00003459 if (LangOpts.C99 || LangOpts.CPlusPlus11)
Douglas Gregorce0e8562010-08-23 21:54:33 +00003460 Results.AddResult(Result("__func__", CCP_Constant));
3461 Results.ExitScope();
3462}
3463
Daniel Dunbar242ea9a2009-11-13 08:58:20 +00003464static void HandleCodeCompleteResults(Sema *S,
3465 CodeCompleteConsumer *CodeCompleter,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003466 CodeCompletionContext Context,
John McCall276321a2010-08-25 06:19:51 +00003467 CodeCompletionResult *Results,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003468 unsigned NumResults) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00003469 if (CodeCompleter)
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003470 CodeCompleter->ProcessCodeCompleteResults(*S, Context, Results, NumResults);
Douglas Gregor3545ff42009-09-21 16:56:56 +00003471}
3472
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003473static enum CodeCompletionContext::Kind mapCodeCompletionContext(Sema &S,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003474 Sema::ParserCompletionContext PCC) {
3475 switch (PCC) {
John McCallfaf5fb42010-08-26 23:41:50 +00003476 case Sema::PCC_Namespace:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003477 return CodeCompletionContext::CCC_TopLevel;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003478
John McCallfaf5fb42010-08-26 23:41:50 +00003479 case Sema::PCC_Class:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003480 return CodeCompletionContext::CCC_ClassStructUnion;
3481
John McCallfaf5fb42010-08-26 23:41:50 +00003482 case Sema::PCC_ObjCInterface:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003483 return CodeCompletionContext::CCC_ObjCInterface;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003484
John McCallfaf5fb42010-08-26 23:41:50 +00003485 case Sema::PCC_ObjCImplementation:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003486 return CodeCompletionContext::CCC_ObjCImplementation;
3487
John McCallfaf5fb42010-08-26 23:41:50 +00003488 case Sema::PCC_ObjCInstanceVariableList:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003489 return CodeCompletionContext::CCC_ObjCIvarList;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003490
John McCallfaf5fb42010-08-26 23:41:50 +00003491 case Sema::PCC_Template:
3492 case Sema::PCC_MemberTemplate:
Douglas Gregor0ac41382010-09-23 23:01:17 +00003493 if (S.CurContext->isFileContext())
3494 return CodeCompletionContext::CCC_TopLevel;
David Blaikie8a40f702012-01-17 06:56:22 +00003495 if (S.CurContext->isRecord())
Douglas Gregor0ac41382010-09-23 23:01:17 +00003496 return CodeCompletionContext::CCC_ClassStructUnion;
David Blaikie8a40f702012-01-17 06:56:22 +00003497 return CodeCompletionContext::CCC_Other;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003498
John McCallfaf5fb42010-08-26 23:41:50 +00003499 case Sema::PCC_RecoveryInFunction:
Douglas Gregor0ac41382010-09-23 23:01:17 +00003500 return CodeCompletionContext::CCC_Recovery;
Douglas Gregorc769d6e2010-10-18 22:01:46 +00003501
John McCallfaf5fb42010-08-26 23:41:50 +00003502 case Sema::PCC_ForInit:
David Blaikiebbafb8a2012-03-11 07:00:24 +00003503 if (S.getLangOpts().CPlusPlus || S.getLangOpts().C99 ||
Erik Pilkingtonfa983902018-10-30 20:31:30 +00003504 S.getLangOpts().ObjC)
Douglas Gregorc769d6e2010-10-18 22:01:46 +00003505 return CodeCompletionContext::CCC_ParenthesizedExpression;
3506 else
3507 return CodeCompletionContext::CCC_Expression;
3508
3509 case Sema::PCC_Expression:
John McCallfaf5fb42010-08-26 23:41:50 +00003510 case Sema::PCC_Condition:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003511 return CodeCompletionContext::CCC_Expression;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003512
John McCallfaf5fb42010-08-26 23:41:50 +00003513 case Sema::PCC_Statement:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003514 return CodeCompletionContext::CCC_Statement;
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003515
John McCallfaf5fb42010-08-26 23:41:50 +00003516 case Sema::PCC_Type:
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003517 return CodeCompletionContext::CCC_Type;
Douglas Gregor5e35d592010-09-14 23:59:36 +00003518
3519 case Sema::PCC_ParenthesizedExpression:
3520 return CodeCompletionContext::CCC_ParenthesizedExpression;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003521
Douglas Gregor80039242011-02-15 20:33:25 +00003522 case Sema::PCC_LocalDeclarationSpecifiers:
3523 return CodeCompletionContext::CCC_Type;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003524 }
David Blaikie8a40f702012-01-17 06:56:22 +00003525
3526 llvm_unreachable("Invalid ParserCompletionContext!");
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003527}
3528
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003529/// If we're in a C++ virtual member function, add completion results
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003530/// that invoke the functions we override, since it's common to invoke the
Douglas Gregorac322ec2010-08-27 21:18:54 +00003531/// overridden function as well as adding new functionality.
3532///
3533/// \param S The semantic analysis object for which we are generating results.
3534///
3535/// \param InContext This context in which the nested-name-specifier preceding
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003536/// the code-completion point
Douglas Gregorac322ec2010-08-27 21:18:54 +00003537static void MaybeAddOverrideCalls(Sema &S, DeclContext *InContext,
3538 ResultBuilder &Results) {
3539 // Look through blocks.
3540 DeclContext *CurContext = S.CurContext;
3541 while (isa<BlockDecl>(CurContext))
3542 CurContext = CurContext->getParent();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003543
3544
Douglas Gregorac322ec2010-08-27 21:18:54 +00003545 CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(CurContext);
3546 if (!Method || !Method->isVirtual())
3547 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003548
3549 // We need to have names for all of the parameters, if we're going to
Douglas Gregorac322ec2010-08-27 21:18:54 +00003550 // generate a forwarding call.
David Majnemer59f77922016-06-24 04:05:48 +00003551 for (auto P : Method->parameters())
Aaron Ballman43b68be2014-03-07 17:50:17 +00003552 if (!P->getDeclName())
Douglas Gregorac322ec2010-08-27 21:18:54 +00003553 return;
Douglas Gregorac322ec2010-08-27 21:18:54 +00003554
Douglas Gregor75acd922011-09-27 23:30:47 +00003555 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
Benjamin Krameracfa3392017-12-17 23:52:45 +00003556 for (const CXXMethodDecl *Overridden : Method->overridden_methods()) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003557 CodeCompletionBuilder Builder(Results.getAllocator(),
3558 Results.getCodeCompletionTUInfo());
Douglas Gregorac322ec2010-08-27 21:18:54 +00003559 if (Overridden->getCanonicalDecl() == Method->getCanonicalDecl())
3560 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003561
Douglas Gregorac322ec2010-08-27 21:18:54 +00003562 // If we need a nested-name-specifier, add one now.
3563 if (!InContext) {
3564 NestedNameSpecifier *NNS
3565 = getRequiredQualification(S.Context, CurContext,
3566 Overridden->getDeclContext());
3567 if (NNS) {
3568 std::string Str;
3569 llvm::raw_string_ostream OS(Str);
Douglas Gregor75acd922011-09-27 23:30:47 +00003570 NNS->print(OS, Policy);
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003571 Builder.AddTextChunk(Results.getAllocator().CopyString(OS.str()));
Douglas Gregorac322ec2010-08-27 21:18:54 +00003572 }
3573 } else if (!InContext->Equals(Overridden->getDeclContext()))
3574 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003575
3576 Builder.AddTypedTextChunk(Results.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003577 Overridden->getNameAsString()));
3578 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregorac322ec2010-08-27 21:18:54 +00003579 bool FirstParam = true;
David Majnemer59f77922016-06-24 04:05:48 +00003580 for (auto P : Method->parameters()) {
Douglas Gregorac322ec2010-08-27 21:18:54 +00003581 if (FirstParam)
3582 FirstParam = false;
3583 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003584 Builder.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregorac322ec2010-08-27 21:18:54 +00003585
Aaron Ballman43b68be2014-03-07 17:50:17 +00003586 Builder.AddPlaceholderChunk(
3587 Results.getAllocator().CopyString(P->getIdentifier()->getName()));
Douglas Gregorac322ec2010-08-27 21:18:54 +00003588 }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003589 Builder.AddChunk(CodeCompletionString::CK_RightParen);
3590 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregorac322ec2010-08-27 21:18:54 +00003591 CCP_SuperCompletion,
Douglas Gregor78254c82012-03-27 23:34:16 +00003592 CXCursor_CXXMethod,
3593 CXAvailability_Available,
3594 Overridden));
Douglas Gregorac322ec2010-08-27 21:18:54 +00003595 Results.Ignore(Overridden);
3596 }
3597}
3598
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003599void Sema::CodeCompleteModuleImport(SourceLocation ImportLoc,
Douglas Gregor07f43572012-01-29 18:15:03 +00003600 ModuleIdPath Path) {
3601 typedef CodeCompletionResult Result;
3602 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003603 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor07f43572012-01-29 18:15:03 +00003604 CodeCompletionContext::CCC_Other);
3605 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003606
Douglas Gregor07f43572012-01-29 18:15:03 +00003607 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003608 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Douglas Gregor07f43572012-01-29 18:15:03 +00003609 typedef CodeCompletionResult Result;
3610 if (Path.empty()) {
3611 // Enumerate all top-level modules.
Dmitri Gribenkof8579502013-01-12 19:30:44 +00003612 SmallVector<Module *, 8> Modules;
Douglas Gregor07f43572012-01-29 18:15:03 +00003613 PP.getHeaderSearchInfo().collectAllModules(Modules);
3614 for (unsigned I = 0, N = Modules.size(); I != N; ++I) {
3615 Builder.AddTypedTextChunk(
3616 Builder.getAllocator().CopyString(Modules[I]->Name));
3617 Results.AddResult(Result(Builder.TakeString(),
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003618 CCP_Declaration,
Argyrios Kyrtzidis345d05f2013-05-29 18:50:15 +00003619 CXCursor_ModuleImportDecl,
Douglas Gregor07f43572012-01-29 18:15:03 +00003620 Modules[I]->isAvailable()
3621 ? CXAvailability_Available
3622 : CXAvailability_NotAvailable));
3623 }
Daniel Jasper07e6c402013-08-05 20:26:17 +00003624 } else if (getLangOpts().Modules) {
Douglas Gregor07f43572012-01-29 18:15:03 +00003625 // Load the named module.
3626 Module *Mod = PP.getModuleLoader().loadModule(ImportLoc, Path,
3627 Module::AllVisible,
3628 /*IsInclusionDirective=*/false);
3629 // Enumerate submodules.
3630 if (Mod) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003631 for (Module::submodule_iterator Sub = Mod->submodule_begin(),
Douglas Gregor07f43572012-01-29 18:15:03 +00003632 SubEnd = Mod->submodule_end();
3633 Sub != SubEnd; ++Sub) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003634
Douglas Gregor07f43572012-01-29 18:15:03 +00003635 Builder.AddTypedTextChunk(
3636 Builder.getAllocator().CopyString((*Sub)->Name));
3637 Results.AddResult(Result(Builder.TakeString(),
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003638 CCP_Declaration,
Argyrios Kyrtzidis345d05f2013-05-29 18:50:15 +00003639 CXCursor_ModuleImportDecl,
Douglas Gregor07f43572012-01-29 18:15:03 +00003640 (*Sub)->isAvailable()
3641 ? CXAvailability_Available
3642 : CXAvailability_NotAvailable));
3643 }
3644 }
3645 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003646 Results.ExitScope();
Douglas Gregor07f43572012-01-29 18:15:03 +00003647 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
3648 Results.data(),Results.size());
3649}
3650
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003651void Sema::CodeCompleteOrdinaryName(Scope *S,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003652 ParserCompletionContext CompletionContext) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003653 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003654 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00003655 mapCodeCompletionContext(*this, CompletionContext));
Douglas Gregorac322ec2010-08-27 21:18:54 +00003656 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003657
Douglas Gregor504a6ae2010-01-10 23:08:15 +00003658 // Determine how to filter results, e.g., so that the names of
3659 // values (functions, enumerators, function templates, etc.) are
3660 // only allowed where we can have an expression.
3661 switch (CompletionContext) {
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003662 case PCC_Namespace:
3663 case PCC_Class:
3664 case PCC_ObjCInterface:
3665 case PCC_ObjCImplementation:
3666 case PCC_ObjCInstanceVariableList:
3667 case PCC_Template:
3668 case PCC_MemberTemplate:
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003669 case PCC_Type:
Douglas Gregor80039242011-02-15 20:33:25 +00003670 case PCC_LocalDeclarationSpecifiers:
Douglas Gregor504a6ae2010-01-10 23:08:15 +00003671 Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
3672 break;
3673
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003674 case PCC_Statement:
Douglas Gregor5e35d592010-09-14 23:59:36 +00003675 case PCC_ParenthesizedExpression:
Douglas Gregor4d755e82010-08-24 23:58:17 +00003676 case PCC_Expression:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003677 case PCC_ForInit:
3678 case PCC_Condition:
David Blaikiebbafb8a2012-03-11 07:00:24 +00003679 if (WantTypesInContext(CompletionContext, getLangOpts()))
Douglas Gregor70febae2010-05-28 00:49:12 +00003680 Results.setFilter(&ResultBuilder::IsOrdinaryName);
3681 else
3682 Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003683
David Blaikiebbafb8a2012-03-11 07:00:24 +00003684 if (getLangOpts().CPlusPlus)
Craig Topperc3ec1492014-05-26 06:22:03 +00003685 MaybeAddOverrideCalls(*this, /*InContext=*/nullptr, Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00003686 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003687
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003688 case PCC_RecoveryInFunction:
Douglas Gregor6da3db42010-05-25 05:58:43 +00003689 // Unfiltered
3690 break;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00003691 }
3692
Douglas Gregor9be0ed42010-08-26 16:36:48 +00003693 // If we are in a C++ non-static member function, check the qualifiers on
Eric Liu2bfd3f52018-10-22 08:47:31 +00003694 // the member function to filter/prioritize the results list and set the
3695 // context to the record context so that accessibility check in base class
3696 // works correctly.
3697 RecordDecl *MemberCompletionRecord = nullptr;
3698 if (CXXMethodDecl *CurMethod = dyn_cast<CXXMethodDecl>(CurContext)) {
3699 if (CurMethod->isInstance()) {
Douglas Gregor9be0ed42010-08-26 16:36:48 +00003700 Results.setObjectTypeQualifiers(
3701 Qualifiers::fromCVRMask(CurMethod->getTypeQualifiers()));
Eric Liu2bfd3f52018-10-22 08:47:31 +00003702 MemberCompletionRecord = CurMethod->getParent();
3703 }
3704 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003705
Eric Liu2bfd3f52018-10-22 08:47:31 +00003706 CodeCompletionDeclConsumer Consumer(Results, CurContext, /*FixIts=*/{},
3707 MemberCompletionRecord);
Douglas Gregor39982192010-08-15 06:18:01 +00003708 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00003709 CodeCompleter->includeGlobals(),
3710 CodeCompleter->loadExternal());
Douglas Gregor92253692009-12-07 09:54:55 +00003711
Douglas Gregorf98e6a22010-01-13 23:51:12 +00003712 AddOrdinaryNameResults(CompletionContext, S, *this, Results);
Douglas Gregor92253692009-12-07 09:54:55 +00003713 Results.ExitScope();
3714
Douglas Gregorce0e8562010-08-23 21:54:33 +00003715 switch (CompletionContext) {
Douglas Gregor5e35d592010-09-14 23:59:36 +00003716 case PCC_ParenthesizedExpression:
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003717 case PCC_Expression:
3718 case PCC_Statement:
3719 case PCC_RecoveryInFunction:
3720 if (S->getFnParent())
Craig Topper12126262015-11-15 17:27:57 +00003721 AddPrettyFunctionResults(getLangOpts(), Results);
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003722 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003723
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003724 case PCC_Namespace:
3725 case PCC_Class:
3726 case PCC_ObjCInterface:
3727 case PCC_ObjCImplementation:
3728 case PCC_ObjCInstanceVariableList:
3729 case PCC_Template:
3730 case PCC_MemberTemplate:
3731 case PCC_ForInit:
3732 case PCC_Condition:
3733 case PCC_Type:
Douglas Gregor80039242011-02-15 20:33:25 +00003734 case PCC_LocalDeclarationSpecifiers:
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003735 break;
Douglas Gregorce0e8562010-08-23 21:54:33 +00003736 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003737
Douglas Gregor9eb77012009-11-07 00:00:49 +00003738 if (CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00003739 AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003740
Douglas Gregor50832e02010-09-20 22:39:41 +00003741 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003742 Results.data(),Results.size());
Douglas Gregor9d64c5e2009-09-21 20:51:25 +00003743}
3744
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003745static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003746 ParsedType Receiver,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00003747 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00003748 bool AtArgumentExpression,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003749 bool IsSuper,
3750 ResultBuilder &Results);
3751
3752void Sema::CodeCompleteDeclSpec(Scope *S, DeclSpec &DS,
3753 bool AllowNonIdentifiers,
3754 bool AllowNestedNameSpecifiers) {
John McCall276321a2010-08-25 06:19:51 +00003755 typedef CodeCompletionResult Result;
Kadir Cetinkayab006e092018-10-24 15:23:49 +00003756 ResultBuilder Results(
3757 *this, CodeCompleter->getAllocator(),
3758 CodeCompleter->getCodeCompletionTUInfo(),
3759 AllowNestedNameSpecifiers
3760 // FIXME: Try to separate codepath leading here to deduce whether we
3761 // need an existing symbol or a new one.
3762 ? CodeCompletionContext::CCC_SymbolOrNewName
3763 : CodeCompletionContext::CCC_NewName);
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003764 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003765
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003766 // Type qualifiers can come after names.
3767 Results.AddResult(Result("const"));
3768 Results.AddResult(Result("volatile"));
David Blaikiebbafb8a2012-03-11 07:00:24 +00003769 if (getLangOpts().C99)
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003770 Results.AddResult(Result("restrict"));
3771
David Blaikiebbafb8a2012-03-11 07:00:24 +00003772 if (getLangOpts().CPlusPlus) {
Alex Lorenz8f4d3992017-02-13 23:19:40 +00003773 if (getLangOpts().CPlusPlus11 &&
3774 (DS.getTypeSpecType() == DeclSpec::TST_class ||
3775 DS.getTypeSpecType() == DeclSpec::TST_struct))
3776 Results.AddResult("final");
3777
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003778 if (AllowNonIdentifiers) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003779 Results.AddResult(Result("operator"));
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003780 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003781
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003782 // Add nested-name-specifiers.
3783 if (AllowNestedNameSpecifiers) {
3784 Results.allowNestedNameSpecifiers();
Douglas Gregor0ac41382010-09-23 23:01:17 +00003785 Results.setFilter(&ResultBuilder::IsImpossibleToSatisfy);
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003786 CodeCompletionDeclConsumer Consumer(Results, CurContext);
3787 LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00003788 CodeCompleter->includeGlobals(),
3789 CodeCompleter->loadExternal());
Craig Topperc3ec1492014-05-26 06:22:03 +00003790 Results.setFilter(nullptr);
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003791 }
3792 }
3793 Results.ExitScope();
3794
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003795 // If we're in a context where we might have an expression (rather than a
3796 // declaration), and what we've seen so far is an Objective-C type that could
3797 // be a receiver of a class message, this may be a class message send with
3798 // the initial opening bracket '[' missing. Add appropriate completions.
3799 if (AllowNonIdentifiers && !AllowNestedNameSpecifiers &&
Richard Smithb4a9e862013-04-12 22:46:28 +00003800 DS.getParsedSpecifiers() == DeclSpec::PQ_TypeSpecifier &&
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003801 DS.getTypeSpecType() == DeclSpec::TST_typename &&
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003802 DS.getTypeSpecComplex() == DeclSpec::TSC_unspecified &&
3803 DS.getTypeSpecSign() == DeclSpec::TSS_unspecified &&
Richard Smithb4a9e862013-04-12 22:46:28 +00003804 !DS.isTypeAltiVecVector() &&
3805 S &&
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003806 (S->getFlags() & Scope::DeclScope) != 0 &&
3807 (S->getFlags() & (Scope::ClassScope | Scope::TemplateParamScope |
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003808 Scope::FunctionPrototypeScope |
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003809 Scope::AtCatchScope)) == 0) {
3810 ParsedType T = DS.getRepAsType();
3811 if (!T.get().isNull() && T.get()->isObjCObjectOrInterfaceType())
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00003812 AddClassMessageCompletions(*this, S, T, None, false, false, Results);
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003813 }
3814
Douglas Gregor56ccce02010-08-24 04:59:56 +00003815 // Note that we intentionally suppress macro results here, since we do not
3816 // encourage using macros to produce the names of entities.
3817
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003818 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0ac41382010-09-23 23:01:17 +00003819 Results.getCompletionContext(),
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003820 Results.data(), Results.size());
3821}
3822
Douglas Gregor68762e72010-08-23 21:17:50 +00003823struct Sema::CodeCompleteExpressionData {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003824 CodeCompleteExpressionData(QualType PreferredType = QualType())
Douglas Gregor68762e72010-08-23 21:17:50 +00003825 : PreferredType(PreferredType), IntegralConstantExpression(false),
3826 ObjCCollection(false) { }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003827
Douglas Gregor68762e72010-08-23 21:17:50 +00003828 QualType PreferredType;
3829 bool IntegralConstantExpression;
3830 bool ObjCCollection;
Chris Lattner0e62c1c2011-07-23 10:55:15 +00003831 SmallVector<Decl *, 4> IgnoreDecls;
Douglas Gregor68762e72010-08-23 21:17:50 +00003832};
3833
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003834/// Perform code-completion in an expression context when we know what
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003835/// type we're looking for.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003836void Sema::CodeCompleteExpression(Scope *S,
Douglas Gregor68762e72010-08-23 21:17:50 +00003837 const CodeCompleteExpressionData &Data) {
Eric Liuf5ba09f2018-07-04 10:01:18 +00003838 ResultBuilder Results(
3839 *this, CodeCompleter->getAllocator(),
3840 CodeCompleter->getCodeCompletionTUInfo(),
3841 CodeCompletionContext(CodeCompletionContext::CCC_Expression,
3842 Data.PreferredType));
Douglas Gregor68762e72010-08-23 21:17:50 +00003843 if (Data.ObjCCollection)
3844 Results.setFilter(&ResultBuilder::IsObjCCollection);
3845 else if (Data.IntegralConstantExpression)
Douglas Gregor85b50632010-07-28 21:50:18 +00003846 Results.setFilter(&ResultBuilder::IsIntegralConstantValue);
David Blaikiebbafb8a2012-03-11 07:00:24 +00003847 else if (WantTypesInContext(PCC_Expression, getLangOpts()))
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003848 Results.setFilter(&ResultBuilder::IsOrdinaryName);
3849 else
3850 Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
Douglas Gregor68762e72010-08-23 21:17:50 +00003851
3852 if (!Data.PreferredType.isNull())
3853 Results.setPreferredType(Data.PreferredType.getNonReferenceType());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003854
Douglas Gregor68762e72010-08-23 21:17:50 +00003855 // Ignore any declarations that we were told that we don't care about.
3856 for (unsigned I = 0, N = Data.IgnoreDecls.size(); I != N; ++I)
3857 Results.Ignore(Data.IgnoreDecls[I]);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003858
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003859 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00003860 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00003861 CodeCompleter->includeGlobals(),
3862 CodeCompleter->loadExternal());
3863
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003864 Results.EnterNewScope();
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003865 AddOrdinaryNameResults(PCC_Expression, S, *this, Results);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003866 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003867
Douglas Gregor55b037b2010-07-08 20:55:51 +00003868 bool PreferredTypeIsPointer = false;
Douglas Gregor68762e72010-08-23 21:17:50 +00003869 if (!Data.PreferredType.isNull())
3870 PreferredTypeIsPointer = Data.PreferredType->isAnyPointerType()
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003871 || Data.PreferredType->isMemberPointerType()
Douglas Gregor68762e72010-08-23 21:17:50 +00003872 || Data.PreferredType->isBlockPointerType();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003873
3874 if (S->getFnParent() &&
3875 !Data.ObjCCollection &&
Douglas Gregorce0e8562010-08-23 21:54:33 +00003876 !Data.IntegralConstantExpression)
Craig Topper12126262015-11-15 17:27:57 +00003877 AddPrettyFunctionResults(getLangOpts(), Results);
Douglas Gregorce0e8562010-08-23 21:54:33 +00003878
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003879 if (CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00003880 AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false,
3881 PreferredTypeIsPointer);
Eric Liuf5ba09f2018-07-04 10:01:18 +00003882 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
3883 Results.data(), Results.size());
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003884}
3885
Ilya Biryukov832c4af2018-09-07 14:04:39 +00003886void Sema::CodeCompleteExpression(Scope *S, QualType PreferredType) {
3887 return CodeCompleteExpression(S, CodeCompleteExpressionData(PreferredType));
3888}
3889
Douglas Gregoreda7e542010-09-18 01:28:11 +00003890void Sema::CodeCompletePostfixExpression(Scope *S, ExprResult E) {
3891 if (E.isInvalid())
3892 CodeCompleteOrdinaryName(S, PCC_RecoveryInFunction);
Erik Pilkingtonfa983902018-10-30 20:31:30 +00003893 else if (getLangOpts().ObjC)
Nikola Smiljanic01a75982014-05-29 10:55:11 +00003894 CodeCompleteObjCInstanceMessage(S, E.get(), None, false);
Douglas Gregored0b69d2010-09-15 16:23:04 +00003895}
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003896
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003897/// The set of properties that have already been added, referenced by
Douglas Gregorb888acf2010-12-09 23:01:55 +00003898/// property name.
3899typedef llvm::SmallPtrSet<IdentifierInfo*, 16> AddedPropertiesSet;
3900
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003901/// Retrieve the container definition, if any?
Douglas Gregor9b4f3702012-06-12 13:44:08 +00003902static ObjCContainerDecl *getContainerDef(ObjCContainerDecl *Container) {
3903 if (ObjCInterfaceDecl *Interface = dyn_cast<ObjCInterfaceDecl>(Container)) {
3904 if (Interface->hasDefinition())
3905 return Interface->getDefinition();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003906
Douglas Gregor9b4f3702012-06-12 13:44:08 +00003907 return Interface;
3908 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003909
Douglas Gregor9b4f3702012-06-12 13:44:08 +00003910 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
3911 if (Protocol->hasDefinition())
3912 return Protocol->getDefinition();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003913
Douglas Gregor9b4f3702012-06-12 13:44:08 +00003914 return Protocol;
3915 }
3916 return Container;
3917}
3918
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003919/// Adds a block invocation code completion result for the given block
Alex Lorenzbaef8022016-11-09 13:43:18 +00003920/// declaration \p BD.
3921static void AddObjCBlockCall(ASTContext &Context, const PrintingPolicy &Policy,
3922 CodeCompletionBuilder &Builder,
3923 const NamedDecl *BD,
3924 const FunctionTypeLoc &BlockLoc,
3925 const FunctionProtoTypeLoc &BlockProtoLoc) {
3926 Builder.AddResultTypeChunk(
3927 GetCompletionTypeString(BlockLoc.getReturnLoc().getType(), Context,
3928 Policy, Builder.getAllocator()));
3929
3930 AddTypedNameChunk(Context, Policy, BD, Builder);
3931 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
3932
3933 if (BlockProtoLoc && BlockProtoLoc.getTypePtr()->isVariadic()) {
3934 Builder.AddPlaceholderChunk("...");
3935 } else {
3936 for (unsigned I = 0, N = BlockLoc.getNumParams(); I != N; ++I) {
3937 if (I)
3938 Builder.AddChunk(CodeCompletionString::CK_Comma);
3939
3940 // Format the placeholder string.
3941 std::string PlaceholderStr =
3942 FormatFunctionParameter(Policy, BlockLoc.getParam(I));
3943
3944 if (I == N - 1 && BlockProtoLoc &&
3945 BlockProtoLoc.getTypePtr()->isVariadic())
3946 PlaceholderStr += ", ...";
3947
3948 // Add the placeholder string.
3949 Builder.AddPlaceholderChunk(
3950 Builder.getAllocator().CopyString(PlaceholderStr));
3951 }
3952 }
3953
3954 Builder.AddChunk(CodeCompletionString::CK_RightParen);
3955}
3956
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003957static void AddObjCProperties(
3958 const CodeCompletionContext &CCContext, ObjCContainerDecl *Container,
3959 bool AllowCategories, bool AllowNullaryMethods, DeclContext *CurContext,
3960 AddedPropertiesSet &AddedProperties, ResultBuilder &Results,
3961 bool IsBaseExprStatement = false, bool IsClassProperty = false) {
John McCall276321a2010-08-25 06:19:51 +00003962 typedef CodeCompletionResult Result;
Douglas Gregor9291bad2009-11-18 01:29:26 +00003963
Douglas Gregor9b4f3702012-06-12 13:44:08 +00003964 // Retrieve the definition.
3965 Container = getContainerDef(Container);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003966
Douglas Gregor9291bad2009-11-18 01:29:26 +00003967 // Add properties in this container.
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003968 const auto AddProperty = [&](const ObjCPropertyDecl *P) {
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003969 if (!AddedProperties.insert(P->getIdentifier()).second)
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003970 return;
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003971
Alex Lorenzbaef8022016-11-09 13:43:18 +00003972 // FIXME: Provide block invocation completion for non-statement
3973 // expressions.
3974 if (!P->getType().getTypePtr()->isBlockPointerType() ||
3975 !IsBaseExprStatement) {
3976 Results.MaybeAddResult(Result(P, Results.getBasePriority(P), nullptr),
3977 CurContext);
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003978 return;
Alex Lorenzbaef8022016-11-09 13:43:18 +00003979 }
3980
3981 // Block setter and invocation completion is provided only when we are able
3982 // to find the FunctionProtoTypeLoc with parameter names for the block.
3983 FunctionTypeLoc BlockLoc;
3984 FunctionProtoTypeLoc BlockProtoLoc;
3985 findTypeLocationForBlockDecl(P->getTypeSourceInfo(), BlockLoc,
3986 BlockProtoLoc);
3987 if (!BlockLoc) {
3988 Results.MaybeAddResult(Result(P, Results.getBasePriority(P), nullptr),
3989 CurContext);
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003990 return;
Alex Lorenzbaef8022016-11-09 13:43:18 +00003991 }
3992
3993 // The default completion result for block properties should be the block
3994 // invocation completion when the base expression is a statement.
3995 CodeCompletionBuilder Builder(Results.getAllocator(),
3996 Results.getCodeCompletionTUInfo());
3997 AddObjCBlockCall(Container->getASTContext(),
3998 getCompletionPrintingPolicy(Results.getSema()), Builder, P,
3999 BlockLoc, BlockProtoLoc);
4000 Results.MaybeAddResult(
4001 Result(Builder.TakeString(), P, Results.getBasePriority(P)),
4002 CurContext);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004003
4004 // Provide additional block setter completion iff the base expression is a
Alex Lorenzbaef8022016-11-09 13:43:18 +00004005 // statement and the block property is mutable.
4006 if (!P->isReadOnly()) {
4007 CodeCompletionBuilder Builder(Results.getAllocator(),
4008 Results.getCodeCompletionTUInfo());
4009 AddResultTypeChunk(Container->getASTContext(),
4010 getCompletionPrintingPolicy(Results.getSema()), P,
4011 CCContext.getBaseType(), Builder);
4012 Builder.AddTypedTextChunk(
4013 Results.getAllocator().CopyString(P->getName()));
4014 Builder.AddChunk(CodeCompletionString::CK_Equal);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004015
Alex Lorenzbaef8022016-11-09 13:43:18 +00004016 std::string PlaceholderStr = formatBlockPlaceholder(
4017 getCompletionPrintingPolicy(Results.getSema()), P, BlockLoc,
4018 BlockProtoLoc, /*SuppressBlockName=*/true);
4019 // Add the placeholder string.
4020 Builder.AddPlaceholderChunk(
4021 Builder.getAllocator().CopyString(PlaceholderStr));
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004022
Alex Lorenz6e0f3932017-01-06 12:00:44 +00004023 // When completing blocks properties that return void the default
4024 // property completion result should show up before the setter,
4025 // otherwise the setter completion should show up before the default
4026 // property completion, as we normally want to use the result of the
4027 // call.
Alex Lorenzbaef8022016-11-09 13:43:18 +00004028 Results.MaybeAddResult(
4029 Result(Builder.TakeString(), P,
Alex Lorenz6e0f3932017-01-06 12:00:44 +00004030 Results.getBasePriority(P) +
4031 (BlockLoc.getTypePtr()->getReturnType()->isVoidType()
4032 ? CCD_BlockPropertySetter
4033 : -CCD_BlockPropertySetter)),
Alex Lorenzbaef8022016-11-09 13:43:18 +00004034 CurContext);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004035 }
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004036 };
4037
4038 if (IsClassProperty) {
4039 for (const auto *P : Container->class_properties())
4040 AddProperty(P);
4041 } else {
4042 for (const auto *P : Container->instance_properties())
4043 AddProperty(P);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004044 }
Craig Topperc3ec1492014-05-26 06:22:03 +00004045
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004046 // Add nullary methods or implicit class properties
Douglas Gregor95147142011-05-05 15:50:42 +00004047 if (AllowNullaryMethods) {
4048 ASTContext &Context = Container->getASTContext();
Douglas Gregor75acd922011-09-27 23:30:47 +00004049 PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema());
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004050 // Adds a method result
4051 const auto AddMethod = [&](const ObjCMethodDecl *M) {
4052 IdentifierInfo *Name = M->getSelector().getIdentifierInfoForSlot(0);
4053 if (!Name)
4054 return;
4055 if (!AddedProperties.insert(Name).second)
4056 return;
4057 CodeCompletionBuilder Builder(Results.getAllocator(),
4058 Results.getCodeCompletionTUInfo());
4059 AddResultTypeChunk(Context, Policy, M, CCContext.getBaseType(), Builder);
4060 Builder.AddTypedTextChunk(
4061 Results.getAllocator().CopyString(Name->getName()));
4062 Results.MaybeAddResult(
4063 Result(Builder.TakeString(), M,
4064 CCP_MemberDeclaration + CCD_MethodAsProperty),
4065 CurContext);
4066 };
4067
4068 if (IsClassProperty) {
4069 for (const auto *M : Container->methods()) {
4070 // Gather the class method that can be used as implicit property
4071 // getters. Methods with arguments or methods that return void aren't
4072 // added to the results as they can't be used as a getter.
4073 if (!M->getSelector().isUnarySelector() ||
4074 M->getReturnType()->isVoidType() || M->isInstanceMethod())
4075 continue;
4076 AddMethod(M);
4077 }
4078 } else {
4079 for (auto *M : Container->methods()) {
4080 if (M->getSelector().isUnarySelector())
4081 AddMethod(M);
4082 }
Douglas Gregor95147142011-05-05 15:50:42 +00004083 }
4084 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004085
Douglas Gregor9291bad2009-11-18 01:29:26 +00004086 // Add properties in referenced protocols.
4087 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Aaron Ballman0f6e64d2014-03-13 22:58:06 +00004088 for (auto *P : Protocol->protocols())
Douglas Gregorc3425b12015-07-07 06:20:19 +00004089 AddObjCProperties(CCContext, P, AllowCategories, AllowNullaryMethods,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004090 CurContext, AddedProperties, Results,
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004091 IsBaseExprStatement, IsClassProperty);
Douglas Gregor9291bad2009-11-18 01:29:26 +00004092 } else if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)){
Douglas Gregor5d649882009-11-18 22:32:06 +00004093 if (AllowCategories) {
4094 // Look through categories.
Aaron Ballman15063e12014-03-13 21:35:02 +00004095 for (auto *Cat : IFace->known_categories())
Douglas Gregorc3425b12015-07-07 06:20:19 +00004096 AddObjCProperties(CCContext, Cat, AllowCategories, AllowNullaryMethods,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004097 CurContext, AddedProperties, Results,
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004098 IsBaseExprStatement, IsClassProperty);
Douglas Gregor5d649882009-11-18 22:32:06 +00004099 }
Aaron Ballman15063e12014-03-13 21:35:02 +00004100
Douglas Gregor9291bad2009-11-18 01:29:26 +00004101 // Look through protocols.
Aaron Ballmana9f49e32014-03-13 20:55:22 +00004102 for (auto *I : IFace->all_referenced_protocols())
Douglas Gregorc3425b12015-07-07 06:20:19 +00004103 AddObjCProperties(CCContext, I, AllowCategories, AllowNullaryMethods,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004104 CurContext, AddedProperties, Results,
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004105 IsBaseExprStatement, IsClassProperty);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004106
Douglas Gregor9291bad2009-11-18 01:29:26 +00004107 // Look in the superclass.
4108 if (IFace->getSuperClass())
Douglas Gregorc3425b12015-07-07 06:20:19 +00004109 AddObjCProperties(CCContext, IFace->getSuperClass(), AllowCategories,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004110 AllowNullaryMethods, CurContext, AddedProperties,
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004111 Results, IsBaseExprStatement, IsClassProperty);
Douglas Gregor9291bad2009-11-18 01:29:26 +00004112 } else if (const ObjCCategoryDecl *Category
4113 = dyn_cast<ObjCCategoryDecl>(Container)) {
4114 // Look through protocols.
Aaron Ballman19a41762014-03-14 12:55:57 +00004115 for (auto *P : Category->protocols())
Douglas Gregorc3425b12015-07-07 06:20:19 +00004116 AddObjCProperties(CCContext, P, AllowCategories, AllowNullaryMethods,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004117 CurContext, AddedProperties, Results,
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004118 IsBaseExprStatement, IsClassProperty);
Douglas Gregor9291bad2009-11-18 01:29:26 +00004119 }
4120}
4121
Alex Lorenz0fe0d982017-05-11 13:41:00 +00004122static void AddRecordMembersCompletionResults(Sema &SemaRef,
4123 ResultBuilder &Results, Scope *S,
4124 QualType BaseType,
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004125 RecordDecl *RD,
4126 Optional<FixItHint> AccessOpFixIt) {
Alex Lorenz0fe0d982017-05-11 13:41:00 +00004127 // Indicate that we are performing a member access, and the cv-qualifiers
4128 // for the base object type.
4129 Results.setObjectTypeQualifiers(BaseType.getQualifiers());
4130
4131 // Access to a C/C++ class, struct, or union.
4132 Results.allowNestedNameSpecifiers();
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004133 std::vector<FixItHint> FixIts;
4134 if (AccessOpFixIt)
4135 FixIts.emplace_back(AccessOpFixIt.getValue());
Eric Liub91e0812018-10-02 10:29:00 +00004136 CodeCompletionDeclConsumer Consumer(Results, SemaRef.CurContext,
4137 std::move(FixIts), RD);
Alex Lorenz0fe0d982017-05-11 13:41:00 +00004138 SemaRef.LookupVisibleDecls(RD, Sema::LookupMemberName, Consumer,
Alex Lorenze6afa392017-05-11 13:48:57 +00004139 SemaRef.CodeCompleter->includeGlobals(),
Sam McCallbb2cf632018-01-12 14:51:47 +00004140 /*IncludeDependentBases=*/true,
4141 SemaRef.CodeCompleter->loadExternal());
Alex Lorenz0fe0d982017-05-11 13:41:00 +00004142
4143 if (SemaRef.getLangOpts().CPlusPlus) {
4144 if (!Results.empty()) {
4145 // The "template" keyword can follow "->" or "." in the grammar.
4146 // However, we only want to suggest the template keyword if something
4147 // is dependent.
4148 bool IsDependent = BaseType->isDependentType();
4149 if (!IsDependent) {
4150 for (Scope *DepScope = S; DepScope; DepScope = DepScope->getParent())
4151 if (DeclContext *Ctx = DepScope->getEntity()) {
4152 IsDependent = Ctx->isDependentContext();
4153 break;
4154 }
4155 }
4156
4157 if (IsDependent)
4158 Results.AddResult(CodeCompletionResult("template"));
4159 }
4160 }
4161}
4162
Douglas Gregor1cc88a92012-01-23 15:59:30 +00004163void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base,
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004164 Expr *OtherOpBase,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004165 SourceLocation OpLoc, bool IsArrow,
4166 bool IsBaseExprStatement) {
Douglas Gregor1cc88a92012-01-23 15:59:30 +00004167 if (!Base || !CodeCompleter)
Douglas Gregor2436e712009-09-17 21:32:03 +00004168 return;
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004169
Douglas Gregor1cc88a92012-01-23 15:59:30 +00004170 ExprResult ConvertedBase = PerformMemberExprBaseConversion(Base, IsArrow);
4171 if (ConvertedBase.isInvalid())
4172 return;
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004173 QualType ConvertedBaseType = ConvertedBase.get()->getType();
4174
4175 enum CodeCompletionContext::Kind contextKind;
Douglas Gregor3545ff42009-09-21 16:56:56 +00004176
4177 if (IsArrow) {
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004178 if (const PointerType *Ptr = ConvertedBaseType->getAs<PointerType>())
4179 ConvertedBaseType = Ptr->getPointeeType();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004180 }
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004181
Douglas Gregor21325842011-07-07 16:03:39 +00004182 if (IsArrow) {
4183 contextKind = CodeCompletionContext::CCC_ArrowMemberAccess;
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004184 } else {
4185 if (ConvertedBaseType->isObjCObjectPointerType() ||
4186 ConvertedBaseType->isObjCObjectOrInterfaceType()) {
Douglas Gregor21325842011-07-07 16:03:39 +00004187 contextKind = CodeCompletionContext::CCC_ObjCPropertyAccess;
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004188 } else {
Douglas Gregor21325842011-07-07 16:03:39 +00004189 contextKind = CodeCompletionContext::CCC_DotMemberAccess;
4190 }
4191 }
Douglas Gregorc3425b12015-07-07 06:20:19 +00004192
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004193 CodeCompletionContext CCContext(contextKind, ConvertedBaseType);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004194 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004195 CodeCompleter->getCodeCompletionTUInfo(), CCContext,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004196 &ResultBuilder::IsMember);
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004197
4198 auto DoCompletion = [&](Expr *Base, bool IsArrow, Optional<FixItHint> AccessOpFixIt) -> bool {
4199 if (!Base)
4200 return false;
4201
4202 ExprResult ConvertedBase = PerformMemberExprBaseConversion(Base, IsArrow);
4203 if (ConvertedBase.isInvalid())
4204 return false;
4205 Base = ConvertedBase.get();
4206
4207 QualType BaseType = Base->getType();
4208
4209 if (IsArrow) {
4210 if (const PointerType *Ptr = BaseType->getAs<PointerType>())
4211 BaseType = Ptr->getPointeeType();
4212 else if (BaseType->isObjCObjectPointerType())
4213 /*Do nothing*/;
4214 else
4215 return false;
4216 }
4217
4218 if (const RecordType *Record = BaseType->getAs<RecordType>()) {
4219 AddRecordMembersCompletionResults(*this, Results, S, BaseType,
4220 Record->getDecl(),
4221 std::move(AccessOpFixIt));
4222 } else if (const auto *TST =
4223 BaseType->getAs<TemplateSpecializationType>()) {
4224 TemplateName TN = TST->getTemplateName();
4225 if (const auto *TD =
4226 dyn_cast_or_null<ClassTemplateDecl>(TN.getAsTemplateDecl())) {
4227 CXXRecordDecl *RD = TD->getTemplatedDecl();
4228 AddRecordMembersCompletionResults(*this, Results, S, BaseType, RD,
4229 std::move(AccessOpFixIt));
4230 }
4231 } else if (const auto *ICNT = BaseType->getAs<InjectedClassNameType>()) {
4232 if (auto *RD = ICNT->getDecl())
4233 AddRecordMembersCompletionResults(*this, Results, S, BaseType, RD,
4234 std::move(AccessOpFixIt));
4235 } else if (!IsArrow && BaseType->isObjCObjectPointerType()) {
4236 // Objective-C property reference.
4237 AddedPropertiesSet AddedProperties;
4238
4239 if (const ObjCObjectPointerType *ObjCPtr =
4240 BaseType->getAsObjCInterfacePointerType()) {
4241 // Add property results based on our interface.
4242 assert(ObjCPtr && "Non-NULL pointer guaranteed above!");
4243 AddObjCProperties(CCContext, ObjCPtr->getInterfaceDecl(), true,
4244 /*AllowNullaryMethods=*/true, CurContext,
4245 AddedProperties, Results, IsBaseExprStatement);
4246 }
4247
4248 // Add properties from the protocols in a qualified interface.
4249 for (auto *I : BaseType->getAs<ObjCObjectPointerType>()->quals())
4250 AddObjCProperties(CCContext, I, true, /*AllowNullaryMethods=*/true,
4251 CurContext, AddedProperties, Results,
4252 IsBaseExprStatement);
4253 } else if ((IsArrow && BaseType->isObjCObjectPointerType()) ||
4254 (!IsArrow && BaseType->isObjCObjectType())) {
4255 // Objective-C instance variable access.
4256 ObjCInterfaceDecl *Class = nullptr;
4257 if (const ObjCObjectPointerType *ObjCPtr =
4258 BaseType->getAs<ObjCObjectPointerType>())
4259 Class = ObjCPtr->getInterfaceDecl();
4260 else
4261 Class = BaseType->getAs<ObjCObjectType>()->getInterface();
4262
4263 // Add all ivars from this class and its superclasses.
4264 if (Class) {
4265 CodeCompletionDeclConsumer Consumer(Results, CurContext);
4266 Results.setFilter(&ResultBuilder::IsObjCIvar);
4267 LookupVisibleDecls(
4268 Class, LookupMemberName, Consumer, CodeCompleter->includeGlobals(),
4269 /*IncludeDependentBases=*/false, CodeCompleter->loadExternal());
4270 }
4271 }
4272
4273 // FIXME: How do we cope with isa?
4274 return true;
4275 };
4276
Douglas Gregor9291bad2009-11-18 01:29:26 +00004277 Results.EnterNewScope();
Alex Lorenz06cfa992016-10-12 11:40:15 +00004278
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004279 bool CompletionSucceded = DoCompletion(Base, IsArrow, None);
4280 if (CodeCompleter->includeFixIts()) {
4281 const CharSourceRange OpRange =
4282 CharSourceRange::getTokenRange(OpLoc, OpLoc);
4283 CompletionSucceded |= DoCompletion(
4284 OtherOpBase, !IsArrow,
4285 FixItHint::CreateReplacement(OpRange, IsArrow ? "." : "->"));
Douglas Gregor3545ff42009-09-21 16:56:56 +00004286 }
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004287
Douglas Gregor9291bad2009-11-18 01:29:26 +00004288 Results.ExitScope();
Daniel Dunbar242ea9a2009-11-13 08:58:20 +00004289
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004290 if (!CompletionSucceded)
4291 return;
4292
Daniel Dunbar242ea9a2009-11-13 08:58:20 +00004293 // Hand off the results found for code completion.
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004294 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4295 Results.data(), Results.size());
Douglas Gregor2436e712009-09-17 21:32:03 +00004296}
4297
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004298void Sema::CodeCompleteObjCClassPropertyRefExpr(Scope *S,
4299 IdentifierInfo &ClassName,
4300 SourceLocation ClassNameLoc,
4301 bool IsBaseExprStatement) {
4302 IdentifierInfo *ClassNamePtr = &ClassName;
4303 ObjCInterfaceDecl *IFace = getObjCInterfaceDecl(ClassNamePtr, ClassNameLoc);
4304 if (!IFace)
4305 return;
4306 CodeCompletionContext CCContext(
4307 CodeCompletionContext::CCC_ObjCPropertyAccess);
4308 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4309 CodeCompleter->getCodeCompletionTUInfo(), CCContext,
4310 &ResultBuilder::IsMember);
4311 Results.EnterNewScope();
4312 AddedPropertiesSet AddedProperties;
4313 AddObjCProperties(CCContext, IFace, true,
4314 /*AllowNullaryMethods=*/true, CurContext, AddedProperties,
4315 Results, IsBaseExprStatement,
4316 /*IsClassProperty=*/true);
4317 Results.ExitScope();
4318 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4319 Results.data(), Results.size());
4320}
4321
Faisal Vali090da2d2018-01-01 18:23:28 +00004322void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) {
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004323 if (!CodeCompleter)
4324 return;
Craig Topperc3ec1492014-05-26 06:22:03 +00004325
4326 ResultBuilder::LookupFilter Filter = nullptr;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004327 enum CodeCompletionContext::Kind ContextKind
4328 = CodeCompletionContext::CCC_Other;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004329 switch ((DeclSpec::TST)TagSpec) {
4330 case DeclSpec::TST_enum:
Douglas Gregor3545ff42009-09-21 16:56:56 +00004331 Filter = &ResultBuilder::IsEnum;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004332 ContextKind = CodeCompletionContext::CCC_EnumTag;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004333 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004334
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004335 case DeclSpec::TST_union:
Douglas Gregor3545ff42009-09-21 16:56:56 +00004336 Filter = &ResultBuilder::IsUnion;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004337 ContextKind = CodeCompletionContext::CCC_UnionTag;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004338 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004339
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004340 case DeclSpec::TST_struct:
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004341 case DeclSpec::TST_class:
Joao Matosdc86f942012-08-31 18:45:21 +00004342 case DeclSpec::TST_interface:
Douglas Gregor3545ff42009-09-21 16:56:56 +00004343 Filter = &ResultBuilder::IsClassOrStruct;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004344 ContextKind = CodeCompletionContext::CCC_ClassOrStructTag;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004345 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004346
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004347 default:
David Blaikie83d382b2011-09-23 05:06:16 +00004348 llvm_unreachable("Unknown type specifier kind in CodeCompleteTag");
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004349 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004350
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004351 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4352 CodeCompleter->getCodeCompletionTUInfo(), ContextKind);
Douglas Gregora6e2edc2010-01-14 03:27:13 +00004353 CodeCompletionDeclConsumer Consumer(Results, CurContext);
John McCalle87beb22010-04-23 18:46:30 +00004354
4355 // First pass: look for tags.
4356 Results.setFilter(Filter);
Douglas Gregor39982192010-08-15 06:18:01 +00004357 LookupVisibleDecls(S, LookupTagName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00004358 CodeCompleter->includeGlobals(),
4359 CodeCompleter->loadExternal());
John McCalle87beb22010-04-23 18:46:30 +00004360
Douglas Gregor39982192010-08-15 06:18:01 +00004361 if (CodeCompleter->includeGlobals()) {
4362 // Second pass: look for nested name specifiers.
4363 Results.setFilter(&ResultBuilder::IsNestedNameSpecifier);
Sam McCallbb2cf632018-01-12 14:51:47 +00004364 LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer,
4365 CodeCompleter->includeGlobals(),
4366 CodeCompleter->loadExternal());
Douglas Gregor39982192010-08-15 06:18:01 +00004367 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004368
Douglas Gregor0ac41382010-09-23 23:01:17 +00004369 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004370 Results.data(),Results.size());
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004371}
4372
Alex Lorenz8f4d3992017-02-13 23:19:40 +00004373static void AddTypeQualifierResults(DeclSpec &DS, ResultBuilder &Results,
4374 const LangOptions &LangOpts) {
4375 if (!(DS.getTypeQualifiers() & DeclSpec::TQ_const))
4376 Results.AddResult("const");
4377 if (!(DS.getTypeQualifiers() & DeclSpec::TQ_volatile))
4378 Results.AddResult("volatile");
4379 if (LangOpts.C99 && !(DS.getTypeQualifiers() & DeclSpec::TQ_restrict))
4380 Results.AddResult("restrict");
4381 if (LangOpts.C11 && !(DS.getTypeQualifiers() & DeclSpec::TQ_atomic))
4382 Results.AddResult("_Atomic");
4383 if (LangOpts.MSVCCompat && !(DS.getTypeQualifiers() & DeclSpec::TQ_unaligned))
4384 Results.AddResult("__unaligned");
4385}
4386
Douglas Gregor28c78432010-08-27 17:35:51 +00004387void Sema::CodeCompleteTypeQualifiers(DeclSpec &DS) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004388 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004389 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004390 CodeCompletionContext::CCC_TypeQualifiers);
Douglas Gregor28c78432010-08-27 17:35:51 +00004391 Results.EnterNewScope();
Alex Lorenz8f4d3992017-02-13 23:19:40 +00004392 AddTypeQualifierResults(DS, Results, LangOpts);
Douglas Gregor28c78432010-08-27 17:35:51 +00004393 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004394 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004395 Results.getCompletionContext(),
Douglas Gregor28c78432010-08-27 17:35:51 +00004396 Results.data(), Results.size());
4397}
4398
Alex Lorenz8f4d3992017-02-13 23:19:40 +00004399void Sema::CodeCompleteFunctionQualifiers(DeclSpec &DS, Declarator &D,
4400 const VirtSpecifiers *VS) {
4401 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4402 CodeCompleter->getCodeCompletionTUInfo(),
4403 CodeCompletionContext::CCC_TypeQualifiers);
4404 Results.EnterNewScope();
4405 AddTypeQualifierResults(DS, Results, LangOpts);
4406 if (LangOpts.CPlusPlus11) {
4407 Results.AddResult("noexcept");
Faisal Vali421b2d12017-12-29 05:41:00 +00004408 if (D.getContext() == DeclaratorContext::MemberContext &&
4409 !D.isCtorOrDtor() && !D.isStaticMember()) {
Alex Lorenz8f4d3992017-02-13 23:19:40 +00004410 if (!VS || !VS->isFinalSpecified())
4411 Results.AddResult("final");
4412 if (!VS || !VS->isOverrideSpecified())
4413 Results.AddResult("override");
4414 }
4415 }
4416 Results.ExitScope();
4417 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4418 Results.data(), Results.size());
4419}
4420
Benjamin Kramer72dae622016-02-18 15:30:24 +00004421void Sema::CodeCompleteBracketDeclarator(Scope *S) {
4422 CodeCompleteExpression(S, QualType(getASTContext().getSizeType()));
4423}
4424
Douglas Gregord328d572009-09-21 18:10:23 +00004425void Sema::CodeCompleteCase(Scope *S) {
John McCallaab3e412010-08-25 08:40:02 +00004426 if (getCurFunction()->SwitchStack.empty() || !CodeCompleter)
Douglas Gregord328d572009-09-21 18:10:23 +00004427 return;
John McCall5939b162011-08-06 07:30:58 +00004428
Richard Smithef6c43d2018-07-26 18:41:30 +00004429 SwitchStmt *Switch = getCurFunction()->SwitchStack.back().getPointer();
Kadir Cetinkaya6d572662018-10-23 13:49:37 +00004430 // Condition expression might be invalid, do not continue in this case.
4431 if (!Switch->getCond())
4432 return;
John McCall5939b162011-08-06 07:30:58 +00004433 QualType type = Switch->getCond()->IgnoreImplicit()->getType();
4434 if (!type->isEnumeralType()) {
4435 CodeCompleteExpressionData Data(type);
Douglas Gregor68762e72010-08-23 21:17:50 +00004436 Data.IntegralConstantExpression = true;
4437 CodeCompleteExpression(S, Data);
Douglas Gregord328d572009-09-21 18:10:23 +00004438 return;
Douglas Gregor85b50632010-07-28 21:50:18 +00004439 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004440
Douglas Gregord328d572009-09-21 18:10:23 +00004441 // Code-complete the cases of a switch statement over an enumeration type
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004442 // by providing the list of
John McCall5939b162011-08-06 07:30:58 +00004443 EnumDecl *Enum = type->castAs<EnumType>()->getDecl();
Douglas Gregor9b4f3702012-06-12 13:44:08 +00004444 if (EnumDecl *Def = Enum->getDefinition())
4445 Enum = Def;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004446
Douglas Gregord328d572009-09-21 18:10:23 +00004447 // Determine which enumerators we have already seen in the switch statement.
4448 // FIXME: Ideally, we would also be able to look *past* the code-completion
4449 // token, in case we are code-completing in the middle of the switch and not
4450 // at the end. However, we aren't able to do so at the moment.
4451 llvm::SmallPtrSet<EnumConstantDecl *, 8> EnumeratorsSeen;
Craig Topperc3ec1492014-05-26 06:22:03 +00004452 NestedNameSpecifier *Qualifier = nullptr;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004453 for (SwitchCase *SC = Switch->getSwitchCaseList(); SC;
Douglas Gregord328d572009-09-21 18:10:23 +00004454 SC = SC->getNextSwitchCase()) {
4455 CaseStmt *Case = dyn_cast<CaseStmt>(SC);
4456 if (!Case)
4457 continue;
4458
4459 Expr *CaseVal = Case->getLHS()->IgnoreParenCasts();
4460 if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CaseVal))
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004461 if (EnumConstantDecl *Enumerator
Douglas Gregord328d572009-09-21 18:10:23 +00004462 = dyn_cast<EnumConstantDecl>(DRE->getDecl())) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004463 // We look into the AST of the case statement to determine which
4464 // enumerator was named. Alternatively, we could compute the value of
Douglas Gregord328d572009-09-21 18:10:23 +00004465 // the integral constant expression, then compare it against the
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004466 // values of each enumerator. However, value-based approach would not
4467 // work as well with C++ templates where enumerators declared within a
Douglas Gregord328d572009-09-21 18:10:23 +00004468 // template are type- and value-dependent.
4469 EnumeratorsSeen.insert(Enumerator);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004470
Douglas Gregorf2510672009-09-21 19:57:38 +00004471 // If this is a qualified-id, keep track of the nested-name-specifier
4472 // so that we can reproduce it as part of code completion, e.g.,
Douglas Gregord328d572009-09-21 18:10:23 +00004473 //
4474 // switch (TagD.getKind()) {
4475 // case TagDecl::TK_enum:
4476 // break;
4477 // case XXX
4478 //
Douglas Gregorf2510672009-09-21 19:57:38 +00004479 // At the XXX, our completions are TagDecl::TK_union,
Douglas Gregord328d572009-09-21 18:10:23 +00004480 // TagDecl::TK_struct, and TagDecl::TK_class, rather than TK_union,
4481 // TK_struct, and TK_class.
Douglas Gregor4bd90e52009-10-23 18:54:35 +00004482 Qualifier = DRE->getQualifier();
Douglas Gregord328d572009-09-21 18:10:23 +00004483 }
4484 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004485
David Blaikiebbafb8a2012-03-11 07:00:24 +00004486 if (getLangOpts().CPlusPlus && !Qualifier && EnumeratorsSeen.empty()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004487 // If there are no prior enumerators in C++, check whether we have to
Douglas Gregorf2510672009-09-21 19:57:38 +00004488 // qualify the names of the enumerators that we suggest, because they
4489 // may not be visible in this scope.
Douglas Gregord3cebdb2012-02-01 05:02:47 +00004490 Qualifier = getRequiredQualification(Context, CurContext, Enum);
Douglas Gregorf2510672009-09-21 19:57:38 +00004491 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004492
Douglas Gregord328d572009-09-21 18:10:23 +00004493 // Add any enumerators that have not yet been mentioned.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004494 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004495 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004496 CodeCompletionContext::CCC_Expression);
Douglas Gregord328d572009-09-21 18:10:23 +00004497 Results.EnterNewScope();
Aaron Ballman23a6dcb2014-03-08 18:45:14 +00004498 for (auto *E : Enum->enumerators()) {
4499 if (EnumeratorsSeen.count(E))
Douglas Gregord328d572009-09-21 18:10:23 +00004500 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004501
Aaron Ballman23a6dcb2014-03-08 18:45:14 +00004502 CodeCompletionResult R(E, CCP_EnumInCase, Qualifier);
Craig Topperc3ec1492014-05-26 06:22:03 +00004503 Results.AddResult(R, CurContext, nullptr, false);
Douglas Gregord328d572009-09-21 18:10:23 +00004504 }
4505 Results.ExitScope();
Douglas Gregor285560922010-04-06 20:02:15 +00004506
Douglas Gregor21325842011-07-07 16:03:39 +00004507 if (CodeCompleter->includeMacros()) {
Eric Liu88de9f62018-09-19 09:34:55 +00004508 AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false);
Douglas Gregor21325842011-07-07 16:03:39 +00004509 }
Eric Liuf5ba09f2018-07-04 10:01:18 +00004510 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4511 Results.data(), Results.size());
Douglas Gregord328d572009-09-21 18:10:23 +00004512}
4513
Robert Wilhelm16e94b92013-08-09 18:02:13 +00004514static bool anyNullArguments(ArrayRef<Expr *> Args) {
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00004515 if (Args.size() && !Args.data())
Douglas Gregor6ed3eb82010-05-30 06:10:08 +00004516 return true;
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00004517
4518 for (unsigned I = 0; I != Args.size(); ++I)
Douglas Gregor6ed3eb82010-05-30 06:10:08 +00004519 if (!Args[I])
4520 return true;
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00004521
Douglas Gregor6ed3eb82010-05-30 06:10:08 +00004522 return false;
4523}
4524
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004525typedef CodeCompleteConsumer::OverloadCandidate ResultCandidate;
4526
Francisco Lopes da Silva8cafefa2015-01-29 05:54:59 +00004527static void mergeCandidatesWithResults(Sema &SemaRef,
4528 SmallVectorImpl<ResultCandidate> &Results,
4529 OverloadCandidateSet &CandidateSet,
4530 SourceLocation Loc) {
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004531 if (!CandidateSet.empty()) {
4532 // Sort the overload candidate set by placing the best overloads first.
4533 std::stable_sort(
4534 CandidateSet.begin(), CandidateSet.end(),
4535 [&](const OverloadCandidate &X, const OverloadCandidate &Y) {
Richard Smith67ef14f2017-09-26 18:37:55 +00004536 return isBetterOverloadCandidate(SemaRef, X, Y, Loc,
4537 CandidateSet.getKind());
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004538 });
4539
4540 // Add the remaining viable overload candidates as code-completion results.
Erik Verbruggen7ec91072017-09-08 10:23:08 +00004541 for (auto &Candidate : CandidateSet) {
4542 if (Candidate.Function && Candidate.Function->isDeleted())
4543 continue;
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004544 if (Candidate.Viable)
4545 Results.push_back(ResultCandidate(Candidate.Function));
Erik Verbruggen7ec91072017-09-08 10:23:08 +00004546 }
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004547 }
4548}
4549
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00004550/// Get the type of the Nth parameter from a given set of overload
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004551/// candidates.
Francisco Lopes da Silva8cafefa2015-01-29 05:54:59 +00004552static QualType getParamType(Sema &SemaRef,
4553 ArrayRef<ResultCandidate> Candidates,
4554 unsigned N) {
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004555
4556 // Given the overloads 'Candidates' for a function call matching all arguments
4557 // up to N, return the type of the Nth parameter if it is the same for all
4558 // overload candidates.
4559 QualType ParamType;
4560 for (auto &Candidate : Candidates) {
4561 if (auto FType = Candidate.getFunctionType())
4562 if (auto Proto = dyn_cast<FunctionProtoType>(FType))
4563 if (N < Proto->getNumParams()) {
4564 if (ParamType.isNull())
4565 ParamType = Proto->getParamType(N);
4566 else if (!SemaRef.Context.hasSameUnqualifiedType(
4567 ParamType.getNonReferenceType(),
4568 Proto->getParamType(N).getNonReferenceType()))
4569 // Otherwise return a default-constructed QualType.
4570 return QualType();
4571 }
4572 }
4573
4574 return ParamType;
4575}
4576
Ilya Biryukov832c4af2018-09-07 14:04:39 +00004577static QualType
4578ProduceSignatureHelp(Sema &SemaRef, Scope *S,
4579 MutableArrayRef<ResultCandidate> Candidates,
4580 unsigned CurrentArg, SourceLocation OpenParLoc) {
4581 if (Candidates.empty())
4582 return QualType();
4583 SemaRef.CodeCompleter->ProcessOverloadCandidates(
4584 SemaRef, CurrentArg, Candidates.data(), Candidates.size(), OpenParLoc);
4585 return getParamType(SemaRef, Candidates, CurrentArg);
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004586}
4587
Ilya Biryukov832c4af2018-09-07 14:04:39 +00004588QualType Sema::ProduceCallSignatureHelp(Scope *S, Expr *Fn,
4589 ArrayRef<Expr *> Args,
4590 SourceLocation OpenParLoc) {
Douglas Gregorcabea402009-09-22 15:41:20 +00004591 if (!CodeCompleter)
Ilya Biryukov832c4af2018-09-07 14:04:39 +00004592 return QualType();
Douglas Gregor3ef59522009-12-11 19:06:04 +00004593
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004594 // FIXME: Provide support for variadic template functions.
Douglas Gregorcabea402009-09-22 15:41:20 +00004595 // Ignore type-dependent call expressions entirely.
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00004596 if (!Fn || Fn->isTypeDependent() || anyNullArguments(Args) ||
4597 Expr::hasAnyTypeDependentArguments(Args)) {
Ilya Biryukov832c4af2018-09-07 14:04:39 +00004598 return QualType();
Douglas Gregor3ef59522009-12-11 19:06:04 +00004599 }
Douglas Gregorcabea402009-09-22 15:41:20 +00004600
John McCall57500772009-12-16 12:17:52 +00004601 // Build an overload candidate set based on the functions we find.
John McCallbc077cf2010-02-08 23:07:23 +00004602 SourceLocation Loc = Fn->getExprLoc();
Richard Smith100b24a2014-04-17 01:52:14 +00004603 OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal);
John McCall57500772009-12-16 12:17:52 +00004604
Chris Lattner0e62c1c2011-07-23 10:55:15 +00004605 SmallVector<ResultCandidate, 8> Results;
Douglas Gregorff59f672010-01-21 15:46:19 +00004606
John McCall57500772009-12-16 12:17:52 +00004607 Expr *NakedFn = Fn->IgnoreParenCasts();
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004608 if (auto ULE = dyn_cast<UnresolvedLookupExpr>(NakedFn))
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00004609 AddOverloadedCallCandidates(ULE, Args, CandidateSet,
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004610 /*PartialOverloading=*/true);
4611 else if (auto UME = dyn_cast<UnresolvedMemberExpr>(NakedFn)) {
4612 TemplateArgumentListInfo TemplateArgsBuffer, *TemplateArgs = nullptr;
4613 if (UME->hasExplicitTemplateArgs()) {
4614 UME->copyTemplateArgumentsInto(TemplateArgsBuffer);
4615 TemplateArgs = &TemplateArgsBuffer;
Douglas Gregorff59f672010-01-21 15:46:19 +00004616 }
Erik Verbruggenf1898cf2017-03-28 07:22:21 +00004617
4618 // Add the base as first argument (use a nullptr if the base is implicit).
4619 SmallVector<Expr *, 12> ArgExprs(
4620 1, UME->isImplicitAccess() ? nullptr : UME->getBase());
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004621 ArgExprs.append(Args.begin(), Args.end());
4622 UnresolvedSet<8> Decls;
4623 Decls.append(UME->decls_begin(), UME->decls_end());
Benjamin Kramere3962ae2017-10-26 08:41:28 +00004624 const bool FirstArgumentIsBase = !UME->isImplicitAccess() && UME->getBase();
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004625 AddFunctionCandidates(Decls, ArgExprs, CandidateSet, TemplateArgs,
4626 /*SuppressUsedConversions=*/false,
Benjamin Kramere3962ae2017-10-26 08:41:28 +00004627 /*PartialOverloading=*/true,
4628 FirstArgumentIsBase);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004629 } else {
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004630 FunctionDecl *FD = nullptr;
4631 if (auto MCE = dyn_cast<MemberExpr>(NakedFn))
4632 FD = dyn_cast<FunctionDecl>(MCE->getMemberDecl());
4633 else if (auto DRE = dyn_cast<DeclRefExpr>(NakedFn))
4634 FD = dyn_cast<FunctionDecl>(DRE->getDecl());
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00004635 if (FD) { // We check whether it's a resolved function declaration.
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00004636 if (!getLangOpts().CPlusPlus ||
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004637 !FD->getType()->getAs<FunctionProtoType>())
4638 Results.push_back(ResultCandidate(FD));
4639 else
4640 AddOverloadCandidate(FD, DeclAccessPair::make(FD, FD->getAccess()),
4641 Args, CandidateSet,
4642 /*SuppressUsedConversions=*/false,
4643 /*PartialOverloading=*/true);
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00004644
4645 } else if (auto DC = NakedFn->getType()->getAsCXXRecordDecl()) {
4646 // If expression's type is CXXRecordDecl, it may overload the function
4647 // call operator, so we check if it does and add them as candidates.
Francisco Lopes da Silvaa349a8a2015-01-25 08:47:59 +00004648 // A complete type is needed to lookup for member function call operators.
Richard Smithdb0ac552015-12-18 22:40:25 +00004649 if (isCompleteType(Loc, NakedFn->getType())) {
Francisco Lopes da Silvaa349a8a2015-01-25 08:47:59 +00004650 DeclarationName OpName = Context.DeclarationNames
4651 .getCXXOperatorName(OO_Call);
4652 LookupResult R(*this, OpName, Loc, LookupOrdinaryName);
4653 LookupQualifiedName(R, DC);
4654 R.suppressDiagnostics();
4655 SmallVector<Expr *, 12> ArgExprs(1, NakedFn);
4656 ArgExprs.append(Args.begin(), Args.end());
4657 AddFunctionCandidates(R.asUnresolvedSet(), ArgExprs, CandidateSet,
4658 /*ExplicitArgs=*/nullptr,
4659 /*SuppressUsedConversions=*/false,
4660 /*PartialOverloading=*/true);
4661 }
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00004662 } else {
4663 // Lastly we check whether expression's type is function pointer or
4664 // function.
4665 QualType T = NakedFn->getType();
4666 if (!T->getPointeeType().isNull())
4667 T = T->getPointeeType();
4668
4669 if (auto FP = T->getAs<FunctionProtoType>()) {
4670 if (!TooManyArguments(FP->getNumParams(), Args.size(),
Francisco Lopes da Silva62a9a4f2015-01-23 13:17:51 +00004671 /*PartialOverloading=*/true) ||
4672 FP->isVariadic())
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00004673 Results.push_back(ResultCandidate(FP));
4674 } else if (auto FT = T->getAs<FunctionType>())
Francisco Lopes da Silva62a9a4f2015-01-23 13:17:51 +00004675 // No prototype and declaration, it may be a K & R style function.
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00004676 Results.push_back(ResultCandidate(FT));
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004677 }
Douglas Gregorcabea402009-09-22 15:41:20 +00004678 }
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004679 mergeCandidatesWithResults(*this, Results, CandidateSet, Loc);
Ilya Biryukov832c4af2018-09-07 14:04:39 +00004680 QualType ParamType =
4681 ProduceSignatureHelp(*this, S, Results, Args.size(), OpenParLoc);
4682 return !CandidateSet.empty() ? ParamType : QualType();
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004683}
4684
Ilya Biryukov832c4af2018-09-07 14:04:39 +00004685QualType Sema::ProduceConstructorSignatureHelp(Scope *S, QualType Type,
4686 SourceLocation Loc,
4687 ArrayRef<Expr *> Args,
4688 SourceLocation OpenParLoc) {
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004689 if (!CodeCompleter)
Ilya Biryukov832c4af2018-09-07 14:04:39 +00004690 return QualType();
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004691
4692 // A complete type is needed to lookup for constructors.
Ilya Biryukovfb9dde72018-05-14 13:50:36 +00004693 CXXRecordDecl *RD =
4694 isCompleteType(Loc, Type) ? Type->getAsCXXRecordDecl() : nullptr;
Ilya Biryukov832c4af2018-09-07 14:04:39 +00004695 if (!RD)
4696 return Type;
Argyrios Kyrtzidisee1d76f2015-03-13 07:39:30 +00004697
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004698 // FIXME: Provide support for member initializers.
4699 // FIXME: Provide support for variadic template constructors.
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004700
4701 OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal);
4702
Argyrios Kyrtzidisee1d76f2015-03-13 07:39:30 +00004703 for (auto C : LookupConstructors(RD)) {
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004704 if (auto FD = dyn_cast<FunctionDecl>(C)) {
4705 AddOverloadCandidate(FD, DeclAccessPair::make(FD, C->getAccess()),
4706 Args, CandidateSet,
4707 /*SuppressUsedConversions=*/false,
4708 /*PartialOverloading=*/true);
4709 } else if (auto FTD = dyn_cast<FunctionTemplateDecl>(C)) {
4710 AddTemplateOverloadCandidate(FTD,
4711 DeclAccessPair::make(FTD, C->getAccess()),
4712 /*ExplicitTemplateArgs=*/nullptr,
4713 Args, CandidateSet,
4714 /*SuppressUsedConversions=*/false,
4715 /*PartialOverloading=*/true);
4716 }
4717 }
4718
4719 SmallVector<ResultCandidate, 8> Results;
4720 mergeCandidatesWithResults(*this, Results, CandidateSet, Loc);
Ilya Biryukov832c4af2018-09-07 14:04:39 +00004721 return ProduceSignatureHelp(*this, S, Results, Args.size(), OpenParLoc);
Douglas Gregorcabea402009-09-22 15:41:20 +00004722}
4723
Kadir Cetinkaya84774c32018-09-11 15:02:18 +00004724QualType Sema::ProduceCtorInitMemberSignatureHelp(
4725 Scope *S, Decl *ConstructorDecl, CXXScopeSpec SS, ParsedType TemplateTypeTy,
4726 ArrayRef<Expr *> ArgExprs, IdentifierInfo *II, SourceLocation OpenParLoc) {
4727 if (!CodeCompleter)
4728 return QualType();
4729
4730 CXXConstructorDecl *Constructor =
4731 dyn_cast<CXXConstructorDecl>(ConstructorDecl);
4732 if (!Constructor)
4733 return QualType();
4734 // FIXME: Add support for Base class constructors as well.
4735 if (ValueDecl *MemberDecl = tryLookupCtorInitMemberDecl(
4736 Constructor->getParent(), SS, TemplateTypeTy, II))
4737 return ProduceConstructorSignatureHelp(getCurScope(), MemberDecl->getType(),
4738 MemberDecl->getLocation(), ArgExprs,
4739 OpenParLoc);
4740 return QualType();
4741}
4742
John McCall48871652010-08-21 09:40:31 +00004743void Sema::CodeCompleteInitializer(Scope *S, Decl *D) {
4744 ValueDecl *VD = dyn_cast_or_null<ValueDecl>(D);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004745 if (!VD) {
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004746 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004747 return;
4748 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004749
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004750 CodeCompleteExpression(S, VD->getType());
4751}
4752
4753void Sema::CodeCompleteReturn(Scope *S) {
4754 QualType ResultType;
4755 if (isa<BlockDecl>(CurContext)) {
4756 if (BlockScopeInfo *BSI = getCurBlock())
4757 ResultType = BSI->ReturnType;
4758 } else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(CurContext))
Alp Toker314cc812014-01-25 16:55:45 +00004759 ResultType = Function->getReturnType();
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004760 else if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(CurContext))
Alp Toker314cc812014-01-25 16:55:45 +00004761 ResultType = Method->getReturnType();
4762
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004763 if (ResultType.isNull())
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004764 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004765 else
4766 CodeCompleteExpression(S, ResultType);
4767}
4768
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004769void Sema::CodeCompleteAfterIf(Scope *S) {
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004770 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004771 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004772 mapCodeCompletionContext(*this, PCC_Statement));
4773 Results.setFilter(&ResultBuilder::IsOrdinaryName);
4774 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004775
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004776 CodeCompletionDeclConsumer Consumer(Results, CurContext);
4777 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00004778 CodeCompleter->includeGlobals(),
4779 CodeCompleter->loadExternal());
4780
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004781 AddOrdinaryNameResults(PCC_Statement, S, *this, Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004782
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004783 // "else" block
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004784 CodeCompletionBuilder Builder(Results.getAllocator(),
4785 Results.getCodeCompletionTUInfo());
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004786 Builder.AddTypedTextChunk("else");
Douglas Gregor3a5d6c22012-02-16 17:49:04 +00004787 if (Results.includeCodePatterns()) {
4788 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4789 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4790 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
4791 Builder.AddPlaceholderChunk("statements");
4792 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
4793 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4794 }
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004795 Results.AddResult(Builder.TakeString());
4796
4797 // "else if" block
4798 Builder.AddTypedTextChunk("else");
4799 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4800 Builder.AddTextChunk("if");
4801 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4802 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00004803 if (getLangOpts().CPlusPlus)
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004804 Builder.AddPlaceholderChunk("condition");
4805 else
4806 Builder.AddPlaceholderChunk("expression");
4807 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor3a5d6c22012-02-16 17:49:04 +00004808 if (Results.includeCodePatterns()) {
4809 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4810 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4811 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
4812 Builder.AddPlaceholderChunk("statements");
4813 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
4814 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4815 }
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004816 Results.AddResult(Builder.TakeString());
4817
4818 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004819
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004820 if (S->getFnParent())
Craig Topper12126262015-11-15 17:27:57 +00004821 AddPrettyFunctionResults(getLangOpts(), Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004822
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004823 if (CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00004824 AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004825
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004826 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4827 Results.data(),Results.size());
4828}
4829
Richard Trieu2bd04012011-09-09 02:00:50 +00004830void Sema::CodeCompleteAssignmentRHS(Scope *S, Expr *LHS) {
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004831 if (LHS)
4832 CodeCompleteExpression(S, static_cast<Expr *>(LHS)->getType());
4833 else
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004834 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004835}
4836
Jeffrey Yasskinc76498d2010-04-08 16:38:48 +00004837void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS,
Douglas Gregor2436e712009-09-17 21:32:03 +00004838 bool EnteringContext) {
Eric Liu06d34022017-12-12 11:35:46 +00004839 if (SS.isEmpty() || !CodeCompleter)
Douglas Gregor2436e712009-09-17 21:32:03 +00004840 return;
Alex Lorenz8a7a4cf2017-06-15 21:40:54 +00004841
Eric Liu06d34022017-12-12 11:35:46 +00004842 // We want to keep the scope specifier even if it's invalid (e.g. the scope
4843 // "a::b::" is not corresponding to any context/namespace in the AST), since
4844 // it can be useful for global code completion which have information about
4845 // contexts/symbols that are not in the AST.
4846 if (SS.isInvalid()) {
Kadir Cetinkayab006e092018-10-24 15:23:49 +00004847 CodeCompletionContext CC(CodeCompletionContext::CCC_Symbol);
Eric Liu06d34022017-12-12 11:35:46 +00004848 CC.setCXXScopeSpecifier(SS);
4849 HandleCodeCompleteResults(this, CodeCompleter, CC, nullptr, 0);
4850 return;
4851 }
Alex Lorenz8a7a4cf2017-06-15 21:40:54 +00004852 // Always pretend to enter a context to ensure that a dependent type
4853 // resolves to a dependent record.
4854 DeclContext *Ctx = computeDeclContext(SS, /*EnteringContext=*/true);
Douglas Gregor3545ff42009-09-21 16:56:56 +00004855 if (!Ctx)
4856 return;
Douglas Gregor800f2f02009-12-11 18:28:39 +00004857
4858 // Try to instantiate any non-dependent declaration contexts before
4859 // we look in them.
John McCall0b66eb32010-05-01 00:40:08 +00004860 if (!isDependentScopeSpecifier(SS) && RequireCompleteDeclContext(SS, Ctx))
Douglas Gregor800f2f02009-12-11 18:28:39 +00004861 return;
4862
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004863 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004864 CodeCompleter->getCodeCompletionTUInfo(),
Kadir Cetinkayab006e092018-10-24 15:23:49 +00004865 CodeCompletionContext::CCC_Symbol);
Douglas Gregorac322ec2010-08-27 21:18:54 +00004866 Results.EnterNewScope();
Eric Liu06d34022017-12-12 11:35:46 +00004867
Douglas Gregor3545ff42009-09-21 16:56:56 +00004868 // The "template" keyword can follow "::" in the grammar, but only
4869 // put it into the grammar if the nested-name-specifier is dependent.
Aaron Ballman4a979672014-01-03 13:56:08 +00004870 NestedNameSpecifier *NNS = SS.getScopeRep();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004871 if (!Results.empty() && NNS->isDependent())
Douglas Gregor78a21012010-01-14 16:01:26 +00004872 Results.AddResult("template");
Douglas Gregorac322ec2010-08-27 21:18:54 +00004873
4874 // Add calls to overridden virtual functions, if there are any.
4875 //
4876 // FIXME: This isn't wonderful, because we don't know whether we're actually
4877 // in a context that permits expressions. This is a general issue with
4878 // qualified-id completions.
4879 if (!EnteringContext)
4880 MaybeAddOverrideCalls(*this, Ctx, Results);
Eric Liu06d34022017-12-12 11:35:46 +00004881 Results.ExitScope();
4882
Eric Liufead6ae2017-12-13 10:26:49 +00004883 if (CodeCompleter->includeNamespaceLevelDecls() ||
4884 (!Ctx->isNamespace() && !Ctx->isTranslationUnit())) {
4885 CodeCompletionDeclConsumer Consumer(Results, CurContext);
4886 LookupVisibleDecls(Ctx, LookupOrdinaryName, Consumer,
4887 /*IncludeGlobalScope=*/true,
Sam McCallbb2cf632018-01-12 14:51:47 +00004888 /*IncludeDependentBases=*/true,
4889 CodeCompleter->loadExternal());
Eric Liufead6ae2017-12-13 10:26:49 +00004890 }
Douglas Gregorac322ec2010-08-27 21:18:54 +00004891
Eric Liu06d34022017-12-12 11:35:46 +00004892 auto CC = Results.getCompletionContext();
4893 CC.setCXXScopeSpecifier(SS);
4894
4895 HandleCodeCompleteResults(this, CodeCompleter, CC, Results.data(),
4896 Results.size());
Douglas Gregor2436e712009-09-17 21:32:03 +00004897}
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00004898
4899void Sema::CodeCompleteUsing(Scope *S) {
4900 if (!CodeCompleter)
4901 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004902
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004903 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004904 CodeCompleter->getCodeCompletionTUInfo(),
Kadir Cetinkayab006e092018-10-24 15:23:49 +00004905 // This can be both a using alias or using
4906 // declaration, in the former we expect a new name and a
4907 // symbol in the latter case.
4908 CodeCompletionContext::CCC_SymbolOrNewName,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004909 &ResultBuilder::IsNestedNameSpecifier);
Douglas Gregor64b12b52009-09-22 23:31:26 +00004910 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004911
Douglas Gregor3545ff42009-09-21 16:56:56 +00004912 // If we aren't in class scope, we could see the "namespace" keyword.
4913 if (!S->isClassScope())
John McCall276321a2010-08-25 06:19:51 +00004914 Results.AddResult(CodeCompletionResult("namespace"));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004915
4916 // After "using", we can see anything that would start a
Douglas Gregor3545ff42009-09-21 16:56:56 +00004917 // nested-name-specifier.
Douglas Gregora6e2edc2010-01-14 03:27:13 +00004918 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00004919 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00004920 CodeCompleter->includeGlobals(),
4921 CodeCompleter->loadExternal());
Douglas Gregor64b12b52009-09-22 23:31:26 +00004922 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00004923
4924 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4925 Results.data(), Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00004926}
4927
4928void Sema::CodeCompleteUsingDirective(Scope *S) {
4929 if (!CodeCompleter)
4930 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004931
Douglas Gregor3545ff42009-09-21 16:56:56 +00004932 // After "using namespace", we expect to see a namespace name or namespace
4933 // alias.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004934 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004935 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004936 CodeCompletionContext::CCC_Namespace,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004937 &ResultBuilder::IsNamespaceOrAlias);
Douglas Gregor64b12b52009-09-22 23:31:26 +00004938 Results.EnterNewScope();
Douglas Gregora6e2edc2010-01-14 03:27:13 +00004939 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00004940 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00004941 CodeCompleter->includeGlobals(),
4942 CodeCompleter->loadExternal());
Douglas Gregor64b12b52009-09-22 23:31:26 +00004943 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00004944 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4945 Results.data(), Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00004946}
4947
4948void Sema::CodeCompleteNamespaceDecl(Scope *S) {
4949 if (!CodeCompleter)
4950 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004951
Ted Kremenekc37877d2013-10-08 17:08:03 +00004952 DeclContext *Ctx = S->getEntity();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004953 if (!S->getParent())
4954 Ctx = Context.getTranslationUnitDecl();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004955
Douglas Gregor0ac41382010-09-23 23:01:17 +00004956 bool SuppressedGlobalResults
4957 = Ctx && !CodeCompleter->includeGlobals() && isa<TranslationUnitDecl>(Ctx);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004958
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004959 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004960 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00004961 SuppressedGlobalResults
4962 ? CodeCompletionContext::CCC_Namespace
4963 : CodeCompletionContext::CCC_Other,
4964 &ResultBuilder::IsNamespace);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004965
Douglas Gregor0ac41382010-09-23 23:01:17 +00004966 if (Ctx && Ctx->isFileContext() && !SuppressedGlobalResults) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00004967 // We only want to see those namespaces that have already been defined
4968 // within this scope, because its likely that the user is creating an
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004969 // extended namespace declaration. Keep track of the most recent
Douglas Gregor3545ff42009-09-21 16:56:56 +00004970 // definition of each namespace.
4971 std::map<NamespaceDecl *, NamespaceDecl *> OrigToLatest;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004972 for (DeclContext::specific_decl_iterator<NamespaceDecl>
Douglas Gregor3545ff42009-09-21 16:56:56 +00004973 NS(Ctx->decls_begin()), NSEnd(Ctx->decls_end());
4974 NS != NSEnd; ++NS)
David Blaikie40ed2972012-06-06 20:45:41 +00004975 OrigToLatest[NS->getOriginalNamespace()] = *NS;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004976
4977 // Add the most recent definition (or extended definition) of each
Douglas Gregor3545ff42009-09-21 16:56:56 +00004978 // namespace to the list of results.
Douglas Gregor64b12b52009-09-22 23:31:26 +00004979 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004980 for (std::map<NamespaceDecl *, NamespaceDecl *>::iterator
Douglas Gregor78254c82012-03-27 23:34:16 +00004981 NS = OrigToLatest.begin(),
4982 NSEnd = OrigToLatest.end();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004983 NS != NSEnd; ++NS)
Douglas Gregor0a0e2b32013-01-31 04:52:16 +00004984 Results.AddResult(CodeCompletionResult(
Craig Topperc3ec1492014-05-26 06:22:03 +00004985 NS->second, Results.getBasePriority(NS->second),
4986 nullptr),
4987 CurContext, nullptr, false);
Douglas Gregor64b12b52009-09-22 23:31:26 +00004988 Results.ExitScope();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004989 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004990
4991 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004992 Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004993 Results.data(),Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00004994}
4995
4996void Sema::CodeCompleteNamespaceAliasDecl(Scope *S) {
4997 if (!CodeCompleter)
4998 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004999
Douglas Gregor3545ff42009-09-21 16:56:56 +00005000 // After "namespace", we expect to see a namespace or alias.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005001 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005002 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005003 CodeCompletionContext::CCC_Namespace,
Douglas Gregor0ac41382010-09-23 23:01:17 +00005004 &ResultBuilder::IsNamespaceOrAlias);
Douglas Gregora6e2edc2010-01-14 03:27:13 +00005005 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00005006 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00005007 CodeCompleter->includeGlobals(),
5008 CodeCompleter->loadExternal());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005009 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0ac41382010-09-23 23:01:17 +00005010 Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005011 Results.data(),Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00005012}
5013
Douglas Gregorc811ede2009-09-18 20:05:18 +00005014void Sema::CodeCompleteOperatorName(Scope *S) {
5015 if (!CodeCompleter)
5016 return;
Douglas Gregor3545ff42009-09-21 16:56:56 +00005017
John McCall276321a2010-08-25 06:19:51 +00005018 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005019 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005020 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005021 CodeCompletionContext::CCC_Type,
Douglas Gregor0ac41382010-09-23 23:01:17 +00005022 &ResultBuilder::IsType);
Douglas Gregor64b12b52009-09-22 23:31:26 +00005023 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005024
Douglas Gregor3545ff42009-09-21 16:56:56 +00005025 // Add the names of overloadable operators.
5026#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
5027 if (std::strcmp(Spelling, "?")) \
Douglas Gregor78a21012010-01-14 16:01:26 +00005028 Results.AddResult(Result(Spelling));
Douglas Gregor3545ff42009-09-21 16:56:56 +00005029#include "clang/Basic/OperatorKinds.def"
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005030
Douglas Gregor3545ff42009-09-21 16:56:56 +00005031 // Add any type names visible from the current scope
Douglas Gregor6ae4c522010-01-14 03:21:49 +00005032 Results.allowNestedNameSpecifiers();
Douglas Gregora6e2edc2010-01-14 03:27:13 +00005033 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00005034 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00005035 CodeCompleter->includeGlobals(),
5036 CodeCompleter->loadExternal());
5037
Douglas Gregor3545ff42009-09-21 16:56:56 +00005038 // Add any type specifiers
David Blaikiebbafb8a2012-03-11 07:00:24 +00005039 AddTypeSpecifierResults(getLangOpts(), Results);
Douglas Gregor64b12b52009-09-22 23:31:26 +00005040 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005041
5042 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5043 Results.data(), Results.size());
Douglas Gregorc811ede2009-09-18 20:05:18 +00005044}
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00005045
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00005046void Sema::CodeCompleteConstructorInitializer(
5047 Decl *ConstructorD,
5048 ArrayRef <CXXCtorInitializer *> Initializers) {
Benjamin Kramera4f8df02015-07-09 15:31:10 +00005049 if (!ConstructorD)
5050 return;
5051
5052 AdjustDeclIfTemplate(ConstructorD);
5053
5054 CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(ConstructorD);
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005055 if (!Constructor)
5056 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005057
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005058 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005059 CodeCompleter->getCodeCompletionTUInfo(),
Kadir Cetinkayab006e092018-10-24 15:23:49 +00005060 CodeCompletionContext::CCC_Symbol);
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005061 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005062
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005063 // Fill in any already-initialized fields or base classes.
5064 llvm::SmallPtrSet<FieldDecl *, 4> InitializedFields;
5065 llvm::SmallPtrSet<CanQualType, 4> InitializedBases;
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00005066 for (unsigned I = 0, E = Initializers.size(); I != E; ++I) {
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005067 if (Initializers[I]->isBaseInitializer())
5068 InitializedBases.insert(
5069 Context.getCanonicalType(QualType(Initializers[I]->getBaseClass(), 0)));
5070 else
Francois Pichetd583da02010-12-04 09:14:42 +00005071 InitializedFields.insert(cast<FieldDecl>(
5072 Initializers[I]->getAnyMember()));
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005073 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005074
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005075 // Add completions for base classes.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005076 CodeCompletionBuilder Builder(Results.getAllocator(),
5077 Results.getCodeCompletionTUInfo());
Benjamin Kramera4f8df02015-07-09 15:31:10 +00005078 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00005079 bool SawLastInitializer = Initializers.empty();
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005080 CXXRecordDecl *ClassDecl = Constructor->getParent();
Aaron Ballman574705e2014-03-13 15:41:46 +00005081 for (const auto &Base : ClassDecl->bases()) {
David Blaikie82e95a32014-11-19 07:49:47 +00005082 if (!InitializedBases.insert(Context.getCanonicalType(Base.getType()))
5083 .second) {
Douglas Gregor99129ef2010-08-29 19:27:27 +00005084 SawLastInitializer
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005085 = !Initializers.empty() &&
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00005086 Initializers.back()->isBaseInitializer() &&
Aaron Ballman574705e2014-03-13 15:41:46 +00005087 Context.hasSameUnqualifiedType(Base.getType(),
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00005088 QualType(Initializers.back()->getBaseClass(), 0));
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005089 continue;
Douglas Gregor99129ef2010-08-29 19:27:27 +00005090 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005091
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005092 Builder.AddTypedTextChunk(
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005093 Results.getAllocator().CopyString(
Aaron Ballman574705e2014-03-13 15:41:46 +00005094 Base.getType().getAsString(Policy)));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005095 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5096 Builder.AddPlaceholderChunk("args");
5097 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005098 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor99129ef2010-08-29 19:27:27 +00005099 SawLastInitializer? CCP_NextInitializer
5100 : CCP_MemberDeclaration));
5101 SawLastInitializer = false;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005102 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005103
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005104 // Add completions for virtual base classes.
Aaron Ballman445a9392014-03-13 16:15:17 +00005105 for (const auto &Base : ClassDecl->vbases()) {
David Blaikie82e95a32014-11-19 07:49:47 +00005106 if (!InitializedBases.insert(Context.getCanonicalType(Base.getType()))
5107 .second) {
Douglas Gregor99129ef2010-08-29 19:27:27 +00005108 SawLastInitializer
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005109 = !Initializers.empty() &&
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00005110 Initializers.back()->isBaseInitializer() &&
Aaron Ballman445a9392014-03-13 16:15:17 +00005111 Context.hasSameUnqualifiedType(Base.getType(),
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00005112 QualType(Initializers.back()->getBaseClass(), 0));
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005113 continue;
Douglas Gregor99129ef2010-08-29 19:27:27 +00005114 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005115
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005116 Builder.AddTypedTextChunk(
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005117 Builder.getAllocator().CopyString(
Aaron Ballman445a9392014-03-13 16:15:17 +00005118 Base.getType().getAsString(Policy)));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005119 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5120 Builder.AddPlaceholderChunk("args");
5121 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005122 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor99129ef2010-08-29 19:27:27 +00005123 SawLastInitializer? CCP_NextInitializer
5124 : CCP_MemberDeclaration));
5125 SawLastInitializer = false;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005126 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005127
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005128 // Add completions for members.
Aaron Ballmane8a8bae2014-03-08 20:12:42 +00005129 for (auto *Field : ClassDecl->fields()) {
David Blaikie82e95a32014-11-19 07:49:47 +00005130 if (!InitializedFields.insert(cast<FieldDecl>(Field->getCanonicalDecl()))
5131 .second) {
Douglas Gregor99129ef2010-08-29 19:27:27 +00005132 SawLastInitializer
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005133 = !Initializers.empty() &&
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00005134 Initializers.back()->isAnyMemberInitializer() &&
Aaron Ballmane8a8bae2014-03-08 20:12:42 +00005135 Initializers.back()->getAnyMember() == Field;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005136 continue;
Douglas Gregor99129ef2010-08-29 19:27:27 +00005137 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005138
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005139 if (!Field->getDeclName())
5140 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005141
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005142 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005143 Field->getIdentifier()->getName()));
5144 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5145 Builder.AddPlaceholderChunk("args");
5146 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005147 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor99129ef2010-08-29 19:27:27 +00005148 SawLastInitializer? CCP_NextInitializer
Douglas Gregorf3af3112010-09-09 21:42:20 +00005149 : CCP_MemberDeclaration,
Douglas Gregor78254c82012-03-27 23:34:16 +00005150 CXCursor_MemberRef,
5151 CXAvailability_Available,
Aaron Ballmane8a8bae2014-03-08 20:12:42 +00005152 Field));
Douglas Gregor99129ef2010-08-29 19:27:27 +00005153 SawLastInitializer = false;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005154 }
5155 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005156
Douglas Gregor0ac41382010-09-23 23:01:17 +00005157 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005158 Results.data(), Results.size());
5159}
5160
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00005161/// Determine whether this scope denotes a namespace.
Douglas Gregord8c61782012-02-15 15:34:24 +00005162static bool isNamespaceScope(Scope *S) {
Ted Kremenekc37877d2013-10-08 17:08:03 +00005163 DeclContext *DC = S->getEntity();
Douglas Gregord8c61782012-02-15 15:34:24 +00005164 if (!DC)
5165 return false;
5166
5167 return DC->isFileContext();
5168}
5169
5170void Sema::CodeCompleteLambdaIntroducer(Scope *S, LambdaIntroducer &Intro,
5171 bool AfterAmpersand) {
5172 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005173 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregord8c61782012-02-15 15:34:24 +00005174 CodeCompletionContext::CCC_Other);
5175 Results.EnterNewScope();
5176
5177 // Note what has already been captured.
5178 llvm::SmallPtrSet<IdentifierInfo *, 4> Known;
5179 bool IncludedThis = false;
Benjamin Kramerf3ca26982014-05-10 16:31:55 +00005180 for (const auto &C : Intro.Captures) {
5181 if (C.Kind == LCK_This) {
Douglas Gregord8c61782012-02-15 15:34:24 +00005182 IncludedThis = true;
5183 continue;
5184 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005185
Benjamin Kramerf3ca26982014-05-10 16:31:55 +00005186 Known.insert(C.Id);
Douglas Gregord8c61782012-02-15 15:34:24 +00005187 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005188
Douglas Gregord8c61782012-02-15 15:34:24 +00005189 // Look for other capturable variables.
5190 for (; S && !isNamespaceScope(S); S = S->getParent()) {
Aaron Ballman35c54952014-03-17 16:55:25 +00005191 for (const auto *D : S->decls()) {
5192 const auto *Var = dyn_cast<VarDecl>(D);
Douglas Gregord8c61782012-02-15 15:34:24 +00005193 if (!Var ||
5194 !Var->hasLocalStorage() ||
5195 Var->hasAttr<BlocksAttr>())
5196 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005197
David Blaikie82e95a32014-11-19 07:49:47 +00005198 if (Known.insert(Var->getIdentifier()).second)
Douglas Gregor0a0e2b32013-01-31 04:52:16 +00005199 Results.AddResult(CodeCompletionResult(Var, CCP_LocalDeclaration),
Craig Topperc3ec1492014-05-26 06:22:03 +00005200 CurContext, nullptr, false);
Douglas Gregord8c61782012-02-15 15:34:24 +00005201 }
5202 }
5203
5204 // Add 'this', if it would be valid.
5205 if (!IncludedThis && !AfterAmpersand && Intro.Default != LCD_ByCopy)
5206 addThisCompletion(*this, Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005207
Douglas Gregord8c61782012-02-15 15:34:24 +00005208 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005209
Douglas Gregord8c61782012-02-15 15:34:24 +00005210 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5211 Results.data(), Results.size());
5212}
5213
James Dennett596e4752012-06-14 03:11:41 +00005214/// Macro that optionally prepends an "@" to the string literal passed in via
5215/// Keyword, depending on whether NeedAt is true or false.
5216#define OBJC_AT_KEYWORD_NAME(NeedAt,Keyword) ((NeedAt)? "@" Keyword : Keyword)
5217
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005218static void AddObjCImplementationResults(const LangOptions &LangOpts,
Douglas Gregorf1934162010-01-13 21:24:21 +00005219 ResultBuilder &Results,
5220 bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005221 typedef CodeCompletionResult Result;
Douglas Gregorf1934162010-01-13 21:24:21 +00005222 // Since we have an implementation, we can end it.
James Dennett596e4752012-06-14 03:11:41 +00005223 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"end")));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005224
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005225 CodeCompletionBuilder Builder(Results.getAllocator(),
5226 Results.getCodeCompletionTUInfo());
Erik Pilkingtonfa983902018-10-30 20:31:30 +00005227 if (LangOpts.ObjC) {
Douglas Gregorf1934162010-01-13 21:24:21 +00005228 // @dynamic
James Dennett596e4752012-06-14 03:11:41 +00005229 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"dynamic"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005230 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5231 Builder.AddPlaceholderChunk("property");
5232 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005233
Douglas Gregorf1934162010-01-13 21:24:21 +00005234 // @synthesize
James Dennett596e4752012-06-14 03:11:41 +00005235 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"synthesize"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005236 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5237 Builder.AddPlaceholderChunk("property");
5238 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005239 }
Douglas Gregorf1934162010-01-13 21:24:21 +00005240}
5241
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005242static void AddObjCInterfaceResults(const LangOptions &LangOpts,
Douglas Gregorf1934162010-01-13 21:24:21 +00005243 ResultBuilder &Results,
5244 bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005245 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005246
Douglas Gregorf1934162010-01-13 21:24:21 +00005247 // Since we have an interface or protocol, we can end it.
James Dennett596e4752012-06-14 03:11:41 +00005248 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"end")));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005249
Erik Pilkingtonfa983902018-10-30 20:31:30 +00005250 if (LangOpts.ObjC) {
Douglas Gregorf1934162010-01-13 21:24:21 +00005251 // @property
James Dennett596e4752012-06-14 03:11:41 +00005252 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"property")));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005253
Douglas Gregorf1934162010-01-13 21:24:21 +00005254 // @required
James Dennett596e4752012-06-14 03:11:41 +00005255 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"required")));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005256
Douglas Gregorf1934162010-01-13 21:24:21 +00005257 // @optional
James Dennett596e4752012-06-14 03:11:41 +00005258 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"optional")));
Douglas Gregorf1934162010-01-13 21:24:21 +00005259 }
5260}
5261
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005262static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005263 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005264 CodeCompletionBuilder Builder(Results.getAllocator(),
5265 Results.getCodeCompletionTUInfo());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005266
Douglas Gregorf1934162010-01-13 21:24:21 +00005267 // @class name ;
James Dennett596e4752012-06-14 03:11:41 +00005268 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"class"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005269 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5270 Builder.AddPlaceholderChunk("name");
5271 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005272
Douglas Gregorf4c33342010-05-28 00:22:41 +00005273 if (Results.includeCodePatterns()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005274 // @interface name
5275 // FIXME: Could introduce the whole pattern, including superclasses and
Douglas Gregorf4c33342010-05-28 00:22:41 +00005276 // such.
James Dennett596e4752012-06-14 03:11:41 +00005277 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"interface"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005278 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5279 Builder.AddPlaceholderChunk("class");
5280 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005281
Douglas Gregorf4c33342010-05-28 00:22:41 +00005282 // @protocol name
James Dennett596e4752012-06-14 03:11:41 +00005283 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"protocol"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005284 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5285 Builder.AddPlaceholderChunk("protocol");
5286 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005287
Douglas Gregorf4c33342010-05-28 00:22:41 +00005288 // @implementation name
James Dennett596e4752012-06-14 03:11:41 +00005289 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"implementation"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005290 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5291 Builder.AddPlaceholderChunk("class");
5292 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00005293 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005294
Douglas Gregorf1934162010-01-13 21:24:21 +00005295 // @compatibility_alias name
James Dennett596e4752012-06-14 03:11:41 +00005296 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"compatibility_alias"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005297 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5298 Builder.AddPlaceholderChunk("alias");
5299 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5300 Builder.AddPlaceholderChunk("class");
5301 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor61e36812013-03-07 23:26:24 +00005302
5303 if (Results.getSema().getLangOpts().Modules) {
5304 // @import name
5305 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "import"));
5306 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5307 Builder.AddPlaceholderChunk("module");
5308 Results.AddResult(Result(Builder.TakeString()));
5309 }
Douglas Gregorf1934162010-01-13 21:24:21 +00005310}
5311
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005312void Sema::CodeCompleteObjCAtDirective(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005313 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005314 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005315 CodeCompletionContext::CCC_Other);
Douglas Gregorf48706c2009-12-07 09:27:33 +00005316 Results.EnterNewScope();
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005317 if (isa<ObjCImplDecl>(CurContext))
David Blaikiebbafb8a2012-03-11 07:00:24 +00005318 AddObjCImplementationResults(getLangOpts(), Results, false);
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005319 else if (CurContext->isObjCContainer())
David Blaikiebbafb8a2012-03-11 07:00:24 +00005320 AddObjCInterfaceResults(getLangOpts(), Results, false);
Douglas Gregorf1934162010-01-13 21:24:21 +00005321 else
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005322 AddObjCTopLevelResults(Results, false);
Douglas Gregorf48706c2009-12-07 09:27:33 +00005323 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005324 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5325 Results.data(), Results.size());
Douglas Gregorf48706c2009-12-07 09:27:33 +00005326}
5327
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005328static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005329 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005330 CodeCompletionBuilder Builder(Results.getAllocator(),
5331 Results.getCodeCompletionTUInfo());
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005332
5333 // @encode ( type-name )
Douglas Gregore5c79d52011-10-18 21:20:17 +00005334 const char *EncodeType = "char[]";
David Blaikiebbafb8a2012-03-11 07:00:24 +00005335 if (Results.getSema().getLangOpts().CPlusPlus ||
5336 Results.getSema().getLangOpts().ConstStrings)
Jordan Rose9da05852012-06-15 18:19:56 +00005337 EncodeType = "const char[]";
Douglas Gregore5c79d52011-10-18 21:20:17 +00005338 Builder.AddResultTypeChunk(EncodeType);
James Dennett596e4752012-06-14 03:11:41 +00005339 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"encode"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005340 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5341 Builder.AddPlaceholderChunk("type-name");
5342 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5343 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005344
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005345 // @protocol ( protocol-name )
Douglas Gregore5c79d52011-10-18 21:20:17 +00005346 Builder.AddResultTypeChunk("Protocol *");
James Dennett596e4752012-06-14 03:11:41 +00005347 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"protocol"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005348 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5349 Builder.AddPlaceholderChunk("protocol-name");
5350 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5351 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005352
5353 // @selector ( selector )
Douglas Gregore5c79d52011-10-18 21:20:17 +00005354 Builder.AddResultTypeChunk("SEL");
James Dennett596e4752012-06-14 03:11:41 +00005355 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"selector"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005356 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5357 Builder.AddPlaceholderChunk("selector");
5358 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5359 Results.AddResult(Result(Builder.TakeString()));
Jordan Rose9da05852012-06-15 18:19:56 +00005360
5361 // @"string"
5362 Builder.AddResultTypeChunk("NSString *");
5363 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"\""));
5364 Builder.AddPlaceholderChunk("string");
5365 Builder.AddTextChunk("\"");
5366 Results.AddResult(Result(Builder.TakeString()));
5367
Douglas Gregor951de302012-07-17 23:24:47 +00005368 // @[objects, ...]
Jordan Rose9da05852012-06-15 18:19:56 +00005369 Builder.AddResultTypeChunk("NSArray *");
James Dennett596e4752012-06-14 03:11:41 +00005370 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"["));
Ted Kremeneke65b0862012-03-06 20:05:56 +00005371 Builder.AddPlaceholderChunk("objects, ...");
Ted Kremeneke65b0862012-03-06 20:05:56 +00005372 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
5373 Results.AddResult(Result(Builder.TakeString()));
5374
Douglas Gregor951de302012-07-17 23:24:47 +00005375 // @{key : object, ...}
Jordan Rose9da05852012-06-15 18:19:56 +00005376 Builder.AddResultTypeChunk("NSDictionary *");
James Dennett596e4752012-06-14 03:11:41 +00005377 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"{"));
Ted Kremeneke65b0862012-03-06 20:05:56 +00005378 Builder.AddPlaceholderChunk("key");
Ted Kremeneke65b0862012-03-06 20:05:56 +00005379 Builder.AddChunk(CodeCompletionString::CK_Colon);
5380 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5381 Builder.AddPlaceholderChunk("object, ...");
Ted Kremeneke65b0862012-03-06 20:05:56 +00005382 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5383 Results.AddResult(Result(Builder.TakeString()));
Jordan Rose9da05852012-06-15 18:19:56 +00005384
Douglas Gregor951de302012-07-17 23:24:47 +00005385 // @(expression)
Jordan Rose9da05852012-06-15 18:19:56 +00005386 Builder.AddResultTypeChunk("id");
5387 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "("));
Jordan Rose9da05852012-06-15 18:19:56 +00005388 Builder.AddPlaceholderChunk("expression");
Jordan Rose9da05852012-06-15 18:19:56 +00005389 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5390 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005391}
5392
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005393static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005394 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005395 CodeCompletionBuilder Builder(Results.getAllocator(),
5396 Results.getCodeCompletionTUInfo());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005397
Douglas Gregorf4c33342010-05-28 00:22:41 +00005398 if (Results.includeCodePatterns()) {
5399 // @try { statements } @catch ( declaration ) { statements } @finally
5400 // { statements }
James Dennett596e4752012-06-14 03:11:41 +00005401 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"try"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005402 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5403 Builder.AddPlaceholderChunk("statements");
5404 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5405 Builder.AddTextChunk("@catch");
5406 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5407 Builder.AddPlaceholderChunk("parameter");
5408 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5409 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5410 Builder.AddPlaceholderChunk("statements");
5411 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5412 Builder.AddTextChunk("@finally");
5413 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5414 Builder.AddPlaceholderChunk("statements");
5415 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5416 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00005417 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005418
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005419 // @throw
James Dennett596e4752012-06-14 03:11:41 +00005420 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"throw"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005421 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5422 Builder.AddPlaceholderChunk("expression");
5423 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005424
Douglas Gregorf4c33342010-05-28 00:22:41 +00005425 if (Results.includeCodePatterns()) {
5426 // @synchronized ( expression ) { statements }
James Dennett596e4752012-06-14 03:11:41 +00005427 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"synchronized"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005428 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5429 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5430 Builder.AddPlaceholderChunk("expression");
5431 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5432 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5433 Builder.AddPlaceholderChunk("statements");
5434 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5435 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00005436 }
Douglas Gregorf1934162010-01-13 21:24:21 +00005437}
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005438
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005439static void AddObjCVisibilityResults(const LangOptions &LangOpts,
Douglas Gregor48d46252010-01-13 21:54:15 +00005440 ResultBuilder &Results,
5441 bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005442 typedef CodeCompletionResult Result;
James Dennett596e4752012-06-14 03:11:41 +00005443 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"private")));
5444 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"protected")));
5445 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"public")));
Erik Pilkingtonfa983902018-10-30 20:31:30 +00005446 if (LangOpts.ObjC)
James Dennett596e4752012-06-14 03:11:41 +00005447 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"package")));
Douglas Gregor48d46252010-01-13 21:54:15 +00005448}
5449
5450void Sema::CodeCompleteObjCAtVisibility(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005451 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005452 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005453 CodeCompletionContext::CCC_Other);
Douglas Gregor48d46252010-01-13 21:54:15 +00005454 Results.EnterNewScope();
David Blaikiebbafb8a2012-03-11 07:00:24 +00005455 AddObjCVisibilityResults(getLangOpts(), Results, false);
Douglas Gregor48d46252010-01-13 21:54:15 +00005456 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005457 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5458 Results.data(), Results.size());
Douglas Gregor48d46252010-01-13 21:54:15 +00005459}
5460
5461void Sema::CodeCompleteObjCAtStatement(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005462 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005463 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005464 CodeCompletionContext::CCC_Other);
Douglas Gregorf1934162010-01-13 21:24:21 +00005465 Results.EnterNewScope();
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005466 AddObjCStatementResults(Results, false);
5467 AddObjCExpressionResults(Results, false);
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005468 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005469 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5470 Results.data(), Results.size());
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005471}
5472
5473void Sema::CodeCompleteObjCAtExpression(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005474 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005475 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005476 CodeCompletionContext::CCC_Other);
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005477 Results.EnterNewScope();
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005478 AddObjCExpressionResults(Results, false);
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005479 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005480 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5481 Results.data(), Results.size());
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005482}
5483
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00005484/// Determine whether the addition of the given flag to an Objective-C
Douglas Gregore6078da2009-11-19 00:14:45 +00005485/// property's attributes will cause a conflict.
Bill Wendling44426052012-12-20 19:22:21 +00005486static bool ObjCPropertyFlagConflicts(unsigned Attributes, unsigned NewFlag) {
Douglas Gregore6078da2009-11-19 00:14:45 +00005487 // Check if we've already added this flag.
Bill Wendling44426052012-12-20 19:22:21 +00005488 if (Attributes & NewFlag)
Douglas Gregore6078da2009-11-19 00:14:45 +00005489 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005490
Bill Wendling44426052012-12-20 19:22:21 +00005491 Attributes |= NewFlag;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005492
Douglas Gregore6078da2009-11-19 00:14:45 +00005493 // Check for collisions with "readonly".
Bill Wendling44426052012-12-20 19:22:21 +00005494 if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) &&
5495 (Attributes & ObjCDeclSpec::DQ_PR_readwrite))
Douglas Gregore6078da2009-11-19 00:14:45 +00005496 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005497
Jordan Rose53cb2f32012-08-20 20:01:13 +00005498 // Check for more than one of { assign, copy, retain, strong, weak }.
Bill Wendling44426052012-12-20 19:22:21 +00005499 unsigned AssignCopyRetMask = Attributes & (ObjCDeclSpec::DQ_PR_assign |
John McCall31168b02011-06-15 23:02:42 +00005500 ObjCDeclSpec::DQ_PR_unsafe_unretained |
Douglas Gregore6078da2009-11-19 00:14:45 +00005501 ObjCDeclSpec::DQ_PR_copy |
Jordan Rose53cb2f32012-08-20 20:01:13 +00005502 ObjCDeclSpec::DQ_PR_retain |
5503 ObjCDeclSpec::DQ_PR_strong |
5504 ObjCDeclSpec::DQ_PR_weak);
Douglas Gregore6078da2009-11-19 00:14:45 +00005505 if (AssignCopyRetMask &&
5506 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_assign &&
John McCall31168b02011-06-15 23:02:42 +00005507 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_unsafe_unretained &&
Douglas Gregore6078da2009-11-19 00:14:45 +00005508 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_copy &&
John McCall31168b02011-06-15 23:02:42 +00005509 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_retain &&
Jordan Rose53cb2f32012-08-20 20:01:13 +00005510 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_strong &&
5511 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_weak)
Douglas Gregore6078da2009-11-19 00:14:45 +00005512 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005513
Douglas Gregore6078da2009-11-19 00:14:45 +00005514 return false;
5515}
5516
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005517void Sema::CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS) {
Steve Naroff936354c2009-10-08 21:55:05 +00005518 if (!CodeCompleter)
5519 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005520
Bill Wendling44426052012-12-20 19:22:21 +00005521 unsigned Attributes = ODS.getPropertyAttributes();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005522
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005523 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005524 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005525 CodeCompletionContext::CCC_Other);
Steve Naroff936354c2009-10-08 21:55:05 +00005526 Results.EnterNewScope();
Bill Wendling44426052012-12-20 19:22:21 +00005527 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readonly))
John McCall276321a2010-08-25 06:19:51 +00005528 Results.AddResult(CodeCompletionResult("readonly"));
Bill Wendling44426052012-12-20 19:22:21 +00005529 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_assign))
John McCall276321a2010-08-25 06:19:51 +00005530 Results.AddResult(CodeCompletionResult("assign"));
Bill Wendling44426052012-12-20 19:22:21 +00005531 if (!ObjCPropertyFlagConflicts(Attributes,
John McCall31168b02011-06-15 23:02:42 +00005532 ObjCDeclSpec::DQ_PR_unsafe_unretained))
5533 Results.AddResult(CodeCompletionResult("unsafe_unretained"));
Bill Wendling44426052012-12-20 19:22:21 +00005534 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readwrite))
John McCall276321a2010-08-25 06:19:51 +00005535 Results.AddResult(CodeCompletionResult("readwrite"));
Bill Wendling44426052012-12-20 19:22:21 +00005536 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_retain))
John McCall276321a2010-08-25 06:19:51 +00005537 Results.AddResult(CodeCompletionResult("retain"));
Bill Wendling44426052012-12-20 19:22:21 +00005538 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_strong))
John McCall31168b02011-06-15 23:02:42 +00005539 Results.AddResult(CodeCompletionResult("strong"));
Bill Wendling44426052012-12-20 19:22:21 +00005540 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_copy))
John McCall276321a2010-08-25 06:19:51 +00005541 Results.AddResult(CodeCompletionResult("copy"));
Bill Wendling44426052012-12-20 19:22:21 +00005542 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_nonatomic))
John McCall276321a2010-08-25 06:19:51 +00005543 Results.AddResult(CodeCompletionResult("nonatomic"));
Bill Wendling44426052012-12-20 19:22:21 +00005544 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_atomic))
Fariborz Jahanian1c2d29e2011-06-11 17:14:27 +00005545 Results.AddResult(CodeCompletionResult("atomic"));
Jordan Rose53cb2f32012-08-20 20:01:13 +00005546
5547 // Only suggest "weak" if we're compiling for ARC-with-weak-references or GC.
John McCall460ce582015-10-22 18:38:17 +00005548 if (getLangOpts().ObjCWeak || getLangOpts().getGC() != LangOptions::NonGC)
Bill Wendling44426052012-12-20 19:22:21 +00005549 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_weak))
Jordan Rose53cb2f32012-08-20 20:01:13 +00005550 Results.AddResult(CodeCompletionResult("weak"));
5551
Bill Wendling44426052012-12-20 19:22:21 +00005552 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_setter)) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005553 CodeCompletionBuilder Setter(Results.getAllocator(),
5554 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005555 Setter.AddTypedTextChunk("setter");
Argyrios Kyrtzidis7bbb8812014-02-20 07:55:15 +00005556 Setter.AddTextChunk("=");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005557 Setter.AddPlaceholderChunk("method");
5558 Results.AddResult(CodeCompletionResult(Setter.TakeString()));
Douglas Gregor45f83ee2009-11-19 00:01:57 +00005559 }
Bill Wendling44426052012-12-20 19:22:21 +00005560 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_getter)) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005561 CodeCompletionBuilder Getter(Results.getAllocator(),
5562 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005563 Getter.AddTypedTextChunk("getter");
Argyrios Kyrtzidis7bbb8812014-02-20 07:55:15 +00005564 Getter.AddTextChunk("=");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005565 Getter.AddPlaceholderChunk("method");
5566 Results.AddResult(CodeCompletionResult(Getter.TakeString()));
Douglas Gregor45f83ee2009-11-19 00:01:57 +00005567 }
Douglas Gregor86b42682015-06-19 18:27:52 +00005568 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_nullability)) {
5569 Results.AddResult(CodeCompletionResult("nonnull"));
5570 Results.AddResult(CodeCompletionResult("nullable"));
5571 Results.AddResult(CodeCompletionResult("null_unspecified"));
5572 Results.AddResult(CodeCompletionResult("null_resettable"));
5573 }
Steve Naroff936354c2009-10-08 21:55:05 +00005574 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005575 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5576 Results.data(), Results.size());
Steve Naroff936354c2009-10-08 21:55:05 +00005577}
Steve Naroffeae65032009-11-07 02:08:14 +00005578
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00005579/// Describes the kind of Objective-C method that we want to find
Douglas Gregorc8537c52009-11-19 07:41:15 +00005580/// via code completion.
5581enum ObjCMethodKind {
Dmitri Gribenko4280e5c2012-06-08 23:13:42 +00005582 MK_Any, ///< Any kind of method, provided it means other specified criteria.
5583 MK_ZeroArgSelector, ///< Zero-argument (unary) selector.
5584 MK_OneArgSelector ///< One-argument selector.
Douglas Gregorc8537c52009-11-19 07:41:15 +00005585};
5586
Douglas Gregor67c692c2010-08-26 15:07:07 +00005587static bool isAcceptableObjCSelector(Selector Sel,
5588 ObjCMethodKind WantKind,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005589 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005590 bool AllowSameLength = true) {
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005591 unsigned NumSelIdents = SelIdents.size();
Douglas Gregor67c692c2010-08-26 15:07:07 +00005592 if (NumSelIdents > Sel.getNumArgs())
5593 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005594
Douglas Gregor67c692c2010-08-26 15:07:07 +00005595 switch (WantKind) {
5596 case MK_Any: break;
5597 case MK_ZeroArgSelector: return Sel.isUnarySelector();
5598 case MK_OneArgSelector: return Sel.getNumArgs() == 1;
5599 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005600
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005601 if (!AllowSameLength && NumSelIdents && NumSelIdents == Sel.getNumArgs())
5602 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005603
Douglas Gregor67c692c2010-08-26 15:07:07 +00005604 for (unsigned I = 0; I != NumSelIdents; ++I)
5605 if (SelIdents[I] != Sel.getIdentifierInfoForSlot(I))
5606 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005607
Douglas Gregor67c692c2010-08-26 15:07:07 +00005608 return true;
5609}
5610
Douglas Gregorc8537c52009-11-19 07:41:15 +00005611static bool isAcceptableObjCMethod(ObjCMethodDecl *Method,
5612 ObjCMethodKind WantKind,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005613 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005614 bool AllowSameLength = true) {
Douglas Gregor67c692c2010-08-26 15:07:07 +00005615 return isAcceptableObjCSelector(Method->getSelector(), WantKind, SelIdents,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005616 AllowSameLength);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005617}
Douglas Gregor1154e272010-09-16 16:06:31 +00005618
5619namespace {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005620 /// A set of selectors, which is used to avoid introducing multiple
Douglas Gregor1154e272010-09-16 16:06:31 +00005621 /// completions with the same selector into the result set.
5622 typedef llvm::SmallPtrSet<Selector, 16> VisitedSelectorSet;
5623}
5624
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005625/// Add all of the Objective-C methods in the given Objective-C
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005626/// container to the set of results.
5627///
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005628/// The container will be a class, protocol, category, or implementation of
5629/// any of the above. This mether will recurse to include methods from
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005630/// the superclasses of classes along with their categories, protocols, and
5631/// implementations.
5632///
5633/// \param Container the container in which we'll look to find methods.
5634///
James Dennett596e4752012-06-14 03:11:41 +00005635/// \param WantInstanceMethods Whether to add instance methods (only); if
5636/// false, this routine will add factory methods (only).
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005637///
5638/// \param CurContext the context in which we're performing the lookup that
5639/// finds methods.
5640///
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005641/// \param AllowSameLength Whether we allow a method to be added to the list
5642/// when it has the same number of parameters as we have selector identifiers.
5643///
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005644/// \param Results the structure into which we'll add results.
Alex Lorenz638dbc32017-01-24 14:15:08 +00005645static void AddObjCMethods(ObjCContainerDecl *Container,
5646 bool WantInstanceMethods, ObjCMethodKind WantKind,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005647 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005648 DeclContext *CurContext,
Alex Lorenz638dbc32017-01-24 14:15:08 +00005649 VisitedSelectorSet &Selectors, bool AllowSameLength,
5650 ResultBuilder &Results, bool InOriginalClass = true,
5651 bool IsRootClass = false) {
John McCall276321a2010-08-25 06:19:51 +00005652 typedef CodeCompletionResult Result;
Douglas Gregor9b4f3702012-06-12 13:44:08 +00005653 Container = getContainerDef(Container);
Douglas Gregor41778c32013-01-30 06:58:39 +00005654 ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container);
Alex Lorenz638dbc32017-01-24 14:15:08 +00005655 IsRootClass = IsRootClass || (IFace && !IFace->getSuperClass());
Aaron Ballmanaff18c02014-03-13 19:03:34 +00005656 for (auto *M : Container->methods()) {
Douglas Gregor41778c32013-01-30 06:58:39 +00005657 // The instance methods on the root class can be messaged via the
5658 // metaclass.
5659 if (M->isInstanceMethod() == WantInstanceMethods ||
Alex Lorenz638dbc32017-01-24 14:15:08 +00005660 (IsRootClass && !WantInstanceMethods)) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005661 // Check whether the selector identifiers we've been given are a
Douglas Gregor1b605f72009-11-19 01:08:35 +00005662 // subset of the identifiers for this particular method.
Aaron Ballmanaff18c02014-03-13 19:03:34 +00005663 if (!isAcceptableObjCMethod(M, WantKind, SelIdents, AllowSameLength))
Douglas Gregor1b605f72009-11-19 01:08:35 +00005664 continue;
Douglas Gregorc8537c52009-11-19 07:41:15 +00005665
David Blaikie82e95a32014-11-19 07:49:47 +00005666 if (!Selectors.insert(M->getSelector()).second)
Douglas Gregor1154e272010-09-16 16:06:31 +00005667 continue;
Craig Topperc3ec1492014-05-26 06:22:03 +00005668
5669 Result R = Result(M, Results.getBasePriority(M), nullptr);
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005670 R.StartParameter = SelIdents.size();
Douglas Gregorc8537c52009-11-19 07:41:15 +00005671 R.AllParametersAreInformative = (WantKind != MK_Any);
Douglas Gregor416b5752010-08-25 01:08:01 +00005672 if (!InOriginalClass)
Eric Liu4a7cd632018-10-24 12:57:27 +00005673 setInBaseClass(R);
Douglas Gregor1b605f72009-11-19 01:08:35 +00005674 Results.MaybeAddResult(R, CurContext);
5675 }
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005676 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005677
Douglas Gregorf37c9492010-09-16 15:34:59 +00005678 // Visit the protocols of protocols.
5679 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Douglas Gregore6e48b12012-01-01 19:29:29 +00005680 if (Protocol->hasDefinition()) {
5681 const ObjCList<ObjCProtocolDecl> &Protocols
5682 = Protocol->getReferencedProtocols();
5683 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005684 E = Protocols.end();
Douglas Gregore6e48b12012-01-01 19:29:29 +00005685 I != E; ++I)
Alex Lorenz638dbc32017-01-24 14:15:08 +00005686 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, CurContext,
5687 Selectors, AllowSameLength, Results, false, IsRootClass);
Douglas Gregore6e48b12012-01-01 19:29:29 +00005688 }
Douglas Gregorf37c9492010-09-16 15:34:59 +00005689 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005690
Douglas Gregorc0ac7d62011-12-15 05:27:12 +00005691 if (!IFace || !IFace->hasDefinition())
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005692 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005693
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005694 // Add methods in protocols.
Aaron Ballmana49c5062014-03-13 20:29:09 +00005695 for (auto *I : IFace->protocols())
Alex Lorenz638dbc32017-01-24 14:15:08 +00005696 AddObjCMethods(I, WantInstanceMethods, WantKind, SelIdents, CurContext,
5697 Selectors, AllowSameLength, Results, false, IsRootClass);
5698
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005699 // Add methods in categories.
Aaron Ballman15063e12014-03-13 21:35:02 +00005700 for (auto *CatDecl : IFace->known_categories()) {
Douglas Gregor048fbfa2013-01-16 23:00:23 +00005701 AddObjCMethods(CatDecl, WantInstanceMethods, WantKind, SelIdents,
Alex Lorenz638dbc32017-01-24 14:15:08 +00005702 CurContext, Selectors, AllowSameLength, Results,
5703 InOriginalClass, IsRootClass);
5704
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005705 // Add a categories protocol methods.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005706 const ObjCList<ObjCProtocolDecl> &Protocols
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005707 = CatDecl->getReferencedProtocols();
5708 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
5709 E = Protocols.end();
5710 I != E; ++I)
Alex Lorenz638dbc32017-01-24 14:15:08 +00005711 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, CurContext,
5712 Selectors, AllowSameLength, Results, false, IsRootClass);
5713
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005714 // Add methods in category implementations.
5715 if (ObjCCategoryImplDecl *Impl = CatDecl->getImplementation())
Alex Lorenz638dbc32017-01-24 14:15:08 +00005716 AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents, CurContext,
5717 Selectors, AllowSameLength, Results, InOriginalClass,
5718 IsRootClass);
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005719 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005720
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005721 // Add methods in superclass.
Alex Lorenz638dbc32017-01-24 14:15:08 +00005722 // Avoid passing in IsRootClass since root classes won't have super classes.
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005723 if (IFace->getSuperClass())
Alex Lorenz638dbc32017-01-24 14:15:08 +00005724 AddObjCMethods(IFace->getSuperClass(), WantInstanceMethods, WantKind,
5725 SelIdents, CurContext, Selectors, AllowSameLength, Results,
5726 /*IsRootClass=*/false);
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005727
5728 // Add methods in our implementation, if any.
5729 if (ObjCImplementationDecl *Impl = IFace->getImplementation())
Alex Lorenz638dbc32017-01-24 14:15:08 +00005730 AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents, CurContext,
5731 Selectors, AllowSameLength, Results, InOriginalClass,
5732 IsRootClass);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005733}
5734
5735
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005736void Sema::CodeCompleteObjCPropertyGetter(Scope *S) {
Douglas Gregorc8537c52009-11-19 07:41:15 +00005737 // Try to find the interface where getters might live.
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005738 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005739 if (!Class) {
5740 if (ObjCCategoryDecl *Category
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005741 = dyn_cast_or_null<ObjCCategoryDecl>(CurContext))
Douglas Gregorc8537c52009-11-19 07:41:15 +00005742 Class = Category->getClassInterface();
5743
5744 if (!Class)
5745 return;
5746 }
5747
5748 // Find all of the potential getters.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005749 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005750 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005751 CodeCompletionContext::CCC_Other);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005752 Results.EnterNewScope();
5753
Douglas Gregor1154e272010-09-16 16:06:31 +00005754 VisitedSelectorSet Selectors;
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005755 AddObjCMethods(Class, true, MK_ZeroArgSelector, None, CurContext, Selectors,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005756 /*AllowSameLength=*/true, Results);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005757 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005758 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5759 Results.data(), Results.size());
Douglas Gregorc8537c52009-11-19 07:41:15 +00005760}
5761
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005762void Sema::CodeCompleteObjCPropertySetter(Scope *S) {
Douglas Gregorc8537c52009-11-19 07:41:15 +00005763 // Try to find the interface where setters might live.
5764 ObjCInterfaceDecl *Class
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005765 = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005766 if (!Class) {
5767 if (ObjCCategoryDecl *Category
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005768 = dyn_cast_or_null<ObjCCategoryDecl>(CurContext))
Douglas Gregorc8537c52009-11-19 07:41:15 +00005769 Class = Category->getClassInterface();
5770
5771 if (!Class)
5772 return;
5773 }
5774
5775 // Find all of the potential getters.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005776 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005777 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005778 CodeCompletionContext::CCC_Other);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005779 Results.EnterNewScope();
5780
Douglas Gregor1154e272010-09-16 16:06:31 +00005781 VisitedSelectorSet Selectors;
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005782 AddObjCMethods(Class, true, MK_OneArgSelector, None, CurContext,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005783 Selectors, /*AllowSameLength=*/true, Results);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005784
5785 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005786 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5787 Results.data(), Results.size());
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005788}
5789
Douglas Gregorf34a6f02011-02-15 22:19:42 +00005790void Sema::CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS,
5791 bool IsParameter) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005792 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005793 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005794 CodeCompletionContext::CCC_Type);
Douglas Gregor99fa2642010-08-24 01:06:58 +00005795 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005796
Douglas Gregor99fa2642010-08-24 01:06:58 +00005797 // Add context-sensitive, Objective-C parameter-passing keywords.
5798 bool AddedInOut = false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005799 if ((DS.getObjCDeclQualifier() &
Douglas Gregor99fa2642010-08-24 01:06:58 +00005800 (ObjCDeclSpec::DQ_In | ObjCDeclSpec::DQ_Inout)) == 0) {
5801 Results.AddResult("in");
5802 Results.AddResult("inout");
5803 AddedInOut = true;
5804 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005805 if ((DS.getObjCDeclQualifier() &
Douglas Gregor99fa2642010-08-24 01:06:58 +00005806 (ObjCDeclSpec::DQ_Out | ObjCDeclSpec::DQ_Inout)) == 0) {
5807 Results.AddResult("out");
5808 if (!AddedInOut)
5809 Results.AddResult("inout");
5810 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005811 if ((DS.getObjCDeclQualifier() &
Douglas Gregor99fa2642010-08-24 01:06:58 +00005812 (ObjCDeclSpec::DQ_Bycopy | ObjCDeclSpec::DQ_Byref |
5813 ObjCDeclSpec::DQ_Oneway)) == 0) {
5814 Results.AddResult("bycopy");
5815 Results.AddResult("byref");
5816 Results.AddResult("oneway");
5817 }
Douglas Gregor86b42682015-06-19 18:27:52 +00005818 if ((DS.getObjCDeclQualifier() & ObjCDeclSpec::DQ_CSNullability) == 0) {
5819 Results.AddResult("nonnull");
5820 Results.AddResult("nullable");
5821 Results.AddResult("null_unspecified");
5822 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005823
5824 // If we're completing the return type of an Objective-C method and the
Douglas Gregorf34a6f02011-02-15 22:19:42 +00005825 // identifier IBAction refers to a macro, provide a completion item for
5826 // an action, e.g.,
5827 // IBAction)<#selector#>:(id)sender
5828 if (DS.getObjCDeclQualifier() == 0 && !IsParameter &&
Richard Smith20e883e2015-04-29 23:20:19 +00005829 PP.isMacroDefined("IBAction")) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005830 CodeCompletionBuilder Builder(Results.getAllocator(),
5831 Results.getCodeCompletionTUInfo(),
5832 CCP_CodePattern, CXAvailability_Available);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00005833 Builder.AddTypedTextChunk("IBAction");
Benjamin Kramerdb534a42012-03-26 16:57:36 +00005834 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00005835 Builder.AddPlaceholderChunk("selector");
Benjamin Kramerdb534a42012-03-26 16:57:36 +00005836 Builder.AddChunk(CodeCompletionString::CK_Colon);
5837 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00005838 Builder.AddTextChunk("id");
Benjamin Kramerdb534a42012-03-26 16:57:36 +00005839 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00005840 Builder.AddTextChunk("sender");
5841 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
5842 }
Douglas Gregored1f5972013-01-30 07:11:43 +00005843
5844 // If we're completing the return type, provide 'instancetype'.
5845 if (!IsParameter) {
5846 Results.AddResult(CodeCompletionResult("instancetype"));
5847 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005848
Douglas Gregor99fa2642010-08-24 01:06:58 +00005849 // Add various builtin type names and specifiers.
5850 AddOrdinaryNameResults(PCC_Type, S, *this, Results);
5851 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005852
Douglas Gregor99fa2642010-08-24 01:06:58 +00005853 // Add the various type names
5854 Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
5855 CodeCompletionDeclConsumer Consumer(Results, CurContext);
5856 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00005857 CodeCompleter->includeGlobals(),
5858 CodeCompleter->loadExternal());
5859
Douglas Gregor99fa2642010-08-24 01:06:58 +00005860 if (CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00005861 AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false);
Douglas Gregor99fa2642010-08-24 01:06:58 +00005862
Eric Liuf5ba09f2018-07-04 10:01:18 +00005863 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor99fa2642010-08-24 01:06:58 +00005864 Results.data(), Results.size());
5865}
5866
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00005867/// When we have an expression with type "id", we may assume
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005868/// that it has some more-specific class type based on knowledge of
5869/// common uses of Objective-C. This routine returns that class type,
5870/// or NULL if no better result could be determined.
5871static ObjCInterfaceDecl *GetAssumedMessageSendExprType(Expr *E) {
Douglas Gregored0b69d2010-09-15 16:23:04 +00005872 ObjCMessageExpr *Msg = dyn_cast_or_null<ObjCMessageExpr>(E);
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005873 if (!Msg)
Craig Topperc3ec1492014-05-26 06:22:03 +00005874 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005875
5876 Selector Sel = Msg->getSelector();
5877 if (Sel.isNull())
Craig Topperc3ec1492014-05-26 06:22:03 +00005878 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005879
5880 IdentifierInfo *Id = Sel.getIdentifierInfoForSlot(0);
5881 if (!Id)
Craig Topperc3ec1492014-05-26 06:22:03 +00005882 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005883
5884 ObjCMethodDecl *Method = Msg->getMethodDecl();
5885 if (!Method)
Craig Topperc3ec1492014-05-26 06:22:03 +00005886 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005887
5888 // Determine the class that we're sending the message to.
Craig Topperc3ec1492014-05-26 06:22:03 +00005889 ObjCInterfaceDecl *IFace = nullptr;
Douglas Gregor9a129192010-04-21 00:45:42 +00005890 switch (Msg->getReceiverKind()) {
5891 case ObjCMessageExpr::Class:
John McCall8b07ec22010-05-15 11:32:37 +00005892 if (const ObjCObjectType *ObjType
5893 = Msg->getClassReceiver()->getAs<ObjCObjectType>())
5894 IFace = ObjType->getInterface();
Douglas Gregor9a129192010-04-21 00:45:42 +00005895 break;
5896
5897 case ObjCMessageExpr::Instance: {
5898 QualType T = Msg->getInstanceReceiver()->getType();
5899 if (const ObjCObjectPointerType *Ptr = T->getAs<ObjCObjectPointerType>())
5900 IFace = Ptr->getInterfaceDecl();
5901 break;
5902 }
5903
5904 case ObjCMessageExpr::SuperInstance:
5905 case ObjCMessageExpr::SuperClass:
5906 break;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005907 }
5908
5909 if (!IFace)
Craig Topperc3ec1492014-05-26 06:22:03 +00005910 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005911
5912 ObjCInterfaceDecl *Super = IFace->getSuperClass();
5913 if (Method->isInstanceMethod())
5914 return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
5915 .Case("retain", IFace)
John McCall31168b02011-06-15 23:02:42 +00005916 .Case("strong", IFace)
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005917 .Case("autorelease", IFace)
5918 .Case("copy", IFace)
5919 .Case("copyWithZone", IFace)
5920 .Case("mutableCopy", IFace)
5921 .Case("mutableCopyWithZone", IFace)
5922 .Case("awakeFromCoder", IFace)
5923 .Case("replacementObjectFromCoder", IFace)
5924 .Case("class", IFace)
5925 .Case("classForCoder", IFace)
5926 .Case("superclass", Super)
Craig Topperc3ec1492014-05-26 06:22:03 +00005927 .Default(nullptr);
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005928
5929 return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
5930 .Case("new", IFace)
5931 .Case("alloc", IFace)
5932 .Case("allocWithZone", IFace)
5933 .Case("class", IFace)
5934 .Case("superclass", Super)
Craig Topperc3ec1492014-05-26 06:22:03 +00005935 .Default(nullptr);
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005936}
5937
Douglas Gregor6fc04132010-08-27 15:10:57 +00005938// Add a special completion for a message send to "super", which fills in the
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005939// most likely case of forwarding all of our arguments to the superclass
Douglas Gregor6fc04132010-08-27 15:10:57 +00005940// function.
5941///
5942/// \param S The semantic analysis object.
5943///
Dmitri Gribenkoadba9be2012-08-23 17:58:28 +00005944/// \param NeedSuperKeyword Whether we need to prefix this completion with
Douglas Gregor6fc04132010-08-27 15:10:57 +00005945/// the "super" keyword. Otherwise, we just need to provide the arguments.
5946///
5947/// \param SelIdents The identifiers in the selector that have already been
5948/// provided as arguments for a send to "super".
5949///
Douglas Gregor6fc04132010-08-27 15:10:57 +00005950/// \param Results The set of results to augment.
5951///
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005952/// \returns the Objective-C method declaration that would be invoked by
Douglas Gregor6fc04132010-08-27 15:10:57 +00005953/// this "super" completion. If NULL, no completion was added.
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005954static ObjCMethodDecl *AddSuperSendCompletion(
5955 Sema &S, bool NeedSuperKeyword,
5956 ArrayRef<IdentifierInfo *> SelIdents,
5957 ResultBuilder &Results) {
Douglas Gregor6fc04132010-08-27 15:10:57 +00005958 ObjCMethodDecl *CurMethod = S.getCurMethodDecl();
5959 if (!CurMethod)
Craig Topperc3ec1492014-05-26 06:22:03 +00005960 return nullptr;
5961
Douglas Gregor6fc04132010-08-27 15:10:57 +00005962 ObjCInterfaceDecl *Class = CurMethod->getClassInterface();
5963 if (!Class)
Craig Topperc3ec1492014-05-26 06:22:03 +00005964 return nullptr;
5965
Douglas Gregor6fc04132010-08-27 15:10:57 +00005966 // Try to find a superclass method with the same selector.
Craig Topperc3ec1492014-05-26 06:22:03 +00005967 ObjCMethodDecl *SuperMethod = nullptr;
Douglas Gregorb5f1e462011-02-16 00:51:18 +00005968 while ((Class = Class->getSuperClass()) && !SuperMethod) {
5969 // Check in the class
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005970 SuperMethod = Class->getMethod(CurMethod->getSelector(),
Douglas Gregor6fc04132010-08-27 15:10:57 +00005971 CurMethod->isInstanceMethod());
5972
Douglas Gregorb5f1e462011-02-16 00:51:18 +00005973 // Check in categories or class extensions.
5974 if (!SuperMethod) {
Aaron Ballman15063e12014-03-13 21:35:02 +00005975 for (const auto *Cat : Class->known_categories()) {
Douglas Gregor048fbfa2013-01-16 23:00:23 +00005976 if ((SuperMethod = Cat->getMethod(CurMethod->getSelector(),
Douglas Gregorb5f1e462011-02-16 00:51:18 +00005977 CurMethod->isInstanceMethod())))
5978 break;
Douglas Gregor048fbfa2013-01-16 23:00:23 +00005979 }
Douglas Gregorb5f1e462011-02-16 00:51:18 +00005980 }
5981 }
5982
Douglas Gregor6fc04132010-08-27 15:10:57 +00005983 if (!SuperMethod)
Craig Topperc3ec1492014-05-26 06:22:03 +00005984 return nullptr;
5985
Douglas Gregor6fc04132010-08-27 15:10:57 +00005986 // Check whether the superclass method has the same signature.
5987 if (CurMethod->param_size() != SuperMethod->param_size() ||
5988 CurMethod->isVariadic() != SuperMethod->isVariadic())
Craig Topperc3ec1492014-05-26 06:22:03 +00005989 return nullptr;
5990
Douglas Gregor6fc04132010-08-27 15:10:57 +00005991 for (ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin(),
5992 CurPEnd = CurMethod->param_end(),
5993 SuperP = SuperMethod->param_begin();
5994 CurP != CurPEnd; ++CurP, ++SuperP) {
5995 // Make sure the parameter types are compatible.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005996 if (!S.Context.hasSameUnqualifiedType((*CurP)->getType(),
Douglas Gregor6fc04132010-08-27 15:10:57 +00005997 (*SuperP)->getType()))
Craig Topperc3ec1492014-05-26 06:22:03 +00005998 return nullptr;
5999
Douglas Gregor6fc04132010-08-27 15:10:57 +00006000 // Make sure we have a parameter name to forward!
6001 if (!(*CurP)->getIdentifier())
Craig Topperc3ec1492014-05-26 06:22:03 +00006002 return nullptr;
Douglas Gregor6fc04132010-08-27 15:10:57 +00006003 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006004
Douglas Gregor6fc04132010-08-27 15:10:57 +00006005 // We have a superclass method. Now, form the send-to-super completion.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006006 CodeCompletionBuilder Builder(Results.getAllocator(),
6007 Results.getCodeCompletionTUInfo());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006008
Douglas Gregor6fc04132010-08-27 15:10:57 +00006009 // Give this completion a return type.
Douglas Gregorc3425b12015-07-07 06:20:19 +00006010 AddResultTypeChunk(S.Context, getCompletionPrintingPolicy(S), SuperMethod,
6011 Results.getCompletionContext().getBaseType(),
Douglas Gregor75acd922011-09-27 23:30:47 +00006012 Builder);
Douglas Gregor6fc04132010-08-27 15:10:57 +00006013
6014 // If we need the "super" keyword, add it (plus some spacing).
6015 if (NeedSuperKeyword) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006016 Builder.AddTypedTextChunk("super");
6017 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregor6fc04132010-08-27 15:10:57 +00006018 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006019
Douglas Gregor6fc04132010-08-27 15:10:57 +00006020 Selector Sel = CurMethod->getSelector();
6021 if (Sel.isUnarySelector()) {
6022 if (NeedSuperKeyword)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00006023 Builder.AddTextChunk(Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00006024 Sel.getNameForSlot(0)));
Douglas Gregor6fc04132010-08-27 15:10:57 +00006025 else
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00006026 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00006027 Sel.getNameForSlot(0)));
Douglas Gregor6fc04132010-08-27 15:10:57 +00006028 } else {
6029 ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin();
6030 for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I, ++CurP) {
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006031 if (I > SelIdents.size())
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006032 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006033
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006034 if (I < SelIdents.size())
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006035 Builder.AddInformativeChunk(
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00006036 Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00006037 Sel.getNameForSlot(I) + ":"));
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006038 else if (NeedSuperKeyword || I > SelIdents.size()) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006039 Builder.AddTextChunk(
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00006040 Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00006041 Sel.getNameForSlot(I) + ":"));
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00006042 Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006043 (*CurP)->getIdentifier()->getName()));
Douglas Gregor6fc04132010-08-27 15:10:57 +00006044 } else {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006045 Builder.AddTypedTextChunk(
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00006046 Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00006047 Sel.getNameForSlot(I) + ":"));
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00006048 Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006049 (*CurP)->getIdentifier()->getName()));
Douglas Gregor6fc04132010-08-27 15:10:57 +00006050 }
6051 }
6052 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006053
Douglas Gregor78254c82012-03-27 23:34:16 +00006054 Results.AddResult(CodeCompletionResult(Builder.TakeString(), SuperMethod,
6055 CCP_SuperCompletion));
Douglas Gregor6fc04132010-08-27 15:10:57 +00006056 return SuperMethod;
6057}
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006058
Douglas Gregora817a192010-05-27 23:06:34 +00006059void Sema::CodeCompleteObjCMessageReceiver(Scope *S) {
John McCall276321a2010-08-25 06:19:51 +00006060 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006061 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006062 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006063 CodeCompletionContext::CCC_ObjCMessageReceiver,
Richard Smith2bf7fdb2013-01-02 11:42:31 +00006064 getLangOpts().CPlusPlus11
Douglas Gregord8c61782012-02-15 15:34:24 +00006065 ? &ResultBuilder::IsObjCMessageReceiverOrLambdaCapture
6066 : &ResultBuilder::IsObjCMessageReceiver);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006067
Douglas Gregora817a192010-05-27 23:06:34 +00006068 CodeCompletionDeclConsumer Consumer(Results, CurContext);
6069 Results.EnterNewScope();
Douglas Gregor39982192010-08-15 06:18:01 +00006070 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00006071 CodeCompleter->includeGlobals(),
6072 CodeCompleter->loadExternal());
6073
Douglas Gregora817a192010-05-27 23:06:34 +00006074 // If we are in an Objective-C method inside a class that has a superclass,
6075 // add "super" as an option.
6076 if (ObjCMethodDecl *Method = getCurMethodDecl())
6077 if (ObjCInterfaceDecl *Iface = Method->getClassInterface())
Douglas Gregor6fc04132010-08-27 15:10:57 +00006078 if (Iface->getSuperClass()) {
Douglas Gregora817a192010-05-27 23:06:34 +00006079 Results.AddResult(Result("super"));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006080
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006081 AddSuperSendCompletion(*this, /*NeedSuperKeyword=*/true, None, Results);
Douglas Gregor6fc04132010-08-27 15:10:57 +00006082 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006083
Richard Smith2bf7fdb2013-01-02 11:42:31 +00006084 if (getLangOpts().CPlusPlus11)
Douglas Gregord8c61782012-02-15 15:34:24 +00006085 addThisCompletion(*this, Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006086
Douglas Gregora817a192010-05-27 23:06:34 +00006087 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006088
Douglas Gregora817a192010-05-27 23:06:34 +00006089 if (CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00006090 AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false);
Douglas Gregor50832e02010-09-20 22:39:41 +00006091 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006092 Results.data(), Results.size());
Douglas Gregora817a192010-05-27 23:06:34 +00006093}
6094
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006095void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006096 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006097 bool AtArgumentExpression) {
Craig Topperc3ec1492014-05-26 06:22:03 +00006098 ObjCInterfaceDecl *CDecl = nullptr;
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006099 if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
6100 // Figure out which interface we're in.
6101 CDecl = CurMethod->getClassInterface();
6102 if (!CDecl)
6103 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006104
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006105 // Find the superclass of this class.
6106 CDecl = CDecl->getSuperClass();
6107 if (!CDecl)
6108 return;
6109
6110 if (CurMethod->isInstanceMethod()) {
6111 // We are inside an instance method, which means that the message
6112 // send [super ...] is actually calling an instance method on the
Douglas Gregor392a84b2010-10-13 21:24:53 +00006113 // current object.
Craig Topperc3ec1492014-05-26 06:22:03 +00006114 return CodeCompleteObjCInstanceMessage(S, nullptr, SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006115 AtArgumentExpression,
Douglas Gregor392a84b2010-10-13 21:24:53 +00006116 CDecl);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006117 }
6118
6119 // Fall through to send to the superclass in CDecl.
6120 } else {
6121 // "super" may be the name of a type or variable. Figure out which
6122 // it is.
Argyrios Kyrtzidis3e56dd42013-03-14 22:56:43 +00006123 IdentifierInfo *Super = getSuperIdentifier();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006124 NamedDecl *ND = LookupSingleName(S, Super, SuperLoc,
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006125 LookupOrdinaryName);
6126 if ((CDecl = dyn_cast_or_null<ObjCInterfaceDecl>(ND))) {
6127 // "super" names an interface. Use it.
6128 } else if (TypeDecl *TD = dyn_cast_or_null<TypeDecl>(ND)) {
John McCall8b07ec22010-05-15 11:32:37 +00006129 if (const ObjCObjectType *Iface
6130 = Context.getTypeDeclType(TD)->getAs<ObjCObjectType>())
6131 CDecl = Iface->getInterface();
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006132 } else if (ND && isa<UnresolvedUsingTypenameDecl>(ND)) {
6133 // "super" names an unresolved type; we can't be more specific.
6134 } else {
6135 // Assume that "super" names some kind of value and parse that way.
6136 CXXScopeSpec SS;
Abramo Bagnara7945c982012-01-27 09:46:47 +00006137 SourceLocation TemplateKWLoc;
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006138 UnqualifiedId id;
6139 id.setIdentifier(Super, SuperLoc);
Abramo Bagnara7945c982012-01-27 09:46:47 +00006140 ExprResult SuperExpr = ActOnIdExpression(S, SS, TemplateKWLoc, id,
6141 false, false);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006142 return CodeCompleteObjCInstanceMessage(S, (Expr *)SuperExpr.get(),
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006143 SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006144 AtArgumentExpression);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006145 }
6146
6147 // Fall through
6148 }
6149
John McCallba7bf592010-08-24 05:47:05 +00006150 ParsedType Receiver;
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006151 if (CDecl)
John McCallba7bf592010-08-24 05:47:05 +00006152 Receiver = ParsedType::make(Context.getObjCInterfaceType(CDecl));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006153 return CodeCompleteObjCClassMessage(S, Receiver, SelIdents,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006154 AtArgumentExpression,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006155 /*IsSuper=*/true);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006156}
6157
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006158/// Given a set of code-completion results for the argument of a message
Douglas Gregor74661272010-09-21 00:03:25 +00006159/// send, determine the preferred type (if any) for that argument expression.
6160static QualType getPreferredArgumentTypeForMessageSend(ResultBuilder &Results,
6161 unsigned NumSelIdents) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006162 typedef CodeCompletionResult Result;
Douglas Gregor74661272010-09-21 00:03:25 +00006163 ASTContext &Context = Results.getSema().Context;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006164
Douglas Gregor74661272010-09-21 00:03:25 +00006165 QualType PreferredType;
6166 unsigned BestPriority = CCP_Unlikely * 2;
6167 Result *ResultsData = Results.data();
6168 for (unsigned I = 0, N = Results.size(); I != N; ++I) {
6169 Result &R = ResultsData[I];
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006170 if (R.Kind == Result::RK_Declaration &&
Douglas Gregor74661272010-09-21 00:03:25 +00006171 isa<ObjCMethodDecl>(R.Declaration)) {
6172 if (R.Priority <= BestPriority) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00006173 const ObjCMethodDecl *Method = cast<ObjCMethodDecl>(R.Declaration);
Douglas Gregor74661272010-09-21 00:03:25 +00006174 if (NumSelIdents <= Method->param_size()) {
Alp Toker03376dc2014-07-07 09:02:20 +00006175 QualType MyPreferredType = Method->parameters()[NumSelIdents - 1]
Douglas Gregor74661272010-09-21 00:03:25 +00006176 ->getType();
6177 if (R.Priority < BestPriority || PreferredType.isNull()) {
6178 BestPriority = R.Priority;
6179 PreferredType = MyPreferredType;
6180 } else if (!Context.hasSameUnqualifiedType(PreferredType,
6181 MyPreferredType)) {
6182 PreferredType = QualType();
6183 }
6184 }
6185 }
6186 }
6187 }
6188
6189 return PreferredType;
6190}
6191
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006192static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006193 ParsedType Receiver,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006194 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006195 bool AtArgumentExpression,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006196 bool IsSuper,
6197 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00006198 typedef CodeCompletionResult Result;
Craig Topperc3ec1492014-05-26 06:22:03 +00006199 ObjCInterfaceDecl *CDecl = nullptr;
6200
Douglas Gregor8ce33212009-11-17 17:59:40 +00006201 // If the given name refers to an interface type, retrieve the
6202 // corresponding declaration.
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006203 if (Receiver) {
Craig Topperc3ec1492014-05-26 06:22:03 +00006204 QualType T = SemaRef.GetTypeFromParser(Receiver, nullptr);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006205 if (!T.isNull())
John McCall8b07ec22010-05-15 11:32:37 +00006206 if (const ObjCObjectType *Interface = T->getAs<ObjCObjectType>())
6207 CDecl = Interface->getInterface();
Douglas Gregor8ce33212009-11-17 17:59:40 +00006208 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006209
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006210 // Add all of the factory methods in this Objective-C class, its protocols,
6211 // superclasses, categories, implementation, etc.
Steve Naroffeae65032009-11-07 02:08:14 +00006212 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006213
6214 // If this is a send-to-super, try to add the special "super" send
Douglas Gregor6fc04132010-08-27 15:10:57 +00006215 // completion.
6216 if (IsSuper) {
6217 if (ObjCMethodDecl *SuperMethod
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006218 = AddSuperSendCompletion(SemaRef, false, SelIdents, Results))
Douglas Gregor6fc04132010-08-27 15:10:57 +00006219 Results.Ignore(SuperMethod);
6220 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006221
Douglas Gregorc2cb2e22010-08-27 15:29:55 +00006222 // If we're inside an Objective-C method definition, prefer its selector to
6223 // others.
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006224 if (ObjCMethodDecl *CurMethod = SemaRef.getCurMethodDecl())
Douglas Gregorc2cb2e22010-08-27 15:29:55 +00006225 Results.setPreferredSelector(CurMethod->getSelector());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006226
Douglas Gregor1154e272010-09-16 16:06:31 +00006227 VisitedSelectorSet Selectors;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006228 if (CDecl)
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006229 AddObjCMethods(CDecl, false, MK_Any, SelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00006230 SemaRef.CurContext, Selectors, AtArgumentExpression,
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006231 Results);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006232 else {
Douglas Gregor6285f752010-04-06 16:40:00 +00006233 // We're messaging "id" as a type; provide all class/factory methods.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006234
Douglas Gregord720daf2010-04-06 17:30:22 +00006235 // If we have an external source, load the entire class method
Sebastian Redld44cd6a2010-08-18 23:57:06 +00006236 // pool from the AST file.
Axel Naumanndd433f02012-10-18 19:05:02 +00006237 if (SemaRef.getExternalSource()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006238 for (uint32_t I = 0,
Axel Naumanndd433f02012-10-18 19:05:02 +00006239 N = SemaRef.getExternalSource()->GetNumExternalSelectors();
John McCall75b960e2010-06-01 09:23:16 +00006240 I != N; ++I) {
Axel Naumanndd433f02012-10-18 19:05:02 +00006241 Selector Sel = SemaRef.getExternalSource()->GetExternalSelector(I);
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006242 if (Sel.isNull() || SemaRef.MethodPool.count(Sel))
Douglas Gregord720daf2010-04-06 17:30:22 +00006243 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006244
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006245 SemaRef.ReadMethodPool(Sel);
Douglas Gregord720daf2010-04-06 17:30:22 +00006246 }
6247 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006248
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006249 for (Sema::GlobalMethodPool::iterator M = SemaRef.MethodPool.begin(),
6250 MEnd = SemaRef.MethodPool.end();
Sebastian Redl75d8a322010-08-02 23:18:59 +00006251 M != MEnd; ++M) {
6252 for (ObjCMethodList *MethList = &M->second.second;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006253 MethList && MethList->getMethod();
Argyrios Kyrtzidisd3da6e02013-04-17 00:08:58 +00006254 MethList = MethList->getNext()) {
Nico Weber2e0c8f72014-12-27 03:58:08 +00006255 if (!isAcceptableObjCMethod(MethList->getMethod(), MK_Any, SelIdents))
Douglas Gregor6285f752010-04-06 16:40:00 +00006256 continue;
Craig Topperc3ec1492014-05-26 06:22:03 +00006257
Nico Weber2e0c8f72014-12-27 03:58:08 +00006258 Result R(MethList->getMethod(),
6259 Results.getBasePriority(MethList->getMethod()), nullptr);
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006260 R.StartParameter = SelIdents.size();
Douglas Gregor6285f752010-04-06 16:40:00 +00006261 R.AllParametersAreInformative = false;
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006262 Results.MaybeAddResult(R, SemaRef.CurContext);
Douglas Gregor6285f752010-04-06 16:40:00 +00006263 }
6264 }
6265 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006266
6267 Results.ExitScope();
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006268}
Douglas Gregor6285f752010-04-06 16:40:00 +00006269
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006270void Sema::CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006271 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006272 bool AtArgumentExpression,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006273 bool IsSuper) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006274
Douglas Gregor63745d52011-07-21 01:05:26 +00006275 QualType T = this->GetTypeFromParser(Receiver);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006276
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006277 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006278 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor63745d52011-07-21 01:05:26 +00006279 CodeCompletionContext(CodeCompletionContext::CCC_ObjCClassMessage,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006280 T, SelIdents));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006281
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006282 AddClassMessageCompletions(*this, S, Receiver, SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006283 AtArgumentExpression, IsSuper, Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006284
6285 // If we're actually at the argument expression (rather than prior to the
Douglas Gregor74661272010-09-21 00:03:25 +00006286 // selector), we're actually performing code completion for an expression.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006287 // Determine whether we have a single, best method. If so, we can
Douglas Gregor74661272010-09-21 00:03:25 +00006288 // code-complete the expression using the corresponding parameter type as
6289 // our preferred type, improving completion results.
6290 if (AtArgumentExpression) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006291 QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006292 SelIdents.size());
Douglas Gregor74661272010-09-21 00:03:25 +00006293 if (PreferredType.isNull())
6294 CodeCompleteOrdinaryName(S, PCC_Expression);
6295 else
6296 CodeCompleteExpression(S, PreferredType);
6297 return;
6298 }
6299
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006300 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor63745d52011-07-21 01:05:26 +00006301 Results.getCompletionContext(),
Douglas Gregor6fc04132010-08-27 15:10:57 +00006302 Results.data(), Results.size());
Steve Naroffeae65032009-11-07 02:08:14 +00006303}
6304
Richard Trieu2bd04012011-09-09 02:00:50 +00006305void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006306 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006307 bool AtArgumentExpression,
Douglas Gregor392a84b2010-10-13 21:24:53 +00006308 ObjCInterfaceDecl *Super) {
John McCall276321a2010-08-25 06:19:51 +00006309 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006310
Steve Naroffeae65032009-11-07 02:08:14 +00006311 Expr *RecExpr = static_cast<Expr *>(Receiver);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006312
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006313 // If necessary, apply function/array conversion to the receiver.
6314 // C99 6.7.5.3p[7,8].
John Wiegley01296292011-04-08 18:41:53 +00006315 if (RecExpr) {
6316 ExprResult Conv = DefaultFunctionArrayLvalueConversion(RecExpr);
6317 if (Conv.isInvalid()) // conversion failed. bail.
6318 return;
Nikola Smiljanic01a75982014-05-29 10:55:11 +00006319 RecExpr = Conv.get();
John Wiegley01296292011-04-08 18:41:53 +00006320 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006321 QualType ReceiverType = RecExpr? RecExpr->getType()
Douglas Gregor392a84b2010-10-13 21:24:53 +00006322 : Super? Context.getObjCObjectPointerType(
6323 Context.getObjCInterfaceType(Super))
6324 : Context.getObjCIdType();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006325
Douglas Gregordc520b02010-11-08 21:12:30 +00006326 // If we're messaging an expression with type "id" or "Class", check
6327 // whether we know something special about the receiver that allows
6328 // us to assume a more-specific receiver type.
Anders Carlsson382ba412014-02-28 19:07:22 +00006329 if (ReceiverType->isObjCIdType() || ReceiverType->isObjCClassType()) {
Douglas Gregordc520b02010-11-08 21:12:30 +00006330 if (ObjCInterfaceDecl *IFace = GetAssumedMessageSendExprType(RecExpr)) {
6331 if (ReceiverType->isObjCClassType())
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006332 return CodeCompleteObjCClassMessage(S,
Douglas Gregordc520b02010-11-08 21:12:30 +00006333 ParsedType::make(Context.getObjCInterfaceType(IFace)),
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006334 SelIdents,
Douglas Gregordc520b02010-11-08 21:12:30 +00006335 AtArgumentExpression, Super);
6336
6337 ReceiverType = Context.getObjCObjectPointerType(
6338 Context.getObjCInterfaceType(IFace));
6339 }
Anders Carlsson382ba412014-02-28 19:07:22 +00006340 } else if (RecExpr && getLangOpts().CPlusPlus) {
6341 ExprResult Conv = PerformContextuallyConvertToObjCPointer(RecExpr);
6342 if (Conv.isUsable()) {
Nikola Smiljanic01a75982014-05-29 10:55:11 +00006343 RecExpr = Conv.get();
Anders Carlsson382ba412014-02-28 19:07:22 +00006344 ReceiverType = RecExpr->getType();
6345 }
6346 }
Douglas Gregordc520b02010-11-08 21:12:30 +00006347
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006348 // Build the set of methods we can see.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006349 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006350 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor63745d52011-07-21 01:05:26 +00006351 CodeCompletionContext(CodeCompletionContext::CCC_ObjCInstanceMessage,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006352 ReceiverType, SelIdents));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006353
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006354 Results.EnterNewScope();
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006355
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006356 // If this is a send-to-super, try to add the special "super" send
Douglas Gregor6fc04132010-08-27 15:10:57 +00006357 // completion.
Douglas Gregor392a84b2010-10-13 21:24:53 +00006358 if (Super) {
Douglas Gregor6fc04132010-08-27 15:10:57 +00006359 if (ObjCMethodDecl *SuperMethod
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006360 = AddSuperSendCompletion(*this, false, SelIdents, Results))
Douglas Gregor6fc04132010-08-27 15:10:57 +00006361 Results.Ignore(SuperMethod);
6362 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006363
Douglas Gregorc2cb2e22010-08-27 15:29:55 +00006364 // If we're inside an Objective-C method definition, prefer its selector to
6365 // others.
6366 if (ObjCMethodDecl *CurMethod = getCurMethodDecl())
6367 Results.setPreferredSelector(CurMethod->getSelector());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006368
Douglas Gregor1154e272010-09-16 16:06:31 +00006369 // Keep track of the selectors we've already added.
6370 VisitedSelectorSet Selectors;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006371
Douglas Gregora3329fa2009-11-18 00:06:18 +00006372 // Handle messages to Class. This really isn't a message to an instance
6373 // method, so we treat it the same way we would treat a message send to a
6374 // class method.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006375 if (ReceiverType->isObjCClassType() ||
Douglas Gregora3329fa2009-11-18 00:06:18 +00006376 ReceiverType->isObjCQualifiedClassType()) {
6377 if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
6378 if (ObjCInterfaceDecl *ClassDecl = CurMethod->getClassInterface())
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006379 AddObjCMethods(ClassDecl, false, MK_Any, SelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00006380 CurContext, Selectors, AtArgumentExpression, Results);
Douglas Gregora3329fa2009-11-18 00:06:18 +00006381 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006382 }
Douglas Gregora3329fa2009-11-18 00:06:18 +00006383 // Handle messages to a qualified ID ("id<foo>").
6384 else if (const ObjCObjectPointerType *QualID
6385 = ReceiverType->getAsObjCQualifiedIdType()) {
6386 // Search protocols for instance methods.
Aaron Ballman83731462014-03-17 16:14:00 +00006387 for (auto *I : QualID->quals())
6388 AddObjCMethods(I, true, MK_Any, SelIdents, CurContext,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00006389 Selectors, AtArgumentExpression, Results);
Douglas Gregora3329fa2009-11-18 00:06:18 +00006390 }
6391 // Handle messages to a pointer to interface type.
6392 else if (const ObjCObjectPointerType *IFacePtr
6393 = ReceiverType->getAsObjCInterfacePointerType()) {
6394 // Search the class, its superclasses, etc., for instance methods.
Douglas Gregorc8537c52009-11-19 07:41:15 +00006395 AddObjCMethods(IFacePtr->getInterfaceDecl(), true, MK_Any, SelIdents,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006396 CurContext, Selectors, AtArgumentExpression,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00006397 Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006398
Douglas Gregora3329fa2009-11-18 00:06:18 +00006399 // Search protocols for instance methods.
Aaron Ballman83731462014-03-17 16:14:00 +00006400 for (auto *I : IFacePtr->quals())
6401 AddObjCMethods(I, true, MK_Any, SelIdents, CurContext,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00006402 Selectors, AtArgumentExpression, Results);
Douglas Gregora3329fa2009-11-18 00:06:18 +00006403 }
Douglas Gregor6285f752010-04-06 16:40:00 +00006404 // Handle messages to "id".
6405 else if (ReceiverType->isObjCIdType()) {
Douglas Gregord720daf2010-04-06 17:30:22 +00006406 // We're messaging "id", so provide all instance methods we know
6407 // about as code-completion results.
6408
6409 // If we have an external source, load the entire class method
Sebastian Redld44cd6a2010-08-18 23:57:06 +00006410 // pool from the AST file.
Douglas Gregord720daf2010-04-06 17:30:22 +00006411 if (ExternalSource) {
John McCall75b960e2010-06-01 09:23:16 +00006412 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
6413 I != N; ++I) {
6414 Selector Sel = ExternalSource->GetExternalSelector(I);
Sebastian Redl75d8a322010-08-02 23:18:59 +00006415 if (Sel.isNull() || MethodPool.count(Sel))
Douglas Gregord720daf2010-04-06 17:30:22 +00006416 continue;
6417
Sebastian Redl75d8a322010-08-02 23:18:59 +00006418 ReadMethodPool(Sel);
Douglas Gregord720daf2010-04-06 17:30:22 +00006419 }
6420 }
6421
Sebastian Redl75d8a322010-08-02 23:18:59 +00006422 for (GlobalMethodPool::iterator M = MethodPool.begin(),
6423 MEnd = MethodPool.end();
6424 M != MEnd; ++M) {
6425 for (ObjCMethodList *MethList = &M->second.first;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006426 MethList && MethList->getMethod();
Argyrios Kyrtzidisd3da6e02013-04-17 00:08:58 +00006427 MethList = MethList->getNext()) {
Nico Weber2e0c8f72014-12-27 03:58:08 +00006428 if (!isAcceptableObjCMethod(MethList->getMethod(), MK_Any, SelIdents))
Douglas Gregor6285f752010-04-06 16:40:00 +00006429 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006430
Nico Weber2e0c8f72014-12-27 03:58:08 +00006431 if (!Selectors.insert(MethList->getMethod()->getSelector()).second)
Douglas Gregor1154e272010-09-16 16:06:31 +00006432 continue;
Craig Topperc3ec1492014-05-26 06:22:03 +00006433
Nico Weber2e0c8f72014-12-27 03:58:08 +00006434 Result R(MethList->getMethod(),
6435 Results.getBasePriority(MethList->getMethod()), nullptr);
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006436 R.StartParameter = SelIdents.size();
Douglas Gregor6285f752010-04-06 16:40:00 +00006437 R.AllParametersAreInformative = false;
6438 Results.MaybeAddResult(R, CurContext);
6439 }
6440 }
6441 }
Steve Naroffeae65032009-11-07 02:08:14 +00006442 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006443
6444
6445 // If we're actually at the argument expression (rather than prior to the
Douglas Gregor74661272010-09-21 00:03:25 +00006446 // selector), we're actually performing code completion for an expression.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006447 // Determine whether we have a single, best method. If so, we can
Douglas Gregor74661272010-09-21 00:03:25 +00006448 // code-complete the expression using the corresponding parameter type as
6449 // our preferred type, improving completion results.
6450 if (AtArgumentExpression) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006451 QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006452 SelIdents.size());
Douglas Gregor74661272010-09-21 00:03:25 +00006453 if (PreferredType.isNull())
6454 CodeCompleteOrdinaryName(S, PCC_Expression);
6455 else
6456 CodeCompleteExpression(S, PreferredType);
6457 return;
6458 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006459
6460 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor63745d52011-07-21 01:05:26 +00006461 Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006462 Results.data(),Results.size());
Steve Naroffeae65032009-11-07 02:08:14 +00006463}
Douglas Gregorbaf69612009-11-18 04:19:12 +00006464
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006465void Sema::CodeCompleteObjCForCollection(Scope *S,
Douglas Gregor68762e72010-08-23 21:17:50 +00006466 DeclGroupPtrTy IterationVar) {
6467 CodeCompleteExpressionData Data;
6468 Data.ObjCCollection = true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006469
Douglas Gregor68762e72010-08-23 21:17:50 +00006470 if (IterationVar.getAsOpaquePtr()) {
Serge Pavlov9ddb76e2013-08-27 13:15:56 +00006471 DeclGroupRef DG = IterationVar.get();
Douglas Gregor68762e72010-08-23 21:17:50 +00006472 for (DeclGroupRef::iterator I = DG.begin(), End = DG.end(); I != End; ++I) {
6473 if (*I)
6474 Data.IgnoreDecls.push_back(*I);
6475 }
6476 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006477
Douglas Gregor68762e72010-08-23 21:17:50 +00006478 CodeCompleteExpression(S, Data);
6479}
6480
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006481void Sema::CodeCompleteObjCSelector(Scope *S,
6482 ArrayRef<IdentifierInfo *> SelIdents) {
Douglas Gregor67c692c2010-08-26 15:07:07 +00006483 // If we have an external source, load the entire class method
6484 // pool from the AST file.
6485 if (ExternalSource) {
6486 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
6487 I != N; ++I) {
6488 Selector Sel = ExternalSource->GetExternalSelector(I);
6489 if (Sel.isNull() || MethodPool.count(Sel))
6490 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006491
Douglas Gregor67c692c2010-08-26 15:07:07 +00006492 ReadMethodPool(Sel);
6493 }
6494 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006495
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006496 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006497 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006498 CodeCompletionContext::CCC_SelectorName);
Douglas Gregor67c692c2010-08-26 15:07:07 +00006499 Results.EnterNewScope();
6500 for (GlobalMethodPool::iterator M = MethodPool.begin(),
6501 MEnd = MethodPool.end();
6502 M != MEnd; ++M) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006503
Douglas Gregor67c692c2010-08-26 15:07:07 +00006504 Selector Sel = M->first;
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006505 if (!isAcceptableObjCSelector(Sel, MK_Any, SelIdents))
Douglas Gregor67c692c2010-08-26 15:07:07 +00006506 continue;
6507
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006508 CodeCompletionBuilder Builder(Results.getAllocator(),
6509 Results.getCodeCompletionTUInfo());
Douglas Gregor67c692c2010-08-26 15:07:07 +00006510 if (Sel.isUnarySelector()) {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00006511 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00006512 Sel.getNameForSlot(0)));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006513 Results.AddResult(Builder.TakeString());
Douglas Gregor67c692c2010-08-26 15:07:07 +00006514 continue;
6515 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006516
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00006517 std::string Accumulator;
Douglas Gregor67c692c2010-08-26 15:07:07 +00006518 for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I) {
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006519 if (I == SelIdents.size()) {
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00006520 if (!Accumulator.empty()) {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00006521 Builder.AddInformativeChunk(Builder.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006522 Accumulator));
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00006523 Accumulator.clear();
6524 }
6525 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006526
Benjamin Kramer632500c2011-07-26 16:59:25 +00006527 Accumulator += Sel.getNameForSlot(I);
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00006528 Accumulator += ':';
Douglas Gregor67c692c2010-08-26 15:07:07 +00006529 }
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00006530 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString( Accumulator));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006531 Results.AddResult(Builder.TakeString());
Douglas Gregor67c692c2010-08-26 15:07:07 +00006532 }
6533 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00006534
6535 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor67c692c2010-08-26 15:07:07 +00006536 Results.data(), Results.size());
6537}
6538
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006539/// Add all of the protocol declarations that we find in the given
Douglas Gregorbaf69612009-11-18 04:19:12 +00006540/// (translation unit) context.
6541static void AddProtocolResults(DeclContext *Ctx, DeclContext *CurContext,
Douglas Gregor5b4671c2009-11-18 04:49:41 +00006542 bool OnlyForwardDeclarations,
Douglas Gregorbaf69612009-11-18 04:19:12 +00006543 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00006544 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006545
Aaron Ballman629afae2014-03-07 19:56:05 +00006546 for (const auto *D : Ctx->decls()) {
Douglas Gregorbaf69612009-11-18 04:19:12 +00006547 // Record any protocols we find.
Aaron Ballman629afae2014-03-07 19:56:05 +00006548 if (const auto *Proto = dyn_cast<ObjCProtocolDecl>(D))
Douglas Gregore6e48b12012-01-01 19:29:29 +00006549 if (!OnlyForwardDeclarations || !Proto->hasDefinition())
Craig Topperc3ec1492014-05-26 06:22:03 +00006550 Results.AddResult(Result(Proto, Results.getBasePriority(Proto),nullptr),
6551 CurContext, nullptr, false);
Douglas Gregorbaf69612009-11-18 04:19:12 +00006552 }
6553}
6554
Craig Topper883dd332015-12-24 23:58:11 +00006555void Sema::CodeCompleteObjCProtocolReferences(
6556 ArrayRef<IdentifierLocPair> Protocols) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006557 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006558 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006559 CodeCompletionContext::CCC_ObjCProtocolName);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006560
Chandler Carruthede11632016-11-04 06:06:50 +00006561 if (CodeCompleter->includeGlobals()) {
Douglas Gregora3b23b02010-12-09 21:44:02 +00006562 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006563
Douglas Gregora3b23b02010-12-09 21:44:02 +00006564 // Tell the result set to ignore all of the protocols we have
6565 // already seen.
6566 // FIXME: This doesn't work when caching code-completion results.
Craig Topper883dd332015-12-24 23:58:11 +00006567 for (const IdentifierLocPair &Pair : Protocols)
6568 if (ObjCProtocolDecl *Protocol = LookupProtocol(Pair.first,
6569 Pair.second))
Douglas Gregora3b23b02010-12-09 21:44:02 +00006570 Results.Ignore(Protocol);
Douglas Gregorbaf69612009-11-18 04:19:12 +00006571
Douglas Gregora3b23b02010-12-09 21:44:02 +00006572 // Add all protocols.
6573 AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, false,
6574 Results);
Douglas Gregor5b4671c2009-11-18 04:49:41 +00006575
Douglas Gregora3b23b02010-12-09 21:44:02 +00006576 Results.ExitScope();
6577 }
Eric Liuf5ba09f2018-07-04 10:01:18 +00006578
6579 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6580 Results.data(), Results.size());
Douglas Gregor5b4671c2009-11-18 04:49:41 +00006581}
6582
6583void Sema::CodeCompleteObjCProtocolDecl(Scope *) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006584 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006585 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006586 CodeCompletionContext::CCC_ObjCProtocolName);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006587
Chandler Carruthede11632016-11-04 06:06:50 +00006588 if (CodeCompleter->includeGlobals()) {
Douglas Gregora3b23b02010-12-09 21:44:02 +00006589 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006590
Douglas Gregora3b23b02010-12-09 21:44:02 +00006591 // Add all protocols.
6592 AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, true,
6593 Results);
Douglas Gregorbaf69612009-11-18 04:19:12 +00006594
Douglas Gregora3b23b02010-12-09 21:44:02 +00006595 Results.ExitScope();
6596 }
Eric Liuf5ba09f2018-07-04 10:01:18 +00006597
6598 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6599 Results.data(), Results.size());
Douglas Gregorbaf69612009-11-18 04:19:12 +00006600}
Douglas Gregor49c22a72009-11-18 16:26:39 +00006601
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006602/// Add all of the Objective-C interface declarations that we find in
Douglas Gregor49c22a72009-11-18 16:26:39 +00006603/// the given (translation unit) context.
6604static void AddInterfaceResults(DeclContext *Ctx, DeclContext *CurContext,
6605 bool OnlyForwardDeclarations,
6606 bool OnlyUnimplemented,
6607 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00006608 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006609
Aaron Ballman629afae2014-03-07 19:56:05 +00006610 for (const auto *D : Ctx->decls()) {
Douglas Gregor1c283312010-08-11 12:19:30 +00006611 // Record any interfaces we find.
Aaron Ballman629afae2014-03-07 19:56:05 +00006612 if (const auto *Class = dyn_cast<ObjCInterfaceDecl>(D))
Douglas Gregordc9166c2011-12-15 20:29:51 +00006613 if ((!OnlyForwardDeclarations || !Class->hasDefinition()) &&
Douglas Gregor1c283312010-08-11 12:19:30 +00006614 (!OnlyUnimplemented || !Class->getImplementation()))
Craig Topperc3ec1492014-05-26 06:22:03 +00006615 Results.AddResult(Result(Class, Results.getBasePriority(Class),nullptr),
6616 CurContext, nullptr, false);
Douglas Gregor49c22a72009-11-18 16:26:39 +00006617 }
6618}
6619
Eric Liuf5ba09f2018-07-04 10:01:18 +00006620void Sema::CodeCompleteObjCInterfaceDecl(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006621 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006622 CodeCompleter->getCodeCompletionTUInfo(),
Eric Liuf5ba09f2018-07-04 10:01:18 +00006623 CodeCompletionContext::CCC_ObjCInterfaceName);
Douglas Gregor49c22a72009-11-18 16:26:39 +00006624 Results.EnterNewScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00006625
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006626 if (CodeCompleter->includeGlobals()) {
6627 // Add all classes.
6628 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
6629 false, Results);
6630 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006631
Douglas Gregor49c22a72009-11-18 16:26:39 +00006632 Results.ExitScope();
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006633
Eric Liuf5ba09f2018-07-04 10:01:18 +00006634 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6635 Results.data(), Results.size());
Douglas Gregor49c22a72009-11-18 16:26:39 +00006636}
6637
Douglas Gregorb2ccf012010-04-15 22:33:43 +00006638void Sema::CodeCompleteObjCSuperclass(Scope *S, IdentifierInfo *ClassName,
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006639 SourceLocation ClassNameLoc) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006640 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006641 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006642 CodeCompletionContext::CCC_ObjCInterfaceName);
Douglas Gregor49c22a72009-11-18 16:26:39 +00006643 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006644
Douglas Gregor49c22a72009-11-18 16:26:39 +00006645 // Make sure that we ignore the class we're currently defining.
6646 NamedDecl *CurClass
Douglas Gregorb2ccf012010-04-15 22:33:43 +00006647 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006648 if (CurClass && isa<ObjCInterfaceDecl>(CurClass))
Douglas Gregor49c22a72009-11-18 16:26:39 +00006649 Results.Ignore(CurClass);
6650
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006651 if (CodeCompleter->includeGlobals()) {
6652 // Add all classes.
6653 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
6654 false, Results);
6655 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006656
Douglas Gregor49c22a72009-11-18 16:26:39 +00006657 Results.ExitScope();
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006658
Eric Liuf5ba09f2018-07-04 10:01:18 +00006659 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6660 Results.data(), Results.size());
Douglas Gregor49c22a72009-11-18 16:26:39 +00006661}
6662
Eric Liuf5ba09f2018-07-04 10:01:18 +00006663void Sema::CodeCompleteObjCImplementationDecl(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006664 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006665 CodeCompleter->getCodeCompletionTUInfo(),
Eric Liuf5ba09f2018-07-04 10:01:18 +00006666 CodeCompletionContext::CCC_ObjCImplementation);
Douglas Gregor49c22a72009-11-18 16:26:39 +00006667 Results.EnterNewScope();
6668
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006669 if (CodeCompleter->includeGlobals()) {
6670 // Add all unimplemented classes.
6671 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
6672 true, Results);
6673 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006674
Douglas Gregor49c22a72009-11-18 16:26:39 +00006675 Results.ExitScope();
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006676
Eric Liuf5ba09f2018-07-04 10:01:18 +00006677 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6678 Results.data(), Results.size());
Douglas Gregor49c22a72009-11-18 16:26:39 +00006679}
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006680
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006681void Sema::CodeCompleteObjCInterfaceCategory(Scope *S,
Douglas Gregorb2ccf012010-04-15 22:33:43 +00006682 IdentifierInfo *ClassName,
6683 SourceLocation ClassNameLoc) {
John McCall276321a2010-08-25 06:19:51 +00006684 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006685
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006686 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006687 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor21325842011-07-07 16:03:39 +00006688 CodeCompletionContext::CCC_ObjCCategoryName);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006689
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006690 // Ignore any categories we find that have already been implemented by this
6691 // interface.
6692 llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
6693 NamedDecl *CurClass
Douglas Gregorb2ccf012010-04-15 22:33:43 +00006694 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006695 if (ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass)){
Aaron Ballman3fe486a2014-03-13 21:23:55 +00006696 for (const auto *Cat : Class->visible_categories())
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006697 CategoryNames.insert(Cat->getIdentifier());
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006698 }
6699
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006700 // Add all of the categories we know about.
6701 Results.EnterNewScope();
6702 TranslationUnitDecl *TU = Context.getTranslationUnitDecl();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006703 for (const auto *D : TU->decls())
Aaron Ballman629afae2014-03-07 19:56:05 +00006704 if (const auto *Category = dyn_cast<ObjCCategoryDecl>(D))
David Blaikie82e95a32014-11-19 07:49:47 +00006705 if (CategoryNames.insert(Category->getIdentifier()).second)
Craig Topperc3ec1492014-05-26 06:22:03 +00006706 Results.AddResult(Result(Category, Results.getBasePriority(Category),
6707 nullptr),
6708 CurContext, nullptr, false);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006709 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00006710
6711 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6712 Results.data(), Results.size());
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006713}
6714
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006715void Sema::CodeCompleteObjCImplementationCategory(Scope *S,
Douglas Gregorb2ccf012010-04-15 22:33:43 +00006716 IdentifierInfo *ClassName,
6717 SourceLocation ClassNameLoc) {
John McCall276321a2010-08-25 06:19:51 +00006718 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006719
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006720 // Find the corresponding interface. If we couldn't find the interface, the
6721 // program itself is ill-formed. However, we'll try to be helpful still by
6722 // providing the list of all of the categories we know about.
6723 NamedDecl *CurClass
Douglas Gregorb2ccf012010-04-15 22:33:43 +00006724 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006725 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass);
6726 if (!Class)
Douglas Gregorb2ccf012010-04-15 22:33:43 +00006727 return CodeCompleteObjCInterfaceCategory(S, ClassName, ClassNameLoc);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006728
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006729 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006730 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor21325842011-07-07 16:03:39 +00006731 CodeCompletionContext::CCC_ObjCCategoryName);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006732
6733 // Add all of the categories that have have corresponding interface
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006734 // declarations in this class and any of its superclasses, except for
6735 // already-implemented categories in the class itself.
6736 llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
6737 Results.EnterNewScope();
6738 bool IgnoreImplemented = true;
6739 while (Class) {
Aaron Ballman3fe486a2014-03-13 21:23:55 +00006740 for (const auto *Cat : Class->visible_categories()) {
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006741 if ((!IgnoreImplemented || !Cat->getImplementation()) &&
David Blaikie82e95a32014-11-19 07:49:47 +00006742 CategoryNames.insert(Cat->getIdentifier()).second)
Craig Topperc3ec1492014-05-26 06:22:03 +00006743 Results.AddResult(Result(Cat, Results.getBasePriority(Cat), nullptr),
6744 CurContext, nullptr, false);
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006745 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006746
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006747 Class = Class->getSuperClass();
6748 IgnoreImplemented = false;
6749 }
6750 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00006751
6752 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6753 Results.data(), Results.size());
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006754}
Douglas Gregor5d649882009-11-18 22:32:06 +00006755
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00006756void Sema::CodeCompleteObjCPropertyDefinition(Scope *S) {
Douglas Gregorc3425b12015-07-07 06:20:19 +00006757 CodeCompletionContext CCContext(CodeCompletionContext::CCC_Other);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006758 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006759 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorc3425b12015-07-07 06:20:19 +00006760 CCContext);
Douglas Gregor5d649882009-11-18 22:32:06 +00006761
6762 // Figure out where this @synthesize lives.
6763 ObjCContainerDecl *Container
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00006764 = dyn_cast_or_null<ObjCContainerDecl>(CurContext);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006765 if (!Container ||
6766 (!isa<ObjCImplementationDecl>(Container) &&
Douglas Gregor5d649882009-11-18 22:32:06 +00006767 !isa<ObjCCategoryImplDecl>(Container)))
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006768 return;
Douglas Gregor5d649882009-11-18 22:32:06 +00006769
6770 // Ignore any properties that have already been implemented.
Douglas Gregor9b4f3702012-06-12 13:44:08 +00006771 Container = getContainerDef(Container);
Aaron Ballman629afae2014-03-07 19:56:05 +00006772 for (const auto *D : Container->decls())
6773 if (const auto *PropertyImpl = dyn_cast<ObjCPropertyImplDecl>(D))
Douglas Gregor5d649882009-11-18 22:32:06 +00006774 Results.Ignore(PropertyImpl->getPropertyDecl());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006775
Douglas Gregor5d649882009-11-18 22:32:06 +00006776 // Add any properties that we find.
Douglas Gregorb888acf2010-12-09 23:01:55 +00006777 AddedPropertiesSet AddedProperties;
Douglas Gregor5d649882009-11-18 22:32:06 +00006778 Results.EnterNewScope();
6779 if (ObjCImplementationDecl *ClassImpl
6780 = dyn_cast<ObjCImplementationDecl>(Container))
Douglas Gregorc3425b12015-07-07 06:20:19 +00006781 AddObjCProperties(CCContext, ClassImpl->getClassInterface(), false,
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006782 /*AllowNullaryMethods=*/false, CurContext,
Douglas Gregorb888acf2010-12-09 23:01:55 +00006783 AddedProperties, Results);
Douglas Gregor5d649882009-11-18 22:32:06 +00006784 else
Douglas Gregorc3425b12015-07-07 06:20:19 +00006785 AddObjCProperties(CCContext,
6786 cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl(),
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006787 false, /*AllowNullaryMethods=*/false, CurContext,
Douglas Gregor95147142011-05-05 15:50:42 +00006788 AddedProperties, Results);
Douglas Gregor5d649882009-11-18 22:32:06 +00006789 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00006790
6791 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6792 Results.data(), Results.size());
Douglas Gregor5d649882009-11-18 22:32:06 +00006793}
6794
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006795void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S,
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00006796 IdentifierInfo *PropertyName) {
John McCall276321a2010-08-25 06:19:51 +00006797 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006798 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006799 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006800 CodeCompletionContext::CCC_Other);
Douglas Gregor5d649882009-11-18 22:32:06 +00006801
6802 // Figure out where this @synthesize lives.
6803 ObjCContainerDecl *Container
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00006804 = dyn_cast_or_null<ObjCContainerDecl>(CurContext);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006805 if (!Container ||
6806 (!isa<ObjCImplementationDecl>(Container) &&
Douglas Gregor5d649882009-11-18 22:32:06 +00006807 !isa<ObjCCategoryImplDecl>(Container)))
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006808 return;
6809
Douglas Gregor5d649882009-11-18 22:32:06 +00006810 // Figure out which interface we're looking into.
Craig Topperc3ec1492014-05-26 06:22:03 +00006811 ObjCInterfaceDecl *Class = nullptr;
Douglas Gregor5d649882009-11-18 22:32:06 +00006812 if (ObjCImplementationDecl *ClassImpl
Manman Ren5b786402016-01-28 18:49:28 +00006813 = dyn_cast<ObjCImplementationDecl>(Container))
Douglas Gregor5d649882009-11-18 22:32:06 +00006814 Class = ClassImpl->getClassInterface();
6815 else
6816 Class = cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl()
6817 ->getClassInterface();
6818
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006819 // Determine the type of the property we're synthesizing.
6820 QualType PropertyType = Context.getObjCIdType();
6821 if (Class) {
Manman Ren5b786402016-01-28 18:49:28 +00006822 if (ObjCPropertyDecl *Property = Class->FindPropertyDeclaration(
6823 PropertyName, ObjCPropertyQueryKind::OBJC_PR_query_instance)) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006824 PropertyType
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006825 = Property->getType().getNonReferenceType().getUnqualifiedType();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006826
6827 // Give preference to ivars
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006828 Results.setPreferredType(PropertyType);
6829 }
6830 }
6831
Douglas Gregor5d649882009-11-18 22:32:06 +00006832 // Add all of the instance variables in this class and its superclasses.
6833 Results.EnterNewScope();
Douglas Gregor331faa02011-04-18 14:13:53 +00006834 bool SawSimilarlyNamedIvar = false;
6835 std::string NameWithPrefix;
6836 NameWithPrefix += '_';
Benjamin Kramer632500c2011-07-26 16:59:25 +00006837 NameWithPrefix += PropertyName->getName();
Douglas Gregor331faa02011-04-18 14:13:53 +00006838 std::string NameWithSuffix = PropertyName->getName().str();
6839 NameWithSuffix += '_';
Douglas Gregor5d649882009-11-18 22:32:06 +00006840 for(; Class; Class = Class->getSuperClass()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006841 for (ObjCIvarDecl *Ivar = Class->all_declared_ivar_begin(); Ivar;
Douglas Gregor331faa02011-04-18 14:13:53 +00006842 Ivar = Ivar->getNextIvar()) {
Craig Topperc3ec1492014-05-26 06:22:03 +00006843 Results.AddResult(Result(Ivar, Results.getBasePriority(Ivar), nullptr),
6844 CurContext, nullptr, false);
6845
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006846 // Determine whether we've seen an ivar with a name similar to the
Douglas Gregor331faa02011-04-18 14:13:53 +00006847 // property.
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006848 if ((PropertyName == Ivar->getIdentifier() ||
Douglas Gregor331faa02011-04-18 14:13:53 +00006849 NameWithPrefix == Ivar->getName() ||
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006850 NameWithSuffix == Ivar->getName())) {
Douglas Gregor331faa02011-04-18 14:13:53 +00006851 SawSimilarlyNamedIvar = true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006852
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006853 // Reduce the priority of this result by one, to give it a slight
6854 // advantage over other results whose names don't match so closely.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006855 if (Results.size() &&
6856 Results.data()[Results.size() - 1].Kind
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006857 == CodeCompletionResult::RK_Declaration &&
6858 Results.data()[Results.size() - 1].Declaration == Ivar)
6859 Results.data()[Results.size() - 1].Priority--;
6860 }
Douglas Gregor331faa02011-04-18 14:13:53 +00006861 }
Douglas Gregor5d649882009-11-18 22:32:06 +00006862 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006863
Douglas Gregor331faa02011-04-18 14:13:53 +00006864 if (!SawSimilarlyNamedIvar) {
6865 // Create ivar result _propName, that the user can use to synthesize
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006866 // an ivar of the appropriate type.
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006867 unsigned Priority = CCP_MemberDeclaration + 1;
Douglas Gregor331faa02011-04-18 14:13:53 +00006868 typedef CodeCompletionResult Result;
6869 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006870 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo(),
6871 Priority,CXAvailability_Available);
Douglas Gregor331faa02011-04-18 14:13:53 +00006872
Douglas Gregor75acd922011-09-27 23:30:47 +00006873 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006874 Builder.AddResultTypeChunk(GetCompletionTypeString(PropertyType, Context,
Douglas Gregor75acd922011-09-27 23:30:47 +00006875 Policy, Allocator));
Douglas Gregor331faa02011-04-18 14:13:53 +00006876 Builder.AddTypedTextChunk(Allocator.CopyString(NameWithPrefix));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006877 Results.AddResult(Result(Builder.TakeString(), Priority,
Douglas Gregor331faa02011-04-18 14:13:53 +00006878 CXCursor_ObjCIvarDecl));
6879 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006880
Douglas Gregor5d649882009-11-18 22:32:06 +00006881 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00006882
6883 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6884 Results.data(), Results.size());
Douglas Gregor5d649882009-11-18 22:32:06 +00006885}
Douglas Gregor636a61e2010-04-07 00:21:17 +00006886
Douglas Gregor416b5752010-08-25 01:08:01 +00006887// Mapping from selectors to the methods that implement that selector, along
6888// with the "in original class" flag.
Benjamin Kramereb8c4462013-06-29 17:52:13 +00006889typedef llvm::DenseMap<
6890 Selector, llvm::PointerIntPair<ObjCMethodDecl *, 1, bool> > KnownMethodsMap;
Douglas Gregor636a61e2010-04-07 00:21:17 +00006891
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006892/// Find all of the methods that reside in the given container
Douglas Gregor636a61e2010-04-07 00:21:17 +00006893/// (and its superclasses, protocols, etc.) that meet the given
6894/// criteria. Insert those methods into the map of known methods,
6895/// indexed by selector so they can be easily found.
6896static void FindImplementableMethods(ASTContext &Context,
6897 ObjCContainerDecl *Container,
Alex Lorenzb8740422017-10-24 16:39:37 +00006898 Optional<bool> WantInstanceMethods,
Douglas Gregor636a61e2010-04-07 00:21:17 +00006899 QualType ReturnType,
Douglas Gregor416b5752010-08-25 01:08:01 +00006900 KnownMethodsMap &KnownMethods,
6901 bool InOriginalClass = true) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00006902 if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)) {
Douglas Gregor9b4f3702012-06-12 13:44:08 +00006903 // Make sure we have a definition; that's what we'll walk.
Douglas Gregorc0ac7d62011-12-15 05:27:12 +00006904 if (!IFace->hasDefinition())
6905 return;
Douglas Gregor9b4f3702012-06-12 13:44:08 +00006906
6907 IFace = IFace->getDefinition();
6908 Container = IFace;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006909
Douglas Gregor636a61e2010-04-07 00:21:17 +00006910 const ObjCList<ObjCProtocolDecl> &Protocols
6911 = IFace->getReferencedProtocols();
6912 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006913 E = Protocols.end();
Douglas Gregor636a61e2010-04-07 00:21:17 +00006914 I != E; ++I)
6915 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006916 KnownMethods, InOriginalClass);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006917
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006918 // Add methods from any class extensions and categories.
Aaron Ballman3fe486a2014-03-13 21:23:55 +00006919 for (auto *Cat : IFace->visible_categories()) {
6920 FindImplementableMethods(Context, Cat, WantInstanceMethods, ReturnType,
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006921 KnownMethods, false);
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006922 }
6923
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006924 // Visit the superclass.
6925 if (IFace->getSuperClass())
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006926 FindImplementableMethods(Context, IFace->getSuperClass(),
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006927 WantInstanceMethods, ReturnType,
6928 KnownMethods, false);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006929 }
6930
6931 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(Container)) {
6932 // Recurse into protocols.
6933 const ObjCList<ObjCProtocolDecl> &Protocols
6934 = Category->getReferencedProtocols();
6935 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006936 E = Protocols.end();
Douglas Gregor636a61e2010-04-07 00:21:17 +00006937 I != E; ++I)
6938 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006939 KnownMethods, InOriginalClass);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006940
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006941 // If this category is the original class, jump to the interface.
6942 if (InOriginalClass && Category->getClassInterface())
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006943 FindImplementableMethods(Context, Category->getClassInterface(),
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006944 WantInstanceMethods, ReturnType, KnownMethods,
6945 false);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006946 }
6947
6948 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Douglas Gregor9b4f3702012-06-12 13:44:08 +00006949 // Make sure we have a definition; that's what we'll walk.
6950 if (!Protocol->hasDefinition())
6951 return;
6952 Protocol = Protocol->getDefinition();
6953 Container = Protocol;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006954
Douglas Gregor9b4f3702012-06-12 13:44:08 +00006955 // Recurse into protocols.
6956 const ObjCList<ObjCProtocolDecl> &Protocols
6957 = Protocol->getReferencedProtocols();
6958 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006959 E = Protocols.end();
Douglas Gregor9b4f3702012-06-12 13:44:08 +00006960 I != E; ++I)
6961 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
6962 KnownMethods, false);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006963 }
6964
6965 // Add methods in this container. This operation occurs last because
6966 // we want the methods from this container to override any methods
6967 // we've previously seen with the same selector.
Aaron Ballmanaff18c02014-03-13 19:03:34 +00006968 for (auto *M : Container->methods()) {
Alex Lorenzb8740422017-10-24 16:39:37 +00006969 if (!WantInstanceMethods || M->isInstanceMethod() == *WantInstanceMethods) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00006970 if (!ReturnType.isNull() &&
Alp Toker314cc812014-01-25 16:55:45 +00006971 !Context.hasSameUnqualifiedType(ReturnType, M->getReturnType()))
Douglas Gregor636a61e2010-04-07 00:21:17 +00006972 continue;
6973
Benjamin Kramereb8c4462013-06-29 17:52:13 +00006974 KnownMethods[M->getSelector()] =
Aaron Ballmanaff18c02014-03-13 19:03:34 +00006975 KnownMethodsMap::mapped_type(M, InOriginalClass);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006976 }
6977 }
6978}
6979
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006980/// Add the parenthesized return or parameter type chunk to a code
Douglas Gregor669a25a2011-02-17 00:22:45 +00006981/// completion string.
6982static void AddObjCPassingTypeChunk(QualType Type,
Douglas Gregor29979142012-04-10 18:35:07 +00006983 unsigned ObjCDeclQuals,
Douglas Gregor669a25a2011-02-17 00:22:45 +00006984 ASTContext &Context,
Douglas Gregor75acd922011-09-27 23:30:47 +00006985 const PrintingPolicy &Policy,
Douglas Gregor669a25a2011-02-17 00:22:45 +00006986 CodeCompletionBuilder &Builder) {
6987 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregor86b42682015-06-19 18:27:52 +00006988 std::string Quals = formatObjCParamQualifiers(ObjCDeclQuals, Type);
Douglas Gregor29979142012-04-10 18:35:07 +00006989 if (!Quals.empty())
6990 Builder.AddTextChunk(Builder.getAllocator().CopyString(Quals));
Douglas Gregor75acd922011-09-27 23:30:47 +00006991 Builder.AddTextChunk(GetCompletionTypeString(Type, Context, Policy,
Douglas Gregor669a25a2011-02-17 00:22:45 +00006992 Builder.getAllocator()));
6993 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6994}
6995
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006996/// Determine whether the given class is or inherits from a class by
Douglas Gregor669a25a2011-02-17 00:22:45 +00006997/// the given name.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006998static bool InheritsFromClassNamed(ObjCInterfaceDecl *Class,
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006999 StringRef Name) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007000 if (!Class)
7001 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007002
Douglas Gregor669a25a2011-02-17 00:22:45 +00007003 if (Class->getIdentifier() && Class->getIdentifier()->getName() == Name)
7004 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007005
Douglas Gregor669a25a2011-02-17 00:22:45 +00007006 return InheritsFromClassNamed(Class->getSuperClass(), Name);
7007}
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007008
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007009/// Add code completions for Objective-C Key-Value Coding (KVC) and
Douglas Gregor669a25a2011-02-17 00:22:45 +00007010/// Key-Value Observing (KVO).
7011static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
7012 bool IsInstanceMethod,
7013 QualType ReturnType,
7014 ASTContext &Context,
Douglas Gregord4a8ced2011-05-04 23:50:46 +00007015 VisitedSelectorSet &KnownSelectors,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007016 ResultBuilder &Results) {
7017 IdentifierInfo *PropName = Property->getIdentifier();
7018 if (!PropName || PropName->getLength() == 0)
7019 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007020
Douglas Gregor75acd922011-09-27 23:30:47 +00007021 PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema());
7022
Douglas Gregor669a25a2011-02-17 00:22:45 +00007023 // Builder that will create each code completion.
7024 typedef CodeCompletionResult Result;
7025 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007026 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007027
Douglas Gregor669a25a2011-02-17 00:22:45 +00007028 // The selector table.
7029 SelectorTable &Selectors = Context.Selectors;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007030
Douglas Gregor669a25a2011-02-17 00:22:45 +00007031 // The property name, copied into the code completion allocation region
7032 // on demand.
7033 struct KeyHolder {
7034 CodeCompletionAllocator &Allocator;
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007035 StringRef Key;
Douglas Gregor669a25a2011-02-17 00:22:45 +00007036 const char *CopiedKey;
Craig Topperc3ec1492014-05-26 06:22:03 +00007037
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007038 KeyHolder(CodeCompletionAllocator &Allocator, StringRef Key)
Craig Topperc3ec1492014-05-26 06:22:03 +00007039 : Allocator(Allocator), Key(Key), CopiedKey(nullptr) {}
7040
Douglas Gregor669a25a2011-02-17 00:22:45 +00007041 operator const char *() {
7042 if (CopiedKey)
7043 return CopiedKey;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007044
Douglas Gregor669a25a2011-02-17 00:22:45 +00007045 return CopiedKey = Allocator.CopyString(Key);
7046 }
7047 } Key(Allocator, PropName->getName());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007048
Douglas Gregor669a25a2011-02-17 00:22:45 +00007049 // The uppercased name of the property name.
7050 std::string UpperKey = PropName->getName();
7051 if (!UpperKey.empty())
Jordan Rose4938f272013-02-09 10:09:43 +00007052 UpperKey[0] = toUppercase(UpperKey[0]);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007053
Douglas Gregor669a25a2011-02-17 00:22:45 +00007054 bool ReturnTypeMatchesProperty = ReturnType.isNull() ||
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007055 Context.hasSameUnqualifiedType(ReturnType.getNonReferenceType(),
Douglas Gregor669a25a2011-02-17 00:22:45 +00007056 Property->getType());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007057 bool ReturnTypeMatchesVoid
Douglas Gregor669a25a2011-02-17 00:22:45 +00007058 = ReturnType.isNull() || ReturnType->isVoidType();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007059
Douglas Gregor669a25a2011-02-17 00:22:45 +00007060 // Add the normal accessor -(type)key.
7061 if (IsInstanceMethod &&
David Blaikie82e95a32014-11-19 07:49:47 +00007062 KnownSelectors.insert(Selectors.getNullarySelector(PropName)).second &&
Douglas Gregor669a25a2011-02-17 00:22:45 +00007063 ReturnTypeMatchesProperty && !Property->getGetterMethodDecl()) {
7064 if (ReturnType.isNull())
Douglas Gregor29979142012-04-10 18:35:07 +00007065 AddObjCPassingTypeChunk(Property->getType(), /*Quals=*/0,
7066 Context, Policy, Builder);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007067
Douglas Gregor669a25a2011-02-17 00:22:45 +00007068 Builder.AddTypedTextChunk(Key);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007069 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007070 CXCursor_ObjCInstanceMethodDecl));
7071 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007072
Douglas Gregor669a25a2011-02-17 00:22:45 +00007073 // If we have an integral or boolean property (or the user has provided
7074 // an integral or boolean return type), add the accessor -(type)isKey.
7075 if (IsInstanceMethod &&
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007076 ((!ReturnType.isNull() &&
Douglas Gregor669a25a2011-02-17 00:22:45 +00007077 (ReturnType->isIntegerType() || ReturnType->isBooleanType())) ||
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007078 (ReturnType.isNull() &&
7079 (Property->getType()->isIntegerType() ||
Douglas Gregor669a25a2011-02-17 00:22:45 +00007080 Property->getType()->isBooleanType())))) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007081 std::string SelectorName = (Twine("is") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007082 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007083 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
7084 .second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007085 if (ReturnType.isNull()) {
7086 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7087 Builder.AddTextChunk("BOOL");
7088 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7089 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007090
Douglas Gregor669a25a2011-02-17 00:22:45 +00007091 Builder.AddTypedTextChunk(
7092 Allocator.CopyString(SelectorId->getName()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007093 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007094 CXCursor_ObjCInstanceMethodDecl));
7095 }
7096 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007097
Douglas Gregor669a25a2011-02-17 00:22:45 +00007098 // Add the normal mutator.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007099 if (IsInstanceMethod && ReturnTypeMatchesVoid &&
Douglas Gregor669a25a2011-02-17 00:22:45 +00007100 !Property->getSetterMethodDecl()) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007101 std::string SelectorName = (Twine("set") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007102 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007103 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007104 if (ReturnType.isNull()) {
7105 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7106 Builder.AddTextChunk("void");
7107 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7108 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007109
Douglas Gregor669a25a2011-02-17 00:22:45 +00007110 Builder.AddTypedTextChunk(
7111 Allocator.CopyString(SelectorId->getName()));
7112 Builder.AddTypedTextChunk(":");
Douglas Gregor29979142012-04-10 18:35:07 +00007113 AddObjCPassingTypeChunk(Property->getType(), /*Quals=*/0,
7114 Context, Policy, Builder);
Douglas Gregor669a25a2011-02-17 00:22:45 +00007115 Builder.AddTextChunk(Key);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007116 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007117 CXCursor_ObjCInstanceMethodDecl));
7118 }
7119 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007120
Douglas Gregor669a25a2011-02-17 00:22:45 +00007121 // Indexed and unordered accessors
7122 unsigned IndexedGetterPriority = CCP_CodePattern;
7123 unsigned IndexedSetterPriority = CCP_CodePattern;
7124 unsigned UnorderedGetterPriority = CCP_CodePattern;
7125 unsigned UnorderedSetterPriority = CCP_CodePattern;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007126 if (const ObjCObjectPointerType *ObjCPointer
Douglas Gregor669a25a2011-02-17 00:22:45 +00007127 = Property->getType()->getAs<ObjCObjectPointerType>()) {
7128 if (ObjCInterfaceDecl *IFace = ObjCPointer->getInterfaceDecl()) {
7129 // If this interface type is not provably derived from a known
7130 // collection, penalize the corresponding completions.
7131 if (!InheritsFromClassNamed(IFace, "NSMutableArray")) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007132 IndexedSetterPriority += CCD_ProbablyNotObjCCollection;
Douglas Gregor669a25a2011-02-17 00:22:45 +00007133 if (!InheritsFromClassNamed(IFace, "NSArray"))
7134 IndexedGetterPriority += CCD_ProbablyNotObjCCollection;
7135 }
7136
7137 if (!InheritsFromClassNamed(IFace, "NSMutableSet")) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007138 UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;
Douglas Gregor669a25a2011-02-17 00:22:45 +00007139 if (!InheritsFromClassNamed(IFace, "NSSet"))
7140 UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;
7141 }
7142 }
7143 } else {
7144 IndexedGetterPriority += CCD_ProbablyNotObjCCollection;
7145 IndexedSetterPriority += CCD_ProbablyNotObjCCollection;
7146 UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;
7147 UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;
7148 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007149
Douglas Gregor669a25a2011-02-17 00:22:45 +00007150 // Add -(NSUInteger)countOf<key>
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007151 if (IsInstanceMethod &&
Douglas Gregor669a25a2011-02-17 00:22:45 +00007152 (ReturnType.isNull() || ReturnType->isIntegerType())) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007153 std::string SelectorName = (Twine("countOf") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007154 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007155 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
7156 .second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007157 if (ReturnType.isNull()) {
7158 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7159 Builder.AddTextChunk("NSUInteger");
7160 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7161 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007162
Douglas Gregor669a25a2011-02-17 00:22:45 +00007163 Builder.AddTypedTextChunk(
7164 Allocator.CopyString(SelectorId->getName()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007165 Results.AddResult(Result(Builder.TakeString(),
7166 std::min(IndexedGetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007167 UnorderedGetterPriority),
7168 CXCursor_ObjCInstanceMethodDecl));
7169 }
7170 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007171
Douglas Gregor669a25a2011-02-17 00:22:45 +00007172 // Indexed getters
7173 // Add -(id)objectInKeyAtIndex:(NSUInteger)index
7174 if (IsInstanceMethod &&
7175 (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007176 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007177 = (Twine("objectIn") + UpperKey + "AtIndex").str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007178 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007179 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007180 if (ReturnType.isNull()) {
7181 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7182 Builder.AddTextChunk("id");
7183 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7184 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007185
Douglas Gregor669a25a2011-02-17 00:22:45 +00007186 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7187 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7188 Builder.AddTextChunk("NSUInteger");
7189 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7190 Builder.AddTextChunk("index");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007191 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007192 CXCursor_ObjCInstanceMethodDecl));
7193 }
7194 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007195
Douglas Gregor669a25a2011-02-17 00:22:45 +00007196 // Add -(NSArray *)keyAtIndexes:(NSIndexSet *)indexes
7197 if (IsInstanceMethod &&
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007198 (ReturnType.isNull() ||
Douglas Gregor669a25a2011-02-17 00:22:45 +00007199 (ReturnType->isObjCObjectPointerType() &&
7200 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
7201 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
7202 ->getName() == "NSArray"))) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007203 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007204 = (Twine(Property->getName()) + "AtIndexes").str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007205 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007206 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007207 if (ReturnType.isNull()) {
7208 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7209 Builder.AddTextChunk("NSArray *");
7210 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7211 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007212
Douglas Gregor669a25a2011-02-17 00:22:45 +00007213 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7214 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7215 Builder.AddTextChunk("NSIndexSet *");
7216 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7217 Builder.AddTextChunk("indexes");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007218 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007219 CXCursor_ObjCInstanceMethodDecl));
7220 }
7221 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007222
Douglas Gregor669a25a2011-02-17 00:22:45 +00007223 // Add -(void)getKey:(type **)buffer range:(NSRange)inRange
7224 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007225 std::string SelectorName = (Twine("get") + UpperKey).str();
Douglas Gregor669a25a2011-02-17 00:22:45 +00007226 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007227 &Context.Idents.get(SelectorName),
Douglas Gregor669a25a2011-02-17 00:22:45 +00007228 &Context.Idents.get("range")
7229 };
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007230
David Blaikie82e95a32014-11-19 07:49:47 +00007231 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007232 if (ReturnType.isNull()) {
7233 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7234 Builder.AddTextChunk("void");
7235 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7236 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007237
Douglas Gregor669a25a2011-02-17 00:22:45 +00007238 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7239 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7240 Builder.AddPlaceholderChunk("object-type");
7241 Builder.AddTextChunk(" **");
7242 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7243 Builder.AddTextChunk("buffer");
7244 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7245 Builder.AddTypedTextChunk("range:");
7246 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7247 Builder.AddTextChunk("NSRange");
7248 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7249 Builder.AddTextChunk("inRange");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007250 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007251 CXCursor_ObjCInstanceMethodDecl));
7252 }
7253 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007254
Douglas Gregor669a25a2011-02-17 00:22:45 +00007255 // Mutable indexed accessors
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007256
Douglas Gregor669a25a2011-02-17 00:22:45 +00007257 // - (void)insertObject:(type *)object inKeyAtIndex:(NSUInteger)index
7258 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007259 std::string SelectorName = (Twine("in") + UpperKey + "AtIndex").str();
Douglas Gregor669a25a2011-02-17 00:22:45 +00007260 IdentifierInfo *SelectorIds[2] = {
7261 &Context.Idents.get("insertObject"),
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007262 &Context.Idents.get(SelectorName)
Douglas Gregor669a25a2011-02-17 00:22:45 +00007263 };
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007264
David Blaikie82e95a32014-11-19 07:49:47 +00007265 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007266 if (ReturnType.isNull()) {
7267 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7268 Builder.AddTextChunk("void");
7269 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7270 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007271
Douglas Gregor669a25a2011-02-17 00:22:45 +00007272 Builder.AddTypedTextChunk("insertObject:");
7273 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7274 Builder.AddPlaceholderChunk("object-type");
7275 Builder.AddTextChunk(" *");
7276 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7277 Builder.AddTextChunk("object");
7278 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7279 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7280 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7281 Builder.AddPlaceholderChunk("NSUInteger");
7282 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7283 Builder.AddTextChunk("index");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007284 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007285 CXCursor_ObjCInstanceMethodDecl));
7286 }
7287 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007288
Douglas Gregor669a25a2011-02-17 00:22:45 +00007289 // - (void)insertKey:(NSArray *)array atIndexes:(NSIndexSet *)indexes
7290 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007291 std::string SelectorName = (Twine("insert") + UpperKey).str();
Douglas Gregor669a25a2011-02-17 00:22:45 +00007292 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007293 &Context.Idents.get(SelectorName),
Douglas Gregor669a25a2011-02-17 00:22:45 +00007294 &Context.Idents.get("atIndexes")
7295 };
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007296
David Blaikie82e95a32014-11-19 07:49:47 +00007297 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007298 if (ReturnType.isNull()) {
7299 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7300 Builder.AddTextChunk("void");
7301 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7302 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007303
Douglas Gregor669a25a2011-02-17 00:22:45 +00007304 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7305 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7306 Builder.AddTextChunk("NSArray *");
7307 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7308 Builder.AddTextChunk("array");
7309 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7310 Builder.AddTypedTextChunk("atIndexes:");
7311 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7312 Builder.AddPlaceholderChunk("NSIndexSet *");
7313 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7314 Builder.AddTextChunk("indexes");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007315 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007316 CXCursor_ObjCInstanceMethodDecl));
7317 }
7318 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007319
Douglas Gregor669a25a2011-02-17 00:22:45 +00007320 // -(void)removeObjectFromKeyAtIndex:(NSUInteger)index
7321 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007322 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007323 = (Twine("removeObjectFrom") + UpperKey + "AtIndex").str();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007324 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007325 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007326 if (ReturnType.isNull()) {
7327 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7328 Builder.AddTextChunk("void");
7329 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7330 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007331
Douglas Gregor669a25a2011-02-17 00:22:45 +00007332 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7333 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7334 Builder.AddTextChunk("NSUInteger");
7335 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7336 Builder.AddTextChunk("index");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007337 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007338 CXCursor_ObjCInstanceMethodDecl));
7339 }
7340 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007341
Douglas Gregor669a25a2011-02-17 00:22:45 +00007342 // -(void)removeKeyAtIndexes:(NSIndexSet *)indexes
7343 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007344 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007345 = (Twine("remove") + UpperKey + "AtIndexes").str();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007346 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007347 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007348 if (ReturnType.isNull()) {
7349 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7350 Builder.AddTextChunk("void");
7351 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7352 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007353
Douglas Gregor669a25a2011-02-17 00:22:45 +00007354 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7355 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7356 Builder.AddTextChunk("NSIndexSet *");
7357 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7358 Builder.AddTextChunk("indexes");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007359 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007360 CXCursor_ObjCInstanceMethodDecl));
7361 }
7362 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007363
Douglas Gregor669a25a2011-02-17 00:22:45 +00007364 // - (void)replaceObjectInKeyAtIndex:(NSUInteger)index withObject:(id)object
7365 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007366 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007367 = (Twine("replaceObjectIn") + UpperKey + "AtIndex").str();
Douglas Gregor669a25a2011-02-17 00:22:45 +00007368 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007369 &Context.Idents.get(SelectorName),
Douglas Gregor669a25a2011-02-17 00:22:45 +00007370 &Context.Idents.get("withObject")
7371 };
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007372
David Blaikie82e95a32014-11-19 07:49:47 +00007373 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007374 if (ReturnType.isNull()) {
7375 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7376 Builder.AddTextChunk("void");
7377 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7378 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007379
Douglas Gregor669a25a2011-02-17 00:22:45 +00007380 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7381 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7382 Builder.AddPlaceholderChunk("NSUInteger");
7383 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7384 Builder.AddTextChunk("index");
7385 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7386 Builder.AddTypedTextChunk("withObject:");
7387 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7388 Builder.AddTextChunk("id");
7389 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7390 Builder.AddTextChunk("object");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007391 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007392 CXCursor_ObjCInstanceMethodDecl));
7393 }
7394 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007395
Douglas Gregor669a25a2011-02-17 00:22:45 +00007396 // - (void)replaceKeyAtIndexes:(NSIndexSet *)indexes withKey:(NSArray *)array
7397 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007398 std::string SelectorName1
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007399 = (Twine("replace") + UpperKey + "AtIndexes").str();
7400 std::string SelectorName2 = (Twine("with") + UpperKey).str();
Douglas Gregor669a25a2011-02-17 00:22:45 +00007401 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007402 &Context.Idents.get(SelectorName1),
7403 &Context.Idents.get(SelectorName2)
Douglas Gregor669a25a2011-02-17 00:22:45 +00007404 };
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007405
David Blaikie82e95a32014-11-19 07:49:47 +00007406 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007407 if (ReturnType.isNull()) {
7408 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7409 Builder.AddTextChunk("void");
7410 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7411 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007412
Douglas Gregor669a25a2011-02-17 00:22:45 +00007413 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName1 + ":"));
7414 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7415 Builder.AddPlaceholderChunk("NSIndexSet *");
7416 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7417 Builder.AddTextChunk("indexes");
7418 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7419 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName2 + ":"));
7420 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7421 Builder.AddTextChunk("NSArray *");
7422 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7423 Builder.AddTextChunk("array");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007424 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007425 CXCursor_ObjCInstanceMethodDecl));
7426 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007427 }
7428
Douglas Gregor669a25a2011-02-17 00:22:45 +00007429 // Unordered getters
7430 // - (NSEnumerator *)enumeratorOfKey
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007431 if (IsInstanceMethod &&
7432 (ReturnType.isNull() ||
Douglas Gregor669a25a2011-02-17 00:22:45 +00007433 (ReturnType->isObjCObjectPointerType() &&
7434 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
7435 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
7436 ->getName() == "NSEnumerator"))) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007437 std::string SelectorName = (Twine("enumeratorOf") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007438 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007439 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
7440 .second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007441 if (ReturnType.isNull()) {
7442 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7443 Builder.AddTextChunk("NSEnumerator *");
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));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007448 Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007449 CXCursor_ObjCInstanceMethodDecl));
7450 }
7451 }
7452
7453 // - (type *)memberOfKey:(type *)object
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007454 if (IsInstanceMethod &&
Douglas Gregor669a25a2011-02-17 00:22:45 +00007455 (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007456 std::string SelectorName = (Twine("memberOf") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007457 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007458 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007459 if (ReturnType.isNull()) {
7460 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7461 Builder.AddPlaceholderChunk("object-type");
7462 Builder.AddTextChunk(" *");
7463 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7464 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007465
Douglas Gregor669a25a2011-02-17 00:22:45 +00007466 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7467 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7468 if (ReturnType.isNull()) {
7469 Builder.AddPlaceholderChunk("object-type");
7470 Builder.AddTextChunk(" *");
7471 } else {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007472 Builder.AddTextChunk(GetCompletionTypeString(ReturnType, Context,
Douglas Gregor75acd922011-09-27 23:30:47 +00007473 Policy,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007474 Builder.getAllocator()));
7475 }
7476 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7477 Builder.AddTextChunk("object");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007478 Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007479 CXCursor_ObjCInstanceMethodDecl));
7480 }
7481 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007482
Douglas Gregor669a25a2011-02-17 00:22:45 +00007483 // Mutable unordered accessors
7484 // - (void)addKeyObject:(type *)object
7485 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007486 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007487 = (Twine("add") + UpperKey + Twine("Object")).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007488 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007489 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007490 if (ReturnType.isNull()) {
7491 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7492 Builder.AddTextChunk("void");
7493 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7494 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007495
Douglas Gregor669a25a2011-02-17 00:22:45 +00007496 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7497 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7498 Builder.AddPlaceholderChunk("object-type");
7499 Builder.AddTextChunk(" *");
7500 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7501 Builder.AddTextChunk("object");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007502 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007503 CXCursor_ObjCInstanceMethodDecl));
7504 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007505 }
Douglas Gregor669a25a2011-02-17 00:22:45 +00007506
7507 // - (void)addKey:(NSSet *)objects
7508 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007509 std::string SelectorName = (Twine("add") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007510 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007511 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007512 if (ReturnType.isNull()) {
7513 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7514 Builder.AddTextChunk("void");
7515 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7516 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007517
Douglas Gregor669a25a2011-02-17 00:22:45 +00007518 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7519 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7520 Builder.AddTextChunk("NSSet *");
7521 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7522 Builder.AddTextChunk("objects");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007523 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007524 CXCursor_ObjCInstanceMethodDecl));
7525 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007526 }
7527
Douglas Gregor669a25a2011-02-17 00:22:45 +00007528 // - (void)removeKeyObject:(type *)object
7529 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007530 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007531 = (Twine("remove") + UpperKey + Twine("Object")).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007532 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007533 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007534 if (ReturnType.isNull()) {
7535 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7536 Builder.AddTextChunk("void");
7537 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7538 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007539
Douglas Gregor669a25a2011-02-17 00:22:45 +00007540 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7541 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7542 Builder.AddPlaceholderChunk("object-type");
7543 Builder.AddTextChunk(" *");
7544 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7545 Builder.AddTextChunk("object");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007546 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007547 CXCursor_ObjCInstanceMethodDecl));
7548 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007549 }
7550
Douglas Gregor669a25a2011-02-17 00:22:45 +00007551 // - (void)removeKey:(NSSet *)objects
7552 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007553 std::string SelectorName = (Twine("remove") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007554 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007555 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007556 if (ReturnType.isNull()) {
7557 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7558 Builder.AddTextChunk("void");
7559 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7560 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007561
Douglas Gregor669a25a2011-02-17 00:22:45 +00007562 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7563 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7564 Builder.AddTextChunk("NSSet *");
7565 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7566 Builder.AddTextChunk("objects");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007567 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007568 CXCursor_ObjCInstanceMethodDecl));
7569 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007570 }
Douglas Gregor669a25a2011-02-17 00:22:45 +00007571
7572 // - (void)intersectKey:(NSSet *)objects
7573 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007574 std::string SelectorName = (Twine("intersect") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007575 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007576 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007577 if (ReturnType.isNull()) {
7578 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7579 Builder.AddTextChunk("void");
7580 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7581 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007582
Douglas Gregor669a25a2011-02-17 00:22:45 +00007583 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7584 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7585 Builder.AddTextChunk("NSSet *");
7586 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7587 Builder.AddTextChunk("objects");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007588 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007589 CXCursor_ObjCInstanceMethodDecl));
7590 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007591 }
7592
Douglas Gregor669a25a2011-02-17 00:22:45 +00007593 // Key-Value Observing
7594 // + (NSSet *)keyPathsForValuesAffectingKey
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007595 if (!IsInstanceMethod &&
7596 (ReturnType.isNull() ||
Douglas Gregor669a25a2011-02-17 00:22:45 +00007597 (ReturnType->isObjCObjectPointerType() &&
7598 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
7599 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
7600 ->getName() == "NSSet"))) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007601 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007602 = (Twine("keyPathsForValuesAffecting") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007603 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007604 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
7605 .second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007606 if (ReturnType.isNull()) {
7607 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Alex Lorenz71ecb072016-12-08 16:49:05 +00007608 Builder.AddTextChunk("NSSet<NSString *> *");
Douglas Gregor669a25a2011-02-17 00:22:45 +00007609 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7610 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007611
Douglas Gregor669a25a2011-02-17 00:22:45 +00007612 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007613 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Douglas Gregor857bcda2011-06-02 04:02:27 +00007614 CXCursor_ObjCClassMethodDecl));
7615 }
7616 }
7617
7618 // + (BOOL)automaticallyNotifiesObserversForKey
7619 if (!IsInstanceMethod &&
7620 (ReturnType.isNull() ||
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007621 ReturnType->isIntegerType() ||
Douglas Gregor857bcda2011-06-02 04:02:27 +00007622 ReturnType->isBooleanType())) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007623 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007624 = (Twine("automaticallyNotifiesObserversOf") + UpperKey).str();
Douglas Gregor857bcda2011-06-02 04:02:27 +00007625 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007626 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
7627 .second) {
Douglas Gregor857bcda2011-06-02 04:02:27 +00007628 if (ReturnType.isNull()) {
7629 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7630 Builder.AddTextChunk("BOOL");
7631 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7632 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007633
Douglas Gregor857bcda2011-06-02 04:02:27 +00007634 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007635 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Douglas Gregor857bcda2011-06-02 04:02:27 +00007636 CXCursor_ObjCClassMethodDecl));
Douglas Gregor669a25a2011-02-17 00:22:45 +00007637 }
7638 }
7639}
7640
Alex Lorenzb8740422017-10-24 16:39:37 +00007641void Sema::CodeCompleteObjCMethodDecl(Scope *S, Optional<bool> IsInstanceMethod,
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00007642 ParsedType ReturnTy) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00007643 // Determine the return type of the method we're declaring, if
7644 // provided.
7645 QualType ReturnType = GetTypeFromParser(ReturnTy);
Craig Topperc3ec1492014-05-26 06:22:03 +00007646 Decl *IDecl = nullptr;
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00007647 if (CurContext->isObjCContainer()) {
7648 ObjCContainerDecl *OCD = dyn_cast<ObjCContainerDecl>(CurContext);
George Burgess IV00f70bd2018-03-01 05:43:23 +00007649 IDecl = OCD;
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00007650 }
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007651 // Determine where we should start searching for methods.
Craig Topperc3ec1492014-05-26 06:22:03 +00007652 ObjCContainerDecl *SearchDecl = nullptr;
Douglas Gregor636a61e2010-04-07 00:21:17 +00007653 bool IsInImplementation = false;
John McCall48871652010-08-21 09:40:31 +00007654 if (Decl *D = IDecl) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00007655 if (ObjCImplementationDecl *Impl = dyn_cast<ObjCImplementationDecl>(D)) {
7656 SearchDecl = Impl->getClassInterface();
Douglas Gregor636a61e2010-04-07 00:21:17 +00007657 IsInImplementation = true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007658 } else if (ObjCCategoryImplDecl *CatImpl
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007659 = dyn_cast<ObjCCategoryImplDecl>(D)) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00007660 SearchDecl = CatImpl->getCategoryDecl();
Douglas Gregor636a61e2010-04-07 00:21:17 +00007661 IsInImplementation = true;
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007662 } else
Douglas Gregor636a61e2010-04-07 00:21:17 +00007663 SearchDecl = dyn_cast<ObjCContainerDecl>(D);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007664 }
7665
7666 if (!SearchDecl && S) {
Ted Kremenekc37877d2013-10-08 17:08:03 +00007667 if (DeclContext *DC = S->getEntity())
Douglas Gregor636a61e2010-04-07 00:21:17 +00007668 SearchDecl = dyn_cast<ObjCContainerDecl>(DC);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007669 }
7670
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007671 if (!SearchDecl) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007672 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00007673 CodeCompletionContext::CCC_Other,
Craig Topperc3ec1492014-05-26 06:22:03 +00007674 nullptr, 0);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007675 return;
7676 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007677
Douglas Gregor636a61e2010-04-07 00:21:17 +00007678 // Find all of the methods that we could declare/implement here.
7679 KnownMethodsMap KnownMethods;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007680 FindImplementableMethods(Context, SearchDecl, IsInstanceMethod,
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007681 ReturnType, KnownMethods);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007682
Douglas Gregor636a61e2010-04-07 00:21:17 +00007683 // Add declarations or definitions for each of the known methods.
John McCall276321a2010-08-25 06:19:51 +00007684 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007685 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007686 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007687 CodeCompletionContext::CCC_Other);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007688 Results.EnterNewScope();
Douglas Gregor75acd922011-09-27 23:30:47 +00007689 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007690 for (KnownMethodsMap::iterator M = KnownMethods.begin(),
Douglas Gregor636a61e2010-04-07 00:21:17 +00007691 MEnd = KnownMethods.end();
7692 M != MEnd; ++M) {
Benjamin Kramereb8c4462013-06-29 17:52:13 +00007693 ObjCMethodDecl *Method = M->second.getPointer();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007694 CodeCompletionBuilder Builder(Results.getAllocator(),
7695 Results.getCodeCompletionTUInfo());
Alex Lorenzb8740422017-10-24 16:39:37 +00007696
7697 // Add the '-'/'+' prefix if it wasn't provided yet.
7698 if (!IsInstanceMethod) {
7699 Builder.AddTextChunk(Method->isInstanceMethod() ? "-" : "+");
7700 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7701 }
7702
Douglas Gregor636a61e2010-04-07 00:21:17 +00007703 // If the result type was not already provided, add it to the
7704 // pattern as (type).
Argyrios Kyrtzidisf0917ab2015-07-24 17:00:19 +00007705 if (ReturnType.isNull()) {
7706 QualType ResTy = Method->getSendResultType().stripObjCKindOfType(Context);
7707 AttributedType::stripOuterNullability(ResTy);
7708 AddObjCPassingTypeChunk(ResTy,
Alp Toker314cc812014-01-25 16:55:45 +00007709 Method->getObjCDeclQualifier(), Context, Policy,
7710 Builder);
Argyrios Kyrtzidisf0917ab2015-07-24 17:00:19 +00007711 }
Douglas Gregor636a61e2010-04-07 00:21:17 +00007712
7713 Selector Sel = Method->getSelector();
7714
7715 // Add the first part of the selector to the pattern.
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00007716 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00007717 Sel.getNameForSlot(0)));
Douglas Gregor636a61e2010-04-07 00:21:17 +00007718
7719 // Add parameters to the pattern.
7720 unsigned I = 0;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007721 for (ObjCMethodDecl::param_iterator P = Method->param_begin(),
Douglas Gregor636a61e2010-04-07 00:21:17 +00007722 PEnd = Method->param_end();
7723 P != PEnd; (void)++P, ++I) {
7724 // Add the part of the selector name.
7725 if (I == 0)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007726 Builder.AddTypedTextChunk(":");
Douglas Gregor636a61e2010-04-07 00:21:17 +00007727 else if (I < Sel.getNumArgs()) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007728 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7729 Builder.AddTypedTextChunk(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00007730 Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":"));
Douglas Gregor636a61e2010-04-07 00:21:17 +00007731 } else
7732 break;
7733
7734 // Add the parameter type.
Douglas Gregor86b42682015-06-19 18:27:52 +00007735 QualType ParamType;
7736 if ((*P)->getObjCDeclQualifier() & Decl::OBJC_TQ_CSNullability)
7737 ParamType = (*P)->getType();
7738 else
7739 ParamType = (*P)->getOriginalType();
Douglas Gregor9b7b3e92015-07-07 06:20:27 +00007740 ParamType = ParamType.substObjCTypeArgs(Context, {},
7741 ObjCSubstitutionContext::Parameter);
Argyrios Kyrtzidisf0917ab2015-07-24 17:00:19 +00007742 AttributedType::stripOuterNullability(ParamType);
Douglas Gregor86b42682015-06-19 18:27:52 +00007743 AddObjCPassingTypeChunk(ParamType,
Douglas Gregor29979142012-04-10 18:35:07 +00007744 (*P)->getObjCDeclQualifier(),
7745 Context, Policy,
Douglas Gregor75acd922011-09-27 23:30:47 +00007746 Builder);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007747
Douglas Gregor636a61e2010-04-07 00:21:17 +00007748 if (IdentifierInfo *Id = (*P)->getIdentifier())
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007749 Builder.AddTextChunk(Builder.getAllocator().CopyString( Id->getName()));
Douglas Gregor636a61e2010-04-07 00:21:17 +00007750 }
7751
7752 if (Method->isVariadic()) {
7753 if (Method->param_size() > 0)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007754 Builder.AddChunk(CodeCompletionString::CK_Comma);
7755 Builder.AddTextChunk("...");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007756 }
Douglas Gregor636a61e2010-04-07 00:21:17 +00007757
Douglas Gregord37c59d2010-05-28 00:57:46 +00007758 if (IsInImplementation && Results.includeCodePatterns()) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00007759 // We will be defining the method here, so add a compound statement.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007760 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7761 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
7762 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
Alp Toker314cc812014-01-25 16:55:45 +00007763 if (!Method->getReturnType()->isVoidType()) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00007764 // If the result type is not void, add a return clause.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007765 Builder.AddTextChunk("return");
7766 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7767 Builder.AddPlaceholderChunk("expression");
7768 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007769 } else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007770 Builder.AddPlaceholderChunk("statements");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007771
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007772 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
7773 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007774 }
7775
Douglas Gregor416b5752010-08-25 01:08:01 +00007776 unsigned Priority = CCP_CodePattern;
Eric Liu4a7cd632018-10-24 12:57:27 +00007777 auto R = Result(Builder.TakeString(), Method, Priority);
Benjamin Kramereb8c4462013-06-29 17:52:13 +00007778 if (!M->second.getInt())
Eric Liu4a7cd632018-10-24 12:57:27 +00007779 setInBaseClass(R);
7780 Results.AddResult(std::move(R));
Douglas Gregor636a61e2010-04-07 00:21:17 +00007781 }
7782
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007783 // Add Key-Value-Coding and Key-Value-Observing accessor methods for all of
Douglas Gregor669a25a2011-02-17 00:22:45 +00007784 // the properties in this class and its categories.
Erik Pilkingtonfa983902018-10-30 20:31:30 +00007785 if (Context.getLangOpts().ObjC) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007786 SmallVector<ObjCContainerDecl *, 4> Containers;
Douglas Gregor669a25a2011-02-17 00:22:45 +00007787 Containers.push_back(SearchDecl);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007788
Douglas Gregord4a8ced2011-05-04 23:50:46 +00007789 VisitedSelectorSet KnownSelectors;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007790 for (KnownMethodsMap::iterator M = KnownMethods.begin(),
Douglas Gregord4a8ced2011-05-04 23:50:46 +00007791 MEnd = KnownMethods.end();
7792 M != MEnd; ++M)
7793 KnownSelectors.insert(M->first);
7794
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007795
Douglas Gregor669a25a2011-02-17 00:22:45 +00007796 ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(SearchDecl);
7797 if (!IFace)
7798 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(SearchDecl))
7799 IFace = Category->getClassInterface();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007800
Aaron Ballman3fe486a2014-03-13 21:23:55 +00007801 if (IFace)
7802 for (auto *Cat : IFace->visible_categories())
7803 Containers.push_back(Cat);
Alex Lorenzb8740422017-10-24 16:39:37 +00007804
7805 if (IsInstanceMethod) {
7806 for (unsigned I = 0, N = Containers.size(); I != N; ++I)
7807 for (auto *P : Containers[I]->instance_properties())
7808 AddObjCKeyValueCompletions(P, *IsInstanceMethod, ReturnType, Context,
7809 KnownSelectors, Results);
7810 }
Douglas Gregor669a25a2011-02-17 00:22:45 +00007811 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007812
Douglas Gregor636a61e2010-04-07 00:21:17 +00007813 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00007814
7815 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
7816 Results.data(), Results.size());
Douglas Gregor636a61e2010-04-07 00:21:17 +00007817}
Douglas Gregor95887f92010-07-08 23:20:03 +00007818
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007819void Sema::CodeCompleteObjCMethodDeclSelector(Scope *S,
Douglas Gregor95887f92010-07-08 23:20:03 +00007820 bool IsInstanceMethod,
Douglas Gregor45879692010-07-08 23:37:41 +00007821 bool AtParameterName,
John McCallba7bf592010-08-24 05:47:05 +00007822 ParsedType ReturnTy,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00007823 ArrayRef<IdentifierInfo *> SelIdents) {
Douglas Gregor95887f92010-07-08 23:20:03 +00007824 // If we have an external source, load the entire class method
Sebastian Redld44cd6a2010-08-18 23:57:06 +00007825 // pool from the AST file.
Douglas Gregor95887f92010-07-08 23:20:03 +00007826 if (ExternalSource) {
7827 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
7828 I != N; ++I) {
7829 Selector Sel = ExternalSource->GetExternalSelector(I);
Sebastian Redl75d8a322010-08-02 23:18:59 +00007830 if (Sel.isNull() || MethodPool.count(Sel))
Douglas Gregor95887f92010-07-08 23:20:03 +00007831 continue;
Sebastian Redl75d8a322010-08-02 23:18:59 +00007832
7833 ReadMethodPool(Sel);
Douglas Gregor95887f92010-07-08 23:20:03 +00007834 }
7835 }
7836
7837 // Build the set of methods we can see.
John McCall276321a2010-08-25 06:19:51 +00007838 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007839 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007840 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007841 CodeCompletionContext::CCC_Other);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007842
Douglas Gregor95887f92010-07-08 23:20:03 +00007843 if (ReturnTy)
7844 Results.setPreferredType(GetTypeFromParser(ReturnTy).getNonReferenceType());
Sebastian Redl75d8a322010-08-02 23:18:59 +00007845
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007846 Results.EnterNewScope();
Sebastian Redl75d8a322010-08-02 23:18:59 +00007847 for (GlobalMethodPool::iterator M = MethodPool.begin(),
7848 MEnd = MethodPool.end();
7849 M != MEnd; ++M) {
7850 for (ObjCMethodList *MethList = IsInstanceMethod ? &M->second.first :
7851 &M->second.second;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007852 MethList && MethList->getMethod();
Argyrios Kyrtzidisd3da6e02013-04-17 00:08:58 +00007853 MethList = MethList->getNext()) {
Nico Weber2e0c8f72014-12-27 03:58:08 +00007854 if (!isAcceptableObjCMethod(MethList->getMethod(), MK_Any, SelIdents))
Douglas Gregor95887f92010-07-08 23:20:03 +00007855 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007856
Douglas Gregor45879692010-07-08 23:37:41 +00007857 if (AtParameterName) {
7858 // Suggest parameter names we've seen before.
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00007859 unsigned NumSelIdents = SelIdents.size();
Nico Weber2e0c8f72014-12-27 03:58:08 +00007860 if (NumSelIdents &&
7861 NumSelIdents <= MethList->getMethod()->param_size()) {
7862 ParmVarDecl *Param =
7863 MethList->getMethod()->parameters()[NumSelIdents - 1];
Douglas Gregor45879692010-07-08 23:37:41 +00007864 if (Param->getIdentifier()) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007865 CodeCompletionBuilder Builder(Results.getAllocator(),
7866 Results.getCodeCompletionTUInfo());
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00007867 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007868 Param->getIdentifier()->getName()));
7869 Results.AddResult(Builder.TakeString());
Douglas Gregor45879692010-07-08 23:37:41 +00007870 }
7871 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007872
Douglas Gregor45879692010-07-08 23:37:41 +00007873 continue;
7874 }
Craig Topperc3ec1492014-05-26 06:22:03 +00007875
Nico Weber2e0c8f72014-12-27 03:58:08 +00007876 Result R(MethList->getMethod(),
7877 Results.getBasePriority(MethList->getMethod()), nullptr);
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00007878 R.StartParameter = SelIdents.size();
Douglas Gregor95887f92010-07-08 23:20:03 +00007879 R.AllParametersAreInformative = false;
7880 R.DeclaringEntity = true;
7881 Results.MaybeAddResult(R, CurContext);
7882 }
7883 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007884
Douglas Gregor95887f92010-07-08 23:20:03 +00007885 Results.ExitScope();
Alex Lorenz847fda12017-01-03 11:56:40 +00007886
7887 if (!AtParameterName && !SelIdents.empty() &&
7888 SelIdents.front()->getName().startswith("init")) {
7889 for (const auto &M : PP.macros()) {
7890 if (M.first->getName() != "NS_DESIGNATED_INITIALIZER")
7891 continue;
7892 Results.EnterNewScope();
7893 CodeCompletionBuilder Builder(Results.getAllocator(),
7894 Results.getCodeCompletionTUInfo());
7895 Builder.AddTypedTextChunk(
7896 Builder.getAllocator().CopyString(M.first->getName()));
7897 Results.AddResult(CodeCompletionResult(Builder.TakeString(), CCP_Macro,
7898 CXCursor_MacroDefinition));
7899 Results.ExitScope();
7900 }
7901 }
7902
Eric Liuf5ba09f2018-07-04 10:01:18 +00007903 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
7904 Results.data(), Results.size());
Douglas Gregor95887f92010-07-08 23:20:03 +00007905}
Douglas Gregorb14904c2010-08-13 22:48:40 +00007906
Douglas Gregorec00a262010-08-24 22:20:20 +00007907void Sema::CodeCompletePreprocessorDirective(bool InConditional) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007908 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007909 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00007910 CodeCompletionContext::CCC_PreprocessorDirective);
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007911 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007912
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007913 // #if <condition>
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007914 CodeCompletionBuilder Builder(Results.getAllocator(),
7915 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007916 Builder.AddTypedTextChunk("if");
7917 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7918 Builder.AddPlaceholderChunk("condition");
7919 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007920
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007921 // #ifdef <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007922 Builder.AddTypedTextChunk("ifdef");
7923 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7924 Builder.AddPlaceholderChunk("macro");
7925 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007926
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007927 // #ifndef <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007928 Builder.AddTypedTextChunk("ifndef");
7929 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7930 Builder.AddPlaceholderChunk("macro");
7931 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007932
7933 if (InConditional) {
7934 // #elif <condition>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007935 Builder.AddTypedTextChunk("elif");
7936 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7937 Builder.AddPlaceholderChunk("condition");
7938 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007939
7940 // #else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007941 Builder.AddTypedTextChunk("else");
7942 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007943
7944 // #endif
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007945 Builder.AddTypedTextChunk("endif");
7946 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007947 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007948
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007949 // #include "header"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007950 Builder.AddTypedTextChunk("include");
7951 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7952 Builder.AddTextChunk("\"");
7953 Builder.AddPlaceholderChunk("header");
7954 Builder.AddTextChunk("\"");
7955 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007956
7957 // #include <header>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007958 Builder.AddTypedTextChunk("include");
7959 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7960 Builder.AddTextChunk("<");
7961 Builder.AddPlaceholderChunk("header");
7962 Builder.AddTextChunk(">");
7963 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007964
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007965 // #define <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007966 Builder.AddTypedTextChunk("define");
7967 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7968 Builder.AddPlaceholderChunk("macro");
7969 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007970
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007971 // #define <macro>(<args>)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007972 Builder.AddTypedTextChunk("define");
7973 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7974 Builder.AddPlaceholderChunk("macro");
7975 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7976 Builder.AddPlaceholderChunk("args");
7977 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7978 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007979
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007980 // #undef <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007981 Builder.AddTypedTextChunk("undef");
7982 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7983 Builder.AddPlaceholderChunk("macro");
7984 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007985
7986 // #line <number>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007987 Builder.AddTypedTextChunk("line");
7988 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7989 Builder.AddPlaceholderChunk("number");
7990 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007991
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007992 // #line <number> "filename"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007993 Builder.AddTypedTextChunk("line");
7994 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7995 Builder.AddPlaceholderChunk("number");
7996 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7997 Builder.AddTextChunk("\"");
7998 Builder.AddPlaceholderChunk("filename");
7999 Builder.AddTextChunk("\"");
8000 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008001
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008002 // #error <message>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008003 Builder.AddTypedTextChunk("error");
8004 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8005 Builder.AddPlaceholderChunk("message");
8006 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008007
8008 // #pragma <arguments>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008009 Builder.AddTypedTextChunk("pragma");
8010 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8011 Builder.AddPlaceholderChunk("arguments");
8012 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008013
Erik Pilkingtonfa983902018-10-30 20:31:30 +00008014 if (getLangOpts().ObjC) {
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008015 // #import "header"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008016 Builder.AddTypedTextChunk("import");
8017 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8018 Builder.AddTextChunk("\"");
8019 Builder.AddPlaceholderChunk("header");
8020 Builder.AddTextChunk("\"");
8021 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008022
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008023 // #import <header>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008024 Builder.AddTypedTextChunk("import");
8025 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8026 Builder.AddTextChunk("<");
8027 Builder.AddPlaceholderChunk("header");
8028 Builder.AddTextChunk(">");
8029 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008030 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008031
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008032 // #include_next "header"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008033 Builder.AddTypedTextChunk("include_next");
8034 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8035 Builder.AddTextChunk("\"");
8036 Builder.AddPlaceholderChunk("header");
8037 Builder.AddTextChunk("\"");
8038 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008039
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008040 // #include_next <header>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008041 Builder.AddTypedTextChunk("include_next");
8042 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8043 Builder.AddTextChunk("<");
8044 Builder.AddPlaceholderChunk("header");
8045 Builder.AddTextChunk(">");
8046 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008047
8048 // #warning <message>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008049 Builder.AddTypedTextChunk("warning");
8050 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8051 Builder.AddPlaceholderChunk("message");
8052 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008053
8054 // Note: #ident and #sccs are such crazy anachronisms that we don't provide
8055 // completions for them. And __include_macros is a Clang-internal extension
8056 // that we don't want to encourage anyone to use.
8057
8058 // FIXME: we don't support #assert or #unassert, so don't suggest them.
8059 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00008060
8061 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008062 Results.data(), Results.size());
8063}
8064
8065void Sema::CodeCompleteInPreprocessorConditionalExclusion(Scope *S) {
Douglas Gregorec00a262010-08-24 22:20:20 +00008066 CodeCompleteOrdinaryName(S,
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008067 S->getFnParent()? Sema::PCC_RecoveryInFunction
John McCallfaf5fb42010-08-26 23:41:50 +00008068 : Sema::PCC_Namespace);
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008069}
8070
Douglas Gregorec00a262010-08-24 22:20:20 +00008071void Sema::CodeCompletePreprocessorMacroName(bool IsDefinition) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008072 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008073 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00008074 IsDefinition? CodeCompletionContext::CCC_MacroName
8075 : CodeCompletionContext::CCC_MacroNameUse);
Douglas Gregor12785102010-08-24 20:21:13 +00008076 if (!IsDefinition && (!CodeCompleter || CodeCompleter->includeMacros())) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008077 // Add just the names of macros, not their arguments.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008078 CodeCompletionBuilder Builder(Results.getAllocator(),
8079 Results.getCodeCompletionTUInfo());
Douglas Gregor12785102010-08-24 20:21:13 +00008080 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008081 for (Preprocessor::macro_iterator M = PP.macro_begin(),
Douglas Gregor12785102010-08-24 20:21:13 +00008082 MEnd = PP.macro_end();
8083 M != MEnd; ++M) {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00008084 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008085 M->first->getName()));
Argyrios Kyrtzidis5c8b1cd2012-09-27 00:24:09 +00008086 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
8087 CCP_CodePattern,
8088 CXCursor_MacroDefinition));
Douglas Gregor12785102010-08-24 20:21:13 +00008089 }
8090 Results.ExitScope();
8091 } else if (IsDefinition) {
8092 // FIXME: Can we detect when the user just wrote an include guard above?
8093 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008094
Douglas Gregor0ac41382010-09-23 23:01:17 +00008095 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008096 Results.data(), Results.size());
Douglas Gregor12785102010-08-24 20:21:13 +00008097}
8098
Douglas Gregorec00a262010-08-24 22:20:20 +00008099void Sema::CodeCompletePreprocessorExpression() {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008100 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008101 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00008102 CodeCompletionContext::CCC_PreprocessorExpression);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008103
Douglas Gregorec00a262010-08-24 22:20:20 +00008104 if (!CodeCompleter || CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00008105 AddMacroResults(PP, Results,
8106 CodeCompleter ? CodeCompleter->loadExternal() : false,
8107 true);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008108
Douglas Gregorec00a262010-08-24 22:20:20 +00008109 // defined (<macro>)
8110 Results.EnterNewScope();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008111 CodeCompletionBuilder Builder(Results.getAllocator(),
8112 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008113 Builder.AddTypedTextChunk("defined");
8114 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8115 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
8116 Builder.AddPlaceholderChunk("macro");
8117 Builder.AddChunk(CodeCompletionString::CK_RightParen);
8118 Results.AddResult(Builder.TakeString());
Douglas Gregorec00a262010-08-24 22:20:20 +00008119 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00008120
8121 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
8122 Results.data(), Results.size());
Douglas Gregorec00a262010-08-24 22:20:20 +00008123}
8124
8125void Sema::CodeCompletePreprocessorMacroArgument(Scope *S,
8126 IdentifierInfo *Macro,
8127 MacroInfo *MacroInfo,
8128 unsigned Argument) {
8129 // FIXME: In the future, we could provide "overload" results, much like we
8130 // do for function calls.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008131
Argyrios Kyrtzidis75f6cd22011-08-18 19:41:28 +00008132 // Now just ignore this. There will be another code-completion callback
8133 // for the expanded tokens.
Douglas Gregorec00a262010-08-24 22:20:20 +00008134}
8135
Sam McCall3d8051a2018-09-18 08:40:41 +00008136// This handles completion inside an #include filename, e.g. #include <foo/ba
8137// We look for the directory "foo" under each directory on the include path,
8138// list its files, and reassemble the appropriate #include.
8139void Sema::CodeCompleteIncludedFile(llvm::StringRef Dir, bool Angled) {
8140 // RelDir should use /, but unescaped \ is possible on windows!
8141 // Our completions will normalize to / for simplicity, this case is rare.
8142 std::string RelDir = llvm::sys::path::convert_to_slash(Dir);
8143 // We need the native slashes for the actual file system interactions.
8144 SmallString<128> NativeRelDir = StringRef(RelDir);
8145 llvm::sys::path::native(NativeRelDir);
8146 auto FS = getSourceManager().getFileManager().getVirtualFileSystem();
8147
8148 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
8149 CodeCompleter->getCodeCompletionTUInfo(),
8150 CodeCompletionContext::CCC_IncludedFile);
8151 llvm::DenseSet<StringRef> SeenResults; // To deduplicate results.
8152
8153 // Helper: adds one file or directory completion result.
8154 auto AddCompletion = [&](StringRef Filename, bool IsDirectory) {
8155 SmallString<64> TypedChunk = Filename;
8156 // Directory completion is up to the slash, e.g. <sys/
8157 TypedChunk.push_back(IsDirectory ? '/' : Angled ? '>' : '"');
8158 auto R = SeenResults.insert(TypedChunk);
8159 if (R.second) { // New completion
8160 const char *InternedTyped = Results.getAllocator().CopyString(TypedChunk);
8161 *R.first = InternedTyped; // Avoid dangling StringRef.
8162 CodeCompletionBuilder Builder(CodeCompleter->getAllocator(),
8163 CodeCompleter->getCodeCompletionTUInfo());
8164 Builder.AddTypedTextChunk(InternedTyped);
8165 // The result is a "Pattern", which is pretty opaque.
8166 // We may want to include the real filename to allow smart ranking.
8167 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
8168 }
8169 };
8170
8171 // Helper: scans IncludeDir for nice files, and adds results for each.
8172 auto AddFilesFromIncludeDir = [&](StringRef IncludeDir, bool IsSystem) {
8173 llvm::SmallString<128> Dir = IncludeDir;
8174 if (!NativeRelDir.empty())
8175 llvm::sys::path::append(Dir, NativeRelDir);
8176
8177 std::error_code EC;
8178 unsigned Count = 0;
8179 for (auto It = FS->dir_begin(Dir, EC);
Jonas Devliegherefc514902018-10-10 13:27:25 +00008180 !EC && It != llvm::vfs::directory_iterator(); It.increment(EC)) {
Sam McCall3d8051a2018-09-18 08:40:41 +00008181 if (++Count == 2500) // If we happen to hit a huge directory,
8182 break; // bail out early so we're not too slow.
8183 StringRef Filename = llvm::sys::path::filename(It->path());
8184 switch (It->type()) {
8185 case llvm::sys::fs::file_type::directory_file:
8186 AddCompletion(Filename, /*IsDirectory=*/true);
8187 break;
8188 case llvm::sys::fs::file_type::regular_file:
8189 // Only files that really look like headers. (Except in system dirs).
8190 if (!IsSystem) {
8191 // Header extensions from Types.def, which we can't depend on here.
8192 if (!(Filename.endswith_lower(".h") ||
8193 Filename.endswith_lower(".hh") ||
8194 Filename.endswith_lower(".hpp") ||
8195 Filename.endswith_lower(".inc")))
8196 break;
8197 }
8198 AddCompletion(Filename, /*IsDirectory=*/false);
8199 break;
8200 default:
8201 break;
8202 }
8203 }
8204 };
8205
8206 // Helper: adds results relative to IncludeDir, if possible.
8207 auto AddFilesFromDirLookup = [&](const DirectoryLookup &IncludeDir,
8208 bool IsSystem) {
8209 llvm::SmallString<128> Dir;
8210 switch (IncludeDir.getLookupType()) {
8211 case DirectoryLookup::LT_HeaderMap:
8212 // header maps are not (currently) enumerable.
8213 break;
8214 case DirectoryLookup::LT_NormalDir:
8215 AddFilesFromIncludeDir(IncludeDir.getDir()->getName(), IsSystem);
8216 break;
8217 case DirectoryLookup::LT_Framework:
8218 AddFilesFromIncludeDir(IncludeDir.getFrameworkDir()->getName(), IsSystem);
8219 break;
8220 }
8221 };
8222
8223 // Finally with all our helpers, we can scan the include path.
8224 // Do this in standard order so deduplication keeps the right file.
8225 // (In case we decide to add more details to the results later).
8226 const auto &S = PP.getHeaderSearchInfo();
8227 using llvm::make_range;
8228 if (!Angled) {
8229 // The current directory is on the include path for "quoted" includes.
8230 auto *CurFile = PP.getCurrentFileLexer()->getFileEntry();
8231 if (CurFile && CurFile->getDir())
8232 AddFilesFromIncludeDir(CurFile->getDir()->getName(), false);
8233 for (const auto &D : make_range(S.quoted_dir_begin(), S.quoted_dir_end()))
8234 AddFilesFromDirLookup(D, false);
8235 }
8236 for (const auto &D : make_range(S.angled_dir_begin(), S.angled_dir_end()))
Sam McCall3e4f5eb2018-10-01 11:56:42 +00008237 AddFilesFromDirLookup(D, false);
Sam McCall3d8051a2018-09-18 08:40:41 +00008238 for (const auto &D : make_range(S.system_dir_begin(), S.system_dir_end()))
8239 AddFilesFromDirLookup(D, true);
8240
8241 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
8242 Results.data(), Results.size());
8243}
8244
Douglas Gregor11583702010-08-25 17:04:25 +00008245void Sema::CodeCompleteNaturalLanguage() {
Douglas Gregor11583702010-08-25 17:04:25 +00008246 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregorea736372010-08-25 17:10:00 +00008247 CodeCompletionContext::CCC_NaturalLanguage,
Craig Topperc3ec1492014-05-26 06:22:03 +00008248 nullptr, 0);
Douglas Gregor11583702010-08-25 17:04:25 +00008249}
8250
Alex Lorenzf7f6f822017-05-09 16:05:04 +00008251void Sema::CodeCompleteAvailabilityPlatformName() {
8252 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
8253 CodeCompleter->getCodeCompletionTUInfo(),
8254 CodeCompletionContext::CCC_Other);
8255 Results.EnterNewScope();
8256 static const char *Platforms[] = {"macOS", "iOS", "watchOS", "tvOS"};
8257 for (const char *Platform : llvm::makeArrayRef(Platforms)) {
8258 Results.AddResult(CodeCompletionResult(Platform));
8259 Results.AddResult(CodeCompletionResult(Results.getAllocator().CopyString(
8260 Twine(Platform) + "ApplicationExtension")));
8261 }
8262 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00008263 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
8264 Results.data(), Results.size());
Alex Lorenzf7f6f822017-05-09 16:05:04 +00008265}
8266
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00008267void Sema::GatherGlobalCodeCompletions(CodeCompletionAllocator &Allocator,
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008268 CodeCompletionTUInfo &CCTUInfo,
Chris Lattner0e62c1c2011-07-23 10:55:15 +00008269 SmallVectorImpl<CodeCompletionResult> &Results) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008270 ResultBuilder Builder(*this, Allocator, CCTUInfo,
8271 CodeCompletionContext::CCC_Recovery);
Douglas Gregor39982192010-08-15 06:18:01 +00008272 if (!CodeCompleter || CodeCompleter->includeGlobals()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008273 CodeCompletionDeclConsumer Consumer(Builder,
Douglas Gregor39982192010-08-15 06:18:01 +00008274 Context.getTranslationUnitDecl());
Sam McCallbb2cf632018-01-12 14:51:47 +00008275 LookupVisibleDecls(Context.getTranslationUnitDecl(), LookupAnyName,
8276 Consumer,
8277 !CodeCompleter || CodeCompleter->loadExternal());
Douglas Gregor39982192010-08-15 06:18:01 +00008278 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008279
Douglas Gregorb14904c2010-08-13 22:48:40 +00008280 if (!CodeCompleter || CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00008281 AddMacroResults(PP, Builder,
8282 CodeCompleter ? CodeCompleter->loadExternal() : false,
8283 true);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008284
Douglas Gregorb14904c2010-08-13 22:48:40 +00008285 Results.clear();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008286 Results.insert(Results.end(),
Douglas Gregorb14904c2010-08-13 22:48:40 +00008287 Builder.data(), Builder.data() + Builder.size());
8288}