blob: 303d96be7a258af1666f1fcac1de02e9fdf29d95 [file] [log] [blame]
Douglas Gregor2436e712009-09-17 21:32:03 +00001//===---------------- SemaCodeComplete.cpp - Code Completion ----*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file defines the code-completion semantic actions.
11//
12//===----------------------------------------------------------------------===//
Eric Liub91e0812018-10-02 10:29:00 +000013#include "clang/AST/Decl.h"
Ilya Biryukov4e7a6fe2017-09-22 19:07:37 +000014#include "clang/AST/DeclCXX.h"
John McCallde6836a2010-08-24 07:21:54 +000015#include "clang/AST/DeclObjC.h"
Douglas Gregorf2510672009-09-21 19:57:38 +000016#include "clang/AST/ExprCXX.h"
Douglas Gregor8ce33212009-11-17 17:59:40 +000017#include "clang/AST/ExprObjC.h"
Ilya Biryukovb5da91c2017-11-08 10:39:09 +000018#include "clang/AST/QualTypeNames.h"
Jordan Rose4938f272013-02-09 10:09:43 +000019#include "clang/Basic/CharInfo.h"
Douglas Gregor07f43572012-01-29 18:15:03 +000020#include "clang/Lex/HeaderSearch.h"
Douglas Gregorf329c7c2009-10-30 16:50:04 +000021#include "clang/Lex/MacroInfo.h"
22#include "clang/Lex/Preprocessor.h"
Chandler Carruth3a022472012-12-04 09:13:33 +000023#include "clang/Sema/CodeCompleteConsumer.h"
Chandler Carruth3a022472012-12-04 09:13:33 +000024#include "clang/Sema/Lookup.h"
25#include "clang/Sema/Overload.h"
26#include "clang/Sema/Scope.h"
27#include "clang/Sema/ScopeInfo.h"
Ilya Biryukov4e7a6fe2017-09-22 19:07:37 +000028#include "clang/Sema/SemaInternal.h"
Douglas Gregor1154e272010-09-16 16:06:31 +000029#include "llvm/ADT/DenseSet.h"
Benjamin Kramere0513cb2012-01-30 16:17:39 +000030#include "llvm/ADT/SmallBitVector.h"
Douglas Gregor3545ff42009-09-21 16:56:56 +000031#include "llvm/ADT/SmallPtrSet.h"
Benjamin Kramer49038022012-02-04 13:45:25 +000032#include "llvm/ADT/SmallString.h"
Douglas Gregore6688e62009-09-28 03:51:44 +000033#include "llvm/ADT/StringExtras.h"
Douglas Gregor9d2ddb22010-04-06 19:22:33 +000034#include "llvm/ADT/StringSwitch.h"
Douglas Gregor67c692c2010-08-26 15:07:07 +000035#include "llvm/ADT/Twine.h"
Sam McCall3d8051a2018-09-18 08:40:41 +000036#include "llvm/ADT/iterator_range.h"
37#include "llvm/Support/Path.h"
Douglas Gregor3545ff42009-09-21 16:56:56 +000038#include <list>
39#include <map>
40#include <vector>
Douglas Gregor2436e712009-09-17 21:32:03 +000041
42using namespace clang;
John McCallaab3e412010-08-25 08:40:02 +000043using namespace sema;
Douglas Gregor2436e712009-09-17 21:32:03 +000044
Douglas Gregor3545ff42009-09-21 16:56:56 +000045namespace {
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000046 /// A container of code-completion results.
Douglas Gregor3545ff42009-09-21 16:56:56 +000047 class ResultBuilder {
48 public:
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000049 /// The type of a name-lookup filter, which can be provided to the
Douglas Gregor3545ff42009-09-21 16:56:56 +000050 /// name-lookup routines to specify which declarations should be included in
51 /// the result set (when it returns true) and which declarations should be
52 /// filtered out (returns false).
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +000053 typedef bool (ResultBuilder::*LookupFilter)(const NamedDecl *) const;
Ivan Donchevskii13d90542017-10-27 11:05:40 +000054
John McCall276321a2010-08-25 06:19:51 +000055 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +000056
Douglas Gregor3545ff42009-09-21 16:56:56 +000057 private:
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000058 /// The actual results we have found.
Douglas Gregor3545ff42009-09-21 16:56:56 +000059 std::vector<Result> Results;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +000060
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000061 /// A record of all of the declarations we have found and placed
Douglas Gregor3545ff42009-09-21 16:56:56 +000062 /// into the result set, used to ensure that no declaration ever gets into
63 /// the result set twice.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +000064 llvm::SmallPtrSet<const Decl*, 16> AllDeclsFound;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +000065
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +000066 typedef std::pair<const NamedDecl *, unsigned> DeclIndexPair;
Douglas Gregor05e7ca32009-12-06 20:23:50 +000067
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000068 /// An entry in the shadow map, which is optimized to store
Douglas Gregor05e7ca32009-12-06 20:23:50 +000069 /// a single (declaration, index) mapping (the common case) but
70 /// can also store a list of (declaration, index) mappings.
71 class ShadowMapEntry {
Chris Lattner0e62c1c2011-07-23 10:55:15 +000072 typedef SmallVector<DeclIndexPair, 4> DeclIndexPairVector;
Douglas Gregor05e7ca32009-12-06 20:23:50 +000073
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000074 /// Contains either the solitary NamedDecl * or a vector
Douglas Gregor05e7ca32009-12-06 20:23:50 +000075 /// of (declaration, index) pairs.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +000076 llvm::PointerUnion<const NamedDecl *, DeclIndexPairVector*> DeclOrVector;
Douglas Gregor05e7ca32009-12-06 20:23:50 +000077
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000078 /// When the entry contains a single declaration, this is
Douglas Gregor05e7ca32009-12-06 20:23:50 +000079 /// the index associated with that entry.
80 unsigned SingleDeclIndex;
81
82 public:
83 ShadowMapEntry() : DeclOrVector(), SingleDeclIndex(0) { }
84
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +000085 void Add(const NamedDecl *ND, unsigned Index) {
Douglas Gregor05e7ca32009-12-06 20:23:50 +000086 if (DeclOrVector.isNull()) {
87 // 0 - > 1 elements: just set the single element information.
88 DeclOrVector = ND;
89 SingleDeclIndex = Index;
90 return;
91 }
92
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +000093 if (const NamedDecl *PrevND =
94 DeclOrVector.dyn_cast<const NamedDecl *>()) {
Douglas Gregor05e7ca32009-12-06 20:23:50 +000095 // 1 -> 2 elements: create the vector of results and push in the
96 // existing declaration.
97 DeclIndexPairVector *Vec = new DeclIndexPairVector;
98 Vec->push_back(DeclIndexPair(PrevND, SingleDeclIndex));
99 DeclOrVector = Vec;
100 }
101
102 // Add the new element to the end of the vector.
103 DeclOrVector.get<DeclIndexPairVector*>()->push_back(
104 DeclIndexPair(ND, Index));
105 }
106
107 void Destroy() {
108 if (DeclIndexPairVector *Vec
109 = DeclOrVector.dyn_cast<DeclIndexPairVector *>()) {
110 delete Vec;
Craig Topperc3ec1492014-05-26 06:22:03 +0000111 DeclOrVector = ((NamedDecl *)nullptr);
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000112 }
113 }
114
115 // Iteration.
116 class iterator;
117 iterator begin() const;
118 iterator end() const;
119 };
120
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000121 /// A mapping from declaration names to the declarations that have
Douglas Gregor3545ff42009-09-21 16:56:56 +0000122 /// this name within a particular scope and their index within the list of
123 /// results.
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000124 typedef llvm::DenseMap<DeclarationName, ShadowMapEntry> ShadowMap;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000125
126 /// The semantic analysis object for which results are being
Douglas Gregor3545ff42009-09-21 16:56:56 +0000127 /// produced.
128 Sema &SemaRef;
Douglas Gregorb278aaf2011-02-01 19:23:04 +0000129
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000130 /// The allocator used to allocate new code-completion strings.
Douglas Gregorbcbf46c2011-02-01 22:57:45 +0000131 CodeCompletionAllocator &Allocator;
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +0000132
133 CodeCompletionTUInfo &CCTUInfo;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000134
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000135 /// If non-NULL, a filter function used to remove any code-completion
Douglas Gregor3545ff42009-09-21 16:56:56 +0000136 /// results that are not desirable.
137 LookupFilter Filter;
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000138
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000139 /// Whether we should allow declarations as
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000140 /// nested-name-specifiers that would otherwise be filtered out.
141 bool AllowNestedNameSpecifiers;
142
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000143 /// If set, the type that we would prefer our resulting value
Douglas Gregor7aa6b222010-05-30 01:49:25 +0000144 /// declarations to have.
145 ///
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000146 /// Closely matching the preferred type gives a boost to a result's
Douglas Gregor7aa6b222010-05-30 01:49:25 +0000147 /// priority.
148 CanQualType PreferredType;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000149
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000150 /// A list of shadow maps, which is used to model name hiding at
Douglas Gregor3545ff42009-09-21 16:56:56 +0000151 /// different levels of, e.g., the inheritance hierarchy.
152 std::list<ShadowMap> ShadowMaps;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000153
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000154 /// If we're potentially referring to a C++ member function, the set
Douglas Gregor9be0ed42010-08-26 16:36:48 +0000155 /// of qualifiers applied to the object type.
156 Qualifiers ObjectTypeQualifiers;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000157
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000158 /// Whether the \p ObjectTypeQualifiers field is active.
Douglas Gregor9be0ed42010-08-26 16:36:48 +0000159 bool HasObjectTypeQualifiers;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000160
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000161 /// The selector that we prefer.
Douglas Gregorc2cb2e22010-08-27 15:29:55 +0000162 Selector PreferredSelector;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000163
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000164 /// The completion context in which we are gathering results.
Douglas Gregor50832e02010-09-20 22:39:41 +0000165 CodeCompletionContext CompletionContext;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000166
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000167 /// If we are in an instance method definition, the \@implementation
Douglas Gregor05fcf842010-11-02 20:36:02 +0000168 /// object.
169 ObjCImplementationDecl *ObjCImplementation;
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000170
Douglas Gregor50832e02010-09-20 22:39:41 +0000171 void AdjustResultPriorityForDecl(Result &R);
Douglas Gregor95887f92010-07-08 23:20:03 +0000172
Douglas Gregor0212fd72010-09-21 16:06:22 +0000173 void MaybeAddConstructorResults(Result R);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000174
Douglas Gregor3545ff42009-09-21 16:56:56 +0000175 public:
Douglas Gregorbcbf46c2011-02-01 22:57:45 +0000176 explicit ResultBuilder(Sema &SemaRef, CodeCompletionAllocator &Allocator,
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +0000177 CodeCompletionTUInfo &CCTUInfo,
Douglas Gregor0ac41382010-09-23 23:01:17 +0000178 const CodeCompletionContext &CompletionContext,
Craig Topperc3ec1492014-05-26 06:22:03 +0000179 LookupFilter Filter = nullptr)
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +0000180 : SemaRef(SemaRef), Allocator(Allocator), CCTUInfo(CCTUInfo),
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000181 Filter(Filter),
182 AllowNestedNameSpecifiers(false), HasObjectTypeQualifiers(false),
Douglas Gregor05fcf842010-11-02 20:36:02 +0000183 CompletionContext(CompletionContext),
Craig Topperc3ec1492014-05-26 06:22:03 +0000184 ObjCImplementation(nullptr)
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000185 {
186 // If this is an Objective-C instance method definition, dig out the
Douglas Gregor05fcf842010-11-02 20:36:02 +0000187 // corresponding implementation.
188 switch (CompletionContext.getKind()) {
189 case CodeCompletionContext::CCC_Expression:
190 case CodeCompletionContext::CCC_ObjCMessageReceiver:
191 case CodeCompletionContext::CCC_ParenthesizedExpression:
192 case CodeCompletionContext::CCC_Statement:
193 case CodeCompletionContext::CCC_Recovery:
194 if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl())
195 if (Method->isInstanceMethod())
196 if (ObjCInterfaceDecl *Interface = Method->getClassInterface())
197 ObjCImplementation = Interface->getImplementation();
198 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000199
Douglas Gregor05fcf842010-11-02 20:36:02 +0000200 default:
201 break;
202 }
203 }
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000204
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000205 /// Determine the priority for a reference to the given declaration.
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000206 unsigned getBasePriority(const NamedDecl *D);
207
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000208 /// Whether we should include code patterns in the completion
Douglas Gregorf64acca2010-05-25 21:41:55 +0000209 /// results.
210 bool includeCodePatterns() const {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000211 return SemaRef.CodeCompleter &&
Douglas Gregorac322ec2010-08-27 21:18:54 +0000212 SemaRef.CodeCompleter->includeCodePatterns();
Douglas Gregorf64acca2010-05-25 21:41:55 +0000213 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000214
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000215 /// Set the filter used for code-completion results.
Douglas Gregor3545ff42009-09-21 16:56:56 +0000216 void setFilter(LookupFilter Filter) {
217 this->Filter = Filter;
218 }
Craig Topperc3ec1492014-05-26 06:22:03 +0000219
220 Result *data() { return Results.empty()? nullptr : &Results.front(); }
Douglas Gregor3545ff42009-09-21 16:56:56 +0000221 unsigned size() const { return Results.size(); }
222 bool empty() const { return Results.empty(); }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000223
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000224 /// Specify the preferred type.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000225 void setPreferredType(QualType T) {
226 PreferredType = SemaRef.Context.getCanonicalType(T);
Douglas Gregor7aa6b222010-05-30 01:49:25 +0000227 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000228
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000229 /// Set the cv-qualifiers on the object type, for us in filtering
Douglas Gregor9be0ed42010-08-26 16:36:48 +0000230 /// calls to member functions.
231 ///
232 /// When there are qualifiers in this set, they will be used to filter
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000233 /// out member functions that aren't available (because there will be a
Douglas Gregor9be0ed42010-08-26 16:36:48 +0000234 /// cv-qualifier mismatch) or prefer functions with an exact qualifier
235 /// match.
236 void setObjectTypeQualifiers(Qualifiers Quals) {
237 ObjectTypeQualifiers = Quals;
238 HasObjectTypeQualifiers = true;
239 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000240
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000241 /// Set the preferred selector.
Douglas Gregorc2cb2e22010-08-27 15:29:55 +0000242 ///
243 /// When an Objective-C method declaration result is added, and that
244 /// method's selector matches this preferred selector, we give that method
245 /// a slight priority boost.
246 void setPreferredSelector(Selector Sel) {
247 PreferredSelector = Sel;
248 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000249
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000250 /// Retrieve the code-completion context for which results are
Douglas Gregor50832e02010-09-20 22:39:41 +0000251 /// being collected.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000252 const CodeCompletionContext &getCompletionContext() const {
253 return CompletionContext;
Douglas Gregor50832e02010-09-20 22:39:41 +0000254 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000255
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000256 /// Specify whether nested-name-specifiers are allowed.
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000257 void allowNestedNameSpecifiers(bool Allow = true) {
258 AllowNestedNameSpecifiers = Allow;
259 }
260
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000261 /// Return the semantic analysis object for which we are collecting
Douglas Gregor74661272010-09-21 00:03:25 +0000262 /// code completion results.
263 Sema &getSema() const { return SemaRef; }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000264
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000265 /// Retrieve the allocator used to allocate code completion strings.
Douglas Gregorbcbf46c2011-02-01 22:57:45 +0000266 CodeCompletionAllocator &getAllocator() const { return Allocator; }
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +0000267
268 CodeCompletionTUInfo &getCodeCompletionTUInfo() const { return CCTUInfo; }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000269
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000270 /// Determine whether the given declaration is at all interesting
Douglas Gregor7c208612010-01-14 00:20:49 +0000271 /// as a code-completion result.
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000272 ///
273 /// \param ND the declaration that we are inspecting.
274 ///
275 /// \param AsNestedNameSpecifier will be set true if this declaration is
276 /// only interesting when it is a nested-name-specifier.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000277 bool isInterestingDecl(const NamedDecl *ND,
278 bool &AsNestedNameSpecifier) const;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000279
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000280 /// Check whether the result is hidden by the Hiding declaration.
Douglas Gregore0717ab2010-01-14 00:41:07 +0000281 ///
282 /// \returns true if the result is hidden and cannot be found, false if
283 /// the hidden result could still be found. When false, \p R may be
284 /// modified to describe how the result can be found (e.g., via extra
285 /// qualification).
286 bool CheckHiddenResult(Result &R, DeclContext *CurContext,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000287 const NamedDecl *Hiding);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000288
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000289 /// Add a new result to this result set (if it isn't already in one
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000290 /// of the shadow maps), or replace an existing result (for, e.g., a
Douglas Gregor3545ff42009-09-21 16:56:56 +0000291 /// redeclaration).
Douglas Gregor2af2f672009-09-21 20:12:40 +0000292 ///
Douglas Gregord8c61782012-02-15 15:34:24 +0000293 /// \param R the result to add (if it is unique).
Douglas Gregor2af2f672009-09-21 20:12:40 +0000294 ///
Douglas Gregord8c61782012-02-15 15:34:24 +0000295 /// \param CurContext the context in which this result will be named.
Craig Topperc3ec1492014-05-26 06:22:03 +0000296 void MaybeAddResult(Result R, DeclContext *CurContext = nullptr);
297
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000298 /// Add a new result to this result set, where we already know
Yaron Keren8fbe43982014-11-14 18:33:42 +0000299 /// the hiding declaration (if any).
Douglas Gregorc580c522010-01-14 01:09:38 +0000300 ///
301 /// \param R the result to add (if it is unique).
302 ///
303 /// \param CurContext the context in which this result will be named.
304 ///
305 /// \param Hiding the declaration that hides the result.
Douglas Gregor09bbc652010-01-14 15:47:35 +0000306 ///
307 /// \param InBaseClass whether the result was found in a base
308 /// class of the searched context.
309 void AddResult(Result R, DeclContext *CurContext, NamedDecl *Hiding,
310 bool InBaseClass);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000311
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000312 /// Add a new non-declaration result to this result set.
Douglas Gregor78a21012010-01-14 16:01:26 +0000313 void AddResult(Result R);
314
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000315 /// Enter into a new scope.
Douglas Gregor3545ff42009-09-21 16:56:56 +0000316 void EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000317
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000318 /// Exit from the current scope.
Douglas Gregor3545ff42009-09-21 16:56:56 +0000319 void ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000320
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000321 /// Ignore this declaration, if it is seen again.
Dmitri Gribenko6cfb1532013-02-14 13:53:30 +0000322 void Ignore(const Decl *D) { AllDeclsFound.insert(D->getCanonicalDecl()); }
Douglas Gregorbaf69612009-11-18 04:19:12 +0000323
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000324 /// Add a visited context.
Haojian Wu10d95c52018-01-17 14:29:25 +0000325 void addVisitedContext(DeclContext *Ctx) {
326 CompletionContext.addVisitedContext(Ctx);
327 }
328
Douglas Gregor3545ff42009-09-21 16:56:56 +0000329 /// \name Name lookup predicates
330 ///
331 /// These predicates can be passed to the name lookup functions to filter the
332 /// results of name lookup. All of the predicates have the same type, so that
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000333 ///
Douglas Gregor3545ff42009-09-21 16:56:56 +0000334 //@{
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000335 bool IsOrdinaryName(const NamedDecl *ND) const;
336 bool IsOrdinaryNonTypeName(const NamedDecl *ND) const;
337 bool IsIntegralConstantValue(const NamedDecl *ND) const;
338 bool IsOrdinaryNonValueName(const NamedDecl *ND) const;
339 bool IsNestedNameSpecifier(const NamedDecl *ND) const;
340 bool IsEnum(const NamedDecl *ND) const;
341 bool IsClassOrStruct(const NamedDecl *ND) const;
342 bool IsUnion(const NamedDecl *ND) const;
343 bool IsNamespace(const NamedDecl *ND) const;
344 bool IsNamespaceOrAlias(const NamedDecl *ND) const;
345 bool IsType(const NamedDecl *ND) const;
346 bool IsMember(const NamedDecl *ND) const;
347 bool IsObjCIvar(const NamedDecl *ND) const;
348 bool IsObjCMessageReceiver(const NamedDecl *ND) const;
349 bool IsObjCMessageReceiverOrLambdaCapture(const NamedDecl *ND) const;
350 bool IsObjCCollection(const NamedDecl *ND) const;
351 bool IsImpossibleToSatisfy(const NamedDecl *ND) const;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000352 //@}
353 };
Alexander Kornienkoab9db512015-06-22 23:07:51 +0000354}
Douglas Gregor3545ff42009-09-21 16:56:56 +0000355
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000356class ResultBuilder::ShadowMapEntry::iterator {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000357 llvm::PointerUnion<const NamedDecl *, const DeclIndexPair *> DeclOrIterator;
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000358 unsigned SingleDeclIndex;
359
360public:
361 typedef DeclIndexPair value_type;
362 typedef value_type reference;
363 typedef std::ptrdiff_t difference_type;
364 typedef std::input_iterator_tag iterator_category;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000365
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000366 class pointer {
367 DeclIndexPair Value;
368
369 public:
370 pointer(const DeclIndexPair &Value) : Value(Value) { }
371
372 const DeclIndexPair *operator->() const {
373 return &Value;
374 }
375 };
Craig Topperc3ec1492014-05-26 06:22:03 +0000376
377 iterator() : DeclOrIterator((NamedDecl *)nullptr), SingleDeclIndex(0) {}
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000378
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000379 iterator(const NamedDecl *SingleDecl, unsigned Index)
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000380 : DeclOrIterator(SingleDecl), SingleDeclIndex(Index) { }
381
382 iterator(const DeclIndexPair *Iterator)
383 : DeclOrIterator(Iterator), SingleDeclIndex(0) { }
384
385 iterator &operator++() {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000386 if (DeclOrIterator.is<const NamedDecl *>()) {
Craig Topperc3ec1492014-05-26 06:22:03 +0000387 DeclOrIterator = (NamedDecl *)nullptr;
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000388 SingleDeclIndex = 0;
389 return *this;
390 }
391
392 const DeclIndexPair *I = DeclOrIterator.get<const DeclIndexPair*>();
393 ++I;
394 DeclOrIterator = I;
395 return *this;
396 }
397
Chris Lattner9795b392010-09-04 18:12:20 +0000398 /*iterator operator++(int) {
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000399 iterator tmp(*this);
400 ++(*this);
401 return tmp;
Chris Lattner9795b392010-09-04 18:12:20 +0000402 }*/
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000403
404 reference operator*() const {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000405 if (const NamedDecl *ND = DeclOrIterator.dyn_cast<const NamedDecl *>())
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000406 return reference(ND, SingleDeclIndex);
407
Douglas Gregor94bb5e82009-12-06 21:27:58 +0000408 return *DeclOrIterator.get<const DeclIndexPair*>();
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000409 }
410
411 pointer operator->() const {
412 return pointer(**this);
413 }
414
415 friend bool operator==(const iterator &X, const iterator &Y) {
Douglas Gregor94bb5e82009-12-06 21:27:58 +0000416 return X.DeclOrIterator.getOpaqueValue()
417 == Y.DeclOrIterator.getOpaqueValue() &&
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000418 X.SingleDeclIndex == Y.SingleDeclIndex;
419 }
420
421 friend bool operator!=(const iterator &X, const iterator &Y) {
Douglas Gregor94bb5e82009-12-06 21:27:58 +0000422 return !(X == Y);
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000423 }
424};
425
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000426ResultBuilder::ShadowMapEntry::iterator
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000427ResultBuilder::ShadowMapEntry::begin() const {
428 if (DeclOrVector.isNull())
429 return iterator();
430
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000431 if (const NamedDecl *ND = DeclOrVector.dyn_cast<const NamedDecl *>())
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000432 return iterator(ND, SingleDeclIndex);
433
434 return iterator(DeclOrVector.get<DeclIndexPairVector *>()->begin());
435}
436
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000437ResultBuilder::ShadowMapEntry::iterator
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000438ResultBuilder::ShadowMapEntry::end() const {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000439 if (DeclOrVector.is<const NamedDecl *>() || DeclOrVector.isNull())
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000440 return iterator();
441
442 return iterator(DeclOrVector.get<DeclIndexPairVector *>()->end());
443}
444
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000445/// Compute the qualification required to get from the current context
Douglas Gregor2af2f672009-09-21 20:12:40 +0000446/// (\p CurContext) to the target context (\p TargetContext).
447///
448/// \param Context the AST context in which the qualification will be used.
449///
450/// \param CurContext the context where an entity is being named, which is
451/// typically based on the current scope.
452///
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000453/// \param TargetContext the context in which the named entity actually
Douglas Gregor2af2f672009-09-21 20:12:40 +0000454/// resides.
455///
456/// \returns a nested name specifier that refers into the target context, or
457/// NULL if no qualification is needed.
458static NestedNameSpecifier *
459getRequiredQualification(ASTContext &Context,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000460 const DeclContext *CurContext,
461 const DeclContext *TargetContext) {
462 SmallVector<const DeclContext *, 4> TargetParents;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000463
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000464 for (const DeclContext *CommonAncestor = TargetContext;
Douglas Gregor2af2f672009-09-21 20:12:40 +0000465 CommonAncestor && !CommonAncestor->Encloses(CurContext);
466 CommonAncestor = CommonAncestor->getLookupParent()) {
467 if (CommonAncestor->isTransparentContext() ||
468 CommonAncestor->isFunctionOrMethod())
469 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000470
Douglas Gregor2af2f672009-09-21 20:12:40 +0000471 TargetParents.push_back(CommonAncestor);
472 }
Craig Topperc3ec1492014-05-26 06:22:03 +0000473
474 NestedNameSpecifier *Result = nullptr;
Douglas Gregor2af2f672009-09-21 20:12:40 +0000475 while (!TargetParents.empty()) {
Robert Wilhelm25284cc2013-08-23 16:11:15 +0000476 const DeclContext *Parent = TargetParents.pop_back_val();
477
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000478 if (const NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Parent)) {
Douglas Gregor68762e72010-08-23 21:17:50 +0000479 if (!Namespace->getIdentifier())
480 continue;
481
Douglas Gregor2af2f672009-09-21 20:12:40 +0000482 Result = NestedNameSpecifier::Create(Context, Result, Namespace);
Douglas Gregor68762e72010-08-23 21:17:50 +0000483 }
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000484 else if (const TagDecl *TD = dyn_cast<TagDecl>(Parent))
Douglas Gregor2af2f672009-09-21 20:12:40 +0000485 Result = NestedNameSpecifier::Create(Context, Result,
486 false,
487 Context.getTypeDeclType(TD).getTypePtr());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000488 }
Douglas Gregor2af2f672009-09-21 20:12:40 +0000489 return Result;
490}
491
Alp Toker034bbd52014-06-30 01:33:53 +0000492/// Determine whether \p Id is a name reserved for the implementation (C99
493/// 7.1.3, C++ [lib.global.names]).
Argyrios Kyrtzidis5d8006d2016-07-01 01:17:02 +0000494static bool isReservedName(const IdentifierInfo *Id,
495 bool doubleUnderscoreOnly = false) {
Alp Toker034bbd52014-06-30 01:33:53 +0000496 if (Id->getLength() < 2)
497 return false;
498 const char *Name = Id->getNameStart();
499 return Name[0] == '_' &&
Argyrios Kyrtzidis5d8006d2016-07-01 01:17:02 +0000500 (Name[1] == '_' || (Name[1] >= 'A' && Name[1] <= 'Z' &&
501 !doubleUnderscoreOnly));
502}
503
504// Some declarations have reserved names that we don't want to ever show.
505// Filter out names reserved for the implementation if they come from a
506// system header.
507static bool shouldIgnoreDueToReservedName(const NamedDecl *ND, Sema &SemaRef) {
508 const IdentifierInfo *Id = ND->getIdentifier();
509 if (!Id)
510 return false;
511
512 // Ignore reserved names for compiler provided decls.
513 if (isReservedName(Id) && ND->getLocation().isInvalid())
514 return true;
515
516 // For system headers ignore only double-underscore names.
517 // This allows for system headers providing private symbols with a single
518 // underscore.
519 if (isReservedName(Id, /*doubleUnderscoreOnly=*/true) &&
520 SemaRef.SourceMgr.isInSystemHeader(
521 SemaRef.SourceMgr.getSpellingLoc(ND->getLocation())))
522 return true;
523
524 return false;
Alp Toker034bbd52014-06-30 01:33:53 +0000525}
526
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000527bool ResultBuilder::isInterestingDecl(const NamedDecl *ND,
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000528 bool &AsNestedNameSpecifier) const {
529 AsNestedNameSpecifier = false;
530
Richard Smithf2005d32015-12-29 23:34:32 +0000531 auto *Named = ND;
Douglas Gregor7c208612010-01-14 00:20:49 +0000532 ND = ND->getUnderlyingDecl();
Douglas Gregor58acf322009-10-09 22:16:47 +0000533
534 // Skip unnamed entities.
Douglas Gregor7c208612010-01-14 00:20:49 +0000535 if (!ND->getDeclName())
536 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000537
Douglas Gregor3545ff42009-09-21 16:56:56 +0000538 // Friend declarations and declarations introduced due to friends are never
539 // added as results.
Richard Smith6eece292015-01-15 02:27:20 +0000540 if (ND->getFriendObjectKind() == Decl::FOK_Undeclared)
Douglas Gregor7c208612010-01-14 00:20:49 +0000541 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000542
Douglas Gregor99fe2ad2009-12-11 17:31:05 +0000543 // Class template (partial) specializations are never added as results.
Douglas Gregor7c208612010-01-14 00:20:49 +0000544 if (isa<ClassTemplateSpecializationDecl>(ND) ||
545 isa<ClassTemplatePartialSpecializationDecl>(ND))
546 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000547
Douglas Gregor99fe2ad2009-12-11 17:31:05 +0000548 // Using declarations themselves are never added as results.
Douglas Gregor7c208612010-01-14 00:20:49 +0000549 if (isa<UsingDecl>(ND))
550 return false;
Argyrios Kyrtzidis5d8006d2016-07-01 01:17:02 +0000551
552 if (shouldIgnoreDueToReservedName(ND, SemaRef))
553 return false;
Douglas Gregor2927c0c2010-11-09 03:59:40 +0000554
Douglas Gregor59cab552010-08-16 23:05:20 +0000555 if (Filter == &ResultBuilder::IsNestedNameSpecifier ||
Richard Smithf2005d32015-12-29 23:34:32 +0000556 (isa<NamespaceDecl>(ND) &&
Douglas Gregor59cab552010-08-16 23:05:20 +0000557 Filter != &ResultBuilder::IsNamespace &&
Douglas Gregor0ac41382010-09-23 23:01:17 +0000558 Filter != &ResultBuilder::IsNamespaceOrAlias &&
Craig Topperc3ec1492014-05-26 06:22:03 +0000559 Filter != nullptr))
Douglas Gregor59cab552010-08-16 23:05:20 +0000560 AsNestedNameSpecifier = true;
561
Douglas Gregor3545ff42009-09-21 16:56:56 +0000562 // Filter out any unwanted results.
Richard Smithf2005d32015-12-29 23:34:32 +0000563 if (Filter && !(this->*Filter)(Named)) {
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000564 // Check whether it is interesting as a nested-name-specifier.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000565 if (AllowNestedNameSpecifiers && SemaRef.getLangOpts().CPlusPlus &&
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000566 IsNestedNameSpecifier(ND) &&
567 (Filter != &ResultBuilder::IsMember ||
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000568 (isa<CXXRecordDecl>(ND) &&
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000569 cast<CXXRecordDecl>(ND)->isInjectedClassName()))) {
570 AsNestedNameSpecifier = true;
571 return true;
572 }
573
Douglas Gregor7c208612010-01-14 00:20:49 +0000574 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000575 }
Douglas Gregor7c208612010-01-14 00:20:49 +0000576 // ... then it must be interesting!
577 return true;
578}
579
Douglas Gregore0717ab2010-01-14 00:41:07 +0000580bool ResultBuilder::CheckHiddenResult(Result &R, DeclContext *CurContext,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000581 const NamedDecl *Hiding) {
Douglas Gregore0717ab2010-01-14 00:41:07 +0000582 // In C, there is no way to refer to a hidden name.
583 // FIXME: This isn't true; we can find a tag name hidden by an ordinary
584 // name if we introduce the tag type.
David Blaikiebbafb8a2012-03-11 07:00:24 +0000585 if (!SemaRef.getLangOpts().CPlusPlus)
Douglas Gregore0717ab2010-01-14 00:41:07 +0000586 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000587
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000588 const DeclContext *HiddenCtx =
589 R.Declaration->getDeclContext()->getRedeclContext();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000590
Douglas Gregore0717ab2010-01-14 00:41:07 +0000591 // There is no way to qualify a name declared in a function or method.
592 if (HiddenCtx->isFunctionOrMethod())
593 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000594
Sebastian Redl50c68252010-08-31 00:36:30 +0000595 if (HiddenCtx == Hiding->getDeclContext()->getRedeclContext())
Douglas Gregore0717ab2010-01-14 00:41:07 +0000596 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000597
Douglas Gregore0717ab2010-01-14 00:41:07 +0000598 // We can refer to the result with the appropriate qualification. Do it.
599 R.Hidden = true;
600 R.QualifierIsInformative = false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000601
Douglas Gregore0717ab2010-01-14 00:41:07 +0000602 if (!R.Qualifier)
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000603 R.Qualifier = getRequiredQualification(SemaRef.Context,
604 CurContext,
Douglas Gregore0717ab2010-01-14 00:41:07 +0000605 R.Declaration->getDeclContext());
606 return false;
607}
608
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000609/// A simplified classification of types used to determine whether two
Douglas Gregor95887f92010-07-08 23:20:03 +0000610/// types are "similar enough" when adjusting priorities.
Douglas Gregor6e240332010-08-16 16:18:59 +0000611SimplifiedTypeClass clang::getSimplifiedTypeClass(CanQualType T) {
Douglas Gregor95887f92010-07-08 23:20:03 +0000612 switch (T->getTypeClass()) {
613 case Type::Builtin:
614 switch (cast<BuiltinType>(T)->getKind()) {
615 case BuiltinType::Void:
616 return STC_Void;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000617
Douglas Gregor95887f92010-07-08 23:20:03 +0000618 case BuiltinType::NullPtr:
619 return STC_Pointer;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000620
Douglas Gregor95887f92010-07-08 23:20:03 +0000621 case BuiltinType::Overload:
622 case BuiltinType::Dependent:
Douglas Gregor95887f92010-07-08 23:20:03 +0000623 return STC_Other;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000624
Douglas Gregor95887f92010-07-08 23:20:03 +0000625 case BuiltinType::ObjCId:
626 case BuiltinType::ObjCClass:
627 case BuiltinType::ObjCSel:
628 return STC_ObjectiveC;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000629
Douglas Gregor95887f92010-07-08 23:20:03 +0000630 default:
631 return STC_Arithmetic;
632 }
David Blaikie8a40f702012-01-17 06:56:22 +0000633
Douglas Gregor95887f92010-07-08 23:20:03 +0000634 case Type::Complex:
635 return STC_Arithmetic;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000636
Douglas Gregor95887f92010-07-08 23:20:03 +0000637 case Type::Pointer:
638 return STC_Pointer;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000639
Douglas Gregor95887f92010-07-08 23:20:03 +0000640 case Type::BlockPointer:
641 return STC_Block;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000642
Douglas Gregor95887f92010-07-08 23:20:03 +0000643 case Type::LValueReference:
644 case Type::RValueReference:
645 return getSimplifiedTypeClass(T->getAs<ReferenceType>()->getPointeeType());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000646
Douglas Gregor95887f92010-07-08 23:20:03 +0000647 case Type::ConstantArray:
648 case Type::IncompleteArray:
649 case Type::VariableArray:
650 case Type::DependentSizedArray:
651 return STC_Array;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000652
Douglas Gregor95887f92010-07-08 23:20:03 +0000653 case Type::DependentSizedExtVector:
654 case Type::Vector:
655 case Type::ExtVector:
656 return STC_Arithmetic;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000657
Douglas Gregor95887f92010-07-08 23:20:03 +0000658 case Type::FunctionProto:
659 case Type::FunctionNoProto:
660 return STC_Function;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000661
Douglas Gregor95887f92010-07-08 23:20:03 +0000662 case Type::Record:
663 return STC_Record;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000664
Douglas Gregor95887f92010-07-08 23:20:03 +0000665 case Type::Enum:
666 return STC_Arithmetic;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000667
Douglas Gregor95887f92010-07-08 23:20:03 +0000668 case Type::ObjCObject:
669 case Type::ObjCInterface:
670 case Type::ObjCObjectPointer:
671 return STC_ObjectiveC;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000672
Douglas Gregor95887f92010-07-08 23:20:03 +0000673 default:
674 return STC_Other;
675 }
676}
677
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000678/// Get the type that a given expression will have if this declaration
Douglas Gregor95887f92010-07-08 23:20:03 +0000679/// is used as an expression in its "typical" code-completion form.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000680QualType clang::getDeclUsageType(ASTContext &C, const NamedDecl *ND) {
George Burgess IV00f70bd2018-03-01 05:43:23 +0000681 ND = ND->getUnderlyingDecl();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000682
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000683 if (const TypeDecl *Type = dyn_cast<TypeDecl>(ND))
Douglas Gregor95887f92010-07-08 23:20:03 +0000684 return C.getTypeDeclType(Type);
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000685 if (const ObjCInterfaceDecl *Iface = dyn_cast<ObjCInterfaceDecl>(ND))
Douglas Gregor95887f92010-07-08 23:20:03 +0000686 return C.getObjCInterfaceType(Iface);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000687
Douglas Gregor95887f92010-07-08 23:20:03 +0000688 QualType T;
Alp Tokera2794f92014-01-22 07:29:52 +0000689 if (const FunctionDecl *Function = ND->getAsFunction())
Douglas Gregor603d81b2010-07-13 08:18:22 +0000690 T = Function->getCallResultType();
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000691 else if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND))
Douglas Gregor603d81b2010-07-13 08:18:22 +0000692 T = Method->getSendResultType();
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000693 else if (const EnumConstantDecl *Enumerator = dyn_cast<EnumConstantDecl>(ND))
Douglas Gregor95887f92010-07-08 23:20:03 +0000694 T = C.getTypeDeclType(cast<EnumDecl>(Enumerator->getDeclContext()));
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000695 else if (const ObjCPropertyDecl *Property = dyn_cast<ObjCPropertyDecl>(ND))
Douglas Gregor95887f92010-07-08 23:20:03 +0000696 T = Property->getType();
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000697 else if (const ValueDecl *Value = dyn_cast<ValueDecl>(ND))
Douglas Gregor95887f92010-07-08 23:20:03 +0000698 T = Value->getType();
699 else
700 return QualType();
Douglas Gregoraf670a82011-04-14 20:33:34 +0000701
702 // Dig through references, function pointers, and block pointers to
703 // get down to the likely type of an expression when the entity is
704 // used.
705 do {
706 if (const ReferenceType *Ref = T->getAs<ReferenceType>()) {
707 T = Ref->getPointeeType();
708 continue;
709 }
710
711 if (const PointerType *Pointer = T->getAs<PointerType>()) {
712 if (Pointer->getPointeeType()->isFunctionType()) {
713 T = Pointer->getPointeeType();
714 continue;
715 }
716
717 break;
718 }
719
720 if (const BlockPointerType *Block = T->getAs<BlockPointerType>()) {
721 T = Block->getPointeeType();
722 continue;
723 }
724
725 if (const FunctionType *Function = T->getAs<FunctionType>()) {
Alp Toker314cc812014-01-25 16:55:45 +0000726 T = Function->getReturnType();
Douglas Gregoraf670a82011-04-14 20:33:34 +0000727 continue;
728 }
729
730 break;
731 } while (true);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000732
Douglas Gregoraf670a82011-04-14 20:33:34 +0000733 return T;
Douglas Gregor95887f92010-07-08 23:20:03 +0000734}
735
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000736unsigned ResultBuilder::getBasePriority(const NamedDecl *ND) {
737 if (!ND)
738 return CCP_Unlikely;
739
740 // Context-based decisions.
Richard Smith541b38b2013-09-20 01:15:31 +0000741 const DeclContext *LexicalDC = ND->getLexicalDeclContext();
742 if (LexicalDC->isFunctionOrMethod()) {
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000743 // _cmd is relatively rare
744 if (const ImplicitParamDecl *ImplicitParam =
745 dyn_cast<ImplicitParamDecl>(ND))
746 if (ImplicitParam->getIdentifier() &&
747 ImplicitParam->getIdentifier()->isStr("_cmd"))
748 return CCP_ObjC_cmd;
749
750 return CCP_LocalDeclaration;
751 }
Richard Smith541b38b2013-09-20 01:15:31 +0000752
753 const DeclContext *DC = ND->getDeclContext()->getRedeclContext();
Ilya Biryukov4e7a6fe2017-09-22 19:07:37 +0000754 if (DC->isRecord() || isa<ObjCContainerDecl>(DC)) {
755 // Explicit destructor calls are very rare.
756 if (isa<CXXDestructorDecl>(ND))
757 return CCP_Unlikely;
758 // Explicit operator and conversion function calls are also very rare.
759 auto DeclNameKind = ND->getDeclName().getNameKind();
760 if (DeclNameKind == DeclarationName::CXXOperatorName ||
761 DeclNameKind == DeclarationName::CXXLiteralOperatorName ||
762 DeclNameKind == DeclarationName::CXXConversionFunctionName)
763 return CCP_Unlikely;
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000764 return CCP_MemberDeclaration;
Ilya Biryukov4e7a6fe2017-09-22 19:07:37 +0000765 }
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000766
767 // Content-based decisions.
768 if (isa<EnumConstantDecl>(ND))
769 return CCP_Constant;
770
Douglas Gregor52e0de42013-01-31 05:03:46 +0000771 // Use CCP_Type for type declarations unless we're in a statement, Objective-C
772 // message receiver, or parenthesized expression context. There, it's as
773 // likely that the user will want to write a type as other declarations.
774 if ((isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND)) &&
775 !(CompletionContext.getKind() == CodeCompletionContext::CCC_Statement ||
776 CompletionContext.getKind()
777 == CodeCompletionContext::CCC_ObjCMessageReceiver ||
778 CompletionContext.getKind()
779 == CodeCompletionContext::CCC_ParenthesizedExpression))
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000780 return CCP_Type;
781
782 return CCP_Declaration;
783}
784
Douglas Gregor50832e02010-09-20 22:39:41 +0000785void ResultBuilder::AdjustResultPriorityForDecl(Result &R) {
786 // If this is an Objective-C method declaration whose selector matches our
787 // preferred selector, give it a priority boost.
788 if (!PreferredSelector.isNull())
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000789 if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(R.Declaration))
Douglas Gregor50832e02010-09-20 22:39:41 +0000790 if (PreferredSelector == Method->getSelector())
791 R.Priority += CCD_SelectorMatch;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000792
Douglas Gregor50832e02010-09-20 22:39:41 +0000793 // If we have a preferred type, adjust the priority for results with exactly-
794 // matching or nearly-matching types.
795 if (!PreferredType.isNull()) {
796 QualType T = getDeclUsageType(SemaRef.Context, R.Declaration);
797 if (!T.isNull()) {
798 CanQualType TC = SemaRef.Context.getCanonicalType(T);
799 // Check for exactly-matching types (modulo qualifiers).
800 if (SemaRef.Context.hasSameUnqualifiedType(PreferredType, TC))
801 R.Priority /= CCF_ExactTypeMatch;
802 // Check for nearly-matching types, based on classification of each.
803 else if ((getSimplifiedTypeClass(PreferredType)
Douglas Gregor95887f92010-07-08 23:20:03 +0000804 == getSimplifiedTypeClass(TC)) &&
Douglas Gregor50832e02010-09-20 22:39:41 +0000805 !(PreferredType->isEnumeralType() && TC->isEnumeralType()))
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000806 R.Priority /= CCF_SimilarTypeMatch;
Douglas Gregor50832e02010-09-20 22:39:41 +0000807 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000808 }
Douglas Gregor95887f92010-07-08 23:20:03 +0000809}
810
Douglas Gregor0212fd72010-09-21 16:06:22 +0000811void ResultBuilder::MaybeAddConstructorResults(Result R) {
David Blaikiebbafb8a2012-03-11 07:00:24 +0000812 if (!SemaRef.getLangOpts().CPlusPlus || !R.Declaration ||
Douglas Gregor0212fd72010-09-21 16:06:22 +0000813 !CompletionContext.wantConstructorResults())
814 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000815
Douglas Gregor0212fd72010-09-21 16:06:22 +0000816 ASTContext &Context = SemaRef.Context;
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000817 const NamedDecl *D = R.Declaration;
Craig Topperc3ec1492014-05-26 06:22:03 +0000818 const CXXRecordDecl *Record = nullptr;
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000819 if (const ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(D))
Douglas Gregor0212fd72010-09-21 16:06:22 +0000820 Record = ClassTemplate->getTemplatedDecl();
821 else if ((Record = dyn_cast<CXXRecordDecl>(D))) {
822 // Skip specializations and partial specializations.
823 if (isa<ClassTemplateSpecializationDecl>(Record))
824 return;
825 } else {
826 // There are no constructors here.
827 return;
828 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000829
Douglas Gregor0212fd72010-09-21 16:06:22 +0000830 Record = Record->getDefinition();
831 if (!Record)
832 return;
833
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000834
Douglas Gregor0212fd72010-09-21 16:06:22 +0000835 QualType RecordTy = Context.getTypeDeclType(Record);
836 DeclarationName ConstructorName
837 = Context.DeclarationNames.getCXXConstructorName(
838 Context.getCanonicalType(RecordTy));
Richard Smithcf4bdde2015-02-21 02:45:19 +0000839 DeclContext::lookup_result Ctors = Record->lookup(ConstructorName);
840 for (DeclContext::lookup_iterator I = Ctors.begin(),
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000841 E = Ctors.end();
842 I != E; ++I) {
David Blaikieff7d47a2012-12-19 00:45:41 +0000843 R.Declaration = *I;
Douglas Gregor0212fd72010-09-21 16:06:22 +0000844 R.CursorKind = getCursorKindForDecl(R.Declaration);
845 Results.push_back(R);
846 }
847}
848
Sam McCall63c59722018-01-22 20:44:47 +0000849static bool isConstructor(const Decl *ND) {
850 if (const auto *Tmpl = dyn_cast<FunctionTemplateDecl>(ND))
851 ND = Tmpl->getTemplatedDecl();
852 return isa<CXXConstructorDecl>(ND);
853}
854
Douglas Gregor7c208612010-01-14 00:20:49 +0000855void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) {
856 assert(!ShadowMaps.empty() && "Must enter into a results scope");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000857
Douglas Gregor7c208612010-01-14 00:20:49 +0000858 if (R.Kind != Result::RK_Declaration) {
859 // For non-declaration results, just add the result.
860 Results.push_back(R);
861 return;
862 }
863
864 // Look through using declarations.
Kirill Bobyrev47d7f522018-07-11 14:49:49 +0000865 if (const UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(R.Declaration)) {
866 CodeCompletionResult Result(Using->getTargetDecl(),
867 getBasePriority(Using->getTargetDecl()),
868 R.Qualifier);
869 Result.ShadowDecl = Using;
870 MaybeAddResult(Result, CurContext);
Douglas Gregor7c208612010-01-14 00:20:49 +0000871 return;
872 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000873
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000874 const Decl *CanonDecl = R.Declaration->getCanonicalDecl();
Douglas Gregor7c208612010-01-14 00:20:49 +0000875 unsigned IDNS = CanonDecl->getIdentifierNamespace();
876
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000877 bool AsNestedNameSpecifier = false;
878 if (!isInterestingDecl(R.Declaration, AsNestedNameSpecifier))
Douglas Gregor7c208612010-01-14 00:20:49 +0000879 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000880
Douglas Gregor0212fd72010-09-21 16:06:22 +0000881 // C++ constructors are never found by name lookup.
Sam McCall63c59722018-01-22 20:44:47 +0000882 if (isConstructor(R.Declaration))
Douglas Gregor0212fd72010-09-21 16:06:22 +0000883 return;
884
Douglas Gregor3545ff42009-09-21 16:56:56 +0000885 ShadowMap &SMap = ShadowMaps.back();
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000886 ShadowMapEntry::iterator I, IEnd;
887 ShadowMap::iterator NamePos = SMap.find(R.Declaration->getDeclName());
888 if (NamePos != SMap.end()) {
889 I = NamePos->second.begin();
890 IEnd = NamePos->second.end();
891 }
892
893 for (; I != IEnd; ++I) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000894 const NamedDecl *ND = I->first;
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000895 unsigned Index = I->second;
Douglas Gregor3545ff42009-09-21 16:56:56 +0000896 if (ND->getCanonicalDecl() == CanonDecl) {
897 // This is a redeclaration. Always pick the newer declaration.
Douglas Gregor3545ff42009-09-21 16:56:56 +0000898 Results[Index].Declaration = R.Declaration;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000899
Douglas Gregor3545ff42009-09-21 16:56:56 +0000900 // We're done.
901 return;
902 }
903 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000904
Douglas Gregor3545ff42009-09-21 16:56:56 +0000905 // This is a new declaration in this scope. However, check whether this
906 // declaration name is hidden by a similarly-named declaration in an outer
907 // scope.
908 std::list<ShadowMap>::iterator SM, SMEnd = ShadowMaps.end();
909 --SMEnd;
910 for (SM = ShadowMaps.begin(); SM != SMEnd; ++SM) {
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000911 ShadowMapEntry::iterator I, IEnd;
912 ShadowMap::iterator NamePos = SM->find(R.Declaration->getDeclName());
913 if (NamePos != SM->end()) {
914 I = NamePos->second.begin();
915 IEnd = NamePos->second.end();
916 }
917 for (; I != IEnd; ++I) {
Douglas Gregor3545ff42009-09-21 16:56:56 +0000918 // A tag declaration does not hide a non-tag declaration.
John McCalle87beb22010-04-23 18:46:30 +0000919 if (I->first->hasTagIdentifierNamespace() &&
Richard Smith541b38b2013-09-20 01:15:31 +0000920 (IDNS & (Decl::IDNS_Member | Decl::IDNS_Ordinary |
921 Decl::IDNS_LocalExtern | Decl::IDNS_ObjCProtocol)))
Douglas Gregor3545ff42009-09-21 16:56:56 +0000922 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000923
Douglas Gregor3545ff42009-09-21 16:56:56 +0000924 // Protocols are in distinct namespaces from everything else.
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000925 if (((I->first->getIdentifierNamespace() & Decl::IDNS_ObjCProtocol)
Douglas Gregor3545ff42009-09-21 16:56:56 +0000926 || (IDNS & Decl::IDNS_ObjCProtocol)) &&
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000927 I->first->getIdentifierNamespace() != IDNS)
Douglas Gregor3545ff42009-09-21 16:56:56 +0000928 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000929
Douglas Gregor3545ff42009-09-21 16:56:56 +0000930 // The newly-added result is hidden by an entry in the shadow map.
Douglas Gregore0717ab2010-01-14 00:41:07 +0000931 if (CheckHiddenResult(R, CurContext, I->first))
Douglas Gregor3545ff42009-09-21 16:56:56 +0000932 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000933
Douglas Gregor3545ff42009-09-21 16:56:56 +0000934 break;
935 }
936 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000937
Douglas Gregor3545ff42009-09-21 16:56:56 +0000938 // Make sure that any given declaration only shows up in the result set once.
David Blaikie82e95a32014-11-19 07:49:47 +0000939 if (!AllDeclsFound.insert(CanonDecl).second)
Douglas Gregor3545ff42009-09-21 16:56:56 +0000940 return;
Douglas Gregorc2cb2e22010-08-27 15:29:55 +0000941
Douglas Gregore412a5a2009-09-23 22:26:46 +0000942 // If the filter is for nested-name-specifiers, then this result starts a
943 // nested-name-specifier.
Douglas Gregora2db7932010-05-26 22:00:08 +0000944 if (AsNestedNameSpecifier) {
Douglas Gregore412a5a2009-09-23 22:26:46 +0000945 R.StartsNestedNameSpecifier = true;
Douglas Gregora2db7932010-05-26 22:00:08 +0000946 R.Priority = CCP_NestedNameSpecifier;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000947 } else
Douglas Gregor50832e02010-09-20 22:39:41 +0000948 AdjustResultPriorityForDecl(R);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000949
Douglas Gregor5bf52692009-09-22 23:15:58 +0000950 // If this result is supposed to have an informative qualifier, add one.
Douglas Gregore412a5a2009-09-23 22:26:46 +0000951 if (R.QualifierIsInformative && !R.Qualifier &&
952 !R.StartsNestedNameSpecifier) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000953 const DeclContext *Ctx = R.Declaration->getDeclContext();
954 if (const NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Ctx))
Craig Topperc3ec1492014-05-26 06:22:03 +0000955 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, nullptr,
956 Namespace);
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000957 else if (const TagDecl *Tag = dyn_cast<TagDecl>(Ctx))
Craig Topperc3ec1492014-05-26 06:22:03 +0000958 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, nullptr,
959 false, SemaRef.Context.getTypeDeclType(Tag).getTypePtr());
Douglas Gregor5bf52692009-09-22 23:15:58 +0000960 else
961 R.QualifierIsInformative = false;
962 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000963
Douglas Gregor3545ff42009-09-21 16:56:56 +0000964 // Insert this result into the set of results and into the current shadow
965 // map.
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000966 SMap[R.Declaration->getDeclName()].Add(R.Declaration, Results.size());
Douglas Gregor3545ff42009-09-21 16:56:56 +0000967 Results.push_back(R);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000968
Douglas Gregor0212fd72010-09-21 16:06:22 +0000969 if (!AsNestedNameSpecifier)
970 MaybeAddConstructorResults(R);
Douglas Gregor3545ff42009-09-21 16:56:56 +0000971}
972
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000973void ResultBuilder::AddResult(Result R, DeclContext *CurContext,
Douglas Gregor09bbc652010-01-14 15:47:35 +0000974 NamedDecl *Hiding, bool InBaseClass = false) {
Douglas Gregor78a21012010-01-14 16:01:26 +0000975 if (R.Kind != Result::RK_Declaration) {
976 // For non-declaration results, just add the result.
977 Results.push_back(R);
978 return;
979 }
980
Douglas Gregorc580c522010-01-14 01:09:38 +0000981 // Look through using declarations.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000982 if (const UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(R.Declaration)) {
Kirill Bobyrev47d7f522018-07-11 14:49:49 +0000983 CodeCompletionResult Result(Using->getTargetDecl(),
984 getBasePriority(Using->getTargetDecl()),
985 R.Qualifier);
986 Result.ShadowDecl = Using;
987 AddResult(Result, CurContext, Hiding);
Douglas Gregorc580c522010-01-14 01:09:38 +0000988 return;
989 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000990
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000991 bool AsNestedNameSpecifier = false;
992 if (!isInterestingDecl(R.Declaration, AsNestedNameSpecifier))
Douglas Gregorc580c522010-01-14 01:09:38 +0000993 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000994
Douglas Gregor0212fd72010-09-21 16:06:22 +0000995 // C++ constructors are never found by name lookup.
Sam McCall63c59722018-01-22 20:44:47 +0000996 if (isConstructor(R.Declaration))
Douglas Gregor0212fd72010-09-21 16:06:22 +0000997 return;
998
Douglas Gregorc580c522010-01-14 01:09:38 +0000999 if (Hiding && CheckHiddenResult(R, CurContext, Hiding))
1000 return;
Nick Lewyckyc3921482012-04-03 21:44:08 +00001001
Douglas Gregorc580c522010-01-14 01:09:38 +00001002 // Make sure that any given declaration only shows up in the result set once.
David Blaikie82e95a32014-11-19 07:49:47 +00001003 if (!AllDeclsFound.insert(R.Declaration->getCanonicalDecl()).second)
Douglas Gregorc580c522010-01-14 01:09:38 +00001004 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001005
Douglas Gregorc580c522010-01-14 01:09:38 +00001006 // If the filter is for nested-name-specifiers, then this result starts a
1007 // nested-name-specifier.
Douglas Gregora2db7932010-05-26 22:00:08 +00001008 if (AsNestedNameSpecifier) {
Douglas Gregorc580c522010-01-14 01:09:38 +00001009 R.StartsNestedNameSpecifier = true;
Douglas Gregora2db7932010-05-26 22:00:08 +00001010 R.Priority = CCP_NestedNameSpecifier;
Kirill Bobyrev47d7f522018-07-11 14:49:49 +00001011 } else if (Filter == &ResultBuilder::IsMember && !R.Qualifier &&
1012 InBaseClass &&
1013 isa<CXXRecordDecl>(
1014 R.Declaration->getDeclContext()->getRedeclContext()))
Douglas Gregor09bbc652010-01-14 15:47:35 +00001015 R.QualifierIsInformative = true;
1016
Douglas Gregorc580c522010-01-14 01:09:38 +00001017 // If this result is supposed to have an informative qualifier, add one.
1018 if (R.QualifierIsInformative && !R.Qualifier &&
1019 !R.StartsNestedNameSpecifier) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001020 const DeclContext *Ctx = R.Declaration->getDeclContext();
1021 if (const NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Ctx))
Craig Topperc3ec1492014-05-26 06:22:03 +00001022 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, nullptr,
1023 Namespace);
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001024 else if (const TagDecl *Tag = dyn_cast<TagDecl>(Ctx))
Craig Topperc3ec1492014-05-26 06:22:03 +00001025 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, nullptr, false,
Douglas Gregor6ae4c522010-01-14 03:21:49 +00001026 SemaRef.Context.getTypeDeclType(Tag).getTypePtr());
Douglas Gregorc580c522010-01-14 01:09:38 +00001027 else
1028 R.QualifierIsInformative = false;
1029 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001030
Douglas Gregora2db7932010-05-26 22:00:08 +00001031 // Adjust the priority if this result comes from a base class.
1032 if (InBaseClass)
1033 R.Priority += CCD_InBaseClass;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001034
Douglas Gregor50832e02010-09-20 22:39:41 +00001035 AdjustResultPriorityForDecl(R);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001036
Douglas Gregor9be0ed42010-08-26 16:36:48 +00001037 if (HasObjectTypeQualifiers)
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001038 if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(R.Declaration))
Douglas Gregor9be0ed42010-08-26 16:36:48 +00001039 if (Method->isInstance()) {
1040 Qualifiers MethodQuals
1041 = Qualifiers::fromCVRMask(Method->getTypeQualifiers());
1042 if (ObjectTypeQualifiers == MethodQuals)
1043 R.Priority += CCD_ObjectQualifierMatch;
1044 else if (ObjectTypeQualifiers - MethodQuals) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001045 // The method cannot be invoked, because doing so would drop
Douglas Gregor9be0ed42010-08-26 16:36:48 +00001046 // qualifiers.
1047 return;
1048 }
1049 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001050
Douglas Gregorc580c522010-01-14 01:09:38 +00001051 // Insert this result into the set of results.
1052 Results.push_back(R);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001053
Douglas Gregor0212fd72010-09-21 16:06:22 +00001054 if (!AsNestedNameSpecifier)
1055 MaybeAddConstructorResults(R);
Douglas Gregorc580c522010-01-14 01:09:38 +00001056}
1057
Douglas Gregor78a21012010-01-14 16:01:26 +00001058void ResultBuilder::AddResult(Result R) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001059 assert(R.Kind != Result::RK_Declaration &&
Douglas Gregor78a21012010-01-14 16:01:26 +00001060 "Declaration results need more context");
1061 Results.push_back(R);
1062}
1063
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001064/// Enter into a new scope.
Benjamin Kramer3204b152015-05-29 19:42:19 +00001065void ResultBuilder::EnterNewScope() { ShadowMaps.emplace_back(); }
Douglas Gregor3545ff42009-09-21 16:56:56 +00001066
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001067/// Exit from the current scope.
Douglas Gregor3545ff42009-09-21 16:56:56 +00001068void ResultBuilder::ExitScope() {
Douglas Gregor05e7ca32009-12-06 20:23:50 +00001069 for (ShadowMap::iterator E = ShadowMaps.back().begin(),
1070 EEnd = ShadowMaps.back().end();
1071 E != EEnd;
1072 ++E)
1073 E->second.Destroy();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001074
Douglas Gregor3545ff42009-09-21 16:56:56 +00001075 ShadowMaps.pop_back();
1076}
1077
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001078/// Determines whether this given declaration will be found by
Douglas Gregor9d64c5e2009-09-21 20:51:25 +00001079/// ordinary name lookup.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001080bool ResultBuilder::IsOrdinaryName(const NamedDecl *ND) const {
George Burgess IV00f70bd2018-03-01 05:43:23 +00001081 ND = ND->getUnderlyingDecl();
Douglas Gregor70febae2010-05-28 00:49:12 +00001082
Richard Smith541b38b2013-09-20 01:15:31 +00001083 // If name lookup finds a local extern declaration, then we are in a
1084 // context where it behaves like an ordinary name.
1085 unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_LocalExtern;
David Blaikiebbafb8a2012-03-11 07:00:24 +00001086 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregor9858ed52010-06-15 20:26:51 +00001087 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member;
David Blaikiebbafb8a2012-03-11 07:00:24 +00001088 else if (SemaRef.getLangOpts().ObjC1) {
Douglas Gregor05fcf842010-11-02 20:36:02 +00001089 if (isa<ObjCIvarDecl>(ND))
1090 return true;
Douglas Gregor05fcf842010-11-02 20:36:02 +00001091 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001092
Douglas Gregor9d64c5e2009-09-21 20:51:25 +00001093 return ND->getIdentifierNamespace() & IDNS;
1094}
1095
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001096/// Determines whether this given declaration will be found by
Douglas Gregor70febae2010-05-28 00:49:12 +00001097/// ordinary name lookup but is not a type name.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001098bool ResultBuilder::IsOrdinaryNonTypeName(const NamedDecl *ND) const {
George Burgess IV00f70bd2018-03-01 05:43:23 +00001099 ND = ND->getUnderlyingDecl();
Alex Lorenzf3df1f72017-11-14 01:46:24 +00001100 if (isa<TypeDecl>(ND))
Douglas Gregor70febae2010-05-28 00:49:12 +00001101 return false;
Alex Lorenzf3df1f72017-11-14 01:46:24 +00001102 // Objective-C interfaces names are not filtered by this method because they
1103 // can be used in a class property expression. We can still filter out
1104 // @class declarations though.
1105 if (const auto *ID = dyn_cast<ObjCInterfaceDecl>(ND)) {
1106 if (!ID->getDefinition())
1107 return false;
1108 }
1109
Richard Smith541b38b2013-09-20 01:15:31 +00001110 unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_LocalExtern;
David Blaikiebbafb8a2012-03-11 07:00:24 +00001111 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregor9858ed52010-06-15 20:26:51 +00001112 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member;
David Blaikiebbafb8a2012-03-11 07:00:24 +00001113 else if (SemaRef.getLangOpts().ObjC1) {
Douglas Gregor05fcf842010-11-02 20:36:02 +00001114 if (isa<ObjCIvarDecl>(ND))
1115 return true;
Douglas Gregor05fcf842010-11-02 20:36:02 +00001116 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001117
Douglas Gregor70febae2010-05-28 00:49:12 +00001118 return ND->getIdentifierNamespace() & IDNS;
1119}
1120
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001121bool ResultBuilder::IsIntegralConstantValue(const NamedDecl *ND) const {
Douglas Gregor85b50632010-07-28 21:50:18 +00001122 if (!IsOrdinaryNonTypeName(ND))
1123 return 0;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001124
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001125 if (const ValueDecl *VD = dyn_cast<ValueDecl>(ND->getUnderlyingDecl()))
Douglas Gregor85b50632010-07-28 21:50:18 +00001126 if (VD->getType()->isIntegralOrEnumerationType())
1127 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001128
Douglas Gregor85b50632010-07-28 21:50:18 +00001129 return false;
1130}
1131
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001132/// Determines whether this given declaration will be found by
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001133/// ordinary name lookup.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001134bool ResultBuilder::IsOrdinaryNonValueName(const NamedDecl *ND) const {
George Burgess IV00f70bd2018-03-01 05:43:23 +00001135 ND = ND->getUnderlyingDecl();
Douglas Gregor70febae2010-05-28 00:49:12 +00001136
Richard Smith541b38b2013-09-20 01:15:31 +00001137 unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_LocalExtern;
David Blaikiebbafb8a2012-03-11 07:00:24 +00001138 if (SemaRef.getLangOpts().CPlusPlus)
John McCalle87beb22010-04-23 18:46:30 +00001139 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001140
1141 return (ND->getIdentifierNamespace() & IDNS) &&
1142 !isa<ValueDecl>(ND) && !isa<FunctionTemplateDecl>(ND) &&
Douglas Gregor70febae2010-05-28 00:49:12 +00001143 !isa<ObjCPropertyDecl>(ND);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001144}
1145
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001146/// Determines whether the given declaration is suitable as the
Douglas Gregor3545ff42009-09-21 16:56:56 +00001147/// start of a C++ nested-name-specifier, e.g., a class or namespace.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001148bool ResultBuilder::IsNestedNameSpecifier(const NamedDecl *ND) const {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001149 // Allow us to find class templates, too.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001150 if (const ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
Douglas Gregor3545ff42009-09-21 16:56:56 +00001151 ND = ClassTemplate->getTemplatedDecl();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001152
Douglas Gregor3545ff42009-09-21 16:56:56 +00001153 return SemaRef.isAcceptableNestedNameSpecifier(ND);
1154}
1155
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001156/// Determines whether the given declaration is an enumeration.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001157bool ResultBuilder::IsEnum(const NamedDecl *ND) const {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001158 return isa<EnumDecl>(ND);
1159}
1160
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001161/// Determines whether the given declaration is a class or struct.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001162bool ResultBuilder::IsClassOrStruct(const NamedDecl *ND) const {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001163 // Allow us to find class templates, too.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001164 if (const ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
Douglas Gregor3545ff42009-09-21 16:56:56 +00001165 ND = ClassTemplate->getTemplatedDecl();
Joao Matosdc86f942012-08-31 18:45:21 +00001166
1167 // For purposes of this check, interfaces match too.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001168 if (const RecordDecl *RD = dyn_cast<RecordDecl>(ND))
Abramo Bagnara6150c882010-05-11 21:36:43 +00001169 return RD->getTagKind() == TTK_Class ||
Joao Matosdc86f942012-08-31 18:45:21 +00001170 RD->getTagKind() == TTK_Struct ||
1171 RD->getTagKind() == TTK_Interface;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001172
Douglas Gregor3545ff42009-09-21 16:56:56 +00001173 return false;
1174}
1175
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001176/// Determines whether the given declaration is a union.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001177bool ResultBuilder::IsUnion(const NamedDecl *ND) const {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001178 // Allow us to find class templates, too.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001179 if (const ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
Douglas Gregor3545ff42009-09-21 16:56:56 +00001180 ND = ClassTemplate->getTemplatedDecl();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001181
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001182 if (const RecordDecl *RD = dyn_cast<RecordDecl>(ND))
Abramo Bagnara6150c882010-05-11 21:36:43 +00001183 return RD->getTagKind() == TTK_Union;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001184
Douglas Gregor3545ff42009-09-21 16:56:56 +00001185 return false;
1186}
1187
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001188/// Determines whether the given declaration is a namespace.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001189bool ResultBuilder::IsNamespace(const NamedDecl *ND) const {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001190 return isa<NamespaceDecl>(ND);
1191}
1192
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001193/// Determines whether the given declaration is a namespace or
Douglas Gregor3545ff42009-09-21 16:56:56 +00001194/// namespace alias.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001195bool ResultBuilder::IsNamespaceOrAlias(const NamedDecl *ND) const {
Richard Smithf2005d32015-12-29 23:34:32 +00001196 return isa<NamespaceDecl>(ND->getUnderlyingDecl());
Douglas Gregor3545ff42009-09-21 16:56:56 +00001197}
1198
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001199/// Determines whether the given declaration is a type.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001200bool ResultBuilder::IsType(const NamedDecl *ND) const {
Richard Smithf2005d32015-12-29 23:34:32 +00001201 ND = ND->getUnderlyingDecl();
Douglas Gregor99fa2642010-08-24 01:06:58 +00001202 return isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND);
Douglas Gregor3545ff42009-09-21 16:56:56 +00001203}
1204
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001205/// Determines which members of a class should be visible via
Douglas Gregor99fe2ad2009-12-11 17:31:05 +00001206/// "." or "->". Only value declarations, nested name specifiers, and
1207/// using declarations thereof should show up.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001208bool ResultBuilder::IsMember(const NamedDecl *ND) const {
Richard Smithf2005d32015-12-29 23:34:32 +00001209 ND = ND->getUnderlyingDecl();
Douglas Gregor70788392009-12-11 18:14:22 +00001210 return isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND) ||
Richard Smithf2005d32015-12-29 23:34:32 +00001211 isa<ObjCPropertyDecl>(ND);
Douglas Gregore412a5a2009-09-23 22:26:46 +00001212}
1213
Douglas Gregora817a192010-05-27 23:06:34 +00001214static bool isObjCReceiverType(ASTContext &C, QualType T) {
1215 T = C.getCanonicalType(T);
1216 switch (T->getTypeClass()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001217 case Type::ObjCObject:
Douglas Gregora817a192010-05-27 23:06:34 +00001218 case Type::ObjCInterface:
1219 case Type::ObjCObjectPointer:
1220 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001221
Douglas Gregora817a192010-05-27 23:06:34 +00001222 case Type::Builtin:
1223 switch (cast<BuiltinType>(T)->getKind()) {
1224 case BuiltinType::ObjCId:
1225 case BuiltinType::ObjCClass:
1226 case BuiltinType::ObjCSel:
1227 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001228
Douglas Gregora817a192010-05-27 23:06:34 +00001229 default:
1230 break;
1231 }
1232 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001233
Douglas Gregora817a192010-05-27 23:06:34 +00001234 default:
1235 break;
1236 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001237
David Blaikiebbafb8a2012-03-11 07:00:24 +00001238 if (!C.getLangOpts().CPlusPlus)
Douglas Gregora817a192010-05-27 23:06:34 +00001239 return false;
1240
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001241 // FIXME: We could perform more analysis here to determine whether a
Douglas Gregora817a192010-05-27 23:06:34 +00001242 // particular class type has any conversions to Objective-C types. For now,
1243 // just accept all class types.
1244 return T->isDependentType() || T->isRecordType();
1245}
1246
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001247bool ResultBuilder::IsObjCMessageReceiver(const NamedDecl *ND) const {
Douglas Gregora817a192010-05-27 23:06:34 +00001248 QualType T = getDeclUsageType(SemaRef.Context, ND);
1249 if (T.isNull())
1250 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001251
Douglas Gregora817a192010-05-27 23:06:34 +00001252 T = SemaRef.Context.getBaseElementType(T);
1253 return isObjCReceiverType(SemaRef.Context, T);
1254}
1255
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001256bool ResultBuilder::IsObjCMessageReceiverOrLambdaCapture(const NamedDecl *ND) const {
Douglas Gregord8c61782012-02-15 15:34:24 +00001257 if (IsObjCMessageReceiver(ND))
1258 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001259
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001260 const VarDecl *Var = dyn_cast<VarDecl>(ND);
Douglas Gregord8c61782012-02-15 15:34:24 +00001261 if (!Var)
1262 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001263
Douglas Gregord8c61782012-02-15 15:34:24 +00001264 return Var->hasLocalStorage() && !Var->hasAttr<BlocksAttr>();
1265}
1266
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001267bool ResultBuilder::IsObjCCollection(const NamedDecl *ND) const {
David Blaikiebbafb8a2012-03-11 07:00:24 +00001268 if ((SemaRef.getLangOpts().CPlusPlus && !IsOrdinaryName(ND)) ||
1269 (!SemaRef.getLangOpts().CPlusPlus && !IsOrdinaryNonTypeName(ND)))
Douglas Gregor68762e72010-08-23 21:17:50 +00001270 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001271
Douglas Gregor68762e72010-08-23 21:17:50 +00001272 QualType T = getDeclUsageType(SemaRef.Context, ND);
1273 if (T.isNull())
1274 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001275
Douglas Gregor68762e72010-08-23 21:17:50 +00001276 T = SemaRef.Context.getBaseElementType(T);
1277 return T->isObjCObjectType() || T->isObjCObjectPointerType() ||
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001278 T->isObjCIdType() ||
David Blaikiebbafb8a2012-03-11 07:00:24 +00001279 (SemaRef.getLangOpts().CPlusPlus && T->isRecordType());
Douglas Gregor68762e72010-08-23 21:17:50 +00001280}
Douglas Gregora817a192010-05-27 23:06:34 +00001281
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001282bool ResultBuilder::IsImpossibleToSatisfy(const NamedDecl *ND) const {
Douglas Gregor0ac41382010-09-23 23:01:17 +00001283 return false;
1284}
1285
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001286/// Determines whether the given declaration is an Objective-C
Douglas Gregor2b8162b2010-01-14 16:08:12 +00001287/// instance variable.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001288bool ResultBuilder::IsObjCIvar(const NamedDecl *ND) const {
Douglas Gregor2b8162b2010-01-14 16:08:12 +00001289 return isa<ObjCIvarDecl>(ND);
1290}
1291
Douglas Gregorc580c522010-01-14 01:09:38 +00001292namespace {
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001293 /// Visible declaration consumer that adds a code-completion result
Douglas Gregorc580c522010-01-14 01:09:38 +00001294 /// for each visible declaration.
1295 class CodeCompletionDeclConsumer : public VisibleDeclConsumer {
1296 ResultBuilder &Results;
1297 DeclContext *CurContext;
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00001298 std::vector<FixItHint> FixIts;
Eric Liub91e0812018-10-02 10:29:00 +00001299 // This is set to the record where the search starts, if this is a record
1300 // member completion.
1301 RecordDecl *MemberCompletionRecord = nullptr;
Haojian Wu10d95c52018-01-17 14:29:25 +00001302
Douglas Gregorc580c522010-01-14 01:09:38 +00001303 public:
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00001304 CodeCompletionDeclConsumer(
1305 ResultBuilder &Results, DeclContext *CurContext,
Eric Liub91e0812018-10-02 10:29:00 +00001306 std::vector<FixItHint> FixIts = std::vector<FixItHint>(),
1307 RecordDecl *MemberCompletionRecord = nullptr)
1308 : Results(Results), CurContext(CurContext), FixIts(std::move(FixIts)),
1309 MemberCompletionRecord(MemberCompletionRecord) {}
Craig Toppere14c0f82014-03-12 04:55:44 +00001310
1311 void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx,
1312 bool InBaseClass) override {
Erik Verbruggen2e657ff2011-10-06 07:27:49 +00001313 bool Accessible = true;
Eric Liub91e0812018-10-02 10:29:00 +00001314 if (Ctx) {
1315 // Set the actual accessing context (i.e. naming class) to the record
1316 // context where the search starts. When `InBaseClass` is true, `Ctx`
1317 // will be the base class, which is not the actual naming class.
1318 DeclContext *AccessingCtx =
1319 MemberCompletionRecord ? MemberCompletionRecord : Ctx;
1320 Accessible = Results.getSema().IsSimplyAccessible(ND, AccessingCtx);
1321 }
Craig Topperc3ec1492014-05-26 06:22:03 +00001322 ResultBuilder::Result Result(ND, Results.getBasePriority(ND), nullptr,
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00001323 false, Accessible, FixIts);
Erik Verbruggen2e657ff2011-10-06 07:27:49 +00001324 Results.AddResult(Result, CurContext, Hiding, InBaseClass);
Douglas Gregorc580c522010-01-14 01:09:38 +00001325 }
Haojian Wu10d95c52018-01-17 14:29:25 +00001326
1327 void EnteredContext(DeclContext* Ctx) override {
1328 Results.addVisitedContext(Ctx);
1329 }
Douglas Gregorc580c522010-01-14 01:09:38 +00001330 };
Alexander Kornienkoab9db512015-06-22 23:07:51 +00001331}
Douglas Gregorc580c522010-01-14 01:09:38 +00001332
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001333/// Add type specifiers for the current language as keyword results.
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001334static void AddTypeSpecifierResults(const LangOptions &LangOpts,
Douglas Gregor3545ff42009-09-21 16:56:56 +00001335 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00001336 typedef CodeCompletionResult Result;
Douglas Gregora2db7932010-05-26 22:00:08 +00001337 Results.AddResult(Result("short", CCP_Type));
1338 Results.AddResult(Result("long", CCP_Type));
1339 Results.AddResult(Result("signed", CCP_Type));
1340 Results.AddResult(Result("unsigned", CCP_Type));
1341 Results.AddResult(Result("void", CCP_Type));
1342 Results.AddResult(Result("char", CCP_Type));
1343 Results.AddResult(Result("int", CCP_Type));
1344 Results.AddResult(Result("float", CCP_Type));
1345 Results.AddResult(Result("double", CCP_Type));
1346 Results.AddResult(Result("enum", CCP_Type));
1347 Results.AddResult(Result("struct", CCP_Type));
1348 Results.AddResult(Result("union", CCP_Type));
1349 Results.AddResult(Result("const", CCP_Type));
1350 Results.AddResult(Result("volatile", CCP_Type));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001351
Douglas Gregor3545ff42009-09-21 16:56:56 +00001352 if (LangOpts.C99) {
1353 // C99-specific
Douglas Gregora2db7932010-05-26 22:00:08 +00001354 Results.AddResult(Result("_Complex", CCP_Type));
1355 Results.AddResult(Result("_Imaginary", CCP_Type));
1356 Results.AddResult(Result("_Bool", CCP_Type));
1357 Results.AddResult(Result("restrict", CCP_Type));
Douglas Gregor3545ff42009-09-21 16:56:56 +00001358 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001359
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00001360 CodeCompletionBuilder Builder(Results.getAllocator(),
1361 Results.getCodeCompletionTUInfo());
Douglas Gregor3545ff42009-09-21 16:56:56 +00001362 if (LangOpts.CPlusPlus) {
1363 // C++-specific
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001364 Results.AddResult(Result("bool", CCP_Type +
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00001365 (LangOpts.ObjC1? CCD_bool_in_ObjC : 0)));
Douglas Gregora2db7932010-05-26 22:00:08 +00001366 Results.AddResult(Result("class", CCP_Type));
1367 Results.AddResult(Result("wchar_t", CCP_Type));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001368
Douglas Gregorf4c33342010-05-28 00:22:41 +00001369 // typename qualified-id
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001370 Builder.AddTypedTextChunk("typename");
1371 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1372 Builder.AddPlaceholderChunk("qualifier");
1373 Builder.AddTextChunk("::");
1374 Builder.AddPlaceholderChunk("name");
1375 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001376
Richard Smith2bf7fdb2013-01-02 11:42:31 +00001377 if (LangOpts.CPlusPlus11) {
Douglas Gregora2db7932010-05-26 22:00:08 +00001378 Results.AddResult(Result("auto", CCP_Type));
1379 Results.AddResult(Result("char16_t", CCP_Type));
1380 Results.AddResult(Result("char32_t", CCP_Type));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001381
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001382 Builder.AddTypedTextChunk("decltype");
1383 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1384 Builder.AddPlaceholderChunk("expression");
1385 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1386 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor3545ff42009-09-21 16:56:56 +00001387 }
Alex Lorenz46eed9d2017-02-13 23:35:59 +00001388 } else
1389 Results.AddResult(Result("__auto_type", CCP_Type));
1390
Richard Smith7b301e22018-05-24 21:51:52 +00001391 // GNU keywords
1392 if (LangOpts.GNUKeywords) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001393 // FIXME: Enable when we actually support decimal floating point.
Douglas Gregor78a21012010-01-14 16:01:26 +00001394 // Results.AddResult(Result("_Decimal32"));
1395 // Results.AddResult(Result("_Decimal64"));
1396 // Results.AddResult(Result("_Decimal128"));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001397
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001398 Builder.AddTypedTextChunk("typeof");
1399 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1400 Builder.AddPlaceholderChunk("expression");
1401 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00001402
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001403 Builder.AddTypedTextChunk("typeof");
1404 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1405 Builder.AddPlaceholderChunk("type");
1406 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1407 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor3545ff42009-09-21 16:56:56 +00001408 }
Douglas Gregor86b42682015-06-19 18:27:52 +00001409
1410 // Nullability
Douglas Gregoraea7afd2015-06-24 22:02:08 +00001411 Results.AddResult(Result("_Nonnull", CCP_Type));
1412 Results.AddResult(Result("_Null_unspecified", CCP_Type));
1413 Results.AddResult(Result("_Nullable", CCP_Type));
Douglas Gregor3545ff42009-09-21 16:56:56 +00001414}
1415
John McCallfaf5fb42010-08-26 23:41:50 +00001416static void AddStorageSpecifiers(Sema::ParserCompletionContext CCC,
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001417 const LangOptions &LangOpts,
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001418 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00001419 typedef CodeCompletionResult Result;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001420 // Note: we don't suggest either "auto" or "register", because both
1421 // are pointless as storage specifiers. Elsewhere, we suggest "auto"
1422 // in C++0x as a type specifier.
Douglas Gregor78a21012010-01-14 16:01:26 +00001423 Results.AddResult(Result("extern"));
1424 Results.AddResult(Result("static"));
Alex Lorenz8f4d3992017-02-13 23:19:40 +00001425
1426 if (LangOpts.CPlusPlus11) {
1427 CodeCompletionAllocator &Allocator = Results.getAllocator();
1428 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
1429
1430 // alignas
1431 Builder.AddTypedTextChunk("alignas");
1432 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1433 Builder.AddPlaceholderChunk("expression");
1434 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1435 Results.AddResult(Result(Builder.TakeString()));
1436
1437 Results.AddResult(Result("constexpr"));
1438 Results.AddResult(Result("thread_local"));
1439 }
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001440}
1441
John McCallfaf5fb42010-08-26 23:41:50 +00001442static void AddFunctionSpecifiers(Sema::ParserCompletionContext CCC,
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001443 const LangOptions &LangOpts,
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001444 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00001445 typedef CodeCompletionResult Result;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001446 switch (CCC) {
John McCallfaf5fb42010-08-26 23:41:50 +00001447 case Sema::PCC_Class:
1448 case Sema::PCC_MemberTemplate:
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001449 if (LangOpts.CPlusPlus) {
Douglas Gregor78a21012010-01-14 16:01:26 +00001450 Results.AddResult(Result("explicit"));
1451 Results.AddResult(Result("friend"));
1452 Results.AddResult(Result("mutable"));
1453 Results.AddResult(Result("virtual"));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001454 }
Adrian Prantlf3b3ccd2017-12-19 22:06:11 +00001455 LLVM_FALLTHROUGH;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001456
John McCallfaf5fb42010-08-26 23:41:50 +00001457 case Sema::PCC_ObjCInterface:
1458 case Sema::PCC_ObjCImplementation:
1459 case Sema::PCC_Namespace:
1460 case Sema::PCC_Template:
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001461 if (LangOpts.CPlusPlus || LangOpts.C99)
Douglas Gregor78a21012010-01-14 16:01:26 +00001462 Results.AddResult(Result("inline"));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001463 break;
1464
John McCallfaf5fb42010-08-26 23:41:50 +00001465 case Sema::PCC_ObjCInstanceVariableList:
1466 case Sema::PCC_Expression:
1467 case Sema::PCC_Statement:
1468 case Sema::PCC_ForInit:
1469 case Sema::PCC_Condition:
1470 case Sema::PCC_RecoveryInFunction:
1471 case Sema::PCC_Type:
Douglas Gregor5e35d592010-09-14 23:59:36 +00001472 case Sema::PCC_ParenthesizedExpression:
Douglas Gregor80039242011-02-15 20:33:25 +00001473 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001474 break;
1475 }
1476}
1477
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001478static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt);
1479static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt);
1480static void AddObjCVisibilityResults(const LangOptions &LangOpts,
Douglas Gregor48d46252010-01-13 21:54:15 +00001481 ResultBuilder &Results,
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001482 bool NeedAt);
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001483static void AddObjCImplementationResults(const LangOptions &LangOpts,
Douglas Gregorf1934162010-01-13 21:24:21 +00001484 ResultBuilder &Results,
1485 bool NeedAt);
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001486static void AddObjCInterfaceResults(const LangOptions &LangOpts,
Douglas Gregorf1934162010-01-13 21:24:21 +00001487 ResultBuilder &Results,
1488 bool NeedAt);
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001489static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt);
Douglas Gregorf1934162010-01-13 21:24:21 +00001490
Douglas Gregorf4c33342010-05-28 00:22:41 +00001491static void AddTypedefResult(ResultBuilder &Results) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00001492 CodeCompletionBuilder Builder(Results.getAllocator(),
1493 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001494 Builder.AddTypedTextChunk("typedef");
1495 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1496 Builder.AddPlaceholderChunk("type");
1497 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1498 Builder.AddPlaceholderChunk("name");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001499 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00001500}
1501
John McCallfaf5fb42010-08-26 23:41:50 +00001502static bool WantTypesInContext(Sema::ParserCompletionContext CCC,
Douglas Gregor70febae2010-05-28 00:49:12 +00001503 const LangOptions &LangOpts) {
Douglas Gregor70febae2010-05-28 00:49:12 +00001504 switch (CCC) {
John McCallfaf5fb42010-08-26 23:41:50 +00001505 case Sema::PCC_Namespace:
1506 case Sema::PCC_Class:
1507 case Sema::PCC_ObjCInstanceVariableList:
1508 case Sema::PCC_Template:
1509 case Sema::PCC_MemberTemplate:
1510 case Sema::PCC_Statement:
1511 case Sema::PCC_RecoveryInFunction:
1512 case Sema::PCC_Type:
Douglas Gregor5e35d592010-09-14 23:59:36 +00001513 case Sema::PCC_ParenthesizedExpression:
Douglas Gregor80039242011-02-15 20:33:25 +00001514 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregor70febae2010-05-28 00:49:12 +00001515 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001516
John McCallfaf5fb42010-08-26 23:41:50 +00001517 case Sema::PCC_Expression:
1518 case Sema::PCC_Condition:
Douglas Gregor5e35d592010-09-14 23:59:36 +00001519 return LangOpts.CPlusPlus;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001520
Douglas Gregor5e35d592010-09-14 23:59:36 +00001521 case Sema::PCC_ObjCInterface:
1522 case Sema::PCC_ObjCImplementation:
Douglas Gregor70febae2010-05-28 00:49:12 +00001523 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001524
John McCallfaf5fb42010-08-26 23:41:50 +00001525 case Sema::PCC_ForInit:
Douglas Gregor5e35d592010-09-14 23:59:36 +00001526 return LangOpts.CPlusPlus || LangOpts.ObjC1 || LangOpts.C99;
Douglas Gregor70febae2010-05-28 00:49:12 +00001527 }
David Blaikie8a40f702012-01-17 06:56:22 +00001528
1529 llvm_unreachable("Invalid ParserCompletionContext!");
Douglas Gregor70febae2010-05-28 00:49:12 +00001530}
1531
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00001532static PrintingPolicy getCompletionPrintingPolicy(const ASTContext &Context,
1533 const Preprocessor &PP) {
1534 PrintingPolicy Policy = Sema::getPrintingPolicy(Context, PP);
Douglas Gregore5c79d52011-10-18 21:20:17 +00001535 Policy.AnonymousTagLocations = false;
1536 Policy.SuppressStrongLifetime = true;
Douglas Gregor2e10cf92011-11-03 00:16:13 +00001537 Policy.SuppressUnwrittenScope = true;
Ilya Biryukovb5da91c2017-11-08 10:39:09 +00001538 Policy.SuppressScope = true;
Douglas Gregore5c79d52011-10-18 21:20:17 +00001539 return Policy;
1540}
1541
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001542/// Retrieve a printing policy suitable for code completion.
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00001543static PrintingPolicy getCompletionPrintingPolicy(Sema &S) {
1544 return getCompletionPrintingPolicy(S.Context, S.PP);
1545}
1546
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001547/// Retrieve the string representation of the given type as a string
Douglas Gregore5c79d52011-10-18 21:20:17 +00001548/// that has the appropriate lifetime for code completion.
1549///
1550/// This routine provides a fast path where we provide constant strings for
1551/// common type names.
1552static const char *GetCompletionTypeString(QualType T,
1553 ASTContext &Context,
1554 const PrintingPolicy &Policy,
1555 CodeCompletionAllocator &Allocator) {
1556 if (!T.getLocalQualifiers()) {
1557 // Built-in type names are constant strings.
1558 if (const BuiltinType *BT = dyn_cast<BuiltinType>(T))
Argyrios Kyrtzidisbbff3da2012-05-05 04:20:28 +00001559 return BT->getNameAsCString(Policy);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001560
Douglas Gregore5c79d52011-10-18 21:20:17 +00001561 // Anonymous tag types are constant strings.
1562 if (const TagType *TagT = dyn_cast<TagType>(T))
1563 if (TagDecl *Tag = TagT->getDecl())
John McCall5ea95772013-03-09 00:54:27 +00001564 if (!Tag->hasNameForLinkage()) {
Douglas Gregore5c79d52011-10-18 21:20:17 +00001565 switch (Tag->getTagKind()) {
1566 case TTK_Struct: return "struct <anonymous>";
Joao Matosdc86f942012-08-31 18:45:21 +00001567 case TTK_Interface: return "__interface <anonymous>";
1568 case TTK_Class: return "class <anonymous>";
Douglas Gregore5c79d52011-10-18 21:20:17 +00001569 case TTK_Union: return "union <anonymous>";
1570 case TTK_Enum: return "enum <anonymous>";
1571 }
1572 }
1573 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001574
Douglas Gregore5c79d52011-10-18 21:20:17 +00001575 // Slow path: format the type as a string.
1576 std::string Result;
1577 T.getAsStringInternal(Result, Policy);
1578 return Allocator.CopyString(Result);
1579}
1580
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001581/// Add a completion for "this", if we're in a member function.
Douglas Gregord8c61782012-02-15 15:34:24 +00001582static void addThisCompletion(Sema &S, ResultBuilder &Results) {
1583 QualType ThisTy = S.getCurrentThisType();
1584 if (ThisTy.isNull())
1585 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001586
Douglas Gregord8c61782012-02-15 15:34:24 +00001587 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00001588 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Douglas Gregord8c61782012-02-15 15:34:24 +00001589 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001590 Builder.AddResultTypeChunk(GetCompletionTypeString(ThisTy,
1591 S.Context,
Douglas Gregord8c61782012-02-15 15:34:24 +00001592 Policy,
1593 Allocator));
1594 Builder.AddTypedTextChunk("this");
Joao Matosdc86f942012-08-31 18:45:21 +00001595 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
Douglas Gregord8c61782012-02-15 15:34:24 +00001596}
1597
Alex Lorenz8f4d3992017-02-13 23:19:40 +00001598static void AddStaticAssertResult(CodeCompletionBuilder &Builder,
1599 ResultBuilder &Results,
1600 const LangOptions &LangOpts) {
1601 if (!LangOpts.CPlusPlus11)
1602 return;
1603
1604 Builder.AddTypedTextChunk("static_assert");
1605 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1606 Builder.AddPlaceholderChunk("expression");
1607 Builder.AddChunk(CodeCompletionString::CK_Comma);
1608 Builder.AddPlaceholderChunk("message");
1609 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1610 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
1611}
1612
Kadir Cetinkayaae45d0a42018-10-02 09:42:31 +00001613namespace {
1614void printOverrideString(llvm::raw_ostream &OS, CodeCompletionString *CCS) {
1615 for (const auto &C : *CCS) {
1616 if (C.Kind == CodeCompletionString::CK_Optional)
1617 printOverrideString(OS, C.Optional);
1618 else
1619 OS << C.Text;
1620 // Add a space after return type.
1621 if (C.Kind == CodeCompletionString::CK_ResultType)
1622 OS << ' ';
1623 }
1624}
1625} // namespace
1626
1627static void AddOverrideResults(ResultBuilder &Results,
1628 const CodeCompletionContext &CCContext,
1629 CodeCompletionBuilder &Builder) {
1630 Sema &S = Results.getSema();
1631 const auto *CR = llvm::dyn_cast<CXXRecordDecl>(S.CurContext);
1632 // If not inside a class/struct/union return empty.
1633 if (!CR)
1634 return;
1635 // First store overrides within current class.
1636 // These are stored by name to make querying fast in the later step.
1637 llvm::StringMap<std::vector<FunctionDecl *>> Overrides;
1638 for (auto *Method : CR->methods()) {
1639 if (!Method->isVirtual() || !Method->getIdentifier())
1640 continue;
1641 Overrides[Method->getName()].push_back(Method);
1642 }
1643
1644 for (const auto &Base : CR->bases()) {
1645 const auto *BR = Base.getType().getTypePtr()->getAsCXXRecordDecl();
1646 if (!BR)
1647 continue;
1648 for (auto *Method : BR->methods()) {
1649 if (!Method->isVirtual() || !Method->getIdentifier())
1650 continue;
1651 const auto it = Overrides.find(Method->getName());
1652 bool IsOverriden = false;
1653 if (it != Overrides.end()) {
1654 for (auto *MD : it->second) {
1655 // If the method in current body is not an overload of this virtual
1656 // function, then it overrides this one.
1657 if (!S.IsOverload(MD, Method, false)) {
1658 IsOverriden = true;
1659 break;
1660 }
1661 }
1662 }
1663 if (!IsOverriden) {
1664 // Generates a new CodeCompletionResult by taking this function and
1665 // converting it into an override declaration with only one chunk in the
1666 // final CodeCompletionString as a TypedTextChunk.
1667 std::string OverrideSignature;
1668 llvm::raw_string_ostream OS(OverrideSignature);
1669 CodeCompletionResult CCR(Method, 0);
1670 PrintingPolicy Policy =
1671 getCompletionPrintingPolicy(S.getASTContext(), S.getPreprocessor());
1672 auto *CCS = CCR.createCodeCompletionStringForOverride(
1673 S.getPreprocessor(), S.getASTContext(), Builder,
1674 /*IncludeBriefComments=*/false, CCContext, Policy);
1675 Results.AddResult(CodeCompletionResult(CCS, Method, CCP_CodePattern));
1676 }
1677 }
1678 }
1679}
1680
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001681/// Add language constructs that show up for "ordinary" names.
John McCallfaf5fb42010-08-26 23:41:50 +00001682static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001683 Scope *S,
1684 Sema &SemaRef,
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001685 ResultBuilder &Results) {
Douglas Gregore5c79d52011-10-18 21:20:17 +00001686 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00001687 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001688
John McCall276321a2010-08-25 06:19:51 +00001689 typedef CodeCompletionResult Result;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001690 switch (CCC) {
John McCallfaf5fb42010-08-26 23:41:50 +00001691 case Sema::PCC_Namespace:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001692 if (SemaRef.getLangOpts().CPlusPlus) {
Douglas Gregorf4c33342010-05-28 00:22:41 +00001693 if (Results.includeCodePatterns()) {
1694 // namespace <identifier> { declarations }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001695 Builder.AddTypedTextChunk("namespace");
1696 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1697 Builder.AddPlaceholderChunk("identifier");
1698 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1699 Builder.AddPlaceholderChunk("declarations");
1700 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1701 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1702 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00001703 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001704
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001705 // namespace identifier = identifier ;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001706 Builder.AddTypedTextChunk("namespace");
1707 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1708 Builder.AddPlaceholderChunk("name");
1709 Builder.AddChunk(CodeCompletionString::CK_Equal);
1710 Builder.AddPlaceholderChunk("namespace");
1711 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001712
1713 // Using directives
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001714 Builder.AddTypedTextChunk("using");
1715 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1716 Builder.AddTextChunk("namespace");
1717 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1718 Builder.AddPlaceholderChunk("identifier");
1719 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001720
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001721 // asm(string-literal)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001722 Builder.AddTypedTextChunk("asm");
1723 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1724 Builder.AddPlaceholderChunk("string-literal");
1725 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1726 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001727
Douglas Gregorf4c33342010-05-28 00:22:41 +00001728 if (Results.includeCodePatterns()) {
1729 // Explicit template instantiation
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001730 Builder.AddTypedTextChunk("template");
1731 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1732 Builder.AddPlaceholderChunk("declaration");
1733 Results.AddResult(Result(Builder.TakeString()));
Eric Liub87c6eb2018-10-15 12:37:23 +00001734 } else {
1735 Results.AddResult(Result("template", CodeCompletionResult::RK_Keyword));
Douglas Gregorf4c33342010-05-28 00:22:41 +00001736 }
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001737 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001738
David Blaikiebbafb8a2012-03-11 07:00:24 +00001739 if (SemaRef.getLangOpts().ObjC1)
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001740 AddObjCTopLevelResults(Results, true);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001741
Douglas Gregorf4c33342010-05-28 00:22:41 +00001742 AddTypedefResult(Results);
Adrian Prantlf3b3ccd2017-12-19 22:06:11 +00001743 LLVM_FALLTHROUGH;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001744
John McCallfaf5fb42010-08-26 23:41:50 +00001745 case Sema::PCC_Class:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001746 if (SemaRef.getLangOpts().CPlusPlus) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001747 // Using declaration
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001748 Builder.AddTypedTextChunk("using");
1749 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1750 Builder.AddPlaceholderChunk("qualifier");
1751 Builder.AddTextChunk("::");
1752 Builder.AddPlaceholderChunk("name");
1753 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001754
Douglas Gregorf4c33342010-05-28 00:22:41 +00001755 // using typename qualifier::name (only in a dependent context)
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001756 if (SemaRef.CurContext->isDependentContext()) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001757 Builder.AddTypedTextChunk("using");
1758 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1759 Builder.AddTextChunk("typename");
1760 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1761 Builder.AddPlaceholderChunk("qualifier");
1762 Builder.AddTextChunk("::");
1763 Builder.AddPlaceholderChunk("name");
1764 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001765 }
1766
Alex Lorenz8f4d3992017-02-13 23:19:40 +00001767 AddStaticAssertResult(Builder, Results, SemaRef.getLangOpts());
1768
John McCallfaf5fb42010-08-26 23:41:50 +00001769 if (CCC == Sema::PCC_Class) {
Douglas Gregorf4c33342010-05-28 00:22:41 +00001770 AddTypedefResult(Results);
1771
Erik Verbruggen6524c052017-10-24 13:46:58 +00001772 bool IsNotInheritanceScope =
1773 !(S->getFlags() & Scope::ClassInheritanceScope);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001774 // public:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001775 Builder.AddTypedTextChunk("public");
Erik Verbruggen6524c052017-10-24 13:46:58 +00001776 if (IsNotInheritanceScope && Results.includeCodePatterns())
Douglas Gregor9489cdf2012-04-10 17:56:28 +00001777 Builder.AddChunk(CodeCompletionString::CK_Colon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001778 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001779
1780 // protected:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001781 Builder.AddTypedTextChunk("protected");
Erik Verbruggen6524c052017-10-24 13:46:58 +00001782 if (IsNotInheritanceScope && Results.includeCodePatterns())
Douglas Gregor9489cdf2012-04-10 17:56:28 +00001783 Builder.AddChunk(CodeCompletionString::CK_Colon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001784 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001785
1786 // private:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001787 Builder.AddTypedTextChunk("private");
Erik Verbruggen6524c052017-10-24 13:46:58 +00001788 if (IsNotInheritanceScope && Results.includeCodePatterns())
Douglas Gregor9489cdf2012-04-10 17:56:28 +00001789 Builder.AddChunk(CodeCompletionString::CK_Colon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001790 Results.AddResult(Result(Builder.TakeString()));
Kadir Cetinkayaae45d0a42018-10-02 09:42:31 +00001791
1792 // FIXME: This adds override results only if we are at the first word of
1793 // the declaration/definition. Also call this from other sides to have
1794 // more use-cases.
1795 AddOverrideResults(Results, CodeCompletionContext::CCC_ClassStructUnion,
1796 Builder);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001797 }
1798 }
Adrian Prantlf3b3ccd2017-12-19 22:06:11 +00001799 LLVM_FALLTHROUGH;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001800
John McCallfaf5fb42010-08-26 23:41:50 +00001801 case Sema::PCC_Template:
1802 case Sema::PCC_MemberTemplate:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001803 if (SemaRef.getLangOpts().CPlusPlus && Results.includeCodePatterns()) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001804 // template < parameters >
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001805 Builder.AddTypedTextChunk("template");
1806 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1807 Builder.AddPlaceholderChunk("parameters");
1808 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1809 Results.AddResult(Result(Builder.TakeString()));
Eric Liub87c6eb2018-10-15 12:37:23 +00001810 } else {
1811 Results.AddResult(Result("template", CodeCompletionResult::RK_Keyword));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001812 }
1813
David Blaikiebbafb8a2012-03-11 07:00:24 +00001814 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
1815 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001816 break;
1817
John McCallfaf5fb42010-08-26 23:41:50 +00001818 case Sema::PCC_ObjCInterface:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001819 AddObjCInterfaceResults(SemaRef.getLangOpts(), Results, true);
1820 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
1821 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregorf1934162010-01-13 21:24:21 +00001822 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001823
John McCallfaf5fb42010-08-26 23:41:50 +00001824 case Sema::PCC_ObjCImplementation:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001825 AddObjCImplementationResults(SemaRef.getLangOpts(), Results, true);
1826 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
1827 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregorf1934162010-01-13 21:24:21 +00001828 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001829
John McCallfaf5fb42010-08-26 23:41:50 +00001830 case Sema::PCC_ObjCInstanceVariableList:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001831 AddObjCVisibilityResults(SemaRef.getLangOpts(), Results, true);
Douglas Gregor48d46252010-01-13 21:54:15 +00001832 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001833
John McCallfaf5fb42010-08-26 23:41:50 +00001834 case Sema::PCC_RecoveryInFunction:
1835 case Sema::PCC_Statement: {
Douglas Gregorf4c33342010-05-28 00:22:41 +00001836 AddTypedefResult(Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001837
David Blaikiebbafb8a2012-03-11 07:00:24 +00001838 if (SemaRef.getLangOpts().CPlusPlus && Results.includeCodePatterns() &&
1839 SemaRef.getLangOpts().CXXExceptions) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001840 Builder.AddTypedTextChunk("try");
1841 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1842 Builder.AddPlaceholderChunk("statements");
1843 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1844 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1845 Builder.AddTextChunk("catch");
1846 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1847 Builder.AddPlaceholderChunk("declaration");
1848 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1849 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1850 Builder.AddPlaceholderChunk("statements");
1851 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1852 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1853 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001854 }
David Blaikiebbafb8a2012-03-11 07:00:24 +00001855 if (SemaRef.getLangOpts().ObjC1)
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001856 AddObjCStatementResults(Results, true);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001857
Douglas Gregorf64acca2010-05-25 21:41:55 +00001858 if (Results.includeCodePatterns()) {
1859 // if (condition) { statements }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001860 Builder.AddTypedTextChunk("if");
1861 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00001862 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001863 Builder.AddPlaceholderChunk("condition");
Douglas Gregorf64acca2010-05-25 21:41:55 +00001864 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001865 Builder.AddPlaceholderChunk("expression");
1866 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1867 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1868 Builder.AddPlaceholderChunk("statements");
1869 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1870 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1871 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001872
Douglas Gregorf64acca2010-05-25 21:41:55 +00001873 // switch (condition) { }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001874 Builder.AddTypedTextChunk("switch");
1875 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00001876 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001877 Builder.AddPlaceholderChunk("condition");
Douglas Gregorf64acca2010-05-25 21:41:55 +00001878 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001879 Builder.AddPlaceholderChunk("expression");
1880 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1881 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1882 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1883 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1884 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf64acca2010-05-25 21:41:55 +00001885 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001886
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001887 // Switch-specific statements.
Sam McCallaeb4b3e2018-10-10 10:51:48 +00001888 if (SemaRef.getCurFunction() &&
1889 !SemaRef.getCurFunction()->SwitchStack.empty()) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001890 // case expression:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001891 Builder.AddTypedTextChunk("case");
1892 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1893 Builder.AddPlaceholderChunk("expression");
1894 Builder.AddChunk(CodeCompletionString::CK_Colon);
1895 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001896
1897 // default:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001898 Builder.AddTypedTextChunk("default");
1899 Builder.AddChunk(CodeCompletionString::CK_Colon);
1900 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001901 }
1902
Douglas Gregorf64acca2010-05-25 21:41:55 +00001903 if (Results.includeCodePatterns()) {
1904 /// while (condition) { statements }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001905 Builder.AddTypedTextChunk("while");
1906 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00001907 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001908 Builder.AddPlaceholderChunk("condition");
Douglas Gregorf64acca2010-05-25 21:41:55 +00001909 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001910 Builder.AddPlaceholderChunk("expression");
1911 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1912 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1913 Builder.AddPlaceholderChunk("statements");
1914 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1915 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1916 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf64acca2010-05-25 21:41:55 +00001917
1918 // do { statements } while ( expression );
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001919 Builder.AddTypedTextChunk("do");
1920 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1921 Builder.AddPlaceholderChunk("statements");
1922 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1923 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1924 Builder.AddTextChunk("while");
1925 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1926 Builder.AddPlaceholderChunk("expression");
1927 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1928 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001929
Douglas Gregorf64acca2010-05-25 21:41:55 +00001930 // for ( for-init-statement ; condition ; expression ) { statements }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001931 Builder.AddTypedTextChunk("for");
1932 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00001933 if (SemaRef.getLangOpts().CPlusPlus || SemaRef.getLangOpts().C99)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001934 Builder.AddPlaceholderChunk("init-statement");
Douglas Gregorf64acca2010-05-25 21:41:55 +00001935 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001936 Builder.AddPlaceholderChunk("init-expression");
1937 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
1938 Builder.AddPlaceholderChunk("condition");
1939 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
1940 Builder.AddPlaceholderChunk("inc-expression");
1941 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1942 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1943 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1944 Builder.AddPlaceholderChunk("statements");
1945 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1946 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1947 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf64acca2010-05-25 21:41:55 +00001948 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001949
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001950 if (S->getContinueParent()) {
1951 // continue ;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001952 Builder.AddTypedTextChunk("continue");
1953 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001954 }
1955
1956 if (S->getBreakParent()) {
1957 // break ;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001958 Builder.AddTypedTextChunk("break");
1959 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001960 }
1961
1962 // "return expression ;" or "return ;", depending on whether we
1963 // know the function is void or not.
1964 bool isVoid = false;
1965 if (FunctionDecl *Function = dyn_cast<FunctionDecl>(SemaRef.CurContext))
Alp Toker314cc812014-01-25 16:55:45 +00001966 isVoid = Function->getReturnType()->isVoidType();
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001967 else if (ObjCMethodDecl *Method
1968 = dyn_cast<ObjCMethodDecl>(SemaRef.CurContext))
Alp Toker314cc812014-01-25 16:55:45 +00001969 isVoid = Method->getReturnType()->isVoidType();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001970 else if (SemaRef.getCurBlock() &&
Douglas Gregor9a28e842010-03-01 23:15:13 +00001971 !SemaRef.getCurBlock()->ReturnType.isNull())
1972 isVoid = SemaRef.getCurBlock()->ReturnType->isVoidType();
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001973 Builder.AddTypedTextChunk("return");
Douglas Gregor44272ca2010-02-18 04:06:48 +00001974 if (!isVoid) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001975 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1976 Builder.AddPlaceholderChunk("expression");
Douglas Gregor44272ca2010-02-18 04:06:48 +00001977 }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001978 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001979
Douglas Gregorf4c33342010-05-28 00:22:41 +00001980 // goto identifier ;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001981 Builder.AddTypedTextChunk("goto");
1982 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1983 Builder.AddPlaceholderChunk("label");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001984 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001985
Douglas Gregorf4c33342010-05-28 00:22:41 +00001986 // Using directives
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001987 Builder.AddTypedTextChunk("using");
1988 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1989 Builder.AddTextChunk("namespace");
1990 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1991 Builder.AddPlaceholderChunk("identifier");
1992 Results.AddResult(Result(Builder.TakeString()));
Alex Lorenz8f4d3992017-02-13 23:19:40 +00001993
1994 AddStaticAssertResult(Builder, Results, SemaRef.getLangOpts());
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001995 }
Galina Kistanovabe3ba9da2017-06-07 06:31:55 +00001996 LLVM_FALLTHROUGH;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001997
1998 // Fall through (for statement expressions).
John McCallfaf5fb42010-08-26 23:41:50 +00001999 case Sema::PCC_ForInit:
2000 case Sema::PCC_Condition:
David Blaikiebbafb8a2012-03-11 07:00:24 +00002001 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002002 // Fall through: conditions and statements can have expressions.
Galina Kistanova33399112017-06-03 06:35:06 +00002003 LLVM_FALLTHROUGH;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002004
Douglas Gregor5e35d592010-09-14 23:59:36 +00002005 case Sema::PCC_ParenthesizedExpression:
David Blaikiebbafb8a2012-03-11 07:00:24 +00002006 if (SemaRef.getLangOpts().ObjCAutoRefCount &&
John McCall31168b02011-06-15 23:02:42 +00002007 CCC == Sema::PCC_ParenthesizedExpression) {
2008 // (__bridge <type>)<expression>
2009 Builder.AddTypedTextChunk("__bridge");
2010 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2011 Builder.AddPlaceholderChunk("type");
2012 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2013 Builder.AddPlaceholderChunk("expression");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002014 Results.AddResult(Result(Builder.TakeString()));
John McCall31168b02011-06-15 23:02:42 +00002015
2016 // (__bridge_transfer <Objective-C type>)<expression>
2017 Builder.AddTypedTextChunk("__bridge_transfer");
2018 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2019 Builder.AddPlaceholderChunk("Objective-C type");
2020 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2021 Builder.AddPlaceholderChunk("expression");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002022 Results.AddResult(Result(Builder.TakeString()));
John McCall31168b02011-06-15 23:02:42 +00002023
2024 // (__bridge_retained <CF type>)<expression>
2025 Builder.AddTypedTextChunk("__bridge_retained");
2026 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2027 Builder.AddPlaceholderChunk("CF type");
2028 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2029 Builder.AddPlaceholderChunk("expression");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002030 Results.AddResult(Result(Builder.TakeString()));
John McCall31168b02011-06-15 23:02:42 +00002031 }
2032 // Fall through
Galina Kistanova33399112017-06-03 06:35:06 +00002033 LLVM_FALLTHROUGH;
John McCall31168b02011-06-15 23:02:42 +00002034
John McCallfaf5fb42010-08-26 23:41:50 +00002035 case Sema::PCC_Expression: {
David Blaikiebbafb8a2012-03-11 07:00:24 +00002036 if (SemaRef.getLangOpts().CPlusPlus) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002037 // 'this', if we're in a non-static member function.
Douglas Gregord8c61782012-02-15 15:34:24 +00002038 addThisCompletion(SemaRef, Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002039
Douglas Gregore5c79d52011-10-18 21:20:17 +00002040 // true
2041 Builder.AddResultTypeChunk("bool");
2042 Builder.AddTypedTextChunk("true");
2043 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002044
Douglas Gregore5c79d52011-10-18 21:20:17 +00002045 // false
2046 Builder.AddResultTypeChunk("bool");
2047 Builder.AddTypedTextChunk("false");
2048 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002049
David Blaikiebbafb8a2012-03-11 07:00:24 +00002050 if (SemaRef.getLangOpts().RTTI) {
Douglas Gregorc05f6572011-04-12 02:47:21 +00002051 // dynamic_cast < type-id > ( expression )
2052 Builder.AddTypedTextChunk("dynamic_cast");
2053 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
2054 Builder.AddPlaceholderChunk("type");
2055 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
2056 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2057 Builder.AddPlaceholderChunk("expression");
2058 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002059 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc05f6572011-04-12 02:47:21 +00002060 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002061
Douglas Gregorf4c33342010-05-28 00:22:41 +00002062 // static_cast < type-id > ( expression )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002063 Builder.AddTypedTextChunk("static_cast");
2064 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
2065 Builder.AddPlaceholderChunk("type");
2066 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
2067 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2068 Builder.AddPlaceholderChunk("expression");
2069 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002070 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002071
Douglas Gregorf4c33342010-05-28 00:22:41 +00002072 // reinterpret_cast < type-id > ( expression )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002073 Builder.AddTypedTextChunk("reinterpret_cast");
2074 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
2075 Builder.AddPlaceholderChunk("type");
2076 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
2077 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2078 Builder.AddPlaceholderChunk("expression");
2079 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002080 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002081
Douglas Gregorf4c33342010-05-28 00:22:41 +00002082 // const_cast < type-id > ( expression )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002083 Builder.AddTypedTextChunk("const_cast");
2084 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
2085 Builder.AddPlaceholderChunk("type");
2086 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
2087 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2088 Builder.AddPlaceholderChunk("expression");
2089 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002090 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002091
David Blaikiebbafb8a2012-03-11 07:00:24 +00002092 if (SemaRef.getLangOpts().RTTI) {
Douglas Gregorc05f6572011-04-12 02:47:21 +00002093 // typeid ( expression-or-type )
Douglas Gregore5c79d52011-10-18 21:20:17 +00002094 Builder.AddResultTypeChunk("std::type_info");
Douglas Gregorc05f6572011-04-12 02:47:21 +00002095 Builder.AddTypedTextChunk("typeid");
2096 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2097 Builder.AddPlaceholderChunk("expression-or-type");
2098 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002099 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc05f6572011-04-12 02:47:21 +00002100 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002101
Douglas Gregorf4c33342010-05-28 00:22:41 +00002102 // new T ( ... )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002103 Builder.AddTypedTextChunk("new");
2104 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2105 Builder.AddPlaceholderChunk("type");
2106 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2107 Builder.AddPlaceholderChunk("expressions");
2108 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002109 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002110
Douglas Gregorf4c33342010-05-28 00:22:41 +00002111 // new T [ ] ( ... )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002112 Builder.AddTypedTextChunk("new");
2113 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2114 Builder.AddPlaceholderChunk("type");
2115 Builder.AddChunk(CodeCompletionString::CK_LeftBracket);
2116 Builder.AddPlaceholderChunk("size");
2117 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
2118 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2119 Builder.AddPlaceholderChunk("expressions");
2120 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002121 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002122
Douglas Gregorf4c33342010-05-28 00:22:41 +00002123 // delete expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00002124 Builder.AddResultTypeChunk("void");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002125 Builder.AddTypedTextChunk("delete");
2126 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2127 Builder.AddPlaceholderChunk("expression");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002128 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002129
Douglas Gregorf4c33342010-05-28 00:22:41 +00002130 // delete [] expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00002131 Builder.AddResultTypeChunk("void");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002132 Builder.AddTypedTextChunk("delete");
2133 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2134 Builder.AddChunk(CodeCompletionString::CK_LeftBracket);
2135 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
2136 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2137 Builder.AddPlaceholderChunk("expression");
2138 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002139
David Blaikiebbafb8a2012-03-11 07:00:24 +00002140 if (SemaRef.getLangOpts().CXXExceptions) {
Douglas Gregorc05f6572011-04-12 02:47:21 +00002141 // throw expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00002142 Builder.AddResultTypeChunk("void");
Douglas Gregorc05f6572011-04-12 02:47:21 +00002143 Builder.AddTypedTextChunk("throw");
2144 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2145 Builder.AddPlaceholderChunk("expression");
2146 Results.AddResult(Result(Builder.TakeString()));
2147 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002148
Douglas Gregora2db7932010-05-26 22:00:08 +00002149 // FIXME: Rethrow?
Douglas Gregor4205fef2011-10-18 16:29:03 +00002150
Richard Smith2bf7fdb2013-01-02 11:42:31 +00002151 if (SemaRef.getLangOpts().CPlusPlus11) {
Douglas Gregor4205fef2011-10-18 16:29:03 +00002152 // nullptr
Douglas Gregore5c79d52011-10-18 21:20:17 +00002153 Builder.AddResultTypeChunk("std::nullptr_t");
Douglas Gregor4205fef2011-10-18 16:29:03 +00002154 Builder.AddTypedTextChunk("nullptr");
2155 Results.AddResult(Result(Builder.TakeString()));
2156
2157 // alignof
Douglas Gregore5c79d52011-10-18 21:20:17 +00002158 Builder.AddResultTypeChunk("size_t");
Douglas Gregor4205fef2011-10-18 16:29:03 +00002159 Builder.AddTypedTextChunk("alignof");
2160 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2161 Builder.AddPlaceholderChunk("type");
2162 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2163 Results.AddResult(Result(Builder.TakeString()));
2164
2165 // noexcept
Douglas Gregore5c79d52011-10-18 21:20:17 +00002166 Builder.AddResultTypeChunk("bool");
Douglas Gregor4205fef2011-10-18 16:29:03 +00002167 Builder.AddTypedTextChunk("noexcept");
2168 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2169 Builder.AddPlaceholderChunk("expression");
2170 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2171 Results.AddResult(Result(Builder.TakeString()));
2172
2173 // sizeof... expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00002174 Builder.AddResultTypeChunk("size_t");
Douglas Gregor4205fef2011-10-18 16:29:03 +00002175 Builder.AddTypedTextChunk("sizeof...");
2176 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2177 Builder.AddPlaceholderChunk("parameter-pack");
2178 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2179 Results.AddResult(Result(Builder.TakeString()));
2180 }
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002181 }
2182
David Blaikiebbafb8a2012-03-11 07:00:24 +00002183 if (SemaRef.getLangOpts().ObjC1) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002184 // Add "super", if we're in an Objective-C class with a superclass.
Ted Kremenek305a0a72010-05-31 21:43:10 +00002185 if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl()) {
2186 // The interface can be NULL.
2187 if (ObjCInterfaceDecl *ID = Method->getClassInterface())
Douglas Gregore5c79d52011-10-18 21:20:17 +00002188 if (ID->getSuperClass()) {
2189 std::string SuperType;
2190 SuperType = ID->getSuperClass()->getNameAsString();
2191 if (Method->isInstanceMethod())
2192 SuperType += " *";
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002193
Douglas Gregore5c79d52011-10-18 21:20:17 +00002194 Builder.AddResultTypeChunk(Allocator.CopyString(SuperType));
2195 Builder.AddTypedTextChunk("super");
2196 Results.AddResult(Result(Builder.TakeString()));
2197 }
Ted Kremenek305a0a72010-05-31 21:43:10 +00002198 }
2199
Douglas Gregorf98e6a22010-01-13 23:51:12 +00002200 AddObjCExpressionResults(Results, true);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002201 }
2202
Jordan Rose58d54722012-06-30 21:33:57 +00002203 if (SemaRef.getLangOpts().C11) {
2204 // _Alignof
2205 Builder.AddResultTypeChunk("size_t");
Richard Smith20e883e2015-04-29 23:20:19 +00002206 if (SemaRef.PP.isMacroDefined("alignof"))
Jordan Rose58d54722012-06-30 21:33:57 +00002207 Builder.AddTypedTextChunk("alignof");
2208 else
2209 Builder.AddTypedTextChunk("_Alignof");
2210 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2211 Builder.AddPlaceholderChunk("type");
2212 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2213 Results.AddResult(Result(Builder.TakeString()));
2214 }
2215
Douglas Gregorf4c33342010-05-28 00:22:41 +00002216 // sizeof expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00002217 Builder.AddResultTypeChunk("size_t");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002218 Builder.AddTypedTextChunk("sizeof");
2219 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2220 Builder.AddPlaceholderChunk("expression-or-type");
2221 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2222 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002223 break;
2224 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002225
John McCallfaf5fb42010-08-26 23:41:50 +00002226 case Sema::PCC_Type:
Douglas Gregor80039242011-02-15 20:33:25 +00002227 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregor99fa2642010-08-24 01:06:58 +00002228 break;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002229 }
2230
David Blaikiebbafb8a2012-03-11 07:00:24 +00002231 if (WantTypesInContext(CCC, SemaRef.getLangOpts()))
2232 AddTypeSpecifierResults(SemaRef.getLangOpts(), Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002233
David Blaikiebbafb8a2012-03-11 07:00:24 +00002234 if (SemaRef.getLangOpts().CPlusPlus && CCC != Sema::PCC_Type)
Douglas Gregor78a21012010-01-14 16:01:26 +00002235 Results.AddResult(Result("operator"));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002236}
2237
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002238/// If the given declaration has an associated type, add it as a result
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002239/// type chunk.
2240static void AddResultTypeChunk(ASTContext &Context,
Douglas Gregor75acd922011-09-27 23:30:47 +00002241 const PrintingPolicy &Policy,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002242 const NamedDecl *ND,
Douglas Gregorc3425b12015-07-07 06:20:19 +00002243 QualType BaseType,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002244 CodeCompletionBuilder &Result) {
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002245 if (!ND)
2246 return;
Douglas Gregor0212fd72010-09-21 16:06:22 +00002247
2248 // Skip constructors and conversion functions, which have their return types
2249 // built into their names.
Sam McCall63c59722018-01-22 20:44:47 +00002250 if (isConstructor(ND) || isa<CXXConversionDecl>(ND))
Douglas Gregor0212fd72010-09-21 16:06:22 +00002251 return;
2252
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002253 // Determine the type of the declaration (if it has a type).
Alp Tokera2794f92014-01-22 07:29:52 +00002254 QualType T;
2255 if (const FunctionDecl *Function = ND->getAsFunction())
Alp Toker314cc812014-01-25 16:55:45 +00002256 T = Function->getReturnType();
Douglas Gregorc3425b12015-07-07 06:20:19 +00002257 else if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND)) {
2258 if (!BaseType.isNull())
2259 T = Method->getSendResultType(BaseType);
2260 else
2261 T = Method->getReturnType();
Ilya Biryukovb5da91c2017-11-08 10:39:09 +00002262 } else if (const EnumConstantDecl *Enumerator = dyn_cast<EnumConstantDecl>(ND)) {
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002263 T = Context.getTypeDeclType(cast<TypeDecl>(Enumerator->getDeclContext()));
Ilya Biryukovb5da91c2017-11-08 10:39:09 +00002264 T = clang::TypeName::getFullyQualifiedType(T, Context);
2265 } else if (isa<UnresolvedUsingValueDecl>(ND)) {
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002266 /* Do nothing: ignore unresolved using declarations*/
Douglas Gregorc3425b12015-07-07 06:20:19 +00002267 } else if (const ObjCIvarDecl *Ivar = dyn_cast<ObjCIvarDecl>(ND)) {
2268 if (!BaseType.isNull())
2269 T = Ivar->getUsageType(BaseType);
2270 else
2271 T = Ivar->getType();
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002272 } else if (const ValueDecl *Value = dyn_cast<ValueDecl>(ND)) {
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002273 T = Value->getType();
Douglas Gregorc3425b12015-07-07 06:20:19 +00002274 } else if (const ObjCPropertyDecl *Property = dyn_cast<ObjCPropertyDecl>(ND)) {
2275 if (!BaseType.isNull())
2276 T = Property->getUsageType(BaseType);
2277 else
2278 T = Property->getType();
2279 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002280
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002281 if (T.isNull() || Context.hasSameType(T, Context.DependentTy))
2282 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002283
Douglas Gregor75acd922011-09-27 23:30:47 +00002284 Result.AddResultTypeChunk(GetCompletionTypeString(T, Context, Policy,
Douglas Gregor304f9b02011-02-01 21:15:40 +00002285 Result.getAllocator()));
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002286}
2287
Richard Smith20e883e2015-04-29 23:20:19 +00002288static void MaybeAddSentinel(Preprocessor &PP,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002289 const NamedDecl *FunctionOrMethod,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002290 CodeCompletionBuilder &Result) {
Douglas Gregordbb71db2010-08-23 23:51:41 +00002291 if (SentinelAttr *Sentinel = FunctionOrMethod->getAttr<SentinelAttr>())
2292 if (Sentinel->getSentinel() == 0) {
Richard Smith20e883e2015-04-29 23:20:19 +00002293 if (PP.getLangOpts().ObjC1 && PP.isMacroDefined("nil"))
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002294 Result.AddTextChunk(", nil");
Richard Smith20e883e2015-04-29 23:20:19 +00002295 else if (PP.isMacroDefined("NULL"))
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002296 Result.AddTextChunk(", NULL");
Douglas Gregordbb71db2010-08-23 23:51:41 +00002297 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002298 Result.AddTextChunk(", (void*)0");
Douglas Gregordbb71db2010-08-23 23:51:41 +00002299 }
2300}
2301
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002302static std::string formatObjCParamQualifiers(unsigned ObjCQuals,
Douglas Gregor86b42682015-06-19 18:27:52 +00002303 QualType &Type) {
Douglas Gregor8f08d742011-07-30 07:55:26 +00002304 std::string Result;
2305 if (ObjCQuals & Decl::OBJC_TQ_In)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002306 Result += "in ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002307 else if (ObjCQuals & Decl::OBJC_TQ_Inout)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002308 Result += "inout ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002309 else if (ObjCQuals & Decl::OBJC_TQ_Out)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002310 Result += "out ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002311 if (ObjCQuals & Decl::OBJC_TQ_Bycopy)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002312 Result += "bycopy ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002313 else if (ObjCQuals & Decl::OBJC_TQ_Byref)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002314 Result += "byref ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002315 if (ObjCQuals & Decl::OBJC_TQ_Oneway)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002316 Result += "oneway ";
Douglas Gregor86b42682015-06-19 18:27:52 +00002317 if (ObjCQuals & Decl::OBJC_TQ_CSNullability) {
2318 if (auto nullability = AttributedType::stripOuterNullability(Type)) {
2319 switch (*nullability) {
2320 case NullabilityKind::NonNull:
2321 Result += "nonnull ";
2322 break;
2323
2324 case NullabilityKind::Nullable:
2325 Result += "nullable ";
2326 break;
2327
2328 case NullabilityKind::Unspecified:
2329 Result += "null_unspecified ";
2330 break;
2331 }
2332 }
2333 }
Douglas Gregor8f08d742011-07-30 07:55:26 +00002334 return Result;
2335}
2336
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002337/// Tries to find the most appropriate type location for an Objective-C
Alex Lorenza1951202016-10-18 10:35:27 +00002338/// block placeholder.
2339///
2340/// This function ignores things like typedefs and qualifiers in order to
2341/// present the most relevant and accurate block placeholders in code completion
2342/// results.
2343static void findTypeLocationForBlockDecl(const TypeSourceInfo *TSInfo,
2344 FunctionTypeLoc &Block,
2345 FunctionProtoTypeLoc &BlockProto,
2346 bool SuppressBlock = false) {
2347 if (!TSInfo)
2348 return;
2349 TypeLoc TL = TSInfo->getTypeLoc().getUnqualifiedLoc();
2350 while (true) {
2351 // Look through typedefs.
2352 if (!SuppressBlock) {
2353 if (TypedefTypeLoc TypedefTL = TL.getAs<TypedefTypeLoc>()) {
2354 if (TypeSourceInfo *InnerTSInfo =
2355 TypedefTL.getTypedefNameDecl()->getTypeSourceInfo()) {
2356 TL = InnerTSInfo->getTypeLoc().getUnqualifiedLoc();
2357 continue;
2358 }
2359 }
2360
2361 // Look through qualified types
2362 if (QualifiedTypeLoc QualifiedTL = TL.getAs<QualifiedTypeLoc>()) {
2363 TL = QualifiedTL.getUnqualifiedLoc();
2364 continue;
2365 }
2366
2367 if (AttributedTypeLoc AttrTL = TL.getAs<AttributedTypeLoc>()) {
2368 TL = AttrTL.getModifiedLoc();
2369 continue;
2370 }
2371 }
2372
2373 // Try to get the function prototype behind the block pointer type,
2374 // then we're done.
2375 if (BlockPointerTypeLoc BlockPtr = TL.getAs<BlockPointerTypeLoc>()) {
2376 TL = BlockPtr.getPointeeLoc().IgnoreParens();
2377 Block = TL.getAs<FunctionTypeLoc>();
2378 BlockProto = TL.getAs<FunctionProtoTypeLoc>();
2379 }
2380 break;
2381 }
2382}
2383
Alex Lorenz920ae142016-10-18 10:38:58 +00002384static std::string
2385formatBlockPlaceholder(const PrintingPolicy &Policy, const NamedDecl *BlockDecl,
2386 FunctionTypeLoc &Block, FunctionProtoTypeLoc &BlockProto,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002387 bool SuppressBlockName = false,
Alex Lorenz920ae142016-10-18 10:38:58 +00002388 bool SuppressBlock = false,
2389 Optional<ArrayRef<QualType>> ObjCSubsts = None);
2390
Richard Smith20e883e2015-04-29 23:20:19 +00002391static std::string FormatFunctionParameter(const PrintingPolicy &Policy,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002392 const ParmVarDecl *Param,
Douglas Gregord793e7c2011-10-18 04:23:19 +00002393 bool SuppressName = false,
Douglas Gregorc3425b12015-07-07 06:20:19 +00002394 bool SuppressBlock = false,
2395 Optional<ArrayRef<QualType>> ObjCSubsts = None) {
Douglas Gregore90dd002010-08-24 16:15:59 +00002396 bool ObjCMethodParam = isa<ObjCMethodDecl>(Param->getDeclContext());
2397 if (Param->getType()->isDependentType() ||
2398 !Param->getType()->isBlockPointerType()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002399 // The argument for a dependent or non-block parameter is a placeholder
Douglas Gregore90dd002010-08-24 16:15:59 +00002400 // containing that parameter's type.
2401 std::string Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002402
Douglas Gregor981a0c42010-08-29 19:47:46 +00002403 if (Param->getIdentifier() && !ObjCMethodParam && !SuppressName)
Douglas Gregore90dd002010-08-24 16:15:59 +00002404 Result = Param->getIdentifier()->getName();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002405
Douglas Gregor86b42682015-06-19 18:27:52 +00002406 QualType Type = Param->getType();
Douglas Gregorc3425b12015-07-07 06:20:19 +00002407 if (ObjCSubsts)
2408 Type = Type.substObjCTypeArgs(Param->getASTContext(), *ObjCSubsts,
2409 ObjCSubstitutionContext::Parameter);
Douglas Gregore90dd002010-08-24 16:15:59 +00002410 if (ObjCMethodParam) {
Douglas Gregor86b42682015-06-19 18:27:52 +00002411 Result = "(" + formatObjCParamQualifiers(Param->getObjCDeclQualifier(),
2412 Type);
2413 Result += Type.getAsString(Policy) + ")";
Douglas Gregor981a0c42010-08-29 19:47:46 +00002414 if (Param->getIdentifier() && !SuppressName)
Douglas Gregore90dd002010-08-24 16:15:59 +00002415 Result += Param->getIdentifier()->getName();
Douglas Gregor86b42682015-06-19 18:27:52 +00002416 } else {
2417 Type.getAsStringInternal(Result, Policy);
Douglas Gregore90dd002010-08-24 16:15:59 +00002418 }
2419 return Result;
2420 }
Alex Lorenza1951202016-10-18 10:35:27 +00002421
Douglas Gregore90dd002010-08-24 16:15:59 +00002422 // The argument for a block pointer parameter is a block literal with
2423 // the appropriate type.
David Blaikie6adc78e2013-02-18 22:06:02 +00002424 FunctionTypeLoc Block;
2425 FunctionProtoTypeLoc BlockProto;
Alex Lorenza1951202016-10-18 10:35:27 +00002426 findTypeLocationForBlockDecl(Param->getTypeSourceInfo(), Block, BlockProto,
2427 SuppressBlock);
Alex Lorenz6bf4a582017-03-13 15:43:42 +00002428 // Try to retrieve the block type information from the property if this is a
2429 // parameter in a setter.
2430 if (!Block && ObjCMethodParam &&
2431 cast<ObjCMethodDecl>(Param->getDeclContext())->isPropertyAccessor()) {
2432 if (const auto *PD = cast<ObjCMethodDecl>(Param->getDeclContext())
2433 ->findPropertyDecl(/*CheckOverrides=*/false))
2434 findTypeLocationForBlockDecl(PD->getTypeSourceInfo(), Block, BlockProto,
2435 SuppressBlock);
2436 }
Douglas Gregore90dd002010-08-24 16:15:59 +00002437
2438 if (!Block) {
2439 // We were unable to find a FunctionProtoTypeLoc with parameter names
2440 // for the block; just use the parameter type as a placeholder.
2441 std::string Result;
Douglas Gregord793e7c2011-10-18 04:23:19 +00002442 if (!ObjCMethodParam && Param->getIdentifier())
2443 Result = Param->getIdentifier()->getName();
2444
Douglas Gregor86b42682015-06-19 18:27:52 +00002445 QualType Type = Param->getType().getUnqualifiedType();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002446
Douglas Gregore90dd002010-08-24 16:15:59 +00002447 if (ObjCMethodParam) {
Alex Lorenz01bcfc12016-11-23 16:28:34 +00002448 Result = Type.getAsString(Policy);
2449 std::string Quals =
2450 formatObjCParamQualifiers(Param->getObjCDeclQualifier(), Type);
2451 if (!Quals.empty())
2452 Result = "(" + Quals + " " + Result + ")";
2453 if (Result.back() != ')')
2454 Result += " ";
Douglas Gregore90dd002010-08-24 16:15:59 +00002455 if (Param->getIdentifier())
2456 Result += Param->getIdentifier()->getName();
Douglas Gregor86b42682015-06-19 18:27:52 +00002457 } else {
2458 Type.getAsStringInternal(Result, Policy);
Douglas Gregore90dd002010-08-24 16:15:59 +00002459 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002460
Douglas Gregore90dd002010-08-24 16:15:59 +00002461 return Result;
2462 }
Alex Lorenz01bcfc12016-11-23 16:28:34 +00002463
Douglas Gregore90dd002010-08-24 16:15:59 +00002464 // We have the function prototype behind the block pointer type, as it was
2465 // written in the source.
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002466 return formatBlockPlaceholder(Policy, Param, Block, BlockProto,
2467 /*SuppressBlockName=*/false, SuppressBlock,
Alex Lorenz920ae142016-10-18 10:38:58 +00002468 ObjCSubsts);
2469}
2470
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002471/// Returns a placeholder string that corresponds to an Objective-C block
Alex Lorenz920ae142016-10-18 10:38:58 +00002472/// declaration.
2473///
2474/// \param BlockDecl A declaration with an Objective-C block type.
2475///
2476/// \param Block The most relevant type location for that block type.
2477///
Alexander Kornienko2a8c18d2018-04-06 15:14:32 +00002478/// \param SuppressBlockName Determines whether or not the name of the block
Alex Lorenz920ae142016-10-18 10:38:58 +00002479/// declaration is included in the resulting string.
2480static std::string
2481formatBlockPlaceholder(const PrintingPolicy &Policy, const NamedDecl *BlockDecl,
2482 FunctionTypeLoc &Block, FunctionProtoTypeLoc &BlockProto,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002483 bool SuppressBlockName, bool SuppressBlock,
Alex Lorenz920ae142016-10-18 10:38:58 +00002484 Optional<ArrayRef<QualType>> ObjCSubsts) {
Douglas Gregor67da50e2010-09-08 22:47:51 +00002485 std::string Result;
Alp Toker314cc812014-01-25 16:55:45 +00002486 QualType ResultType = Block.getTypePtr()->getReturnType();
Douglas Gregorc3425b12015-07-07 06:20:19 +00002487 if (ObjCSubsts)
Alex Lorenz920ae142016-10-18 10:38:58 +00002488 ResultType =
2489 ResultType.substObjCTypeArgs(BlockDecl->getASTContext(), *ObjCSubsts,
2490 ObjCSubstitutionContext::Result);
Douglas Gregord793e7c2011-10-18 04:23:19 +00002491 if (!ResultType->isVoidType() || SuppressBlock)
John McCall31168b02011-06-15 23:02:42 +00002492 ResultType.getAsStringInternal(Result, Policy);
Douglas Gregord793e7c2011-10-18 04:23:19 +00002493
2494 // Format the parameter list.
2495 std::string Params;
Alp Tokerb3fd5cf2014-01-21 00:32:38 +00002496 if (!BlockProto || Block.getNumParams() == 0) {
David Blaikie6adc78e2013-02-18 22:06:02 +00002497 if (BlockProto && BlockProto.getTypePtr()->isVariadic())
Douglas Gregord793e7c2011-10-18 04:23:19 +00002498 Params = "(...)";
Douglas Gregoraf25cfa2010-10-02 23:49:58 +00002499 else
Douglas Gregord793e7c2011-10-18 04:23:19 +00002500 Params = "(void)";
Douglas Gregor67da50e2010-09-08 22:47:51 +00002501 } else {
Douglas Gregord793e7c2011-10-18 04:23:19 +00002502 Params += "(";
Alp Tokerb3fd5cf2014-01-21 00:32:38 +00002503 for (unsigned I = 0, N = Block.getNumParams(); I != N; ++I) {
Douglas Gregor67da50e2010-09-08 22:47:51 +00002504 if (I)
Douglas Gregord793e7c2011-10-18 04:23:19 +00002505 Params += ", ";
Richard Smith20e883e2015-04-29 23:20:19 +00002506 Params += FormatFunctionParameter(Policy, Block.getParam(I),
Alp Tokerb3fd5cf2014-01-21 00:32:38 +00002507 /*SuppressName=*/false,
Alex Lorenz920ae142016-10-18 10:38:58 +00002508 /*SuppressBlock=*/true, ObjCSubsts);
Alp Tokerb3fd5cf2014-01-21 00:32:38 +00002509
David Blaikie6adc78e2013-02-18 22:06:02 +00002510 if (I == N - 1 && BlockProto.getTypePtr()->isVariadic())
Douglas Gregord793e7c2011-10-18 04:23:19 +00002511 Params += ", ...";
Douglas Gregor67da50e2010-09-08 22:47:51 +00002512 }
Douglas Gregord793e7c2011-10-18 04:23:19 +00002513 Params += ")";
Douglas Gregor400f5972010-08-31 05:13:43 +00002514 }
Alex Lorenz920ae142016-10-18 10:38:58 +00002515
Douglas Gregord793e7c2011-10-18 04:23:19 +00002516 if (SuppressBlock) {
2517 // Format as a parameter.
2518 Result = Result + " (^";
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002519 if (!SuppressBlockName && BlockDecl->getIdentifier())
Alex Lorenz920ae142016-10-18 10:38:58 +00002520 Result += BlockDecl->getIdentifier()->getName();
Douglas Gregord793e7c2011-10-18 04:23:19 +00002521 Result += ")";
2522 Result += Params;
2523 } else {
2524 // Format as a block literal argument.
2525 Result = '^' + Result;
2526 Result += Params;
Alex Lorenz920ae142016-10-18 10:38:58 +00002527
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002528 if (!SuppressBlockName && BlockDecl->getIdentifier())
Alex Lorenz920ae142016-10-18 10:38:58 +00002529 Result += BlockDecl->getIdentifier()->getName();
Douglas Gregord793e7c2011-10-18 04:23:19 +00002530 }
Alex Lorenz920ae142016-10-18 10:38:58 +00002531
Douglas Gregore90dd002010-08-24 16:15:59 +00002532 return Result;
2533}
2534
Erik Verbruggen11338c52017-07-19 10:45:40 +00002535static std::string GetDefaultValueString(const ParmVarDecl *Param,
2536 const SourceManager &SM,
2537 const LangOptions &LangOpts) {
Ilya Biryukovb6d1ec82017-07-21 09:24:00 +00002538 const SourceRange SrcRange = Param->getDefaultArgRange();
Erik Verbruggen11338c52017-07-19 10:45:40 +00002539 CharSourceRange CharSrcRange = CharSourceRange::getTokenRange(SrcRange);
2540 bool Invalid = CharSrcRange.isInvalid();
2541 if (Invalid)
2542 return "";
2543 StringRef srcText = Lexer::getSourceText(CharSrcRange, SM, LangOpts, &Invalid);
2544 if (Invalid)
2545 return "";
2546
2547 if (srcText.empty() || srcText == "=") {
2548 // Lexer can't determine the value.
2549 // This happens if the code is incorrect (for example class is forward declared).
2550 return "";
2551 }
Erik Verbruggen797980e2017-07-19 11:15:36 +00002552 std::string DefValue(srcText.str());
Erik Verbruggen11338c52017-07-19 10:45:40 +00002553 // FIXME: remove this check if the Lexer::getSourceText value is fixed and
2554 // this value always has (or always does not have) '=' in front of it
2555 if (DefValue.at(0) != '=') {
2556 // If we don't have '=' in front of value.
2557 // Lexer returns built-in types values without '=' and user-defined types values with it.
2558 return " = " + DefValue;
2559 }
2560 return " " + DefValue;
2561}
2562
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002563/// Add function parameter chunks to the given code completion string.
Richard Smith20e883e2015-04-29 23:20:19 +00002564static void AddFunctionParameterChunks(Preprocessor &PP,
Douglas Gregor75acd922011-09-27 23:30:47 +00002565 const PrintingPolicy &Policy,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002566 const FunctionDecl *Function,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002567 CodeCompletionBuilder &Result,
2568 unsigned Start = 0,
2569 bool InOptional = false) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002570 bool FirstParameter = true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002571
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002572 for (unsigned P = Start, N = Function->getNumParams(); P != N; ++P) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002573 const ParmVarDecl *Param = Function->getParamDecl(P);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002574
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002575 if (Param->hasDefaultArg() && !InOptional) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002576 // When we see an optional default argument, put that argument and
2577 // the remaining default arguments into a new, optional string.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00002578 CodeCompletionBuilder Opt(Result.getAllocator(),
2579 Result.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002580 if (!FirstParameter)
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002581 Opt.AddChunk(CodeCompletionString::CK_Comma);
Richard Smith20e883e2015-04-29 23:20:19 +00002582 AddFunctionParameterChunks(PP, Policy, Function, Opt, P, true);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002583 Result.AddOptionalChunk(Opt.TakeString());
2584 break;
Douglas Gregor3545ff42009-09-21 16:56:56 +00002585 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002586
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002587 if (FirstParameter)
2588 FirstParameter = false;
2589 else
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002590 Result.AddChunk(CodeCompletionString::CK_Comma);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002591
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002592 InOptional = false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002593
Douglas Gregor3545ff42009-09-21 16:56:56 +00002594 // Format the placeholder string.
Richard Smith20e883e2015-04-29 23:20:19 +00002595 std::string PlaceholderStr = FormatFunctionParameter(Policy, Param);
Erik Verbruggen11338c52017-07-19 10:45:40 +00002596 if (Param->hasDefaultArg())
2597 PlaceholderStr += GetDefaultValueString(Param, PP.getSourceManager(), PP.getLangOpts());
Richard Smith20e883e2015-04-29 23:20:19 +00002598
Douglas Gregor400f5972010-08-31 05:13:43 +00002599 if (Function->isVariadic() && P == N - 1)
2600 PlaceholderStr += ", ...";
2601
Douglas Gregor3545ff42009-09-21 16:56:56 +00002602 // Add the placeholder string.
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002603 Result.AddPlaceholderChunk(
2604 Result.getAllocator().CopyString(PlaceholderStr));
Douglas Gregor3545ff42009-09-21 16:56:56 +00002605 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002606
2607 if (const FunctionProtoType *Proto
Douglas Gregorba449032009-09-22 21:42:17 +00002608 = Function->getType()->getAs<FunctionProtoType>())
Douglas Gregordbb71db2010-08-23 23:51:41 +00002609 if (Proto->isVariadic()) {
Alp Toker9cacbab2014-01-20 20:26:09 +00002610 if (Proto->getNumParams() == 0)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002611 Result.AddPlaceholderChunk("...");
Douglas Gregordbb71db2010-08-23 23:51:41 +00002612
Richard Smith20e883e2015-04-29 23:20:19 +00002613 MaybeAddSentinel(PP, Function, Result);
Douglas Gregordbb71db2010-08-23 23:51:41 +00002614 }
Douglas Gregor3545ff42009-09-21 16:56:56 +00002615}
2616
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002617/// Add template parameter chunks to the given code completion string.
Douglas Gregor3545ff42009-09-21 16:56:56 +00002618static void AddTemplateParameterChunks(ASTContext &Context,
Douglas Gregor75acd922011-09-27 23:30:47 +00002619 const PrintingPolicy &Policy,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002620 const TemplateDecl *Template,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002621 CodeCompletionBuilder &Result,
2622 unsigned MaxParameters = 0,
2623 unsigned Start = 0,
2624 bool InDefaultArg = false) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002625 bool FirstParameter = true;
Richard Smith6eece292015-01-15 02:27:20 +00002626
2627 // Prefer to take the template parameter names from the first declaration of
2628 // the template.
2629 Template = cast<TemplateDecl>(Template->getCanonicalDecl());
2630
Douglas Gregor3545ff42009-09-21 16:56:56 +00002631 TemplateParameterList *Params = Template->getTemplateParameters();
2632 TemplateParameterList::iterator PEnd = Params->end();
2633 if (MaxParameters)
2634 PEnd = Params->begin() + MaxParameters;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002635 for (TemplateParameterList::iterator P = Params->begin() + Start;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002636 P != PEnd; ++P) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002637 bool HasDefaultArg = false;
2638 std::string PlaceholderStr;
2639 if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*P)) {
2640 if (TTP->wasDeclaredWithTypename())
2641 PlaceholderStr = "typename";
2642 else
2643 PlaceholderStr = "class";
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002644
Douglas Gregor3545ff42009-09-21 16:56:56 +00002645 if (TTP->getIdentifier()) {
2646 PlaceholderStr += ' ';
2647 PlaceholderStr += TTP->getIdentifier()->getName();
2648 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002649
Douglas Gregor3545ff42009-09-21 16:56:56 +00002650 HasDefaultArg = TTP->hasDefaultArgument();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002651 } else if (NonTypeTemplateParmDecl *NTTP
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002652 = dyn_cast<NonTypeTemplateParmDecl>(*P)) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002653 if (NTTP->getIdentifier())
2654 PlaceholderStr = NTTP->getIdentifier()->getName();
John McCall31168b02011-06-15 23:02:42 +00002655 NTTP->getType().getAsStringInternal(PlaceholderStr, Policy);
Douglas Gregor3545ff42009-09-21 16:56:56 +00002656 HasDefaultArg = NTTP->hasDefaultArgument();
2657 } else {
2658 assert(isa<TemplateTemplateParmDecl>(*P));
2659 TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*P);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002660
Douglas Gregor3545ff42009-09-21 16:56:56 +00002661 // Since putting the template argument list into the placeholder would
2662 // be very, very long, we just use an abbreviation.
2663 PlaceholderStr = "template<...> class";
2664 if (TTP->getIdentifier()) {
2665 PlaceholderStr += ' ';
2666 PlaceholderStr += TTP->getIdentifier()->getName();
2667 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002668
Douglas Gregor3545ff42009-09-21 16:56:56 +00002669 HasDefaultArg = TTP->hasDefaultArgument();
2670 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002671
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002672 if (HasDefaultArg && !InDefaultArg) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002673 // When we see an optional default argument, put that argument and
2674 // the remaining default arguments into a new, optional string.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00002675 CodeCompletionBuilder Opt(Result.getAllocator(),
2676 Result.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002677 if (!FirstParameter)
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002678 Opt.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor75acd922011-09-27 23:30:47 +00002679 AddTemplateParameterChunks(Context, Policy, Template, Opt, MaxParameters,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002680 P - Params->begin(), true);
2681 Result.AddOptionalChunk(Opt.TakeString());
2682 break;
Douglas Gregor3545ff42009-09-21 16:56:56 +00002683 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002684
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002685 InDefaultArg = false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002686
Douglas Gregor3545ff42009-09-21 16:56:56 +00002687 if (FirstParameter)
2688 FirstParameter = false;
2689 else
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002690 Result.AddChunk(CodeCompletionString::CK_Comma);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002691
Douglas Gregor3545ff42009-09-21 16:56:56 +00002692 // Add the placeholder string.
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002693 Result.AddPlaceholderChunk(
2694 Result.getAllocator().CopyString(PlaceholderStr));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002695 }
Douglas Gregor3545ff42009-09-21 16:56:56 +00002696}
2697
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002698/// Add a qualifier to the given code-completion string, if the
Douglas Gregorf2510672009-09-21 19:57:38 +00002699/// provided nested-name-specifier is non-NULL.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002700static void
2701AddQualifierToCompletionString(CodeCompletionBuilder &Result,
2702 NestedNameSpecifier *Qualifier,
Douglas Gregor0f622362009-12-11 18:44:16 +00002703 bool QualifierIsInformative,
Douglas Gregor75acd922011-09-27 23:30:47 +00002704 ASTContext &Context,
2705 const PrintingPolicy &Policy) {
Douglas Gregorf2510672009-09-21 19:57:38 +00002706 if (!Qualifier)
2707 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002708
Douglas Gregorf2510672009-09-21 19:57:38 +00002709 std::string PrintedNNS;
2710 {
2711 llvm::raw_string_ostream OS(PrintedNNS);
Douglas Gregor75acd922011-09-27 23:30:47 +00002712 Qualifier->print(OS, Policy);
Douglas Gregorf2510672009-09-21 19:57:38 +00002713 }
Douglas Gregor5bf52692009-09-22 23:15:58 +00002714 if (QualifierIsInformative)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002715 Result.AddInformativeChunk(Result.getAllocator().CopyString(PrintedNNS));
Douglas Gregor5bf52692009-09-22 23:15:58 +00002716 else
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002717 Result.AddTextChunk(Result.getAllocator().CopyString(PrintedNNS));
Douglas Gregorf2510672009-09-21 19:57:38 +00002718}
2719
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002720static void
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002721AddFunctionTypeQualsToCompletionString(CodeCompletionBuilder &Result,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002722 const FunctionDecl *Function) {
Douglas Gregor0f622362009-12-11 18:44:16 +00002723 const FunctionProtoType *Proto
2724 = Function->getType()->getAs<FunctionProtoType>();
2725 if (!Proto || !Proto->getTypeQuals())
2726 return;
2727
Douglas Gregor304f9b02011-02-01 21:15:40 +00002728 // FIXME: Add ref-qualifier!
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002729
Douglas Gregor304f9b02011-02-01 21:15:40 +00002730 // Handle single qualifiers without copying
2731 if (Proto->getTypeQuals() == Qualifiers::Const) {
2732 Result.AddInformativeChunk(" const");
2733 return;
2734 }
2735
2736 if (Proto->getTypeQuals() == Qualifiers::Volatile) {
2737 Result.AddInformativeChunk(" volatile");
2738 return;
2739 }
2740
2741 if (Proto->getTypeQuals() == Qualifiers::Restrict) {
2742 Result.AddInformativeChunk(" restrict");
2743 return;
2744 }
2745
2746 // Handle multiple qualifiers.
Douglas Gregor0f622362009-12-11 18:44:16 +00002747 std::string QualsStr;
David Blaikief5697e52012-08-10 00:55:35 +00002748 if (Proto->isConst())
Douglas Gregor0f622362009-12-11 18:44:16 +00002749 QualsStr += " const";
David Blaikief5697e52012-08-10 00:55:35 +00002750 if (Proto->isVolatile())
Douglas Gregor0f622362009-12-11 18:44:16 +00002751 QualsStr += " volatile";
David Blaikief5697e52012-08-10 00:55:35 +00002752 if (Proto->isRestrict())
Douglas Gregor0f622362009-12-11 18:44:16 +00002753 QualsStr += " restrict";
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002754 Result.AddInformativeChunk(Result.getAllocator().CopyString(QualsStr));
Douglas Gregor0f622362009-12-11 18:44:16 +00002755}
2756
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002757/// Add the name of the given declaration
Douglas Gregor75acd922011-09-27 23:30:47 +00002758static void AddTypedNameChunk(ASTContext &Context, const PrintingPolicy &Policy,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002759 const NamedDecl *ND,
2760 CodeCompletionBuilder &Result) {
Douglas Gregor0212fd72010-09-21 16:06:22 +00002761 DeclarationName Name = ND->getDeclName();
2762 if (!Name)
2763 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002764
Douglas Gregor0212fd72010-09-21 16:06:22 +00002765 switch (Name.getNameKind()) {
Douglas Gregor304f9b02011-02-01 21:15:40 +00002766 case DeclarationName::CXXOperatorName: {
Craig Topperc3ec1492014-05-26 06:22:03 +00002767 const char *OperatorName = nullptr;
Douglas Gregor304f9b02011-02-01 21:15:40 +00002768 switch (Name.getCXXOverloadedOperator()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002769 case OO_None:
Douglas Gregor304f9b02011-02-01 21:15:40 +00002770 case OO_Conditional:
2771 case NUM_OVERLOADED_OPERATORS:
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002772 OperatorName = "operator";
Douglas Gregor304f9b02011-02-01 21:15:40 +00002773 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002774
Douglas Gregor304f9b02011-02-01 21:15:40 +00002775#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
2776 case OO_##Name: OperatorName = "operator" Spelling; break;
2777#define OVERLOADED_OPERATOR_MULTI(Name,Spelling,Unary,Binary,MemberOnly)
2778#include "clang/Basic/OperatorKinds.def"
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002779
Douglas Gregor304f9b02011-02-01 21:15:40 +00002780 case OO_New: OperatorName = "operator new"; break;
2781 case OO_Delete: OperatorName = "operator delete"; break;
2782 case OO_Array_New: OperatorName = "operator new[]"; break;
2783 case OO_Array_Delete: OperatorName = "operator delete[]"; break;
2784 case OO_Call: OperatorName = "operator()"; break;
2785 case OO_Subscript: OperatorName = "operator[]"; break;
2786 }
2787 Result.AddTypedTextChunk(OperatorName);
2788 break;
2789 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002790
Douglas Gregor0212fd72010-09-21 16:06:22 +00002791 case DeclarationName::Identifier:
2792 case DeclarationName::CXXConversionFunctionName:
Douglas Gregor0212fd72010-09-21 16:06:22 +00002793 case DeclarationName::CXXDestructorName:
2794 case DeclarationName::CXXLiteralOperatorName:
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002795 Result.AddTypedTextChunk(
2796 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor0212fd72010-09-21 16:06:22 +00002797 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002798
Richard Smith35845152017-02-07 01:37:30 +00002799 case DeclarationName::CXXDeductionGuideName:
Douglas Gregor0212fd72010-09-21 16:06:22 +00002800 case DeclarationName::CXXUsingDirective:
2801 case DeclarationName::ObjCZeroArgSelector:
2802 case DeclarationName::ObjCOneArgSelector:
2803 case DeclarationName::ObjCMultiArgSelector:
2804 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002805
Douglas Gregor0212fd72010-09-21 16:06:22 +00002806 case DeclarationName::CXXConstructorName: {
Craig Topperc3ec1492014-05-26 06:22:03 +00002807 CXXRecordDecl *Record = nullptr;
Douglas Gregor0212fd72010-09-21 16:06:22 +00002808 QualType Ty = Name.getCXXNameType();
2809 if (const RecordType *RecordTy = Ty->getAs<RecordType>())
2810 Record = cast<CXXRecordDecl>(RecordTy->getDecl());
2811 else if (const InjectedClassNameType *InjectedTy
2812 = Ty->getAs<InjectedClassNameType>())
2813 Record = InjectedTy->getDecl();
2814 else {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002815 Result.AddTypedTextChunk(
2816 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor0212fd72010-09-21 16:06:22 +00002817 break;
2818 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002819
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002820 Result.AddTypedTextChunk(
2821 Result.getAllocator().CopyString(Record->getNameAsString()));
Douglas Gregor0212fd72010-09-21 16:06:22 +00002822 if (ClassTemplateDecl *Template = Record->getDescribedClassTemplate()) {
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002823 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Douglas Gregor75acd922011-09-27 23:30:47 +00002824 AddTemplateParameterChunks(Context, Policy, Template, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002825 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregor0212fd72010-09-21 16:06:22 +00002826 }
2827 break;
2828 }
2829 }
2830}
2831
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002832CodeCompletionString *CodeCompletionResult::CreateCodeCompletionString(Sema &S,
Douglas Gregorc3425b12015-07-07 06:20:19 +00002833 const CodeCompletionContext &CCContext,
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00002834 CodeCompletionAllocator &Allocator,
Dmitri Gribenko3292d062012-07-02 17:35:10 +00002835 CodeCompletionTUInfo &CCTUInfo,
2836 bool IncludeBriefComments) {
Douglas Gregorc3425b12015-07-07 06:20:19 +00002837 return CreateCodeCompletionString(S.Context, S.PP, CCContext, Allocator,
2838 CCTUInfo, IncludeBriefComments);
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002839}
2840
Eric Liu00f43c92018-07-06 09:43:57 +00002841CodeCompletionString *CodeCompletionResult::CreateCodeCompletionStringForMacro(
2842 Preprocessor &PP, CodeCompletionAllocator &Allocator,
2843 CodeCompletionTUInfo &CCTUInfo) {
2844 assert(Kind == RK_Macro);
2845 CodeCompletionBuilder Result(Allocator, CCTUInfo, Priority, Availability);
2846 const MacroInfo *MI = PP.getMacroInfo(Macro);
2847 Result.AddTypedTextChunk(Result.getAllocator().CopyString(Macro->getName()));
2848
2849 if (!MI || !MI->isFunctionLike())
2850 return Result.TakeString();
2851
2852 // Format a function-like macro with placeholders for the arguments.
2853 Result.AddChunk(CodeCompletionString::CK_LeftParen);
2854 MacroInfo::param_iterator A = MI->param_begin(), AEnd = MI->param_end();
2855
2856 // C99 variadic macros add __VA_ARGS__ at the end. Skip it.
2857 if (MI->isC99Varargs()) {
2858 --AEnd;
2859
2860 if (A == AEnd) {
2861 Result.AddPlaceholderChunk("...");
2862 }
2863 }
2864
2865 for (MacroInfo::param_iterator A = MI->param_begin(); A != AEnd; ++A) {
2866 if (A != MI->param_begin())
2867 Result.AddChunk(CodeCompletionString::CK_Comma);
2868
2869 if (MI->isVariadic() && (A + 1) == AEnd) {
2870 SmallString<32> Arg = (*A)->getName();
2871 if (MI->isC99Varargs())
2872 Arg += ", ...";
2873 else
2874 Arg += "...";
2875 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg));
2876 break;
2877 }
2878
2879 // Non-variadic macros are simple.
2880 Result.AddPlaceholderChunk(
2881 Result.getAllocator().CopyString((*A)->getName()));
2882 }
2883 Result.AddChunk(CodeCompletionString::CK_RightParen);
2884 return Result.TakeString();
2885}
2886
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002887/// If possible, create a new code completion string for the given
Douglas Gregor3545ff42009-09-21 16:56:56 +00002888/// result.
2889///
2890/// \returns Either a new, heap-allocated code completion string describing
2891/// how to use this result, or NULL to indicate that the string or name of the
2892/// result is all that is needed.
2893CodeCompletionString *
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002894CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx,
2895 Preprocessor &PP,
Douglas Gregorc3425b12015-07-07 06:20:19 +00002896 const CodeCompletionContext &CCContext,
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00002897 CodeCompletionAllocator &Allocator,
Dmitri Gribenko3292d062012-07-02 17:35:10 +00002898 CodeCompletionTUInfo &CCTUInfo,
2899 bool IncludeBriefComments) {
Eric Liu00f43c92018-07-06 09:43:57 +00002900 if (Kind == RK_Macro)
2901 return CreateCodeCompletionStringForMacro(PP, Allocator, CCTUInfo);
2902
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00002903 CodeCompletionBuilder Result(Allocator, CCTUInfo, Priority, Availability);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002904
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002905 PrintingPolicy Policy = getCompletionPrintingPolicy(Ctx, PP);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002906 if (Kind == RK_Pattern) {
2907 Pattern->Priority = Priority;
2908 Pattern->Availability = Availability;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002909
Douglas Gregor78254c82012-03-27 23:34:16 +00002910 if (Declaration) {
2911 Result.addParentContext(Declaration->getDeclContext());
Douglas Gregor78254c82012-03-27 23:34:16 +00002912 Pattern->ParentName = Result.getParentName();
Ilya Biryukova3f955b2018-05-16 12:30:01 +00002913 if (const RawComment *RC =
2914 getPatternCompletionComment(Ctx, Declaration)) {
2915 Result.addBriefComment(RC->getBriefText(Ctx));
2916 Pattern->BriefComment = Result.getBriefComment();
2917 }
Douglas Gregor78254c82012-03-27 23:34:16 +00002918 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002919
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002920 return Pattern;
2921 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002922
Douglas Gregorf09935f2009-12-01 05:55:20 +00002923 if (Kind == RK_Keyword) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002924 Result.AddTypedTextChunk(Keyword);
2925 return Result.TakeString();
Douglas Gregorf09935f2009-12-01 05:55:20 +00002926 }
Douglas Gregorf64acca2010-05-25 21:41:55 +00002927 assert(Kind == RK_Declaration && "Missed a result kind?");
Kadir Cetinkayaae45d0a42018-10-02 09:42:31 +00002928 return createCodeCompletionStringForDecl(PP, Ctx, Result, IncludeBriefComments,
2929 CCContext, Policy);
2930}
2931
2932CodeCompletionString *
2933CodeCompletionResult::createCodeCompletionStringForOverride(
2934 Preprocessor &PP, ASTContext &Ctx, CodeCompletionBuilder &Result,
2935 bool IncludeBriefComments, const CodeCompletionContext &CCContext,
2936 PrintingPolicy &Policy) {
2937 std::string OverrideSignature;
2938 llvm::raw_string_ostream OS(OverrideSignature);
2939 auto *CCS = createCodeCompletionStringForDecl(PP, Ctx, Result,
2940 /*IncludeBriefComments=*/false,
2941 CCContext, Policy);
2942 printOverrideString(OS, CCS);
2943 OS << " override";
2944 Result.AddTypedTextChunk(Result.getAllocator().CopyString(OS.str()));
2945 return Result.TakeString();
2946}
2947
2948CodeCompletionString *CodeCompletionResult::createCodeCompletionStringForDecl(
2949 Preprocessor &PP, ASTContext &Ctx, CodeCompletionBuilder &Result,
2950 bool IncludeBriefComments, const CodeCompletionContext &CCContext,
2951 PrintingPolicy &Policy) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002952 const NamedDecl *ND = Declaration;
Douglas Gregor78254c82012-03-27 23:34:16 +00002953 Result.addParentContext(ND->getDeclContext());
Dmitri Gribenko3292d062012-07-02 17:35:10 +00002954
2955 if (IncludeBriefComments) {
2956 // Add documentation comment, if it exists.
Ilya Biryukova3f955b2018-05-16 12:30:01 +00002957 if (const RawComment *RC = getCompletionComment(Ctx, Declaration)) {
Dmitri Gribenko3292d062012-07-02 17:35:10 +00002958 Result.addBriefComment(RC->getBriefText(Ctx));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002959 }
Dmitri Gribenko3292d062012-07-02 17:35:10 +00002960 }
2961
Douglas Gregor9eb77012009-11-07 00:00:49 +00002962 if (StartsNestedNameSpecifier) {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002963 Result.AddTypedTextChunk(
2964 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002965 Result.AddTextChunk("::");
2966 return Result.TakeString();
Douglas Gregor9eb77012009-11-07 00:00:49 +00002967 }
Erik Verbruggen98ea7f62011-10-14 15:31:08 +00002968
Aaron Ballmanbe22bcb2014-03-10 17:08:28 +00002969 for (const auto *I : ND->specific_attrs<AnnotateAttr>())
2970 Result.AddAnnotation(Result.getAllocator().CopyString(I->getAnnotation()));
Aaron Ballmanb97112e2014-03-08 22:19:01 +00002971
Douglas Gregorc3425b12015-07-07 06:20:19 +00002972 AddResultTypeChunk(Ctx, Policy, ND, CCContext.getBaseType(), Result);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002973
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002974 if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(ND)) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002975 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002976 Ctx, Policy);
2977 AddTypedNameChunk(Ctx, Policy, ND, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002978 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Richard Smith20e883e2015-04-29 23:20:19 +00002979 AddFunctionParameterChunks(PP, Policy, Function, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002980 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor0f622362009-12-11 18:44:16 +00002981 AddFunctionTypeQualsToCompletionString(Result, Function);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002982 return Result.TakeString();
Douglas Gregor3545ff42009-09-21 16:56:56 +00002983 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002984
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002985 if (const FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND)) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002986 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002987 Ctx, Policy);
Douglas Gregor3545ff42009-09-21 16:56:56 +00002988 FunctionDecl *Function = FunTmpl->getTemplatedDecl();
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002989 AddTypedNameChunk(Ctx, Policy, Function, Result);
Douglas Gregor0212fd72010-09-21 16:06:22 +00002990
Douglas Gregor3545ff42009-09-21 16:56:56 +00002991 // Figure out which template parameters are deduced (or have default
2992 // arguments).
Benjamin Kramere0513cb2012-01-30 16:17:39 +00002993 llvm::SmallBitVector Deduced;
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002994 Sema::MarkDeducedTemplateParameters(Ctx, FunTmpl, Deduced);
Douglas Gregor3545ff42009-09-21 16:56:56 +00002995 unsigned LastDeducibleArgument;
2996 for (LastDeducibleArgument = Deduced.size(); LastDeducibleArgument > 0;
2997 --LastDeducibleArgument) {
2998 if (!Deduced[LastDeducibleArgument - 1]) {
2999 // C++0x: Figure out if the template argument has a default. If so,
3000 // the user doesn't need to type this argument.
3001 // FIXME: We need to abstract template parameters better!
3002 bool HasDefaultArg = false;
3003 NamedDecl *Param = FunTmpl->getTemplateParameters()->getParam(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003004 LastDeducibleArgument - 1);
Douglas Gregor3545ff42009-09-21 16:56:56 +00003005 if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param))
3006 HasDefaultArg = TTP->hasDefaultArgument();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003007 else if (NonTypeTemplateParmDecl *NTTP
Douglas Gregor3545ff42009-09-21 16:56:56 +00003008 = dyn_cast<NonTypeTemplateParmDecl>(Param))
3009 HasDefaultArg = NTTP->hasDefaultArgument();
3010 else {
3011 assert(isa<TemplateTemplateParmDecl>(Param));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003012 HasDefaultArg
Douglas Gregor9eb77012009-11-07 00:00:49 +00003013 = cast<TemplateTemplateParmDecl>(Param)->hasDefaultArgument();
Douglas Gregor3545ff42009-09-21 16:56:56 +00003014 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003015
Douglas Gregor3545ff42009-09-21 16:56:56 +00003016 if (!HasDefaultArg)
3017 break;
3018 }
3019 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003020
Douglas Gregor3545ff42009-09-21 16:56:56 +00003021 if (LastDeducibleArgument) {
3022 // Some of the function template arguments cannot be deduced from a
3023 // function call, so we introduce an explicit template argument list
3024 // containing all of the arguments up to the first deducible argument.
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003025 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003026 AddTemplateParameterChunks(Ctx, Policy, FunTmpl, Result,
Douglas Gregor3545ff42009-09-21 16:56:56 +00003027 LastDeducibleArgument);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003028 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregor3545ff42009-09-21 16:56:56 +00003029 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003030
Douglas Gregor3545ff42009-09-21 16:56:56 +00003031 // Add the function parameters
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003032 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Richard Smith20e883e2015-04-29 23:20:19 +00003033 AddFunctionParameterChunks(PP, Policy, Function, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003034 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor0f622362009-12-11 18:44:16 +00003035 AddFunctionTypeQualsToCompletionString(Result, Function);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003036 return Result.TakeString();
Douglas Gregor3545ff42009-09-21 16:56:56 +00003037 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003038
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00003039 if (const TemplateDecl *Template = dyn_cast<TemplateDecl>(ND)) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003040 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003041 Ctx, Policy);
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003042 Result.AddTypedTextChunk(
3043 Result.getAllocator().CopyString(Template->getNameAsString()));
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003044 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003045 AddTemplateParameterChunks(Ctx, Policy, Template, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003046 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003047 return Result.TakeString();
Douglas Gregor3545ff42009-09-21 16:56:56 +00003048 }
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00003049 if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND)) {
Douglas Gregord3c5d792009-11-17 16:44:22 +00003050 Selector Sel = Method->getSelector();
3051 if (Sel.isUnarySelector()) {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003052 Result.AddTypedTextChunk(Result.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00003053 Sel.getNameForSlot(0)));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003054 return Result.TakeString();
Douglas Gregord3c5d792009-11-17 16:44:22 +00003055 }
3056
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00003057 std::string SelName = Sel.getNameForSlot(0).str();
Douglas Gregor1b605f72009-11-19 01:08:35 +00003058 SelName += ':';
3059 if (StartParameter == 0)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003060 Result.AddTypedTextChunk(Result.getAllocator().CopyString(SelName));
Douglas Gregor1b605f72009-11-19 01:08:35 +00003061 else {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003062 Result.AddInformativeChunk(Result.getAllocator().CopyString(SelName));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003063
Douglas Gregor1b605f72009-11-19 01:08:35 +00003064 // If there is only one parameter, and we're past it, add an empty
3065 // typed-text chunk since there is nothing to type.
3066 if (Method->param_size() == 1)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003067 Result.AddTypedTextChunk("");
Douglas Gregor1b605f72009-11-19 01:08:35 +00003068 }
Douglas Gregord3c5d792009-11-17 16:44:22 +00003069 unsigned Idx = 0;
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00003070 for (ObjCMethodDecl::param_const_iterator P = Method->param_begin(),
3071 PEnd = Method->param_end();
Douglas Gregord3c5d792009-11-17 16:44:22 +00003072 P != PEnd; (void)++P, ++Idx) {
3073 if (Idx > 0) {
Douglas Gregor1b605f72009-11-19 01:08:35 +00003074 std::string Keyword;
3075 if (Idx > StartParameter)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003076 Result.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregord3c5d792009-11-17 16:44:22 +00003077 if (IdentifierInfo *II = Sel.getIdentifierInfoForSlot(Idx))
Benjamin Kramer632500c2011-07-26 16:59:25 +00003078 Keyword += II->getName();
Douglas Gregord3c5d792009-11-17 16:44:22 +00003079 Keyword += ":";
Douglas Gregor95887f92010-07-08 23:20:03 +00003080 if (Idx < StartParameter || AllParametersAreInformative)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003081 Result.AddInformativeChunk(Result.getAllocator().CopyString(Keyword));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003082 else
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003083 Result.AddTypedTextChunk(Result.getAllocator().CopyString(Keyword));
Douglas Gregord3c5d792009-11-17 16:44:22 +00003084 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003085
Douglas Gregor1b605f72009-11-19 01:08:35 +00003086 // If we're before the starting parameter, skip the placeholder.
3087 if (Idx < StartParameter)
3088 continue;
Douglas Gregord3c5d792009-11-17 16:44:22 +00003089
3090 std::string Arg;
Douglas Gregorc3425b12015-07-07 06:20:19 +00003091 QualType ParamType = (*P)->getType();
3092 Optional<ArrayRef<QualType>> ObjCSubsts;
3093 if (!CCContext.getBaseType().isNull())
3094 ObjCSubsts = CCContext.getBaseType()->getObjCSubstitutions(Method);
3095
3096 if (ParamType->isBlockPointerType() && !DeclaringEntity)
3097 Arg = FormatFunctionParameter(Policy, *P, true,
3098 /*SuppressBlock=*/false,
3099 ObjCSubsts);
Douglas Gregore90dd002010-08-24 16:15:59 +00003100 else {
Douglas Gregorc3425b12015-07-07 06:20:19 +00003101 if (ObjCSubsts)
3102 ParamType = ParamType.substObjCTypeArgs(Ctx, *ObjCSubsts,
3103 ObjCSubstitutionContext::Parameter);
Douglas Gregor86b42682015-06-19 18:27:52 +00003104 Arg = "(" + formatObjCParamQualifiers((*P)->getObjCDeclQualifier(),
Douglas Gregorc3425b12015-07-07 06:20:19 +00003105 ParamType);
3106 Arg += ParamType.getAsString(Policy) + ")";
Douglas Gregore90dd002010-08-24 16:15:59 +00003107 if (IdentifierInfo *II = (*P)->getIdentifier())
Douglas Gregor981a0c42010-08-29 19:47:46 +00003108 if (DeclaringEntity || AllParametersAreInformative)
Benjamin Kramer632500c2011-07-26 16:59:25 +00003109 Arg += II->getName();
Douglas Gregore90dd002010-08-24 16:15:59 +00003110 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003111
Douglas Gregor400f5972010-08-31 05:13:43 +00003112 if (Method->isVariadic() && (P + 1) == PEnd)
3113 Arg += ", ...";
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003114
Douglas Gregor95887f92010-07-08 23:20:03 +00003115 if (DeclaringEntity)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003116 Result.AddTextChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregor95887f92010-07-08 23:20:03 +00003117 else if (AllParametersAreInformative)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003118 Result.AddInformativeChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregorc8537c52009-11-19 07:41:15 +00003119 else
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003120 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregord3c5d792009-11-17 16:44:22 +00003121 }
3122
Douglas Gregor04c5f972009-12-23 00:21:46 +00003123 if (Method->isVariadic()) {
Douglas Gregor400f5972010-08-31 05:13:43 +00003124 if (Method->param_size() == 0) {
3125 if (DeclaringEntity)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003126 Result.AddTextChunk(", ...");
Douglas Gregor400f5972010-08-31 05:13:43 +00003127 else if (AllParametersAreInformative)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003128 Result.AddInformativeChunk(", ...");
Douglas Gregor400f5972010-08-31 05:13:43 +00003129 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003130 Result.AddPlaceholderChunk(", ...");
Douglas Gregor400f5972010-08-31 05:13:43 +00003131 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003132
Richard Smith20e883e2015-04-29 23:20:19 +00003133 MaybeAddSentinel(PP, Method, Result);
Douglas Gregor04c5f972009-12-23 00:21:46 +00003134 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003135
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003136 return Result.TakeString();
Douglas Gregord3c5d792009-11-17 16:44:22 +00003137 }
3138
Douglas Gregorf09935f2009-12-01 05:55:20 +00003139 if (Qualifier)
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003140 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003141 Ctx, Policy);
Douglas Gregorf09935f2009-12-01 05:55:20 +00003142
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003143 Result.AddTypedTextChunk(
Kadir Cetinkayaae45d0a42018-10-02 09:42:31 +00003144 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003145 return Result.TakeString();
Douglas Gregor3545ff42009-09-21 16:56:56 +00003146}
3147
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003148const RawComment *clang::getCompletionComment(const ASTContext &Ctx,
3149 const NamedDecl *ND) {
3150 if (!ND)
3151 return nullptr;
3152 if (auto *RC = Ctx.getRawCommentForAnyRedecl(ND))
3153 return RC;
3154
3155 // Try to find comment from a property for ObjC methods.
3156 const ObjCMethodDecl *M = dyn_cast<ObjCMethodDecl>(ND);
3157 if (!M)
3158 return nullptr;
3159 const ObjCPropertyDecl *PDecl = M->findPropertyDecl();
3160 if (!PDecl)
3161 return nullptr;
3162
3163 return Ctx.getRawCommentForAnyRedecl(PDecl);
3164}
3165
3166const RawComment *clang::getPatternCompletionComment(const ASTContext &Ctx,
3167 const NamedDecl *ND) {
3168 const ObjCMethodDecl *M = dyn_cast_or_null<ObjCMethodDecl>(ND);
3169 if (!M || !M->isPropertyAccessor())
3170 return nullptr;
3171
3172 // Provide code completion comment for self.GetterName where
3173 // GetterName is the getter method for a property with name
3174 // different from the property name (declared via a property
3175 // getter attribute.
3176 const ObjCPropertyDecl *PDecl = M->findPropertyDecl();
3177 if (!PDecl)
3178 return nullptr;
3179 if (PDecl->getGetterName() == M->getSelector() &&
3180 PDecl->getIdentifier() != M->getIdentifier()) {
3181 if (auto *RC = Ctx.getRawCommentForAnyRedecl(M))
3182 return RC;
3183 if (auto *RC = Ctx.getRawCommentForAnyRedecl(PDecl))
3184 return RC;
3185 }
3186 return nullptr;
3187}
3188
3189const RawComment *clang::getParameterComment(
3190 const ASTContext &Ctx,
3191 const CodeCompleteConsumer::OverloadCandidate &Result,
3192 unsigned ArgIndex) {
3193 auto FDecl = Result.getFunction();
3194 if (!FDecl)
3195 return nullptr;
3196 if (ArgIndex < FDecl->getNumParams())
3197 return Ctx.getRawCommentForAnyRedecl(FDecl->getParamDecl(ArgIndex));
3198 return nullptr;
3199}
3200
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003201/// Add function overload parameter chunks to the given code completion
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003202/// string.
3203static void AddOverloadParameterChunks(ASTContext &Context,
3204 const PrintingPolicy &Policy,
3205 const FunctionDecl *Function,
3206 const FunctionProtoType *Prototype,
3207 CodeCompletionBuilder &Result,
3208 unsigned CurrentArg,
3209 unsigned Start = 0,
3210 bool InOptional = false) {
3211 bool FirstParameter = true;
3212 unsigned NumParams = Function ? Function->getNumParams()
3213 : Prototype->getNumParams();
3214
3215 for (unsigned P = Start; P != NumParams; ++P) {
3216 if (Function && Function->getParamDecl(P)->hasDefaultArg() && !InOptional) {
3217 // When we see an optional default argument, put that argument and
3218 // the remaining default arguments into a new, optional string.
3219 CodeCompletionBuilder Opt(Result.getAllocator(),
3220 Result.getCodeCompletionTUInfo());
3221 if (!FirstParameter)
3222 Opt.AddChunk(CodeCompletionString::CK_Comma);
3223 // Optional sections are nested.
3224 AddOverloadParameterChunks(Context, Policy, Function, Prototype, Opt,
3225 CurrentArg, P, /*InOptional=*/true);
3226 Result.AddOptionalChunk(Opt.TakeString());
3227 return;
3228 }
3229
3230 if (FirstParameter)
3231 FirstParameter = false;
3232 else
3233 Result.AddChunk(CodeCompletionString::CK_Comma);
3234
3235 InOptional = false;
3236
3237 // Format the placeholder string.
3238 std::string Placeholder;
Erik Verbruggen11338c52017-07-19 10:45:40 +00003239 if (Function) {
3240 const ParmVarDecl *Param = Function->getParamDecl(P);
3241 Placeholder = FormatFunctionParameter(Policy, Param);
3242 if (Param->hasDefaultArg())
3243 Placeholder += GetDefaultValueString(Param, Context.getSourceManager(), Context.getLangOpts());
3244 } else {
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003245 Placeholder = Prototype->getParamType(P).getAsString(Policy);
Erik Verbruggen11338c52017-07-19 10:45:40 +00003246 }
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003247
3248 if (P == CurrentArg)
3249 Result.AddCurrentParameterChunk(
3250 Result.getAllocator().CopyString(Placeholder));
3251 else
3252 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Placeholder));
3253 }
3254
3255 if (Prototype && Prototype->isVariadic()) {
3256 CodeCompletionBuilder Opt(Result.getAllocator(),
3257 Result.getCodeCompletionTUInfo());
3258 if (!FirstParameter)
3259 Opt.AddChunk(CodeCompletionString::CK_Comma);
3260
3261 if (CurrentArg < NumParams)
3262 Opt.AddPlaceholderChunk("...");
3263 else
3264 Opt.AddCurrentParameterChunk("...");
3265
3266 Result.AddOptionalChunk(Opt.TakeString());
3267 }
3268}
3269
Douglas Gregorf0f51982009-09-23 00:34:09 +00003270CodeCompletionString *
3271CodeCompleteConsumer::OverloadCandidate::CreateSignatureString(
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003272 unsigned CurrentArg, Sema &S,
3273 CodeCompletionAllocator &Allocator,
3274 CodeCompletionTUInfo &CCTUInfo,
3275 bool IncludeBriefComments) const {
Douglas Gregor75acd922011-09-27 23:30:47 +00003276 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
John McCall31168b02011-06-15 23:02:42 +00003277
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003278 // FIXME: Set priority, availability appropriately.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003279 CodeCompletionBuilder Result(Allocator,CCTUInfo, 1, CXAvailability_Available);
Douglas Gregorf0f51982009-09-23 00:34:09 +00003280 FunctionDecl *FDecl = getFunction();
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003281 const FunctionProtoType *Proto
Douglas Gregorf0f51982009-09-23 00:34:09 +00003282 = dyn_cast<FunctionProtoType>(getFunctionType());
3283 if (!FDecl && !Proto) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003284 // Function without a prototype. Just give the return type and a
Douglas Gregorf0f51982009-09-23 00:34:09 +00003285 // highlighted ellipsis.
3286 const FunctionType *FT = getFunctionType();
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003287 Result.AddResultTypeChunk(Result.getAllocator().CopyString(
3288 FT->getReturnType().getAsString(Policy)));
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003289 Result.AddChunk(CodeCompletionString::CK_LeftParen);
3290 Result.AddChunk(CodeCompletionString::CK_CurrentParameter, "...");
3291 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003292 return Result.TakeString();
Douglas Gregorf0f51982009-09-23 00:34:09 +00003293 }
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003294
3295 if (FDecl) {
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003296 if (IncludeBriefComments) {
3297 if (auto RC = getParameterComment(S.getASTContext(), *this, CurrentArg))
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003298 Result.addBriefComment(RC->getBriefText(S.getASTContext()));
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003299 }
Douglas Gregorc3425b12015-07-07 06:20:19 +00003300 AddResultTypeChunk(S.Context, Policy, FDecl, QualType(), Result);
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003301 Result.AddTextChunk(
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003302 Result.getAllocator().CopyString(FDecl->getNameAsString()));
3303 } else {
3304 Result.AddResultTypeChunk(
3305 Result.getAllocator().CopyString(
Alp Toker314cc812014-01-25 16:55:45 +00003306 Proto->getReturnType().getAsString(Policy)));
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003307 }
Alp Toker314cc812014-01-25 16:55:45 +00003308
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003309 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003310 AddOverloadParameterChunks(S.getASTContext(), Policy, FDecl, Proto, Result,
3311 CurrentArg);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003312 Result.AddChunk(CodeCompletionString::CK_RightParen);
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003313
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003314 return Result.TakeString();
Douglas Gregorf0f51982009-09-23 00:34:09 +00003315}
3316
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003317unsigned clang::getMacroUsagePriority(StringRef MacroName,
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00003318 const LangOptions &LangOpts,
Douglas Gregor6e240332010-08-16 16:18:59 +00003319 bool PreferredTypeIsPointer) {
3320 unsigned Priority = CCP_Macro;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003321
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00003322 // Treat the "nil", "Nil" and "NULL" macros as null pointer constants.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003323 if (MacroName.equals("nil") || MacroName.equals("NULL") ||
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00003324 MacroName.equals("Nil")) {
Douglas Gregor6e240332010-08-16 16:18:59 +00003325 Priority = CCP_Constant;
3326 if (PreferredTypeIsPointer)
3327 Priority = Priority / CCF_SimilarTypeMatch;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003328 }
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00003329 // Treat "YES", "NO", "true", and "false" as constants.
3330 else if (MacroName.equals("YES") || MacroName.equals("NO") ||
3331 MacroName.equals("true") || MacroName.equals("false"))
3332 Priority = CCP_Constant;
3333 // Treat "bool" as a type.
3334 else if (MacroName.equals("bool"))
3335 Priority = CCP_Type + (LangOpts.ObjC1? CCD_bool_in_ObjC : 0);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003336
3337
Douglas Gregor6e240332010-08-16 16:18:59 +00003338 return Priority;
3339}
3340
Dmitri Gribenkobdc80de2013-01-11 20:32:41 +00003341CXCursorKind clang::getCursorKindForDecl(const Decl *D) {
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003342 if (!D)
3343 return CXCursor_UnexposedDecl;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003344
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003345 switch (D->getKind()) {
3346 case Decl::Enum: return CXCursor_EnumDecl;
3347 case Decl::EnumConstant: return CXCursor_EnumConstantDecl;
3348 case Decl::Field: return CXCursor_FieldDecl;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003349 case Decl::Function:
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003350 return CXCursor_FunctionDecl;
3351 case Decl::ObjCCategory: return CXCursor_ObjCCategoryDecl;
3352 case Decl::ObjCCategoryImpl: return CXCursor_ObjCCategoryImplDecl;
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003353 case Decl::ObjCImplementation: return CXCursor_ObjCImplementationDecl;
Douglas Gregordeafd0b2011-12-27 22:43:10 +00003354
Argyrios Kyrtzidis3698cef2012-01-24 21:39:26 +00003355 case Decl::ObjCInterface: return CXCursor_ObjCInterfaceDecl;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003356 case Decl::ObjCIvar: return CXCursor_ObjCIvarDecl;
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003357 case Decl::ObjCMethod:
3358 return cast<ObjCMethodDecl>(D)->isInstanceMethod()
3359 ? CXCursor_ObjCInstanceMethodDecl : CXCursor_ObjCClassMethodDecl;
3360 case Decl::CXXMethod: return CXCursor_CXXMethod;
3361 case Decl::CXXConstructor: return CXCursor_Constructor;
3362 case Decl::CXXDestructor: return CXCursor_Destructor;
3363 case Decl::CXXConversion: return CXCursor_ConversionFunction;
3364 case Decl::ObjCProperty: return CXCursor_ObjCPropertyDecl;
Argyrios Kyrtzidis3698cef2012-01-24 21:39:26 +00003365 case Decl::ObjCProtocol: return CXCursor_ObjCProtocolDecl;
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003366 case Decl::ParmVar: return CXCursor_ParmDecl;
3367 case Decl::Typedef: return CXCursor_TypedefDecl;
Richard Smithdda56e42011-04-15 14:24:37 +00003368 case Decl::TypeAlias: return CXCursor_TypeAliasDecl;
Sergey Kalinichev8f3b1872015-11-15 13:48:32 +00003369 case Decl::TypeAliasTemplate: return CXCursor_TypeAliasTemplateDecl;
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003370 case Decl::Var: return CXCursor_VarDecl;
3371 case Decl::Namespace: return CXCursor_Namespace;
3372 case Decl::NamespaceAlias: return CXCursor_NamespaceAlias;
3373 case Decl::TemplateTypeParm: return CXCursor_TemplateTypeParameter;
3374 case Decl::NonTypeTemplateParm:return CXCursor_NonTypeTemplateParameter;
3375 case Decl::TemplateTemplateParm:return CXCursor_TemplateTemplateParameter;
3376 case Decl::FunctionTemplate: return CXCursor_FunctionTemplate;
3377 case Decl::ClassTemplate: return CXCursor_ClassTemplate;
Argyrios Kyrtzidis12afd702011-09-30 17:58:23 +00003378 case Decl::AccessSpec: return CXCursor_CXXAccessSpecifier;
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003379 case Decl::ClassTemplatePartialSpecialization:
3380 return CXCursor_ClassTemplatePartialSpecialization;
3381 case Decl::UsingDirective: return CXCursor_UsingDirective;
Olivier Goffart81978012016-06-09 16:15:55 +00003382 case Decl::StaticAssert: return CXCursor_StaticAssert;
Olivier Goffartd211c642016-11-04 06:29:27 +00003383 case Decl::Friend: return CXCursor_FriendDecl;
Douglas Gregor3e653b32012-04-30 23:41:16 +00003384 case Decl::TranslationUnit: return CXCursor_TranslationUnit;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003385
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003386 case Decl::Using:
3387 case Decl::UnresolvedUsingValue:
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003388 case Decl::UnresolvedUsingTypename:
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003389 return CXCursor_UsingDeclaration;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003390
Douglas Gregor4cd65962011-06-03 23:08:58 +00003391 case Decl::ObjCPropertyImpl:
3392 switch (cast<ObjCPropertyImplDecl>(D)->getPropertyImplementation()) {
3393 case ObjCPropertyImplDecl::Dynamic:
3394 return CXCursor_ObjCDynamicDecl;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003395
Douglas Gregor4cd65962011-06-03 23:08:58 +00003396 case ObjCPropertyImplDecl::Synthesize:
3397 return CXCursor_ObjCSynthesizeDecl;
3398 }
Argyrios Kyrtzidis50e5b1d2012-10-05 00:22:24 +00003399
3400 case Decl::Import:
3401 return CXCursor_ModuleImportDecl;
Douglas Gregor85f3f952015-07-07 03:57:15 +00003402
3403 case Decl::ObjCTypeParam: return CXCursor_TemplateTypeParameter;
3404
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003405 default:
Dmitri Gribenkobdc80de2013-01-11 20:32:41 +00003406 if (const TagDecl *TD = dyn_cast<TagDecl>(D)) {
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003407 switch (TD->getTagKind()) {
Joao Matosdc86f942012-08-31 18:45:21 +00003408 case TTK_Interface: // fall through
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003409 case TTK_Struct: return CXCursor_StructDecl;
3410 case TTK_Class: return CXCursor_ClassDecl;
3411 case TTK_Union: return CXCursor_UnionDecl;
3412 case TTK_Enum: return CXCursor_EnumDecl;
3413 }
3414 }
3415 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003416
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003417 return CXCursor_UnexposedDecl;
3418}
3419
Douglas Gregor55b037b2010-07-08 20:55:51 +00003420static void AddMacroResults(Preprocessor &PP, ResultBuilder &Results,
Eric Liu88de9f62018-09-19 09:34:55 +00003421 bool LoadExternal, bool IncludeUndefined,
Douglas Gregor55b037b2010-07-08 20:55:51 +00003422 bool TargetTypeIsPointer = false) {
John McCall276321a2010-08-25 06:19:51 +00003423 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003424
Douglas Gregorf329c7c2009-10-30 16:50:04 +00003425 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003426
Eric Liu88de9f62018-09-19 09:34:55 +00003427 for (Preprocessor::macro_iterator M = PP.macro_begin(LoadExternal),
3428 MEnd = PP.macro_end(LoadExternal);
Douglas Gregor55b037b2010-07-08 20:55:51 +00003429 M != MEnd; ++M) {
Richard Smith20e883e2015-04-29 23:20:19 +00003430 auto MD = PP.getMacroDefinition(M->first);
3431 if (IncludeUndefined || MD) {
Eric Liud485df12018-09-05 14:59:17 +00003432 MacroInfo *MI = MD.getMacroInfo();
3433 if (MI && MI->isUsedForHeaderGuard())
3434 continue;
Argyrios Kyrtzidis9ef53ce2014-04-09 18:21:23 +00003435
Eric Liud485df12018-09-05 14:59:17 +00003436 Results.AddResult(
3437 Result(M->first, MI,
3438 getMacroUsagePriority(M->first->getName(), PP.getLangOpts(),
3439 TargetTypeIsPointer)));
Argyrios Kyrtzidis9ef53ce2014-04-09 18:21:23 +00003440 }
Douglas Gregor55b037b2010-07-08 20:55:51 +00003441 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003442
Douglas Gregorf329c7c2009-10-30 16:50:04 +00003443 Results.ExitScope();
3444}
3445
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003446static void AddPrettyFunctionResults(const LangOptions &LangOpts,
Douglas Gregorce0e8562010-08-23 21:54:33 +00003447 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00003448 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003449
Douglas Gregorce0e8562010-08-23 21:54:33 +00003450 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003451
Douglas Gregorce0e8562010-08-23 21:54:33 +00003452 Results.AddResult(Result("__PRETTY_FUNCTION__", CCP_Constant));
3453 Results.AddResult(Result("__FUNCTION__", CCP_Constant));
Richard Smith2bf7fdb2013-01-02 11:42:31 +00003454 if (LangOpts.C99 || LangOpts.CPlusPlus11)
Douglas Gregorce0e8562010-08-23 21:54:33 +00003455 Results.AddResult(Result("__func__", CCP_Constant));
3456 Results.ExitScope();
3457}
3458
Daniel Dunbar242ea9a2009-11-13 08:58:20 +00003459static void HandleCodeCompleteResults(Sema *S,
3460 CodeCompleteConsumer *CodeCompleter,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003461 CodeCompletionContext Context,
John McCall276321a2010-08-25 06:19:51 +00003462 CodeCompletionResult *Results,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003463 unsigned NumResults) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00003464 if (CodeCompleter)
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003465 CodeCompleter->ProcessCodeCompleteResults(*S, Context, Results, NumResults);
Douglas Gregor3545ff42009-09-21 16:56:56 +00003466}
3467
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003468static enum CodeCompletionContext::Kind mapCodeCompletionContext(Sema &S,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003469 Sema::ParserCompletionContext PCC) {
3470 switch (PCC) {
John McCallfaf5fb42010-08-26 23:41:50 +00003471 case Sema::PCC_Namespace:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003472 return CodeCompletionContext::CCC_TopLevel;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003473
John McCallfaf5fb42010-08-26 23:41:50 +00003474 case Sema::PCC_Class:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003475 return CodeCompletionContext::CCC_ClassStructUnion;
3476
John McCallfaf5fb42010-08-26 23:41:50 +00003477 case Sema::PCC_ObjCInterface:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003478 return CodeCompletionContext::CCC_ObjCInterface;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003479
John McCallfaf5fb42010-08-26 23:41:50 +00003480 case Sema::PCC_ObjCImplementation:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003481 return CodeCompletionContext::CCC_ObjCImplementation;
3482
John McCallfaf5fb42010-08-26 23:41:50 +00003483 case Sema::PCC_ObjCInstanceVariableList:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003484 return CodeCompletionContext::CCC_ObjCIvarList;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003485
John McCallfaf5fb42010-08-26 23:41:50 +00003486 case Sema::PCC_Template:
3487 case Sema::PCC_MemberTemplate:
Douglas Gregor0ac41382010-09-23 23:01:17 +00003488 if (S.CurContext->isFileContext())
3489 return CodeCompletionContext::CCC_TopLevel;
David Blaikie8a40f702012-01-17 06:56:22 +00003490 if (S.CurContext->isRecord())
Douglas Gregor0ac41382010-09-23 23:01:17 +00003491 return CodeCompletionContext::CCC_ClassStructUnion;
David Blaikie8a40f702012-01-17 06:56:22 +00003492 return CodeCompletionContext::CCC_Other;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003493
John McCallfaf5fb42010-08-26 23:41:50 +00003494 case Sema::PCC_RecoveryInFunction:
Douglas Gregor0ac41382010-09-23 23:01:17 +00003495 return CodeCompletionContext::CCC_Recovery;
Douglas Gregorc769d6e2010-10-18 22:01:46 +00003496
John McCallfaf5fb42010-08-26 23:41:50 +00003497 case Sema::PCC_ForInit:
David Blaikiebbafb8a2012-03-11 07:00:24 +00003498 if (S.getLangOpts().CPlusPlus || S.getLangOpts().C99 ||
3499 S.getLangOpts().ObjC1)
Douglas Gregorc769d6e2010-10-18 22:01:46 +00003500 return CodeCompletionContext::CCC_ParenthesizedExpression;
3501 else
3502 return CodeCompletionContext::CCC_Expression;
3503
3504 case Sema::PCC_Expression:
John McCallfaf5fb42010-08-26 23:41:50 +00003505 case Sema::PCC_Condition:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003506 return CodeCompletionContext::CCC_Expression;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003507
John McCallfaf5fb42010-08-26 23:41:50 +00003508 case Sema::PCC_Statement:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003509 return CodeCompletionContext::CCC_Statement;
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003510
John McCallfaf5fb42010-08-26 23:41:50 +00003511 case Sema::PCC_Type:
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003512 return CodeCompletionContext::CCC_Type;
Douglas Gregor5e35d592010-09-14 23:59:36 +00003513
3514 case Sema::PCC_ParenthesizedExpression:
3515 return CodeCompletionContext::CCC_ParenthesizedExpression;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003516
Douglas Gregor80039242011-02-15 20:33:25 +00003517 case Sema::PCC_LocalDeclarationSpecifiers:
3518 return CodeCompletionContext::CCC_Type;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003519 }
David Blaikie8a40f702012-01-17 06:56:22 +00003520
3521 llvm_unreachable("Invalid ParserCompletionContext!");
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003522}
3523
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003524/// If we're in a C++ virtual member function, add completion results
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003525/// that invoke the functions we override, since it's common to invoke the
Douglas Gregorac322ec2010-08-27 21:18:54 +00003526/// overridden function as well as adding new functionality.
3527///
3528/// \param S The semantic analysis object for which we are generating results.
3529///
3530/// \param InContext This context in which the nested-name-specifier preceding
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003531/// the code-completion point
Douglas Gregorac322ec2010-08-27 21:18:54 +00003532static void MaybeAddOverrideCalls(Sema &S, DeclContext *InContext,
3533 ResultBuilder &Results) {
3534 // Look through blocks.
3535 DeclContext *CurContext = S.CurContext;
3536 while (isa<BlockDecl>(CurContext))
3537 CurContext = CurContext->getParent();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003538
3539
Douglas Gregorac322ec2010-08-27 21:18:54 +00003540 CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(CurContext);
3541 if (!Method || !Method->isVirtual())
3542 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003543
3544 // We need to have names for all of the parameters, if we're going to
Douglas Gregorac322ec2010-08-27 21:18:54 +00003545 // generate a forwarding call.
David Majnemer59f77922016-06-24 04:05:48 +00003546 for (auto P : Method->parameters())
Aaron Ballman43b68be2014-03-07 17:50:17 +00003547 if (!P->getDeclName())
Douglas Gregorac322ec2010-08-27 21:18:54 +00003548 return;
Douglas Gregorac322ec2010-08-27 21:18:54 +00003549
Douglas Gregor75acd922011-09-27 23:30:47 +00003550 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
Benjamin Krameracfa3392017-12-17 23:52:45 +00003551 for (const CXXMethodDecl *Overridden : Method->overridden_methods()) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003552 CodeCompletionBuilder Builder(Results.getAllocator(),
3553 Results.getCodeCompletionTUInfo());
Douglas Gregorac322ec2010-08-27 21:18:54 +00003554 if (Overridden->getCanonicalDecl() == Method->getCanonicalDecl())
3555 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003556
Douglas Gregorac322ec2010-08-27 21:18:54 +00003557 // If we need a nested-name-specifier, add one now.
3558 if (!InContext) {
3559 NestedNameSpecifier *NNS
3560 = getRequiredQualification(S.Context, CurContext,
3561 Overridden->getDeclContext());
3562 if (NNS) {
3563 std::string Str;
3564 llvm::raw_string_ostream OS(Str);
Douglas Gregor75acd922011-09-27 23:30:47 +00003565 NNS->print(OS, Policy);
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003566 Builder.AddTextChunk(Results.getAllocator().CopyString(OS.str()));
Douglas Gregorac322ec2010-08-27 21:18:54 +00003567 }
3568 } else if (!InContext->Equals(Overridden->getDeclContext()))
3569 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003570
3571 Builder.AddTypedTextChunk(Results.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003572 Overridden->getNameAsString()));
3573 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregorac322ec2010-08-27 21:18:54 +00003574 bool FirstParam = true;
David Majnemer59f77922016-06-24 04:05:48 +00003575 for (auto P : Method->parameters()) {
Douglas Gregorac322ec2010-08-27 21:18:54 +00003576 if (FirstParam)
3577 FirstParam = false;
3578 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003579 Builder.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregorac322ec2010-08-27 21:18:54 +00003580
Aaron Ballman43b68be2014-03-07 17:50:17 +00003581 Builder.AddPlaceholderChunk(
3582 Results.getAllocator().CopyString(P->getIdentifier()->getName()));
Douglas Gregorac322ec2010-08-27 21:18:54 +00003583 }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003584 Builder.AddChunk(CodeCompletionString::CK_RightParen);
3585 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregorac322ec2010-08-27 21:18:54 +00003586 CCP_SuperCompletion,
Douglas Gregor78254c82012-03-27 23:34:16 +00003587 CXCursor_CXXMethod,
3588 CXAvailability_Available,
3589 Overridden));
Douglas Gregorac322ec2010-08-27 21:18:54 +00003590 Results.Ignore(Overridden);
3591 }
3592}
3593
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003594void Sema::CodeCompleteModuleImport(SourceLocation ImportLoc,
Douglas Gregor07f43572012-01-29 18:15:03 +00003595 ModuleIdPath Path) {
3596 typedef CodeCompletionResult Result;
3597 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003598 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor07f43572012-01-29 18:15:03 +00003599 CodeCompletionContext::CCC_Other);
3600 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003601
Douglas Gregor07f43572012-01-29 18:15:03 +00003602 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003603 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Douglas Gregor07f43572012-01-29 18:15:03 +00003604 typedef CodeCompletionResult Result;
3605 if (Path.empty()) {
3606 // Enumerate all top-level modules.
Dmitri Gribenkof8579502013-01-12 19:30:44 +00003607 SmallVector<Module *, 8> Modules;
Douglas Gregor07f43572012-01-29 18:15:03 +00003608 PP.getHeaderSearchInfo().collectAllModules(Modules);
3609 for (unsigned I = 0, N = Modules.size(); I != N; ++I) {
3610 Builder.AddTypedTextChunk(
3611 Builder.getAllocator().CopyString(Modules[I]->Name));
3612 Results.AddResult(Result(Builder.TakeString(),
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003613 CCP_Declaration,
Argyrios Kyrtzidis345d05f2013-05-29 18:50:15 +00003614 CXCursor_ModuleImportDecl,
Douglas Gregor07f43572012-01-29 18:15:03 +00003615 Modules[I]->isAvailable()
3616 ? CXAvailability_Available
3617 : CXAvailability_NotAvailable));
3618 }
Daniel Jasper07e6c402013-08-05 20:26:17 +00003619 } else if (getLangOpts().Modules) {
Douglas Gregor07f43572012-01-29 18:15:03 +00003620 // Load the named module.
3621 Module *Mod = PP.getModuleLoader().loadModule(ImportLoc, Path,
3622 Module::AllVisible,
3623 /*IsInclusionDirective=*/false);
3624 // Enumerate submodules.
3625 if (Mod) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003626 for (Module::submodule_iterator Sub = Mod->submodule_begin(),
Douglas Gregor07f43572012-01-29 18:15:03 +00003627 SubEnd = Mod->submodule_end();
3628 Sub != SubEnd; ++Sub) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003629
Douglas Gregor07f43572012-01-29 18:15:03 +00003630 Builder.AddTypedTextChunk(
3631 Builder.getAllocator().CopyString((*Sub)->Name));
3632 Results.AddResult(Result(Builder.TakeString(),
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003633 CCP_Declaration,
Argyrios Kyrtzidis345d05f2013-05-29 18:50:15 +00003634 CXCursor_ModuleImportDecl,
Douglas Gregor07f43572012-01-29 18:15:03 +00003635 (*Sub)->isAvailable()
3636 ? CXAvailability_Available
3637 : CXAvailability_NotAvailable));
3638 }
3639 }
3640 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003641 Results.ExitScope();
Douglas Gregor07f43572012-01-29 18:15:03 +00003642 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
3643 Results.data(),Results.size());
3644}
3645
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003646void Sema::CodeCompleteOrdinaryName(Scope *S,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003647 ParserCompletionContext CompletionContext) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003648 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003649 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00003650 mapCodeCompletionContext(*this, CompletionContext));
Douglas Gregorac322ec2010-08-27 21:18:54 +00003651 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003652
Douglas Gregor504a6ae2010-01-10 23:08:15 +00003653 // Determine how to filter results, e.g., so that the names of
3654 // values (functions, enumerators, function templates, etc.) are
3655 // only allowed where we can have an expression.
3656 switch (CompletionContext) {
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003657 case PCC_Namespace:
3658 case PCC_Class:
3659 case PCC_ObjCInterface:
3660 case PCC_ObjCImplementation:
3661 case PCC_ObjCInstanceVariableList:
3662 case PCC_Template:
3663 case PCC_MemberTemplate:
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003664 case PCC_Type:
Douglas Gregor80039242011-02-15 20:33:25 +00003665 case PCC_LocalDeclarationSpecifiers:
Douglas Gregor504a6ae2010-01-10 23:08:15 +00003666 Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
3667 break;
3668
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003669 case PCC_Statement:
Douglas Gregor5e35d592010-09-14 23:59:36 +00003670 case PCC_ParenthesizedExpression:
Douglas Gregor4d755e82010-08-24 23:58:17 +00003671 case PCC_Expression:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003672 case PCC_ForInit:
3673 case PCC_Condition:
David Blaikiebbafb8a2012-03-11 07:00:24 +00003674 if (WantTypesInContext(CompletionContext, getLangOpts()))
Douglas Gregor70febae2010-05-28 00:49:12 +00003675 Results.setFilter(&ResultBuilder::IsOrdinaryName);
3676 else
3677 Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003678
David Blaikiebbafb8a2012-03-11 07:00:24 +00003679 if (getLangOpts().CPlusPlus)
Craig Topperc3ec1492014-05-26 06:22:03 +00003680 MaybeAddOverrideCalls(*this, /*InContext=*/nullptr, Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00003681 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003682
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003683 case PCC_RecoveryInFunction:
Douglas Gregor6da3db42010-05-25 05:58:43 +00003684 // Unfiltered
3685 break;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00003686 }
3687
Douglas Gregor9be0ed42010-08-26 16:36:48 +00003688 // If we are in a C++ non-static member function, check the qualifiers on
3689 // the member function to filter/prioritize the results list.
3690 if (CXXMethodDecl *CurMethod = dyn_cast<CXXMethodDecl>(CurContext))
3691 if (CurMethod->isInstance())
3692 Results.setObjectTypeQualifiers(
3693 Qualifiers::fromCVRMask(CurMethod->getTypeQualifiers()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003694
Douglas Gregorc580c522010-01-14 01:09:38 +00003695 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00003696 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00003697 CodeCompleter->includeGlobals(),
3698 CodeCompleter->loadExternal());
Douglas Gregor92253692009-12-07 09:54:55 +00003699
Douglas Gregorf98e6a22010-01-13 23:51:12 +00003700 AddOrdinaryNameResults(CompletionContext, S, *this, Results);
Douglas Gregor92253692009-12-07 09:54:55 +00003701 Results.ExitScope();
3702
Douglas Gregorce0e8562010-08-23 21:54:33 +00003703 switch (CompletionContext) {
Douglas Gregor5e35d592010-09-14 23:59:36 +00003704 case PCC_ParenthesizedExpression:
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003705 case PCC_Expression:
3706 case PCC_Statement:
3707 case PCC_RecoveryInFunction:
3708 if (S->getFnParent())
Craig Topper12126262015-11-15 17:27:57 +00003709 AddPrettyFunctionResults(getLangOpts(), Results);
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003710 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003711
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003712 case PCC_Namespace:
3713 case PCC_Class:
3714 case PCC_ObjCInterface:
3715 case PCC_ObjCImplementation:
3716 case PCC_ObjCInstanceVariableList:
3717 case PCC_Template:
3718 case PCC_MemberTemplate:
3719 case PCC_ForInit:
3720 case PCC_Condition:
3721 case PCC_Type:
Douglas Gregor80039242011-02-15 20:33:25 +00003722 case PCC_LocalDeclarationSpecifiers:
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003723 break;
Douglas Gregorce0e8562010-08-23 21:54:33 +00003724 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003725
Douglas Gregor9eb77012009-11-07 00:00:49 +00003726 if (CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00003727 AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003728
Douglas Gregor50832e02010-09-20 22:39:41 +00003729 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003730 Results.data(),Results.size());
Douglas Gregor9d64c5e2009-09-21 20:51:25 +00003731}
3732
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003733static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003734 ParsedType Receiver,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00003735 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00003736 bool AtArgumentExpression,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003737 bool IsSuper,
3738 ResultBuilder &Results);
3739
3740void Sema::CodeCompleteDeclSpec(Scope *S, DeclSpec &DS,
3741 bool AllowNonIdentifiers,
3742 bool AllowNestedNameSpecifiers) {
John McCall276321a2010-08-25 06:19:51 +00003743 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003744 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003745 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00003746 AllowNestedNameSpecifiers
3747 ? CodeCompletionContext::CCC_PotentiallyQualifiedName
3748 : CodeCompletionContext::CCC_Name);
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003749 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003750
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003751 // Type qualifiers can come after names.
3752 Results.AddResult(Result("const"));
3753 Results.AddResult(Result("volatile"));
David Blaikiebbafb8a2012-03-11 07:00:24 +00003754 if (getLangOpts().C99)
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003755 Results.AddResult(Result("restrict"));
3756
David Blaikiebbafb8a2012-03-11 07:00:24 +00003757 if (getLangOpts().CPlusPlus) {
Alex Lorenz8f4d3992017-02-13 23:19:40 +00003758 if (getLangOpts().CPlusPlus11 &&
3759 (DS.getTypeSpecType() == DeclSpec::TST_class ||
3760 DS.getTypeSpecType() == DeclSpec::TST_struct))
3761 Results.AddResult("final");
3762
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003763 if (AllowNonIdentifiers) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003764 Results.AddResult(Result("operator"));
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003765 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003766
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003767 // Add nested-name-specifiers.
3768 if (AllowNestedNameSpecifiers) {
3769 Results.allowNestedNameSpecifiers();
Douglas Gregor0ac41382010-09-23 23:01:17 +00003770 Results.setFilter(&ResultBuilder::IsImpossibleToSatisfy);
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003771 CodeCompletionDeclConsumer Consumer(Results, CurContext);
3772 LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00003773 CodeCompleter->includeGlobals(),
3774 CodeCompleter->loadExternal());
Craig Topperc3ec1492014-05-26 06:22:03 +00003775 Results.setFilter(nullptr);
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003776 }
3777 }
3778 Results.ExitScope();
3779
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003780 // If we're in a context where we might have an expression (rather than a
3781 // declaration), and what we've seen so far is an Objective-C type that could
3782 // be a receiver of a class message, this may be a class message send with
3783 // the initial opening bracket '[' missing. Add appropriate completions.
3784 if (AllowNonIdentifiers && !AllowNestedNameSpecifiers &&
Richard Smithb4a9e862013-04-12 22:46:28 +00003785 DS.getParsedSpecifiers() == DeclSpec::PQ_TypeSpecifier &&
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003786 DS.getTypeSpecType() == DeclSpec::TST_typename &&
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003787 DS.getTypeSpecComplex() == DeclSpec::TSC_unspecified &&
3788 DS.getTypeSpecSign() == DeclSpec::TSS_unspecified &&
Richard Smithb4a9e862013-04-12 22:46:28 +00003789 !DS.isTypeAltiVecVector() &&
3790 S &&
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003791 (S->getFlags() & Scope::DeclScope) != 0 &&
3792 (S->getFlags() & (Scope::ClassScope | Scope::TemplateParamScope |
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003793 Scope::FunctionPrototypeScope |
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003794 Scope::AtCatchScope)) == 0) {
3795 ParsedType T = DS.getRepAsType();
3796 if (!T.get().isNull() && T.get()->isObjCObjectOrInterfaceType())
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00003797 AddClassMessageCompletions(*this, S, T, None, false, false, Results);
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003798 }
3799
Douglas Gregor56ccce02010-08-24 04:59:56 +00003800 // Note that we intentionally suppress macro results here, since we do not
3801 // encourage using macros to produce the names of entities.
3802
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003803 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0ac41382010-09-23 23:01:17 +00003804 Results.getCompletionContext(),
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003805 Results.data(), Results.size());
3806}
3807
Douglas Gregor68762e72010-08-23 21:17:50 +00003808struct Sema::CodeCompleteExpressionData {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003809 CodeCompleteExpressionData(QualType PreferredType = QualType())
Douglas Gregor68762e72010-08-23 21:17:50 +00003810 : PreferredType(PreferredType), IntegralConstantExpression(false),
3811 ObjCCollection(false) { }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003812
Douglas Gregor68762e72010-08-23 21:17:50 +00003813 QualType PreferredType;
3814 bool IntegralConstantExpression;
3815 bool ObjCCollection;
Chris Lattner0e62c1c2011-07-23 10:55:15 +00003816 SmallVector<Decl *, 4> IgnoreDecls;
Douglas Gregor68762e72010-08-23 21:17:50 +00003817};
3818
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003819/// Perform code-completion in an expression context when we know what
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003820/// type we're looking for.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003821void Sema::CodeCompleteExpression(Scope *S,
Douglas Gregor68762e72010-08-23 21:17:50 +00003822 const CodeCompleteExpressionData &Data) {
Eric Liuf5ba09f2018-07-04 10:01:18 +00003823 ResultBuilder Results(
3824 *this, CodeCompleter->getAllocator(),
3825 CodeCompleter->getCodeCompletionTUInfo(),
3826 CodeCompletionContext(CodeCompletionContext::CCC_Expression,
3827 Data.PreferredType));
Douglas Gregor68762e72010-08-23 21:17:50 +00003828 if (Data.ObjCCollection)
3829 Results.setFilter(&ResultBuilder::IsObjCCollection);
3830 else if (Data.IntegralConstantExpression)
Douglas Gregor85b50632010-07-28 21:50:18 +00003831 Results.setFilter(&ResultBuilder::IsIntegralConstantValue);
David Blaikiebbafb8a2012-03-11 07:00:24 +00003832 else if (WantTypesInContext(PCC_Expression, getLangOpts()))
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003833 Results.setFilter(&ResultBuilder::IsOrdinaryName);
3834 else
3835 Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
Douglas Gregor68762e72010-08-23 21:17:50 +00003836
3837 if (!Data.PreferredType.isNull())
3838 Results.setPreferredType(Data.PreferredType.getNonReferenceType());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003839
Douglas Gregor68762e72010-08-23 21:17:50 +00003840 // Ignore any declarations that we were told that we don't care about.
3841 for (unsigned I = 0, N = Data.IgnoreDecls.size(); I != N; ++I)
3842 Results.Ignore(Data.IgnoreDecls[I]);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003843
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003844 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00003845 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00003846 CodeCompleter->includeGlobals(),
3847 CodeCompleter->loadExternal());
3848
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003849 Results.EnterNewScope();
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003850 AddOrdinaryNameResults(PCC_Expression, S, *this, Results);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003851 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003852
Douglas Gregor55b037b2010-07-08 20:55:51 +00003853 bool PreferredTypeIsPointer = false;
Douglas Gregor68762e72010-08-23 21:17:50 +00003854 if (!Data.PreferredType.isNull())
3855 PreferredTypeIsPointer = Data.PreferredType->isAnyPointerType()
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003856 || Data.PreferredType->isMemberPointerType()
Douglas Gregor68762e72010-08-23 21:17:50 +00003857 || Data.PreferredType->isBlockPointerType();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003858
3859 if (S->getFnParent() &&
3860 !Data.ObjCCollection &&
Douglas Gregorce0e8562010-08-23 21:54:33 +00003861 !Data.IntegralConstantExpression)
Craig Topper12126262015-11-15 17:27:57 +00003862 AddPrettyFunctionResults(getLangOpts(), Results);
Douglas Gregorce0e8562010-08-23 21:54:33 +00003863
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003864 if (CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00003865 AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false,
3866 PreferredTypeIsPointer);
Eric Liuf5ba09f2018-07-04 10:01:18 +00003867 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
3868 Results.data(), Results.size());
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003869}
3870
Ilya Biryukov832c4af2018-09-07 14:04:39 +00003871void Sema::CodeCompleteExpression(Scope *S, QualType PreferredType) {
3872 return CodeCompleteExpression(S, CodeCompleteExpressionData(PreferredType));
3873}
3874
Douglas Gregoreda7e542010-09-18 01:28:11 +00003875void Sema::CodeCompletePostfixExpression(Scope *S, ExprResult E) {
3876 if (E.isInvalid())
3877 CodeCompleteOrdinaryName(S, PCC_RecoveryInFunction);
David Blaikiebbafb8a2012-03-11 07:00:24 +00003878 else if (getLangOpts().ObjC1)
Nikola Smiljanic01a75982014-05-29 10:55:11 +00003879 CodeCompleteObjCInstanceMessage(S, E.get(), None, false);
Douglas Gregored0b69d2010-09-15 16:23:04 +00003880}
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003881
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003882/// The set of properties that have already been added, referenced by
Douglas Gregorb888acf2010-12-09 23:01:55 +00003883/// property name.
3884typedef llvm::SmallPtrSet<IdentifierInfo*, 16> AddedPropertiesSet;
3885
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003886/// Retrieve the container definition, if any?
Douglas Gregor9b4f3702012-06-12 13:44:08 +00003887static ObjCContainerDecl *getContainerDef(ObjCContainerDecl *Container) {
3888 if (ObjCInterfaceDecl *Interface = dyn_cast<ObjCInterfaceDecl>(Container)) {
3889 if (Interface->hasDefinition())
3890 return Interface->getDefinition();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003891
Douglas Gregor9b4f3702012-06-12 13:44:08 +00003892 return Interface;
3893 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003894
Douglas Gregor9b4f3702012-06-12 13:44:08 +00003895 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
3896 if (Protocol->hasDefinition())
3897 return Protocol->getDefinition();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003898
Douglas Gregor9b4f3702012-06-12 13:44:08 +00003899 return Protocol;
3900 }
3901 return Container;
3902}
3903
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003904/// Adds a block invocation code completion result for the given block
Alex Lorenzbaef8022016-11-09 13:43:18 +00003905/// declaration \p BD.
3906static void AddObjCBlockCall(ASTContext &Context, const PrintingPolicy &Policy,
3907 CodeCompletionBuilder &Builder,
3908 const NamedDecl *BD,
3909 const FunctionTypeLoc &BlockLoc,
3910 const FunctionProtoTypeLoc &BlockProtoLoc) {
3911 Builder.AddResultTypeChunk(
3912 GetCompletionTypeString(BlockLoc.getReturnLoc().getType(), Context,
3913 Policy, Builder.getAllocator()));
3914
3915 AddTypedNameChunk(Context, Policy, BD, Builder);
3916 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
3917
3918 if (BlockProtoLoc && BlockProtoLoc.getTypePtr()->isVariadic()) {
3919 Builder.AddPlaceholderChunk("...");
3920 } else {
3921 for (unsigned I = 0, N = BlockLoc.getNumParams(); I != N; ++I) {
3922 if (I)
3923 Builder.AddChunk(CodeCompletionString::CK_Comma);
3924
3925 // Format the placeholder string.
3926 std::string PlaceholderStr =
3927 FormatFunctionParameter(Policy, BlockLoc.getParam(I));
3928
3929 if (I == N - 1 && BlockProtoLoc &&
3930 BlockProtoLoc.getTypePtr()->isVariadic())
3931 PlaceholderStr += ", ...";
3932
3933 // Add the placeholder string.
3934 Builder.AddPlaceholderChunk(
3935 Builder.getAllocator().CopyString(PlaceholderStr));
3936 }
3937 }
3938
3939 Builder.AddChunk(CodeCompletionString::CK_RightParen);
3940}
3941
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003942static void AddObjCProperties(
3943 const CodeCompletionContext &CCContext, ObjCContainerDecl *Container,
3944 bool AllowCategories, bool AllowNullaryMethods, DeclContext *CurContext,
3945 AddedPropertiesSet &AddedProperties, ResultBuilder &Results,
3946 bool IsBaseExprStatement = false, bool IsClassProperty = false) {
John McCall276321a2010-08-25 06:19:51 +00003947 typedef CodeCompletionResult Result;
Douglas Gregor9291bad2009-11-18 01:29:26 +00003948
Douglas Gregor9b4f3702012-06-12 13:44:08 +00003949 // Retrieve the definition.
3950 Container = getContainerDef(Container);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003951
Douglas Gregor9291bad2009-11-18 01:29:26 +00003952 // Add properties in this container.
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003953 const auto AddProperty = [&](const ObjCPropertyDecl *P) {
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003954 if (!AddedProperties.insert(P->getIdentifier()).second)
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003955 return;
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003956
Alex Lorenzbaef8022016-11-09 13:43:18 +00003957 // FIXME: Provide block invocation completion for non-statement
3958 // expressions.
3959 if (!P->getType().getTypePtr()->isBlockPointerType() ||
3960 !IsBaseExprStatement) {
3961 Results.MaybeAddResult(Result(P, Results.getBasePriority(P), nullptr),
3962 CurContext);
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003963 return;
Alex Lorenzbaef8022016-11-09 13:43:18 +00003964 }
3965
3966 // Block setter and invocation completion is provided only when we are able
3967 // to find the FunctionProtoTypeLoc with parameter names for the block.
3968 FunctionTypeLoc BlockLoc;
3969 FunctionProtoTypeLoc BlockProtoLoc;
3970 findTypeLocationForBlockDecl(P->getTypeSourceInfo(), BlockLoc,
3971 BlockProtoLoc);
3972 if (!BlockLoc) {
3973 Results.MaybeAddResult(Result(P, Results.getBasePriority(P), nullptr),
3974 CurContext);
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003975 return;
Alex Lorenzbaef8022016-11-09 13:43:18 +00003976 }
3977
3978 // The default completion result for block properties should be the block
3979 // invocation completion when the base expression is a statement.
3980 CodeCompletionBuilder Builder(Results.getAllocator(),
3981 Results.getCodeCompletionTUInfo());
3982 AddObjCBlockCall(Container->getASTContext(),
3983 getCompletionPrintingPolicy(Results.getSema()), Builder, P,
3984 BlockLoc, BlockProtoLoc);
3985 Results.MaybeAddResult(
3986 Result(Builder.TakeString(), P, Results.getBasePriority(P)),
3987 CurContext);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003988
3989 // Provide additional block setter completion iff the base expression is a
Alex Lorenzbaef8022016-11-09 13:43:18 +00003990 // statement and the block property is mutable.
3991 if (!P->isReadOnly()) {
3992 CodeCompletionBuilder Builder(Results.getAllocator(),
3993 Results.getCodeCompletionTUInfo());
3994 AddResultTypeChunk(Container->getASTContext(),
3995 getCompletionPrintingPolicy(Results.getSema()), P,
3996 CCContext.getBaseType(), Builder);
3997 Builder.AddTypedTextChunk(
3998 Results.getAllocator().CopyString(P->getName()));
3999 Builder.AddChunk(CodeCompletionString::CK_Equal);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004000
Alex Lorenzbaef8022016-11-09 13:43:18 +00004001 std::string PlaceholderStr = formatBlockPlaceholder(
4002 getCompletionPrintingPolicy(Results.getSema()), P, BlockLoc,
4003 BlockProtoLoc, /*SuppressBlockName=*/true);
4004 // Add the placeholder string.
4005 Builder.AddPlaceholderChunk(
4006 Builder.getAllocator().CopyString(PlaceholderStr));
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004007
Alex Lorenz6e0f3932017-01-06 12:00:44 +00004008 // When completing blocks properties that return void the default
4009 // property completion result should show up before the setter,
4010 // otherwise the setter completion should show up before the default
4011 // property completion, as we normally want to use the result of the
4012 // call.
Alex Lorenzbaef8022016-11-09 13:43:18 +00004013 Results.MaybeAddResult(
4014 Result(Builder.TakeString(), P,
Alex Lorenz6e0f3932017-01-06 12:00:44 +00004015 Results.getBasePriority(P) +
4016 (BlockLoc.getTypePtr()->getReturnType()->isVoidType()
4017 ? CCD_BlockPropertySetter
4018 : -CCD_BlockPropertySetter)),
Alex Lorenzbaef8022016-11-09 13:43:18 +00004019 CurContext);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004020 }
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004021 };
4022
4023 if (IsClassProperty) {
4024 for (const auto *P : Container->class_properties())
4025 AddProperty(P);
4026 } else {
4027 for (const auto *P : Container->instance_properties())
4028 AddProperty(P);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004029 }
Craig Topperc3ec1492014-05-26 06:22:03 +00004030
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004031 // Add nullary methods or implicit class properties
Douglas Gregor95147142011-05-05 15:50:42 +00004032 if (AllowNullaryMethods) {
4033 ASTContext &Context = Container->getASTContext();
Douglas Gregor75acd922011-09-27 23:30:47 +00004034 PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema());
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004035 // Adds a method result
4036 const auto AddMethod = [&](const ObjCMethodDecl *M) {
4037 IdentifierInfo *Name = M->getSelector().getIdentifierInfoForSlot(0);
4038 if (!Name)
4039 return;
4040 if (!AddedProperties.insert(Name).second)
4041 return;
4042 CodeCompletionBuilder Builder(Results.getAllocator(),
4043 Results.getCodeCompletionTUInfo());
4044 AddResultTypeChunk(Context, Policy, M, CCContext.getBaseType(), Builder);
4045 Builder.AddTypedTextChunk(
4046 Results.getAllocator().CopyString(Name->getName()));
4047 Results.MaybeAddResult(
4048 Result(Builder.TakeString(), M,
4049 CCP_MemberDeclaration + CCD_MethodAsProperty),
4050 CurContext);
4051 };
4052
4053 if (IsClassProperty) {
4054 for (const auto *M : Container->methods()) {
4055 // Gather the class method that can be used as implicit property
4056 // getters. Methods with arguments or methods that return void aren't
4057 // added to the results as they can't be used as a getter.
4058 if (!M->getSelector().isUnarySelector() ||
4059 M->getReturnType()->isVoidType() || M->isInstanceMethod())
4060 continue;
4061 AddMethod(M);
4062 }
4063 } else {
4064 for (auto *M : Container->methods()) {
4065 if (M->getSelector().isUnarySelector())
4066 AddMethod(M);
4067 }
Douglas Gregor95147142011-05-05 15:50:42 +00004068 }
4069 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004070
Douglas Gregor9291bad2009-11-18 01:29:26 +00004071 // Add properties in referenced protocols.
4072 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Aaron Ballman0f6e64d2014-03-13 22:58:06 +00004073 for (auto *P : Protocol->protocols())
Douglas Gregorc3425b12015-07-07 06:20:19 +00004074 AddObjCProperties(CCContext, P, AllowCategories, AllowNullaryMethods,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004075 CurContext, AddedProperties, Results,
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004076 IsBaseExprStatement, IsClassProperty);
Douglas Gregor9291bad2009-11-18 01:29:26 +00004077 } else if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)){
Douglas Gregor5d649882009-11-18 22:32:06 +00004078 if (AllowCategories) {
4079 // Look through categories.
Aaron Ballman15063e12014-03-13 21:35:02 +00004080 for (auto *Cat : IFace->known_categories())
Douglas Gregorc3425b12015-07-07 06:20:19 +00004081 AddObjCProperties(CCContext, Cat, AllowCategories, AllowNullaryMethods,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004082 CurContext, AddedProperties, Results,
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004083 IsBaseExprStatement, IsClassProperty);
Douglas Gregor5d649882009-11-18 22:32:06 +00004084 }
Aaron Ballman15063e12014-03-13 21:35:02 +00004085
Douglas Gregor9291bad2009-11-18 01:29:26 +00004086 // Look through protocols.
Aaron Ballmana9f49e32014-03-13 20:55:22 +00004087 for (auto *I : IFace->all_referenced_protocols())
Douglas Gregorc3425b12015-07-07 06:20:19 +00004088 AddObjCProperties(CCContext, I, AllowCategories, AllowNullaryMethods,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004089 CurContext, AddedProperties, Results,
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004090 IsBaseExprStatement, IsClassProperty);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004091
Douglas Gregor9291bad2009-11-18 01:29:26 +00004092 // Look in the superclass.
4093 if (IFace->getSuperClass())
Douglas Gregorc3425b12015-07-07 06:20:19 +00004094 AddObjCProperties(CCContext, IFace->getSuperClass(), AllowCategories,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004095 AllowNullaryMethods, CurContext, AddedProperties,
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004096 Results, IsBaseExprStatement, IsClassProperty);
Douglas Gregor9291bad2009-11-18 01:29:26 +00004097 } else if (const ObjCCategoryDecl *Category
4098 = dyn_cast<ObjCCategoryDecl>(Container)) {
4099 // Look through protocols.
Aaron Ballman19a41762014-03-14 12:55:57 +00004100 for (auto *P : Category->protocols())
Douglas Gregorc3425b12015-07-07 06:20:19 +00004101 AddObjCProperties(CCContext, P, AllowCategories, AllowNullaryMethods,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004102 CurContext, AddedProperties, Results,
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004103 IsBaseExprStatement, IsClassProperty);
Douglas Gregor9291bad2009-11-18 01:29:26 +00004104 }
4105}
4106
Alex Lorenz0fe0d982017-05-11 13:41:00 +00004107static void AddRecordMembersCompletionResults(Sema &SemaRef,
4108 ResultBuilder &Results, Scope *S,
4109 QualType BaseType,
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004110 RecordDecl *RD,
4111 Optional<FixItHint> AccessOpFixIt) {
Alex Lorenz0fe0d982017-05-11 13:41:00 +00004112 // Indicate that we are performing a member access, and the cv-qualifiers
4113 // for the base object type.
4114 Results.setObjectTypeQualifiers(BaseType.getQualifiers());
4115
4116 // Access to a C/C++ class, struct, or union.
4117 Results.allowNestedNameSpecifiers();
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004118 std::vector<FixItHint> FixIts;
4119 if (AccessOpFixIt)
4120 FixIts.emplace_back(AccessOpFixIt.getValue());
Eric Liub91e0812018-10-02 10:29:00 +00004121 CodeCompletionDeclConsumer Consumer(Results, SemaRef.CurContext,
4122 std::move(FixIts), RD);
Alex Lorenz0fe0d982017-05-11 13:41:00 +00004123 SemaRef.LookupVisibleDecls(RD, Sema::LookupMemberName, Consumer,
Alex Lorenze6afa392017-05-11 13:48:57 +00004124 SemaRef.CodeCompleter->includeGlobals(),
Sam McCallbb2cf632018-01-12 14:51:47 +00004125 /*IncludeDependentBases=*/true,
4126 SemaRef.CodeCompleter->loadExternal());
Alex Lorenz0fe0d982017-05-11 13:41:00 +00004127
4128 if (SemaRef.getLangOpts().CPlusPlus) {
4129 if (!Results.empty()) {
4130 // The "template" keyword can follow "->" or "." in the grammar.
4131 // However, we only want to suggest the template keyword if something
4132 // is dependent.
4133 bool IsDependent = BaseType->isDependentType();
4134 if (!IsDependent) {
4135 for (Scope *DepScope = S; DepScope; DepScope = DepScope->getParent())
4136 if (DeclContext *Ctx = DepScope->getEntity()) {
4137 IsDependent = Ctx->isDependentContext();
4138 break;
4139 }
4140 }
4141
4142 if (IsDependent)
4143 Results.AddResult(CodeCompletionResult("template"));
4144 }
4145 }
4146}
4147
Douglas Gregor1cc88a92012-01-23 15:59:30 +00004148void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base,
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004149 Expr *OtherOpBase,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004150 SourceLocation OpLoc, bool IsArrow,
4151 bool IsBaseExprStatement) {
Douglas Gregor1cc88a92012-01-23 15:59:30 +00004152 if (!Base || !CodeCompleter)
Douglas Gregor2436e712009-09-17 21:32:03 +00004153 return;
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004154
Douglas Gregor1cc88a92012-01-23 15:59:30 +00004155 ExprResult ConvertedBase = PerformMemberExprBaseConversion(Base, IsArrow);
4156 if (ConvertedBase.isInvalid())
4157 return;
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004158 QualType ConvertedBaseType = ConvertedBase.get()->getType();
4159
4160 enum CodeCompletionContext::Kind contextKind;
Douglas Gregor3545ff42009-09-21 16:56:56 +00004161
4162 if (IsArrow) {
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004163 if (const PointerType *Ptr = ConvertedBaseType->getAs<PointerType>())
4164 ConvertedBaseType = Ptr->getPointeeType();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004165 }
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004166
Douglas Gregor21325842011-07-07 16:03:39 +00004167 if (IsArrow) {
4168 contextKind = CodeCompletionContext::CCC_ArrowMemberAccess;
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004169 } else {
4170 if (ConvertedBaseType->isObjCObjectPointerType() ||
4171 ConvertedBaseType->isObjCObjectOrInterfaceType()) {
Douglas Gregor21325842011-07-07 16:03:39 +00004172 contextKind = CodeCompletionContext::CCC_ObjCPropertyAccess;
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004173 } else {
Douglas Gregor21325842011-07-07 16:03:39 +00004174 contextKind = CodeCompletionContext::CCC_DotMemberAccess;
4175 }
4176 }
Douglas Gregorc3425b12015-07-07 06:20:19 +00004177
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004178 CodeCompletionContext CCContext(contextKind, ConvertedBaseType);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004179 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004180 CodeCompleter->getCodeCompletionTUInfo(), CCContext,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004181 &ResultBuilder::IsMember);
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004182
4183 auto DoCompletion = [&](Expr *Base, bool IsArrow, Optional<FixItHint> AccessOpFixIt) -> bool {
4184 if (!Base)
4185 return false;
4186
4187 ExprResult ConvertedBase = PerformMemberExprBaseConversion(Base, IsArrow);
4188 if (ConvertedBase.isInvalid())
4189 return false;
4190 Base = ConvertedBase.get();
4191
4192 QualType BaseType = Base->getType();
4193
4194 if (IsArrow) {
4195 if (const PointerType *Ptr = BaseType->getAs<PointerType>())
4196 BaseType = Ptr->getPointeeType();
4197 else if (BaseType->isObjCObjectPointerType())
4198 /*Do nothing*/;
4199 else
4200 return false;
4201 }
4202
4203 if (const RecordType *Record = BaseType->getAs<RecordType>()) {
4204 AddRecordMembersCompletionResults(*this, Results, S, BaseType,
4205 Record->getDecl(),
4206 std::move(AccessOpFixIt));
4207 } else if (const auto *TST =
4208 BaseType->getAs<TemplateSpecializationType>()) {
4209 TemplateName TN = TST->getTemplateName();
4210 if (const auto *TD =
4211 dyn_cast_or_null<ClassTemplateDecl>(TN.getAsTemplateDecl())) {
4212 CXXRecordDecl *RD = TD->getTemplatedDecl();
4213 AddRecordMembersCompletionResults(*this, Results, S, BaseType, RD,
4214 std::move(AccessOpFixIt));
4215 }
4216 } else if (const auto *ICNT = BaseType->getAs<InjectedClassNameType>()) {
4217 if (auto *RD = ICNT->getDecl())
4218 AddRecordMembersCompletionResults(*this, Results, S, BaseType, RD,
4219 std::move(AccessOpFixIt));
4220 } else if (!IsArrow && BaseType->isObjCObjectPointerType()) {
4221 // Objective-C property reference.
4222 AddedPropertiesSet AddedProperties;
4223
4224 if (const ObjCObjectPointerType *ObjCPtr =
4225 BaseType->getAsObjCInterfacePointerType()) {
4226 // Add property results based on our interface.
4227 assert(ObjCPtr && "Non-NULL pointer guaranteed above!");
4228 AddObjCProperties(CCContext, ObjCPtr->getInterfaceDecl(), true,
4229 /*AllowNullaryMethods=*/true, CurContext,
4230 AddedProperties, Results, IsBaseExprStatement);
4231 }
4232
4233 // Add properties from the protocols in a qualified interface.
4234 for (auto *I : BaseType->getAs<ObjCObjectPointerType>()->quals())
4235 AddObjCProperties(CCContext, I, true, /*AllowNullaryMethods=*/true,
4236 CurContext, AddedProperties, Results,
4237 IsBaseExprStatement);
4238 } else if ((IsArrow && BaseType->isObjCObjectPointerType()) ||
4239 (!IsArrow && BaseType->isObjCObjectType())) {
4240 // Objective-C instance variable access.
4241 ObjCInterfaceDecl *Class = nullptr;
4242 if (const ObjCObjectPointerType *ObjCPtr =
4243 BaseType->getAs<ObjCObjectPointerType>())
4244 Class = ObjCPtr->getInterfaceDecl();
4245 else
4246 Class = BaseType->getAs<ObjCObjectType>()->getInterface();
4247
4248 // Add all ivars from this class and its superclasses.
4249 if (Class) {
4250 CodeCompletionDeclConsumer Consumer(Results, CurContext);
4251 Results.setFilter(&ResultBuilder::IsObjCIvar);
4252 LookupVisibleDecls(
4253 Class, LookupMemberName, Consumer, CodeCompleter->includeGlobals(),
4254 /*IncludeDependentBases=*/false, CodeCompleter->loadExternal());
4255 }
4256 }
4257
4258 // FIXME: How do we cope with isa?
4259 return true;
4260 };
4261
Douglas Gregor9291bad2009-11-18 01:29:26 +00004262 Results.EnterNewScope();
Alex Lorenz06cfa992016-10-12 11:40:15 +00004263
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004264 bool CompletionSucceded = DoCompletion(Base, IsArrow, None);
4265 if (CodeCompleter->includeFixIts()) {
4266 const CharSourceRange OpRange =
4267 CharSourceRange::getTokenRange(OpLoc, OpLoc);
4268 CompletionSucceded |= DoCompletion(
4269 OtherOpBase, !IsArrow,
4270 FixItHint::CreateReplacement(OpRange, IsArrow ? "." : "->"));
Douglas Gregor3545ff42009-09-21 16:56:56 +00004271 }
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004272
Douglas Gregor9291bad2009-11-18 01:29:26 +00004273 Results.ExitScope();
Daniel Dunbar242ea9a2009-11-13 08:58:20 +00004274
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004275 if (!CompletionSucceded)
4276 return;
4277
Daniel Dunbar242ea9a2009-11-13 08:58:20 +00004278 // Hand off the results found for code completion.
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004279 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4280 Results.data(), Results.size());
Douglas Gregor2436e712009-09-17 21:32:03 +00004281}
4282
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004283void Sema::CodeCompleteObjCClassPropertyRefExpr(Scope *S,
4284 IdentifierInfo &ClassName,
4285 SourceLocation ClassNameLoc,
4286 bool IsBaseExprStatement) {
4287 IdentifierInfo *ClassNamePtr = &ClassName;
4288 ObjCInterfaceDecl *IFace = getObjCInterfaceDecl(ClassNamePtr, ClassNameLoc);
4289 if (!IFace)
4290 return;
4291 CodeCompletionContext CCContext(
4292 CodeCompletionContext::CCC_ObjCPropertyAccess);
4293 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4294 CodeCompleter->getCodeCompletionTUInfo(), CCContext,
4295 &ResultBuilder::IsMember);
4296 Results.EnterNewScope();
4297 AddedPropertiesSet AddedProperties;
4298 AddObjCProperties(CCContext, IFace, true,
4299 /*AllowNullaryMethods=*/true, CurContext, AddedProperties,
4300 Results, IsBaseExprStatement,
4301 /*IsClassProperty=*/true);
4302 Results.ExitScope();
4303 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4304 Results.data(), Results.size());
4305}
4306
Faisal Vali090da2d2018-01-01 18:23:28 +00004307void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) {
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004308 if (!CodeCompleter)
4309 return;
Craig Topperc3ec1492014-05-26 06:22:03 +00004310
4311 ResultBuilder::LookupFilter Filter = nullptr;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004312 enum CodeCompletionContext::Kind ContextKind
4313 = CodeCompletionContext::CCC_Other;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004314 switch ((DeclSpec::TST)TagSpec) {
4315 case DeclSpec::TST_enum:
Douglas Gregor3545ff42009-09-21 16:56:56 +00004316 Filter = &ResultBuilder::IsEnum;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004317 ContextKind = CodeCompletionContext::CCC_EnumTag;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004318 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004319
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004320 case DeclSpec::TST_union:
Douglas Gregor3545ff42009-09-21 16:56:56 +00004321 Filter = &ResultBuilder::IsUnion;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004322 ContextKind = CodeCompletionContext::CCC_UnionTag;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004323 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004324
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004325 case DeclSpec::TST_struct:
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004326 case DeclSpec::TST_class:
Joao Matosdc86f942012-08-31 18:45:21 +00004327 case DeclSpec::TST_interface:
Douglas Gregor3545ff42009-09-21 16:56:56 +00004328 Filter = &ResultBuilder::IsClassOrStruct;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004329 ContextKind = CodeCompletionContext::CCC_ClassOrStructTag;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004330 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004331
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004332 default:
David Blaikie83d382b2011-09-23 05:06:16 +00004333 llvm_unreachable("Unknown type specifier kind in CodeCompleteTag");
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004334 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004335
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004336 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4337 CodeCompleter->getCodeCompletionTUInfo(), ContextKind);
Douglas Gregora6e2edc2010-01-14 03:27:13 +00004338 CodeCompletionDeclConsumer Consumer(Results, CurContext);
John McCalle87beb22010-04-23 18:46:30 +00004339
4340 // First pass: look for tags.
4341 Results.setFilter(Filter);
Douglas Gregor39982192010-08-15 06:18:01 +00004342 LookupVisibleDecls(S, LookupTagName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00004343 CodeCompleter->includeGlobals(),
4344 CodeCompleter->loadExternal());
John McCalle87beb22010-04-23 18:46:30 +00004345
Douglas Gregor39982192010-08-15 06:18:01 +00004346 if (CodeCompleter->includeGlobals()) {
4347 // Second pass: look for nested name specifiers.
4348 Results.setFilter(&ResultBuilder::IsNestedNameSpecifier);
Sam McCallbb2cf632018-01-12 14:51:47 +00004349 LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer,
4350 CodeCompleter->includeGlobals(),
4351 CodeCompleter->loadExternal());
Douglas Gregor39982192010-08-15 06:18:01 +00004352 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004353
Douglas Gregor0ac41382010-09-23 23:01:17 +00004354 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004355 Results.data(),Results.size());
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004356}
4357
Alex Lorenz8f4d3992017-02-13 23:19:40 +00004358static void AddTypeQualifierResults(DeclSpec &DS, ResultBuilder &Results,
4359 const LangOptions &LangOpts) {
4360 if (!(DS.getTypeQualifiers() & DeclSpec::TQ_const))
4361 Results.AddResult("const");
4362 if (!(DS.getTypeQualifiers() & DeclSpec::TQ_volatile))
4363 Results.AddResult("volatile");
4364 if (LangOpts.C99 && !(DS.getTypeQualifiers() & DeclSpec::TQ_restrict))
4365 Results.AddResult("restrict");
4366 if (LangOpts.C11 && !(DS.getTypeQualifiers() & DeclSpec::TQ_atomic))
4367 Results.AddResult("_Atomic");
4368 if (LangOpts.MSVCCompat && !(DS.getTypeQualifiers() & DeclSpec::TQ_unaligned))
4369 Results.AddResult("__unaligned");
4370}
4371
Douglas Gregor28c78432010-08-27 17:35:51 +00004372void Sema::CodeCompleteTypeQualifiers(DeclSpec &DS) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004373 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004374 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004375 CodeCompletionContext::CCC_TypeQualifiers);
Douglas Gregor28c78432010-08-27 17:35:51 +00004376 Results.EnterNewScope();
Alex Lorenz8f4d3992017-02-13 23:19:40 +00004377 AddTypeQualifierResults(DS, Results, LangOpts);
Douglas Gregor28c78432010-08-27 17:35:51 +00004378 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004379 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004380 Results.getCompletionContext(),
Douglas Gregor28c78432010-08-27 17:35:51 +00004381 Results.data(), Results.size());
4382}
4383
Alex Lorenz8f4d3992017-02-13 23:19:40 +00004384void Sema::CodeCompleteFunctionQualifiers(DeclSpec &DS, Declarator &D,
4385 const VirtSpecifiers *VS) {
4386 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4387 CodeCompleter->getCodeCompletionTUInfo(),
4388 CodeCompletionContext::CCC_TypeQualifiers);
4389 Results.EnterNewScope();
4390 AddTypeQualifierResults(DS, Results, LangOpts);
4391 if (LangOpts.CPlusPlus11) {
4392 Results.AddResult("noexcept");
Faisal Vali421b2d12017-12-29 05:41:00 +00004393 if (D.getContext() == DeclaratorContext::MemberContext &&
4394 !D.isCtorOrDtor() && !D.isStaticMember()) {
Alex Lorenz8f4d3992017-02-13 23:19:40 +00004395 if (!VS || !VS->isFinalSpecified())
4396 Results.AddResult("final");
4397 if (!VS || !VS->isOverrideSpecified())
4398 Results.AddResult("override");
4399 }
4400 }
4401 Results.ExitScope();
4402 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4403 Results.data(), Results.size());
4404}
4405
Benjamin Kramer72dae622016-02-18 15:30:24 +00004406void Sema::CodeCompleteBracketDeclarator(Scope *S) {
4407 CodeCompleteExpression(S, QualType(getASTContext().getSizeType()));
4408}
4409
Douglas Gregord328d572009-09-21 18:10:23 +00004410void Sema::CodeCompleteCase(Scope *S) {
John McCallaab3e412010-08-25 08:40:02 +00004411 if (getCurFunction()->SwitchStack.empty() || !CodeCompleter)
Douglas Gregord328d572009-09-21 18:10:23 +00004412 return;
John McCall5939b162011-08-06 07:30:58 +00004413
Richard Smithef6c43d2018-07-26 18:41:30 +00004414 SwitchStmt *Switch = getCurFunction()->SwitchStack.back().getPointer();
John McCall5939b162011-08-06 07:30:58 +00004415 QualType type = Switch->getCond()->IgnoreImplicit()->getType();
4416 if (!type->isEnumeralType()) {
4417 CodeCompleteExpressionData Data(type);
Douglas Gregor68762e72010-08-23 21:17:50 +00004418 Data.IntegralConstantExpression = true;
4419 CodeCompleteExpression(S, Data);
Douglas Gregord328d572009-09-21 18:10:23 +00004420 return;
Douglas Gregor85b50632010-07-28 21:50:18 +00004421 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004422
Douglas Gregord328d572009-09-21 18:10:23 +00004423 // Code-complete the cases of a switch statement over an enumeration type
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004424 // by providing the list of
John McCall5939b162011-08-06 07:30:58 +00004425 EnumDecl *Enum = type->castAs<EnumType>()->getDecl();
Douglas Gregor9b4f3702012-06-12 13:44:08 +00004426 if (EnumDecl *Def = Enum->getDefinition())
4427 Enum = Def;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004428
Douglas Gregord328d572009-09-21 18:10:23 +00004429 // Determine which enumerators we have already seen in the switch statement.
4430 // FIXME: Ideally, we would also be able to look *past* the code-completion
4431 // token, in case we are code-completing in the middle of the switch and not
4432 // at the end. However, we aren't able to do so at the moment.
4433 llvm::SmallPtrSet<EnumConstantDecl *, 8> EnumeratorsSeen;
Craig Topperc3ec1492014-05-26 06:22:03 +00004434 NestedNameSpecifier *Qualifier = nullptr;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004435 for (SwitchCase *SC = Switch->getSwitchCaseList(); SC;
Douglas Gregord328d572009-09-21 18:10:23 +00004436 SC = SC->getNextSwitchCase()) {
4437 CaseStmt *Case = dyn_cast<CaseStmt>(SC);
4438 if (!Case)
4439 continue;
4440
4441 Expr *CaseVal = Case->getLHS()->IgnoreParenCasts();
4442 if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CaseVal))
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004443 if (EnumConstantDecl *Enumerator
Douglas Gregord328d572009-09-21 18:10:23 +00004444 = dyn_cast<EnumConstantDecl>(DRE->getDecl())) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004445 // We look into the AST of the case statement to determine which
4446 // enumerator was named. Alternatively, we could compute the value of
Douglas Gregord328d572009-09-21 18:10:23 +00004447 // the integral constant expression, then compare it against the
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004448 // values of each enumerator. However, value-based approach would not
4449 // work as well with C++ templates where enumerators declared within a
Douglas Gregord328d572009-09-21 18:10:23 +00004450 // template are type- and value-dependent.
4451 EnumeratorsSeen.insert(Enumerator);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004452
Douglas Gregorf2510672009-09-21 19:57:38 +00004453 // If this is a qualified-id, keep track of the nested-name-specifier
4454 // so that we can reproduce it as part of code completion, e.g.,
Douglas Gregord328d572009-09-21 18:10:23 +00004455 //
4456 // switch (TagD.getKind()) {
4457 // case TagDecl::TK_enum:
4458 // break;
4459 // case XXX
4460 //
Douglas Gregorf2510672009-09-21 19:57:38 +00004461 // At the XXX, our completions are TagDecl::TK_union,
Douglas Gregord328d572009-09-21 18:10:23 +00004462 // TagDecl::TK_struct, and TagDecl::TK_class, rather than TK_union,
4463 // TK_struct, and TK_class.
Douglas Gregor4bd90e52009-10-23 18:54:35 +00004464 Qualifier = DRE->getQualifier();
Douglas Gregord328d572009-09-21 18:10:23 +00004465 }
4466 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004467
David Blaikiebbafb8a2012-03-11 07:00:24 +00004468 if (getLangOpts().CPlusPlus && !Qualifier && EnumeratorsSeen.empty()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004469 // If there are no prior enumerators in C++, check whether we have to
Douglas Gregorf2510672009-09-21 19:57:38 +00004470 // qualify the names of the enumerators that we suggest, because they
4471 // may not be visible in this scope.
Douglas Gregord3cebdb2012-02-01 05:02:47 +00004472 Qualifier = getRequiredQualification(Context, CurContext, Enum);
Douglas Gregorf2510672009-09-21 19:57:38 +00004473 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004474
Douglas Gregord328d572009-09-21 18:10:23 +00004475 // Add any enumerators that have not yet been mentioned.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004476 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004477 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004478 CodeCompletionContext::CCC_Expression);
Douglas Gregord328d572009-09-21 18:10:23 +00004479 Results.EnterNewScope();
Aaron Ballman23a6dcb2014-03-08 18:45:14 +00004480 for (auto *E : Enum->enumerators()) {
4481 if (EnumeratorsSeen.count(E))
Douglas Gregord328d572009-09-21 18:10:23 +00004482 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004483
Aaron Ballman23a6dcb2014-03-08 18:45:14 +00004484 CodeCompletionResult R(E, CCP_EnumInCase, Qualifier);
Craig Topperc3ec1492014-05-26 06:22:03 +00004485 Results.AddResult(R, CurContext, nullptr, false);
Douglas Gregord328d572009-09-21 18:10:23 +00004486 }
4487 Results.ExitScope();
Douglas Gregor285560922010-04-06 20:02:15 +00004488
Douglas Gregor21325842011-07-07 16:03:39 +00004489 if (CodeCompleter->includeMacros()) {
Eric Liu88de9f62018-09-19 09:34:55 +00004490 AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false);
Douglas Gregor21325842011-07-07 16:03:39 +00004491 }
Eric Liuf5ba09f2018-07-04 10:01:18 +00004492 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4493 Results.data(), Results.size());
Douglas Gregord328d572009-09-21 18:10:23 +00004494}
4495
Robert Wilhelm16e94b92013-08-09 18:02:13 +00004496static bool anyNullArguments(ArrayRef<Expr *> Args) {
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00004497 if (Args.size() && !Args.data())
Douglas Gregor6ed3eb82010-05-30 06:10:08 +00004498 return true;
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00004499
4500 for (unsigned I = 0; I != Args.size(); ++I)
Douglas Gregor6ed3eb82010-05-30 06:10:08 +00004501 if (!Args[I])
4502 return true;
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00004503
Douglas Gregor6ed3eb82010-05-30 06:10:08 +00004504 return false;
4505}
4506
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004507typedef CodeCompleteConsumer::OverloadCandidate ResultCandidate;
4508
Francisco Lopes da Silva8cafefa2015-01-29 05:54:59 +00004509static void mergeCandidatesWithResults(Sema &SemaRef,
4510 SmallVectorImpl<ResultCandidate> &Results,
4511 OverloadCandidateSet &CandidateSet,
4512 SourceLocation Loc) {
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004513 if (!CandidateSet.empty()) {
4514 // Sort the overload candidate set by placing the best overloads first.
4515 std::stable_sort(
4516 CandidateSet.begin(), CandidateSet.end(),
4517 [&](const OverloadCandidate &X, const OverloadCandidate &Y) {
Richard Smith67ef14f2017-09-26 18:37:55 +00004518 return isBetterOverloadCandidate(SemaRef, X, Y, Loc,
4519 CandidateSet.getKind());
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004520 });
4521
4522 // Add the remaining viable overload candidates as code-completion results.
Erik Verbruggen7ec91072017-09-08 10:23:08 +00004523 for (auto &Candidate : CandidateSet) {
4524 if (Candidate.Function && Candidate.Function->isDeleted())
4525 continue;
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004526 if (Candidate.Viable)
4527 Results.push_back(ResultCandidate(Candidate.Function));
Erik Verbruggen7ec91072017-09-08 10:23:08 +00004528 }
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004529 }
4530}
4531
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00004532/// Get the type of the Nth parameter from a given set of overload
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004533/// candidates.
Francisco Lopes da Silva8cafefa2015-01-29 05:54:59 +00004534static QualType getParamType(Sema &SemaRef,
4535 ArrayRef<ResultCandidate> Candidates,
4536 unsigned N) {
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004537
4538 // Given the overloads 'Candidates' for a function call matching all arguments
4539 // up to N, return the type of the Nth parameter if it is the same for all
4540 // overload candidates.
4541 QualType ParamType;
4542 for (auto &Candidate : Candidates) {
4543 if (auto FType = Candidate.getFunctionType())
4544 if (auto Proto = dyn_cast<FunctionProtoType>(FType))
4545 if (N < Proto->getNumParams()) {
4546 if (ParamType.isNull())
4547 ParamType = Proto->getParamType(N);
4548 else if (!SemaRef.Context.hasSameUnqualifiedType(
4549 ParamType.getNonReferenceType(),
4550 Proto->getParamType(N).getNonReferenceType()))
4551 // Otherwise return a default-constructed QualType.
4552 return QualType();
4553 }
4554 }
4555
4556 return ParamType;
4557}
4558
Ilya Biryukov832c4af2018-09-07 14:04:39 +00004559static QualType
4560ProduceSignatureHelp(Sema &SemaRef, Scope *S,
4561 MutableArrayRef<ResultCandidate> Candidates,
4562 unsigned CurrentArg, SourceLocation OpenParLoc) {
4563 if (Candidates.empty())
4564 return QualType();
4565 SemaRef.CodeCompleter->ProcessOverloadCandidates(
4566 SemaRef, CurrentArg, Candidates.data(), Candidates.size(), OpenParLoc);
4567 return getParamType(SemaRef, Candidates, CurrentArg);
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004568}
4569
Ilya Biryukov832c4af2018-09-07 14:04:39 +00004570QualType Sema::ProduceCallSignatureHelp(Scope *S, Expr *Fn,
4571 ArrayRef<Expr *> Args,
4572 SourceLocation OpenParLoc) {
Douglas Gregorcabea402009-09-22 15:41:20 +00004573 if (!CodeCompleter)
Ilya Biryukov832c4af2018-09-07 14:04:39 +00004574 return QualType();
Douglas Gregor3ef59522009-12-11 19:06:04 +00004575
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004576 // FIXME: Provide support for variadic template functions.
Douglas Gregorcabea402009-09-22 15:41:20 +00004577 // Ignore type-dependent call expressions entirely.
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00004578 if (!Fn || Fn->isTypeDependent() || anyNullArguments(Args) ||
4579 Expr::hasAnyTypeDependentArguments(Args)) {
Ilya Biryukov832c4af2018-09-07 14:04:39 +00004580 return QualType();
Douglas Gregor3ef59522009-12-11 19:06:04 +00004581 }
Douglas Gregorcabea402009-09-22 15:41:20 +00004582
John McCall57500772009-12-16 12:17:52 +00004583 // Build an overload candidate set based on the functions we find.
John McCallbc077cf2010-02-08 23:07:23 +00004584 SourceLocation Loc = Fn->getExprLoc();
Richard Smith100b24a2014-04-17 01:52:14 +00004585 OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal);
John McCall57500772009-12-16 12:17:52 +00004586
Chris Lattner0e62c1c2011-07-23 10:55:15 +00004587 SmallVector<ResultCandidate, 8> Results;
Douglas Gregorff59f672010-01-21 15:46:19 +00004588
John McCall57500772009-12-16 12:17:52 +00004589 Expr *NakedFn = Fn->IgnoreParenCasts();
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004590 if (auto ULE = dyn_cast<UnresolvedLookupExpr>(NakedFn))
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00004591 AddOverloadedCallCandidates(ULE, Args, CandidateSet,
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004592 /*PartialOverloading=*/true);
4593 else if (auto UME = dyn_cast<UnresolvedMemberExpr>(NakedFn)) {
4594 TemplateArgumentListInfo TemplateArgsBuffer, *TemplateArgs = nullptr;
4595 if (UME->hasExplicitTemplateArgs()) {
4596 UME->copyTemplateArgumentsInto(TemplateArgsBuffer);
4597 TemplateArgs = &TemplateArgsBuffer;
Douglas Gregorff59f672010-01-21 15:46:19 +00004598 }
Erik Verbruggenf1898cf2017-03-28 07:22:21 +00004599
4600 // Add the base as first argument (use a nullptr if the base is implicit).
4601 SmallVector<Expr *, 12> ArgExprs(
4602 1, UME->isImplicitAccess() ? nullptr : UME->getBase());
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004603 ArgExprs.append(Args.begin(), Args.end());
4604 UnresolvedSet<8> Decls;
4605 Decls.append(UME->decls_begin(), UME->decls_end());
Benjamin Kramere3962ae2017-10-26 08:41:28 +00004606 const bool FirstArgumentIsBase = !UME->isImplicitAccess() && UME->getBase();
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004607 AddFunctionCandidates(Decls, ArgExprs, CandidateSet, TemplateArgs,
4608 /*SuppressUsedConversions=*/false,
Benjamin Kramere3962ae2017-10-26 08:41:28 +00004609 /*PartialOverloading=*/true,
4610 FirstArgumentIsBase);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004611 } else {
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004612 FunctionDecl *FD = nullptr;
4613 if (auto MCE = dyn_cast<MemberExpr>(NakedFn))
4614 FD = dyn_cast<FunctionDecl>(MCE->getMemberDecl());
4615 else if (auto DRE = dyn_cast<DeclRefExpr>(NakedFn))
4616 FD = dyn_cast<FunctionDecl>(DRE->getDecl());
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00004617 if (FD) { // We check whether it's a resolved function declaration.
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00004618 if (!getLangOpts().CPlusPlus ||
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004619 !FD->getType()->getAs<FunctionProtoType>())
4620 Results.push_back(ResultCandidate(FD));
4621 else
4622 AddOverloadCandidate(FD, DeclAccessPair::make(FD, FD->getAccess()),
4623 Args, CandidateSet,
4624 /*SuppressUsedConversions=*/false,
4625 /*PartialOverloading=*/true);
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00004626
4627 } else if (auto DC = NakedFn->getType()->getAsCXXRecordDecl()) {
4628 // If expression's type is CXXRecordDecl, it may overload the function
4629 // call operator, so we check if it does and add them as candidates.
Francisco Lopes da Silvaa349a8a2015-01-25 08:47:59 +00004630 // A complete type is needed to lookup for member function call operators.
Richard Smithdb0ac552015-12-18 22:40:25 +00004631 if (isCompleteType(Loc, NakedFn->getType())) {
Francisco Lopes da Silvaa349a8a2015-01-25 08:47:59 +00004632 DeclarationName OpName = Context.DeclarationNames
4633 .getCXXOperatorName(OO_Call);
4634 LookupResult R(*this, OpName, Loc, LookupOrdinaryName);
4635 LookupQualifiedName(R, DC);
4636 R.suppressDiagnostics();
4637 SmallVector<Expr *, 12> ArgExprs(1, NakedFn);
4638 ArgExprs.append(Args.begin(), Args.end());
4639 AddFunctionCandidates(R.asUnresolvedSet(), ArgExprs, CandidateSet,
4640 /*ExplicitArgs=*/nullptr,
4641 /*SuppressUsedConversions=*/false,
4642 /*PartialOverloading=*/true);
4643 }
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00004644 } else {
4645 // Lastly we check whether expression's type is function pointer or
4646 // function.
4647 QualType T = NakedFn->getType();
4648 if (!T->getPointeeType().isNull())
4649 T = T->getPointeeType();
4650
4651 if (auto FP = T->getAs<FunctionProtoType>()) {
4652 if (!TooManyArguments(FP->getNumParams(), Args.size(),
Francisco Lopes da Silva62a9a4f2015-01-23 13:17:51 +00004653 /*PartialOverloading=*/true) ||
4654 FP->isVariadic())
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00004655 Results.push_back(ResultCandidate(FP));
4656 } else if (auto FT = T->getAs<FunctionType>())
Francisco Lopes da Silva62a9a4f2015-01-23 13:17:51 +00004657 // No prototype and declaration, it may be a K & R style function.
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00004658 Results.push_back(ResultCandidate(FT));
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004659 }
Douglas Gregorcabea402009-09-22 15:41:20 +00004660 }
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004661 mergeCandidatesWithResults(*this, Results, CandidateSet, Loc);
Ilya Biryukov832c4af2018-09-07 14:04:39 +00004662 QualType ParamType =
4663 ProduceSignatureHelp(*this, S, Results, Args.size(), OpenParLoc);
4664 return !CandidateSet.empty() ? ParamType : QualType();
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004665}
4666
Ilya Biryukov832c4af2018-09-07 14:04:39 +00004667QualType Sema::ProduceConstructorSignatureHelp(Scope *S, QualType Type,
4668 SourceLocation Loc,
4669 ArrayRef<Expr *> Args,
4670 SourceLocation OpenParLoc) {
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004671 if (!CodeCompleter)
Ilya Biryukov832c4af2018-09-07 14:04:39 +00004672 return QualType();
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004673
4674 // A complete type is needed to lookup for constructors.
Ilya Biryukovfb9dde72018-05-14 13:50:36 +00004675 CXXRecordDecl *RD =
4676 isCompleteType(Loc, Type) ? Type->getAsCXXRecordDecl() : nullptr;
Ilya Biryukov832c4af2018-09-07 14:04:39 +00004677 if (!RD)
4678 return Type;
Argyrios Kyrtzidisee1d76f2015-03-13 07:39:30 +00004679
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004680 // FIXME: Provide support for member initializers.
4681 // FIXME: Provide support for variadic template constructors.
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004682
4683 OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal);
4684
Argyrios Kyrtzidisee1d76f2015-03-13 07:39:30 +00004685 for (auto C : LookupConstructors(RD)) {
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004686 if (auto FD = dyn_cast<FunctionDecl>(C)) {
4687 AddOverloadCandidate(FD, DeclAccessPair::make(FD, C->getAccess()),
4688 Args, CandidateSet,
4689 /*SuppressUsedConversions=*/false,
4690 /*PartialOverloading=*/true);
4691 } else if (auto FTD = dyn_cast<FunctionTemplateDecl>(C)) {
4692 AddTemplateOverloadCandidate(FTD,
4693 DeclAccessPair::make(FTD, C->getAccess()),
4694 /*ExplicitTemplateArgs=*/nullptr,
4695 Args, CandidateSet,
4696 /*SuppressUsedConversions=*/false,
4697 /*PartialOverloading=*/true);
4698 }
4699 }
4700
4701 SmallVector<ResultCandidate, 8> Results;
4702 mergeCandidatesWithResults(*this, Results, CandidateSet, Loc);
Ilya Biryukov832c4af2018-09-07 14:04:39 +00004703 return ProduceSignatureHelp(*this, S, Results, Args.size(), OpenParLoc);
Douglas Gregorcabea402009-09-22 15:41:20 +00004704}
4705
Kadir Cetinkaya84774c32018-09-11 15:02:18 +00004706QualType Sema::ProduceCtorInitMemberSignatureHelp(
4707 Scope *S, Decl *ConstructorDecl, CXXScopeSpec SS, ParsedType TemplateTypeTy,
4708 ArrayRef<Expr *> ArgExprs, IdentifierInfo *II, SourceLocation OpenParLoc) {
4709 if (!CodeCompleter)
4710 return QualType();
4711
4712 CXXConstructorDecl *Constructor =
4713 dyn_cast<CXXConstructorDecl>(ConstructorDecl);
4714 if (!Constructor)
4715 return QualType();
4716 // FIXME: Add support for Base class constructors as well.
4717 if (ValueDecl *MemberDecl = tryLookupCtorInitMemberDecl(
4718 Constructor->getParent(), SS, TemplateTypeTy, II))
4719 return ProduceConstructorSignatureHelp(getCurScope(), MemberDecl->getType(),
4720 MemberDecl->getLocation(), ArgExprs,
4721 OpenParLoc);
4722 return QualType();
4723}
4724
John McCall48871652010-08-21 09:40:31 +00004725void Sema::CodeCompleteInitializer(Scope *S, Decl *D) {
4726 ValueDecl *VD = dyn_cast_or_null<ValueDecl>(D);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004727 if (!VD) {
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004728 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004729 return;
4730 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004731
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004732 CodeCompleteExpression(S, VD->getType());
4733}
4734
4735void Sema::CodeCompleteReturn(Scope *S) {
4736 QualType ResultType;
4737 if (isa<BlockDecl>(CurContext)) {
4738 if (BlockScopeInfo *BSI = getCurBlock())
4739 ResultType = BSI->ReturnType;
4740 } else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(CurContext))
Alp Toker314cc812014-01-25 16:55:45 +00004741 ResultType = Function->getReturnType();
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004742 else if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(CurContext))
Alp Toker314cc812014-01-25 16:55:45 +00004743 ResultType = Method->getReturnType();
4744
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004745 if (ResultType.isNull())
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004746 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004747 else
4748 CodeCompleteExpression(S, ResultType);
4749}
4750
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004751void Sema::CodeCompleteAfterIf(Scope *S) {
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004752 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004753 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004754 mapCodeCompletionContext(*this, PCC_Statement));
4755 Results.setFilter(&ResultBuilder::IsOrdinaryName);
4756 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004757
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004758 CodeCompletionDeclConsumer Consumer(Results, CurContext);
4759 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00004760 CodeCompleter->includeGlobals(),
4761 CodeCompleter->loadExternal());
4762
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004763 AddOrdinaryNameResults(PCC_Statement, S, *this, Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004764
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004765 // "else" block
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004766 CodeCompletionBuilder Builder(Results.getAllocator(),
4767 Results.getCodeCompletionTUInfo());
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004768 Builder.AddTypedTextChunk("else");
Douglas Gregor3a5d6c22012-02-16 17:49:04 +00004769 if (Results.includeCodePatterns()) {
4770 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4771 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4772 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
4773 Builder.AddPlaceholderChunk("statements");
4774 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
4775 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4776 }
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004777 Results.AddResult(Builder.TakeString());
4778
4779 // "else if" block
4780 Builder.AddTypedTextChunk("else");
4781 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4782 Builder.AddTextChunk("if");
4783 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4784 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00004785 if (getLangOpts().CPlusPlus)
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004786 Builder.AddPlaceholderChunk("condition");
4787 else
4788 Builder.AddPlaceholderChunk("expression");
4789 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor3a5d6c22012-02-16 17:49:04 +00004790 if (Results.includeCodePatterns()) {
4791 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4792 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4793 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
4794 Builder.AddPlaceholderChunk("statements");
4795 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
4796 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4797 }
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004798 Results.AddResult(Builder.TakeString());
4799
4800 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004801
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004802 if (S->getFnParent())
Craig Topper12126262015-11-15 17:27:57 +00004803 AddPrettyFunctionResults(getLangOpts(), Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004804
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004805 if (CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00004806 AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004807
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004808 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4809 Results.data(),Results.size());
4810}
4811
Richard Trieu2bd04012011-09-09 02:00:50 +00004812void Sema::CodeCompleteAssignmentRHS(Scope *S, Expr *LHS) {
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004813 if (LHS)
4814 CodeCompleteExpression(S, static_cast<Expr *>(LHS)->getType());
4815 else
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004816 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004817}
4818
Jeffrey Yasskinc76498d2010-04-08 16:38:48 +00004819void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS,
Douglas Gregor2436e712009-09-17 21:32:03 +00004820 bool EnteringContext) {
Eric Liu06d34022017-12-12 11:35:46 +00004821 if (SS.isEmpty() || !CodeCompleter)
Douglas Gregor2436e712009-09-17 21:32:03 +00004822 return;
Alex Lorenz8a7a4cf2017-06-15 21:40:54 +00004823
Eric Liu06d34022017-12-12 11:35:46 +00004824 // We want to keep the scope specifier even if it's invalid (e.g. the scope
4825 // "a::b::" is not corresponding to any context/namespace in the AST), since
4826 // it can be useful for global code completion which have information about
4827 // contexts/symbols that are not in the AST.
4828 if (SS.isInvalid()) {
4829 CodeCompletionContext CC(CodeCompletionContext::CCC_Name);
4830 CC.setCXXScopeSpecifier(SS);
4831 HandleCodeCompleteResults(this, CodeCompleter, CC, nullptr, 0);
4832 return;
4833 }
Alex Lorenz8a7a4cf2017-06-15 21:40:54 +00004834 // Always pretend to enter a context to ensure that a dependent type
4835 // resolves to a dependent record.
4836 DeclContext *Ctx = computeDeclContext(SS, /*EnteringContext=*/true);
Douglas Gregor3545ff42009-09-21 16:56:56 +00004837 if (!Ctx)
4838 return;
Douglas Gregor800f2f02009-12-11 18:28:39 +00004839
4840 // Try to instantiate any non-dependent declaration contexts before
4841 // we look in them.
John McCall0b66eb32010-05-01 00:40:08 +00004842 if (!isDependentScopeSpecifier(SS) && RequireCompleteDeclContext(SS, Ctx))
Douglas Gregor800f2f02009-12-11 18:28:39 +00004843 return;
4844
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004845 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004846 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004847 CodeCompletionContext::CCC_Name);
Douglas Gregorac322ec2010-08-27 21:18:54 +00004848 Results.EnterNewScope();
Eric Liu06d34022017-12-12 11:35:46 +00004849
Douglas Gregor3545ff42009-09-21 16:56:56 +00004850 // The "template" keyword can follow "::" in the grammar, but only
4851 // put it into the grammar if the nested-name-specifier is dependent.
Aaron Ballman4a979672014-01-03 13:56:08 +00004852 NestedNameSpecifier *NNS = SS.getScopeRep();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004853 if (!Results.empty() && NNS->isDependent())
Douglas Gregor78a21012010-01-14 16:01:26 +00004854 Results.AddResult("template");
Douglas Gregorac322ec2010-08-27 21:18:54 +00004855
4856 // Add calls to overridden virtual functions, if there are any.
4857 //
4858 // FIXME: This isn't wonderful, because we don't know whether we're actually
4859 // in a context that permits expressions. This is a general issue with
4860 // qualified-id completions.
4861 if (!EnteringContext)
4862 MaybeAddOverrideCalls(*this, Ctx, Results);
Eric Liu06d34022017-12-12 11:35:46 +00004863 Results.ExitScope();
4864
Eric Liufead6ae2017-12-13 10:26:49 +00004865 if (CodeCompleter->includeNamespaceLevelDecls() ||
4866 (!Ctx->isNamespace() && !Ctx->isTranslationUnit())) {
4867 CodeCompletionDeclConsumer Consumer(Results, CurContext);
4868 LookupVisibleDecls(Ctx, LookupOrdinaryName, Consumer,
4869 /*IncludeGlobalScope=*/true,
Sam McCallbb2cf632018-01-12 14:51:47 +00004870 /*IncludeDependentBases=*/true,
4871 CodeCompleter->loadExternal());
Eric Liufead6ae2017-12-13 10:26:49 +00004872 }
Douglas Gregorac322ec2010-08-27 21:18:54 +00004873
Eric Liu06d34022017-12-12 11:35:46 +00004874 auto CC = Results.getCompletionContext();
4875 CC.setCXXScopeSpecifier(SS);
4876
4877 HandleCodeCompleteResults(this, CodeCompleter, CC, Results.data(),
4878 Results.size());
Douglas Gregor2436e712009-09-17 21:32:03 +00004879}
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00004880
4881void Sema::CodeCompleteUsing(Scope *S) {
4882 if (!CodeCompleter)
4883 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004884
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004885 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004886 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00004887 CodeCompletionContext::CCC_PotentiallyQualifiedName,
4888 &ResultBuilder::IsNestedNameSpecifier);
Douglas Gregor64b12b52009-09-22 23:31:26 +00004889 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004890
Douglas Gregor3545ff42009-09-21 16:56:56 +00004891 // If we aren't in class scope, we could see the "namespace" keyword.
4892 if (!S->isClassScope())
John McCall276321a2010-08-25 06:19:51 +00004893 Results.AddResult(CodeCompletionResult("namespace"));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004894
4895 // After "using", we can see anything that would start a
Douglas Gregor3545ff42009-09-21 16:56:56 +00004896 // nested-name-specifier.
Douglas Gregora6e2edc2010-01-14 03:27:13 +00004897 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00004898 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00004899 CodeCompleter->includeGlobals(),
4900 CodeCompleter->loadExternal());
Douglas Gregor64b12b52009-09-22 23:31:26 +00004901 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00004902
4903 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4904 Results.data(), Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00004905}
4906
4907void Sema::CodeCompleteUsingDirective(Scope *S) {
4908 if (!CodeCompleter)
4909 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004910
Douglas Gregor3545ff42009-09-21 16:56:56 +00004911 // After "using namespace", we expect to see a namespace name or namespace
4912 // alias.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004913 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004914 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004915 CodeCompletionContext::CCC_Namespace,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004916 &ResultBuilder::IsNamespaceOrAlias);
Douglas Gregor64b12b52009-09-22 23:31:26 +00004917 Results.EnterNewScope();
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 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4924 Results.data(), Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00004925}
4926
4927void Sema::CodeCompleteNamespaceDecl(Scope *S) {
4928 if (!CodeCompleter)
4929 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004930
Ted Kremenekc37877d2013-10-08 17:08:03 +00004931 DeclContext *Ctx = S->getEntity();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004932 if (!S->getParent())
4933 Ctx = Context.getTranslationUnitDecl();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004934
Douglas Gregor0ac41382010-09-23 23:01:17 +00004935 bool SuppressedGlobalResults
4936 = Ctx && !CodeCompleter->includeGlobals() && isa<TranslationUnitDecl>(Ctx);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004937
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004938 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004939 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00004940 SuppressedGlobalResults
4941 ? CodeCompletionContext::CCC_Namespace
4942 : CodeCompletionContext::CCC_Other,
4943 &ResultBuilder::IsNamespace);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004944
Douglas Gregor0ac41382010-09-23 23:01:17 +00004945 if (Ctx && Ctx->isFileContext() && !SuppressedGlobalResults) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00004946 // We only want to see those namespaces that have already been defined
4947 // within this scope, because its likely that the user is creating an
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004948 // extended namespace declaration. Keep track of the most recent
Douglas Gregor3545ff42009-09-21 16:56:56 +00004949 // definition of each namespace.
4950 std::map<NamespaceDecl *, NamespaceDecl *> OrigToLatest;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004951 for (DeclContext::specific_decl_iterator<NamespaceDecl>
Douglas Gregor3545ff42009-09-21 16:56:56 +00004952 NS(Ctx->decls_begin()), NSEnd(Ctx->decls_end());
4953 NS != NSEnd; ++NS)
David Blaikie40ed2972012-06-06 20:45:41 +00004954 OrigToLatest[NS->getOriginalNamespace()] = *NS;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004955
4956 // Add the most recent definition (or extended definition) of each
Douglas Gregor3545ff42009-09-21 16:56:56 +00004957 // namespace to the list of results.
Douglas Gregor64b12b52009-09-22 23:31:26 +00004958 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004959 for (std::map<NamespaceDecl *, NamespaceDecl *>::iterator
Douglas Gregor78254c82012-03-27 23:34:16 +00004960 NS = OrigToLatest.begin(),
4961 NSEnd = OrigToLatest.end();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004962 NS != NSEnd; ++NS)
Douglas Gregor0a0e2b32013-01-31 04:52:16 +00004963 Results.AddResult(CodeCompletionResult(
Craig Topperc3ec1492014-05-26 06:22:03 +00004964 NS->second, Results.getBasePriority(NS->second),
4965 nullptr),
4966 CurContext, nullptr, false);
Douglas Gregor64b12b52009-09-22 23:31:26 +00004967 Results.ExitScope();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004968 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004969
4970 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004971 Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004972 Results.data(),Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00004973}
4974
4975void Sema::CodeCompleteNamespaceAliasDecl(Scope *S) {
4976 if (!CodeCompleter)
4977 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004978
Douglas Gregor3545ff42009-09-21 16:56:56 +00004979 // After "namespace", we expect to see a namespace or alias.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004980 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004981 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004982 CodeCompletionContext::CCC_Namespace,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004983 &ResultBuilder::IsNamespaceOrAlias);
Douglas Gregora6e2edc2010-01-14 03:27:13 +00004984 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00004985 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00004986 CodeCompleter->includeGlobals(),
4987 CodeCompleter->loadExternal());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004988 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004989 Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004990 Results.data(),Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00004991}
4992
Douglas Gregorc811ede2009-09-18 20:05:18 +00004993void Sema::CodeCompleteOperatorName(Scope *S) {
4994 if (!CodeCompleter)
4995 return;
Douglas Gregor3545ff42009-09-21 16:56:56 +00004996
John McCall276321a2010-08-25 06:19:51 +00004997 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004998 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004999 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005000 CodeCompletionContext::CCC_Type,
Douglas Gregor0ac41382010-09-23 23:01:17 +00005001 &ResultBuilder::IsType);
Douglas Gregor64b12b52009-09-22 23:31:26 +00005002 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005003
Douglas Gregor3545ff42009-09-21 16:56:56 +00005004 // Add the names of overloadable operators.
5005#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
5006 if (std::strcmp(Spelling, "?")) \
Douglas Gregor78a21012010-01-14 16:01:26 +00005007 Results.AddResult(Result(Spelling));
Douglas Gregor3545ff42009-09-21 16:56:56 +00005008#include "clang/Basic/OperatorKinds.def"
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005009
Douglas Gregor3545ff42009-09-21 16:56:56 +00005010 // Add any type names visible from the current scope
Douglas Gregor6ae4c522010-01-14 03:21:49 +00005011 Results.allowNestedNameSpecifiers();
Douglas Gregora6e2edc2010-01-14 03:27:13 +00005012 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00005013 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00005014 CodeCompleter->includeGlobals(),
5015 CodeCompleter->loadExternal());
5016
Douglas Gregor3545ff42009-09-21 16:56:56 +00005017 // Add any type specifiers
David Blaikiebbafb8a2012-03-11 07:00:24 +00005018 AddTypeSpecifierResults(getLangOpts(), Results);
Douglas Gregor64b12b52009-09-22 23:31:26 +00005019 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005020
5021 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5022 Results.data(), Results.size());
Douglas Gregorc811ede2009-09-18 20:05:18 +00005023}
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00005024
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00005025void Sema::CodeCompleteConstructorInitializer(
5026 Decl *ConstructorD,
5027 ArrayRef <CXXCtorInitializer *> Initializers) {
Benjamin Kramera4f8df02015-07-09 15:31:10 +00005028 if (!ConstructorD)
5029 return;
5030
5031 AdjustDeclIfTemplate(ConstructorD);
5032
5033 CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(ConstructorD);
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005034 if (!Constructor)
5035 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005036
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005037 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005038 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00005039 CodeCompletionContext::CCC_PotentiallyQualifiedName);
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005040 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005041
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005042 // Fill in any already-initialized fields or base classes.
5043 llvm::SmallPtrSet<FieldDecl *, 4> InitializedFields;
5044 llvm::SmallPtrSet<CanQualType, 4> InitializedBases;
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00005045 for (unsigned I = 0, E = Initializers.size(); I != E; ++I) {
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005046 if (Initializers[I]->isBaseInitializer())
5047 InitializedBases.insert(
5048 Context.getCanonicalType(QualType(Initializers[I]->getBaseClass(), 0)));
5049 else
Francois Pichetd583da02010-12-04 09:14:42 +00005050 InitializedFields.insert(cast<FieldDecl>(
5051 Initializers[I]->getAnyMember()));
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005052 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005053
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005054 // Add completions for base classes.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005055 CodeCompletionBuilder Builder(Results.getAllocator(),
5056 Results.getCodeCompletionTUInfo());
Benjamin Kramera4f8df02015-07-09 15:31:10 +00005057 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00005058 bool SawLastInitializer = Initializers.empty();
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005059 CXXRecordDecl *ClassDecl = Constructor->getParent();
Aaron Ballman574705e2014-03-13 15:41:46 +00005060 for (const auto &Base : ClassDecl->bases()) {
David Blaikie82e95a32014-11-19 07:49:47 +00005061 if (!InitializedBases.insert(Context.getCanonicalType(Base.getType()))
5062 .second) {
Douglas Gregor99129ef2010-08-29 19:27:27 +00005063 SawLastInitializer
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005064 = !Initializers.empty() &&
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00005065 Initializers.back()->isBaseInitializer() &&
Aaron Ballman574705e2014-03-13 15:41:46 +00005066 Context.hasSameUnqualifiedType(Base.getType(),
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00005067 QualType(Initializers.back()->getBaseClass(), 0));
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005068 continue;
Douglas Gregor99129ef2010-08-29 19:27:27 +00005069 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005070
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005071 Builder.AddTypedTextChunk(
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005072 Results.getAllocator().CopyString(
Aaron Ballman574705e2014-03-13 15:41:46 +00005073 Base.getType().getAsString(Policy)));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005074 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5075 Builder.AddPlaceholderChunk("args");
5076 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005077 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor99129ef2010-08-29 19:27:27 +00005078 SawLastInitializer? CCP_NextInitializer
5079 : CCP_MemberDeclaration));
5080 SawLastInitializer = false;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005081 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005082
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005083 // Add completions for virtual base classes.
Aaron Ballman445a9392014-03-13 16:15:17 +00005084 for (const auto &Base : ClassDecl->vbases()) {
David Blaikie82e95a32014-11-19 07:49:47 +00005085 if (!InitializedBases.insert(Context.getCanonicalType(Base.getType()))
5086 .second) {
Douglas Gregor99129ef2010-08-29 19:27:27 +00005087 SawLastInitializer
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005088 = !Initializers.empty() &&
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00005089 Initializers.back()->isBaseInitializer() &&
Aaron Ballman445a9392014-03-13 16:15:17 +00005090 Context.hasSameUnqualifiedType(Base.getType(),
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00005091 QualType(Initializers.back()->getBaseClass(), 0));
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005092 continue;
Douglas Gregor99129ef2010-08-29 19:27:27 +00005093 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005094
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005095 Builder.AddTypedTextChunk(
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005096 Builder.getAllocator().CopyString(
Aaron Ballman445a9392014-03-13 16:15:17 +00005097 Base.getType().getAsString(Policy)));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005098 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5099 Builder.AddPlaceholderChunk("args");
5100 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005101 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor99129ef2010-08-29 19:27:27 +00005102 SawLastInitializer? CCP_NextInitializer
5103 : CCP_MemberDeclaration));
5104 SawLastInitializer = false;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005105 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005106
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005107 // Add completions for members.
Aaron Ballmane8a8bae2014-03-08 20:12:42 +00005108 for (auto *Field : ClassDecl->fields()) {
David Blaikie82e95a32014-11-19 07:49:47 +00005109 if (!InitializedFields.insert(cast<FieldDecl>(Field->getCanonicalDecl()))
5110 .second) {
Douglas Gregor99129ef2010-08-29 19:27:27 +00005111 SawLastInitializer
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005112 = !Initializers.empty() &&
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00005113 Initializers.back()->isAnyMemberInitializer() &&
Aaron Ballmane8a8bae2014-03-08 20:12:42 +00005114 Initializers.back()->getAnyMember() == Field;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005115 continue;
Douglas Gregor99129ef2010-08-29 19:27:27 +00005116 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005117
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005118 if (!Field->getDeclName())
5119 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005120
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005121 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005122 Field->getIdentifier()->getName()));
5123 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5124 Builder.AddPlaceholderChunk("args");
5125 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005126 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor99129ef2010-08-29 19:27:27 +00005127 SawLastInitializer? CCP_NextInitializer
Douglas Gregorf3af3112010-09-09 21:42:20 +00005128 : CCP_MemberDeclaration,
Douglas Gregor78254c82012-03-27 23:34:16 +00005129 CXCursor_MemberRef,
5130 CXAvailability_Available,
Aaron Ballmane8a8bae2014-03-08 20:12:42 +00005131 Field));
Douglas Gregor99129ef2010-08-29 19:27:27 +00005132 SawLastInitializer = false;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005133 }
5134 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005135
Douglas Gregor0ac41382010-09-23 23:01:17 +00005136 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005137 Results.data(), Results.size());
5138}
5139
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00005140/// Determine whether this scope denotes a namespace.
Douglas Gregord8c61782012-02-15 15:34:24 +00005141static bool isNamespaceScope(Scope *S) {
Ted Kremenekc37877d2013-10-08 17:08:03 +00005142 DeclContext *DC = S->getEntity();
Douglas Gregord8c61782012-02-15 15:34:24 +00005143 if (!DC)
5144 return false;
5145
5146 return DC->isFileContext();
5147}
5148
5149void Sema::CodeCompleteLambdaIntroducer(Scope *S, LambdaIntroducer &Intro,
5150 bool AfterAmpersand) {
5151 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005152 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregord8c61782012-02-15 15:34:24 +00005153 CodeCompletionContext::CCC_Other);
5154 Results.EnterNewScope();
5155
5156 // Note what has already been captured.
5157 llvm::SmallPtrSet<IdentifierInfo *, 4> Known;
5158 bool IncludedThis = false;
Benjamin Kramerf3ca26982014-05-10 16:31:55 +00005159 for (const auto &C : Intro.Captures) {
5160 if (C.Kind == LCK_This) {
Douglas Gregord8c61782012-02-15 15:34:24 +00005161 IncludedThis = true;
5162 continue;
5163 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005164
Benjamin Kramerf3ca26982014-05-10 16:31:55 +00005165 Known.insert(C.Id);
Douglas Gregord8c61782012-02-15 15:34:24 +00005166 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005167
Douglas Gregord8c61782012-02-15 15:34:24 +00005168 // Look for other capturable variables.
5169 for (; S && !isNamespaceScope(S); S = S->getParent()) {
Aaron Ballman35c54952014-03-17 16:55:25 +00005170 for (const auto *D : S->decls()) {
5171 const auto *Var = dyn_cast<VarDecl>(D);
Douglas Gregord8c61782012-02-15 15:34:24 +00005172 if (!Var ||
5173 !Var->hasLocalStorage() ||
5174 Var->hasAttr<BlocksAttr>())
5175 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005176
David Blaikie82e95a32014-11-19 07:49:47 +00005177 if (Known.insert(Var->getIdentifier()).second)
Douglas Gregor0a0e2b32013-01-31 04:52:16 +00005178 Results.AddResult(CodeCompletionResult(Var, CCP_LocalDeclaration),
Craig Topperc3ec1492014-05-26 06:22:03 +00005179 CurContext, nullptr, false);
Douglas Gregord8c61782012-02-15 15:34:24 +00005180 }
5181 }
5182
5183 // Add 'this', if it would be valid.
5184 if (!IncludedThis && !AfterAmpersand && Intro.Default != LCD_ByCopy)
5185 addThisCompletion(*this, Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005186
Douglas Gregord8c61782012-02-15 15:34:24 +00005187 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005188
Douglas Gregord8c61782012-02-15 15:34:24 +00005189 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5190 Results.data(), Results.size());
5191}
5192
James Dennett596e4752012-06-14 03:11:41 +00005193/// Macro that optionally prepends an "@" to the string literal passed in via
5194/// Keyword, depending on whether NeedAt is true or false.
5195#define OBJC_AT_KEYWORD_NAME(NeedAt,Keyword) ((NeedAt)? "@" Keyword : Keyword)
5196
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005197static void AddObjCImplementationResults(const LangOptions &LangOpts,
Douglas Gregorf1934162010-01-13 21:24:21 +00005198 ResultBuilder &Results,
5199 bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005200 typedef CodeCompletionResult Result;
Douglas Gregorf1934162010-01-13 21:24:21 +00005201 // Since we have an implementation, we can end it.
James Dennett596e4752012-06-14 03:11:41 +00005202 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"end")));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005203
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005204 CodeCompletionBuilder Builder(Results.getAllocator(),
5205 Results.getCodeCompletionTUInfo());
Douglas Gregorf1934162010-01-13 21:24:21 +00005206 if (LangOpts.ObjC2) {
5207 // @dynamic
James Dennett596e4752012-06-14 03:11:41 +00005208 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"dynamic"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005209 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5210 Builder.AddPlaceholderChunk("property");
5211 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005212
Douglas Gregorf1934162010-01-13 21:24:21 +00005213 // @synthesize
James Dennett596e4752012-06-14 03:11:41 +00005214 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"synthesize"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005215 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5216 Builder.AddPlaceholderChunk("property");
5217 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005218 }
Douglas Gregorf1934162010-01-13 21:24:21 +00005219}
5220
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005221static void AddObjCInterfaceResults(const LangOptions &LangOpts,
Douglas Gregorf1934162010-01-13 21:24:21 +00005222 ResultBuilder &Results,
5223 bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005224 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005225
Douglas Gregorf1934162010-01-13 21:24:21 +00005226 // Since we have an interface or protocol, we can end it.
James Dennett596e4752012-06-14 03:11:41 +00005227 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"end")));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005228
Douglas Gregorf1934162010-01-13 21:24:21 +00005229 if (LangOpts.ObjC2) {
5230 // @property
James Dennett596e4752012-06-14 03:11:41 +00005231 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"property")));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005232
Douglas Gregorf1934162010-01-13 21:24:21 +00005233 // @required
James Dennett596e4752012-06-14 03:11:41 +00005234 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"required")));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005235
Douglas Gregorf1934162010-01-13 21:24:21 +00005236 // @optional
James Dennett596e4752012-06-14 03:11:41 +00005237 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"optional")));
Douglas Gregorf1934162010-01-13 21:24:21 +00005238 }
5239}
5240
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005241static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005242 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005243 CodeCompletionBuilder Builder(Results.getAllocator(),
5244 Results.getCodeCompletionTUInfo());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005245
Douglas Gregorf1934162010-01-13 21:24:21 +00005246 // @class name ;
James Dennett596e4752012-06-14 03:11:41 +00005247 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"class"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005248 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5249 Builder.AddPlaceholderChunk("name");
5250 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005251
Douglas Gregorf4c33342010-05-28 00:22:41 +00005252 if (Results.includeCodePatterns()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005253 // @interface name
5254 // FIXME: Could introduce the whole pattern, including superclasses and
Douglas Gregorf4c33342010-05-28 00:22:41 +00005255 // such.
James Dennett596e4752012-06-14 03:11:41 +00005256 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"interface"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005257 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5258 Builder.AddPlaceholderChunk("class");
5259 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005260
Douglas Gregorf4c33342010-05-28 00:22:41 +00005261 // @protocol name
James Dennett596e4752012-06-14 03:11:41 +00005262 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"protocol"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005263 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5264 Builder.AddPlaceholderChunk("protocol");
5265 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005266
Douglas Gregorf4c33342010-05-28 00:22:41 +00005267 // @implementation name
James Dennett596e4752012-06-14 03:11:41 +00005268 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"implementation"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005269 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5270 Builder.AddPlaceholderChunk("class");
5271 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00005272 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005273
Douglas Gregorf1934162010-01-13 21:24:21 +00005274 // @compatibility_alias name
James Dennett596e4752012-06-14 03:11:41 +00005275 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"compatibility_alias"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005276 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5277 Builder.AddPlaceholderChunk("alias");
5278 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5279 Builder.AddPlaceholderChunk("class");
5280 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor61e36812013-03-07 23:26:24 +00005281
5282 if (Results.getSema().getLangOpts().Modules) {
5283 // @import name
5284 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "import"));
5285 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5286 Builder.AddPlaceholderChunk("module");
5287 Results.AddResult(Result(Builder.TakeString()));
5288 }
Douglas Gregorf1934162010-01-13 21:24:21 +00005289}
5290
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005291void Sema::CodeCompleteObjCAtDirective(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005292 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005293 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005294 CodeCompletionContext::CCC_Other);
Douglas Gregorf48706c2009-12-07 09:27:33 +00005295 Results.EnterNewScope();
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005296 if (isa<ObjCImplDecl>(CurContext))
David Blaikiebbafb8a2012-03-11 07:00:24 +00005297 AddObjCImplementationResults(getLangOpts(), Results, false);
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005298 else if (CurContext->isObjCContainer())
David Blaikiebbafb8a2012-03-11 07:00:24 +00005299 AddObjCInterfaceResults(getLangOpts(), Results, false);
Douglas Gregorf1934162010-01-13 21:24:21 +00005300 else
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005301 AddObjCTopLevelResults(Results, false);
Douglas Gregorf48706c2009-12-07 09:27:33 +00005302 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005303 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5304 Results.data(), Results.size());
Douglas Gregorf48706c2009-12-07 09:27:33 +00005305}
5306
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005307static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005308 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005309 CodeCompletionBuilder Builder(Results.getAllocator(),
5310 Results.getCodeCompletionTUInfo());
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005311
5312 // @encode ( type-name )
Douglas Gregore5c79d52011-10-18 21:20:17 +00005313 const char *EncodeType = "char[]";
David Blaikiebbafb8a2012-03-11 07:00:24 +00005314 if (Results.getSema().getLangOpts().CPlusPlus ||
5315 Results.getSema().getLangOpts().ConstStrings)
Jordan Rose9da05852012-06-15 18:19:56 +00005316 EncodeType = "const char[]";
Douglas Gregore5c79d52011-10-18 21:20:17 +00005317 Builder.AddResultTypeChunk(EncodeType);
James Dennett596e4752012-06-14 03:11:41 +00005318 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"encode"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005319 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5320 Builder.AddPlaceholderChunk("type-name");
5321 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5322 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005323
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005324 // @protocol ( protocol-name )
Douglas Gregore5c79d52011-10-18 21:20:17 +00005325 Builder.AddResultTypeChunk("Protocol *");
James Dennett596e4752012-06-14 03:11:41 +00005326 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"protocol"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005327 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5328 Builder.AddPlaceholderChunk("protocol-name");
5329 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5330 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005331
5332 // @selector ( selector )
Douglas Gregore5c79d52011-10-18 21:20:17 +00005333 Builder.AddResultTypeChunk("SEL");
James Dennett596e4752012-06-14 03:11:41 +00005334 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"selector"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005335 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5336 Builder.AddPlaceholderChunk("selector");
5337 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5338 Results.AddResult(Result(Builder.TakeString()));
Jordan Rose9da05852012-06-15 18:19:56 +00005339
5340 // @"string"
5341 Builder.AddResultTypeChunk("NSString *");
5342 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"\""));
5343 Builder.AddPlaceholderChunk("string");
5344 Builder.AddTextChunk("\"");
5345 Results.AddResult(Result(Builder.TakeString()));
5346
Douglas Gregor951de302012-07-17 23:24:47 +00005347 // @[objects, ...]
Jordan Rose9da05852012-06-15 18:19:56 +00005348 Builder.AddResultTypeChunk("NSArray *");
James Dennett596e4752012-06-14 03:11:41 +00005349 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"["));
Ted Kremeneke65b0862012-03-06 20:05:56 +00005350 Builder.AddPlaceholderChunk("objects, ...");
Ted Kremeneke65b0862012-03-06 20:05:56 +00005351 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
5352 Results.AddResult(Result(Builder.TakeString()));
5353
Douglas Gregor951de302012-07-17 23:24:47 +00005354 // @{key : object, ...}
Jordan Rose9da05852012-06-15 18:19:56 +00005355 Builder.AddResultTypeChunk("NSDictionary *");
James Dennett596e4752012-06-14 03:11:41 +00005356 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"{"));
Ted Kremeneke65b0862012-03-06 20:05:56 +00005357 Builder.AddPlaceholderChunk("key");
Ted Kremeneke65b0862012-03-06 20:05:56 +00005358 Builder.AddChunk(CodeCompletionString::CK_Colon);
5359 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5360 Builder.AddPlaceholderChunk("object, ...");
Ted Kremeneke65b0862012-03-06 20:05:56 +00005361 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5362 Results.AddResult(Result(Builder.TakeString()));
Jordan Rose9da05852012-06-15 18:19:56 +00005363
Douglas Gregor951de302012-07-17 23:24:47 +00005364 // @(expression)
Jordan Rose9da05852012-06-15 18:19:56 +00005365 Builder.AddResultTypeChunk("id");
5366 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "("));
Jordan Rose9da05852012-06-15 18:19:56 +00005367 Builder.AddPlaceholderChunk("expression");
Jordan Rose9da05852012-06-15 18:19:56 +00005368 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5369 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005370}
5371
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005372static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005373 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005374 CodeCompletionBuilder Builder(Results.getAllocator(),
5375 Results.getCodeCompletionTUInfo());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005376
Douglas Gregorf4c33342010-05-28 00:22:41 +00005377 if (Results.includeCodePatterns()) {
5378 // @try { statements } @catch ( declaration ) { statements } @finally
5379 // { statements }
James Dennett596e4752012-06-14 03:11:41 +00005380 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"try"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005381 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5382 Builder.AddPlaceholderChunk("statements");
5383 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5384 Builder.AddTextChunk("@catch");
5385 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5386 Builder.AddPlaceholderChunk("parameter");
5387 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5388 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5389 Builder.AddPlaceholderChunk("statements");
5390 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5391 Builder.AddTextChunk("@finally");
5392 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5393 Builder.AddPlaceholderChunk("statements");
5394 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5395 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00005396 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005397
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005398 // @throw
James Dennett596e4752012-06-14 03:11:41 +00005399 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"throw"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005400 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5401 Builder.AddPlaceholderChunk("expression");
5402 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005403
Douglas Gregorf4c33342010-05-28 00:22:41 +00005404 if (Results.includeCodePatterns()) {
5405 // @synchronized ( expression ) { statements }
James Dennett596e4752012-06-14 03:11:41 +00005406 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"synchronized"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005407 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5408 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5409 Builder.AddPlaceholderChunk("expression");
5410 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5411 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5412 Builder.AddPlaceholderChunk("statements");
5413 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5414 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00005415 }
Douglas Gregorf1934162010-01-13 21:24:21 +00005416}
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005417
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005418static void AddObjCVisibilityResults(const LangOptions &LangOpts,
Douglas Gregor48d46252010-01-13 21:54:15 +00005419 ResultBuilder &Results,
5420 bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005421 typedef CodeCompletionResult Result;
James Dennett596e4752012-06-14 03:11:41 +00005422 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"private")));
5423 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"protected")));
5424 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"public")));
Douglas Gregor48d46252010-01-13 21:54:15 +00005425 if (LangOpts.ObjC2)
James Dennett596e4752012-06-14 03:11:41 +00005426 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"package")));
Douglas Gregor48d46252010-01-13 21:54:15 +00005427}
5428
5429void Sema::CodeCompleteObjCAtVisibility(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005430 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005431 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005432 CodeCompletionContext::CCC_Other);
Douglas Gregor48d46252010-01-13 21:54:15 +00005433 Results.EnterNewScope();
David Blaikiebbafb8a2012-03-11 07:00:24 +00005434 AddObjCVisibilityResults(getLangOpts(), Results, false);
Douglas Gregor48d46252010-01-13 21:54:15 +00005435 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005436 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5437 Results.data(), Results.size());
Douglas Gregor48d46252010-01-13 21:54:15 +00005438}
5439
5440void Sema::CodeCompleteObjCAtStatement(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005441 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005442 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005443 CodeCompletionContext::CCC_Other);
Douglas Gregorf1934162010-01-13 21:24:21 +00005444 Results.EnterNewScope();
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005445 AddObjCStatementResults(Results, false);
5446 AddObjCExpressionResults(Results, false);
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005447 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005448 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5449 Results.data(), Results.size());
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005450}
5451
5452void Sema::CodeCompleteObjCAtExpression(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005453 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005454 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005455 CodeCompletionContext::CCC_Other);
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005456 Results.EnterNewScope();
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005457 AddObjCExpressionResults(Results, false);
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005458 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005459 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5460 Results.data(), Results.size());
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005461}
5462
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00005463/// Determine whether the addition of the given flag to an Objective-C
Douglas Gregore6078da2009-11-19 00:14:45 +00005464/// property's attributes will cause a conflict.
Bill Wendling44426052012-12-20 19:22:21 +00005465static bool ObjCPropertyFlagConflicts(unsigned Attributes, unsigned NewFlag) {
Douglas Gregore6078da2009-11-19 00:14:45 +00005466 // Check if we've already added this flag.
Bill Wendling44426052012-12-20 19:22:21 +00005467 if (Attributes & NewFlag)
Douglas Gregore6078da2009-11-19 00:14:45 +00005468 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005469
Bill Wendling44426052012-12-20 19:22:21 +00005470 Attributes |= NewFlag;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005471
Douglas Gregore6078da2009-11-19 00:14:45 +00005472 // Check for collisions with "readonly".
Bill Wendling44426052012-12-20 19:22:21 +00005473 if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) &&
5474 (Attributes & ObjCDeclSpec::DQ_PR_readwrite))
Douglas Gregore6078da2009-11-19 00:14:45 +00005475 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005476
Jordan Rose53cb2f32012-08-20 20:01:13 +00005477 // Check for more than one of { assign, copy, retain, strong, weak }.
Bill Wendling44426052012-12-20 19:22:21 +00005478 unsigned AssignCopyRetMask = Attributes & (ObjCDeclSpec::DQ_PR_assign |
John McCall31168b02011-06-15 23:02:42 +00005479 ObjCDeclSpec::DQ_PR_unsafe_unretained |
Douglas Gregore6078da2009-11-19 00:14:45 +00005480 ObjCDeclSpec::DQ_PR_copy |
Jordan Rose53cb2f32012-08-20 20:01:13 +00005481 ObjCDeclSpec::DQ_PR_retain |
5482 ObjCDeclSpec::DQ_PR_strong |
5483 ObjCDeclSpec::DQ_PR_weak);
Douglas Gregore6078da2009-11-19 00:14:45 +00005484 if (AssignCopyRetMask &&
5485 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_assign &&
John McCall31168b02011-06-15 23:02:42 +00005486 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_unsafe_unretained &&
Douglas Gregore6078da2009-11-19 00:14:45 +00005487 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_copy &&
John McCall31168b02011-06-15 23:02:42 +00005488 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_retain &&
Jordan Rose53cb2f32012-08-20 20:01:13 +00005489 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_strong &&
5490 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_weak)
Douglas Gregore6078da2009-11-19 00:14:45 +00005491 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005492
Douglas Gregore6078da2009-11-19 00:14:45 +00005493 return false;
5494}
5495
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005496void Sema::CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS) {
Steve Naroff936354c2009-10-08 21:55:05 +00005497 if (!CodeCompleter)
5498 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005499
Bill Wendling44426052012-12-20 19:22:21 +00005500 unsigned Attributes = ODS.getPropertyAttributes();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005501
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005502 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005503 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005504 CodeCompletionContext::CCC_Other);
Steve Naroff936354c2009-10-08 21:55:05 +00005505 Results.EnterNewScope();
Bill Wendling44426052012-12-20 19:22:21 +00005506 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readonly))
John McCall276321a2010-08-25 06:19:51 +00005507 Results.AddResult(CodeCompletionResult("readonly"));
Bill Wendling44426052012-12-20 19:22:21 +00005508 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_assign))
John McCall276321a2010-08-25 06:19:51 +00005509 Results.AddResult(CodeCompletionResult("assign"));
Bill Wendling44426052012-12-20 19:22:21 +00005510 if (!ObjCPropertyFlagConflicts(Attributes,
John McCall31168b02011-06-15 23:02:42 +00005511 ObjCDeclSpec::DQ_PR_unsafe_unretained))
5512 Results.AddResult(CodeCompletionResult("unsafe_unretained"));
Bill Wendling44426052012-12-20 19:22:21 +00005513 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readwrite))
John McCall276321a2010-08-25 06:19:51 +00005514 Results.AddResult(CodeCompletionResult("readwrite"));
Bill Wendling44426052012-12-20 19:22:21 +00005515 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_retain))
John McCall276321a2010-08-25 06:19:51 +00005516 Results.AddResult(CodeCompletionResult("retain"));
Bill Wendling44426052012-12-20 19:22:21 +00005517 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_strong))
John McCall31168b02011-06-15 23:02:42 +00005518 Results.AddResult(CodeCompletionResult("strong"));
Bill Wendling44426052012-12-20 19:22:21 +00005519 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_copy))
John McCall276321a2010-08-25 06:19:51 +00005520 Results.AddResult(CodeCompletionResult("copy"));
Bill Wendling44426052012-12-20 19:22:21 +00005521 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_nonatomic))
John McCall276321a2010-08-25 06:19:51 +00005522 Results.AddResult(CodeCompletionResult("nonatomic"));
Bill Wendling44426052012-12-20 19:22:21 +00005523 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_atomic))
Fariborz Jahanian1c2d29e2011-06-11 17:14:27 +00005524 Results.AddResult(CodeCompletionResult("atomic"));
Jordan Rose53cb2f32012-08-20 20:01:13 +00005525
5526 // Only suggest "weak" if we're compiling for ARC-with-weak-references or GC.
John McCall460ce582015-10-22 18:38:17 +00005527 if (getLangOpts().ObjCWeak || getLangOpts().getGC() != LangOptions::NonGC)
Bill Wendling44426052012-12-20 19:22:21 +00005528 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_weak))
Jordan Rose53cb2f32012-08-20 20:01:13 +00005529 Results.AddResult(CodeCompletionResult("weak"));
5530
Bill Wendling44426052012-12-20 19:22:21 +00005531 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_setter)) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005532 CodeCompletionBuilder Setter(Results.getAllocator(),
5533 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005534 Setter.AddTypedTextChunk("setter");
Argyrios Kyrtzidis7bbb8812014-02-20 07:55:15 +00005535 Setter.AddTextChunk("=");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005536 Setter.AddPlaceholderChunk("method");
5537 Results.AddResult(CodeCompletionResult(Setter.TakeString()));
Douglas Gregor45f83ee2009-11-19 00:01:57 +00005538 }
Bill Wendling44426052012-12-20 19:22:21 +00005539 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_getter)) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005540 CodeCompletionBuilder Getter(Results.getAllocator(),
5541 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005542 Getter.AddTypedTextChunk("getter");
Argyrios Kyrtzidis7bbb8812014-02-20 07:55:15 +00005543 Getter.AddTextChunk("=");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005544 Getter.AddPlaceholderChunk("method");
5545 Results.AddResult(CodeCompletionResult(Getter.TakeString()));
Douglas Gregor45f83ee2009-11-19 00:01:57 +00005546 }
Douglas Gregor86b42682015-06-19 18:27:52 +00005547 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_nullability)) {
5548 Results.AddResult(CodeCompletionResult("nonnull"));
5549 Results.AddResult(CodeCompletionResult("nullable"));
5550 Results.AddResult(CodeCompletionResult("null_unspecified"));
5551 Results.AddResult(CodeCompletionResult("null_resettable"));
5552 }
Steve Naroff936354c2009-10-08 21:55:05 +00005553 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005554 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5555 Results.data(), Results.size());
Steve Naroff936354c2009-10-08 21:55:05 +00005556}
Steve Naroffeae65032009-11-07 02:08:14 +00005557
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00005558/// Describes the kind of Objective-C method that we want to find
Douglas Gregorc8537c52009-11-19 07:41:15 +00005559/// via code completion.
5560enum ObjCMethodKind {
Dmitri Gribenko4280e5c2012-06-08 23:13:42 +00005561 MK_Any, ///< Any kind of method, provided it means other specified criteria.
5562 MK_ZeroArgSelector, ///< Zero-argument (unary) selector.
5563 MK_OneArgSelector ///< One-argument selector.
Douglas Gregorc8537c52009-11-19 07:41:15 +00005564};
5565
Douglas Gregor67c692c2010-08-26 15:07:07 +00005566static bool isAcceptableObjCSelector(Selector Sel,
5567 ObjCMethodKind WantKind,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005568 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005569 bool AllowSameLength = true) {
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005570 unsigned NumSelIdents = SelIdents.size();
Douglas Gregor67c692c2010-08-26 15:07:07 +00005571 if (NumSelIdents > Sel.getNumArgs())
5572 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005573
Douglas Gregor67c692c2010-08-26 15:07:07 +00005574 switch (WantKind) {
5575 case MK_Any: break;
5576 case MK_ZeroArgSelector: return Sel.isUnarySelector();
5577 case MK_OneArgSelector: return Sel.getNumArgs() == 1;
5578 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005579
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005580 if (!AllowSameLength && NumSelIdents && NumSelIdents == Sel.getNumArgs())
5581 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005582
Douglas Gregor67c692c2010-08-26 15:07:07 +00005583 for (unsigned I = 0; I != NumSelIdents; ++I)
5584 if (SelIdents[I] != Sel.getIdentifierInfoForSlot(I))
5585 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005586
Douglas Gregor67c692c2010-08-26 15:07:07 +00005587 return true;
5588}
5589
Douglas Gregorc8537c52009-11-19 07:41:15 +00005590static bool isAcceptableObjCMethod(ObjCMethodDecl *Method,
5591 ObjCMethodKind WantKind,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005592 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005593 bool AllowSameLength = true) {
Douglas Gregor67c692c2010-08-26 15:07:07 +00005594 return isAcceptableObjCSelector(Method->getSelector(), WantKind, SelIdents,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005595 AllowSameLength);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005596}
Douglas Gregor1154e272010-09-16 16:06:31 +00005597
5598namespace {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005599 /// A set of selectors, which is used to avoid introducing multiple
Douglas Gregor1154e272010-09-16 16:06:31 +00005600 /// completions with the same selector into the result set.
5601 typedef llvm::SmallPtrSet<Selector, 16> VisitedSelectorSet;
5602}
5603
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005604/// Add all of the Objective-C methods in the given Objective-C
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005605/// container to the set of results.
5606///
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005607/// The container will be a class, protocol, category, or implementation of
5608/// any of the above. This mether will recurse to include methods from
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005609/// the superclasses of classes along with their categories, protocols, and
5610/// implementations.
5611///
5612/// \param Container the container in which we'll look to find methods.
5613///
James Dennett596e4752012-06-14 03:11:41 +00005614/// \param WantInstanceMethods Whether to add instance methods (only); if
5615/// false, this routine will add factory methods (only).
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005616///
5617/// \param CurContext the context in which we're performing the lookup that
5618/// finds methods.
5619///
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005620/// \param AllowSameLength Whether we allow a method to be added to the list
5621/// when it has the same number of parameters as we have selector identifiers.
5622///
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005623/// \param Results the structure into which we'll add results.
Alex Lorenz638dbc32017-01-24 14:15:08 +00005624static void AddObjCMethods(ObjCContainerDecl *Container,
5625 bool WantInstanceMethods, ObjCMethodKind WantKind,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005626 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005627 DeclContext *CurContext,
Alex Lorenz638dbc32017-01-24 14:15:08 +00005628 VisitedSelectorSet &Selectors, bool AllowSameLength,
5629 ResultBuilder &Results, bool InOriginalClass = true,
5630 bool IsRootClass = false) {
John McCall276321a2010-08-25 06:19:51 +00005631 typedef CodeCompletionResult Result;
Douglas Gregor9b4f3702012-06-12 13:44:08 +00005632 Container = getContainerDef(Container);
Douglas Gregor41778c32013-01-30 06:58:39 +00005633 ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container);
Alex Lorenz638dbc32017-01-24 14:15:08 +00005634 IsRootClass = IsRootClass || (IFace && !IFace->getSuperClass());
Aaron Ballmanaff18c02014-03-13 19:03:34 +00005635 for (auto *M : Container->methods()) {
Douglas Gregor41778c32013-01-30 06:58:39 +00005636 // The instance methods on the root class can be messaged via the
5637 // metaclass.
5638 if (M->isInstanceMethod() == WantInstanceMethods ||
Alex Lorenz638dbc32017-01-24 14:15:08 +00005639 (IsRootClass && !WantInstanceMethods)) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005640 // Check whether the selector identifiers we've been given are a
Douglas Gregor1b605f72009-11-19 01:08:35 +00005641 // subset of the identifiers for this particular method.
Aaron Ballmanaff18c02014-03-13 19:03:34 +00005642 if (!isAcceptableObjCMethod(M, WantKind, SelIdents, AllowSameLength))
Douglas Gregor1b605f72009-11-19 01:08:35 +00005643 continue;
Douglas Gregorc8537c52009-11-19 07:41:15 +00005644
David Blaikie82e95a32014-11-19 07:49:47 +00005645 if (!Selectors.insert(M->getSelector()).second)
Douglas Gregor1154e272010-09-16 16:06:31 +00005646 continue;
Craig Topperc3ec1492014-05-26 06:22:03 +00005647
5648 Result R = Result(M, Results.getBasePriority(M), nullptr);
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005649 R.StartParameter = SelIdents.size();
Douglas Gregorc8537c52009-11-19 07:41:15 +00005650 R.AllParametersAreInformative = (WantKind != MK_Any);
Douglas Gregor416b5752010-08-25 01:08:01 +00005651 if (!InOriginalClass)
5652 R.Priority += CCD_InBaseClass;
Douglas Gregor1b605f72009-11-19 01:08:35 +00005653 Results.MaybeAddResult(R, CurContext);
5654 }
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005655 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005656
Douglas Gregorf37c9492010-09-16 15:34:59 +00005657 // Visit the protocols of protocols.
5658 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Douglas Gregore6e48b12012-01-01 19:29:29 +00005659 if (Protocol->hasDefinition()) {
5660 const ObjCList<ObjCProtocolDecl> &Protocols
5661 = Protocol->getReferencedProtocols();
5662 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005663 E = Protocols.end();
Douglas Gregore6e48b12012-01-01 19:29:29 +00005664 I != E; ++I)
Alex Lorenz638dbc32017-01-24 14:15:08 +00005665 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, CurContext,
5666 Selectors, AllowSameLength, Results, false, IsRootClass);
Douglas Gregore6e48b12012-01-01 19:29:29 +00005667 }
Douglas Gregorf37c9492010-09-16 15:34:59 +00005668 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005669
Douglas Gregorc0ac7d62011-12-15 05:27:12 +00005670 if (!IFace || !IFace->hasDefinition())
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005671 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005672
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005673 // Add methods in protocols.
Aaron Ballmana49c5062014-03-13 20:29:09 +00005674 for (auto *I : IFace->protocols())
Alex Lorenz638dbc32017-01-24 14:15:08 +00005675 AddObjCMethods(I, WantInstanceMethods, WantKind, SelIdents, CurContext,
5676 Selectors, AllowSameLength, Results, false, IsRootClass);
5677
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005678 // Add methods in categories.
Aaron Ballman15063e12014-03-13 21:35:02 +00005679 for (auto *CatDecl : IFace->known_categories()) {
Douglas Gregor048fbfa2013-01-16 23:00:23 +00005680 AddObjCMethods(CatDecl, WantInstanceMethods, WantKind, SelIdents,
Alex Lorenz638dbc32017-01-24 14:15:08 +00005681 CurContext, Selectors, AllowSameLength, Results,
5682 InOriginalClass, IsRootClass);
5683
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005684 // Add a categories protocol methods.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005685 const ObjCList<ObjCProtocolDecl> &Protocols
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005686 = CatDecl->getReferencedProtocols();
5687 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
5688 E = Protocols.end();
5689 I != E; ++I)
Alex Lorenz638dbc32017-01-24 14:15:08 +00005690 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, CurContext,
5691 Selectors, AllowSameLength, Results, false, IsRootClass);
5692
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005693 // Add methods in category implementations.
5694 if (ObjCCategoryImplDecl *Impl = CatDecl->getImplementation())
Alex Lorenz638dbc32017-01-24 14:15:08 +00005695 AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents, CurContext,
5696 Selectors, AllowSameLength, Results, InOriginalClass,
5697 IsRootClass);
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005698 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005699
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005700 // Add methods in superclass.
Alex Lorenz638dbc32017-01-24 14:15:08 +00005701 // Avoid passing in IsRootClass since root classes won't have super classes.
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005702 if (IFace->getSuperClass())
Alex Lorenz638dbc32017-01-24 14:15:08 +00005703 AddObjCMethods(IFace->getSuperClass(), WantInstanceMethods, WantKind,
5704 SelIdents, CurContext, Selectors, AllowSameLength, Results,
5705 /*IsRootClass=*/false);
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005706
5707 // Add methods in our implementation, if any.
5708 if (ObjCImplementationDecl *Impl = IFace->getImplementation())
Alex Lorenz638dbc32017-01-24 14:15:08 +00005709 AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents, CurContext,
5710 Selectors, AllowSameLength, Results, InOriginalClass,
5711 IsRootClass);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005712}
5713
5714
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005715void Sema::CodeCompleteObjCPropertyGetter(Scope *S) {
Douglas Gregorc8537c52009-11-19 07:41:15 +00005716 // Try to find the interface where getters might live.
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005717 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005718 if (!Class) {
5719 if (ObjCCategoryDecl *Category
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005720 = dyn_cast_or_null<ObjCCategoryDecl>(CurContext))
Douglas Gregorc8537c52009-11-19 07:41:15 +00005721 Class = Category->getClassInterface();
5722
5723 if (!Class)
5724 return;
5725 }
5726
5727 // Find all of the potential getters.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005728 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005729 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005730 CodeCompletionContext::CCC_Other);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005731 Results.EnterNewScope();
5732
Douglas Gregor1154e272010-09-16 16:06:31 +00005733 VisitedSelectorSet Selectors;
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005734 AddObjCMethods(Class, true, MK_ZeroArgSelector, None, CurContext, Selectors,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005735 /*AllowSameLength=*/true, Results);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005736 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005737 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5738 Results.data(), Results.size());
Douglas Gregorc8537c52009-11-19 07:41:15 +00005739}
5740
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005741void Sema::CodeCompleteObjCPropertySetter(Scope *S) {
Douglas Gregorc8537c52009-11-19 07:41:15 +00005742 // Try to find the interface where setters might live.
5743 ObjCInterfaceDecl *Class
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005744 = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005745 if (!Class) {
5746 if (ObjCCategoryDecl *Category
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005747 = dyn_cast_or_null<ObjCCategoryDecl>(CurContext))
Douglas Gregorc8537c52009-11-19 07:41:15 +00005748 Class = Category->getClassInterface();
5749
5750 if (!Class)
5751 return;
5752 }
5753
5754 // Find all of the potential getters.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005755 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005756 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005757 CodeCompletionContext::CCC_Other);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005758 Results.EnterNewScope();
5759
Douglas Gregor1154e272010-09-16 16:06:31 +00005760 VisitedSelectorSet Selectors;
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005761 AddObjCMethods(Class, true, MK_OneArgSelector, None, CurContext,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005762 Selectors, /*AllowSameLength=*/true, Results);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005763
5764 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005765 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5766 Results.data(), Results.size());
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005767}
5768
Douglas Gregorf34a6f02011-02-15 22:19:42 +00005769void Sema::CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS,
5770 bool IsParameter) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005771 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005772 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005773 CodeCompletionContext::CCC_Type);
Douglas Gregor99fa2642010-08-24 01:06:58 +00005774 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005775
Douglas Gregor99fa2642010-08-24 01:06:58 +00005776 // Add context-sensitive, Objective-C parameter-passing keywords.
5777 bool AddedInOut = false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005778 if ((DS.getObjCDeclQualifier() &
Douglas Gregor99fa2642010-08-24 01:06:58 +00005779 (ObjCDeclSpec::DQ_In | ObjCDeclSpec::DQ_Inout)) == 0) {
5780 Results.AddResult("in");
5781 Results.AddResult("inout");
5782 AddedInOut = true;
5783 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005784 if ((DS.getObjCDeclQualifier() &
Douglas Gregor99fa2642010-08-24 01:06:58 +00005785 (ObjCDeclSpec::DQ_Out | ObjCDeclSpec::DQ_Inout)) == 0) {
5786 Results.AddResult("out");
5787 if (!AddedInOut)
5788 Results.AddResult("inout");
5789 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005790 if ((DS.getObjCDeclQualifier() &
Douglas Gregor99fa2642010-08-24 01:06:58 +00005791 (ObjCDeclSpec::DQ_Bycopy | ObjCDeclSpec::DQ_Byref |
5792 ObjCDeclSpec::DQ_Oneway)) == 0) {
5793 Results.AddResult("bycopy");
5794 Results.AddResult("byref");
5795 Results.AddResult("oneway");
5796 }
Douglas Gregor86b42682015-06-19 18:27:52 +00005797 if ((DS.getObjCDeclQualifier() & ObjCDeclSpec::DQ_CSNullability) == 0) {
5798 Results.AddResult("nonnull");
5799 Results.AddResult("nullable");
5800 Results.AddResult("null_unspecified");
5801 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005802
5803 // If we're completing the return type of an Objective-C method and the
Douglas Gregorf34a6f02011-02-15 22:19:42 +00005804 // identifier IBAction refers to a macro, provide a completion item for
5805 // an action, e.g.,
5806 // IBAction)<#selector#>:(id)sender
5807 if (DS.getObjCDeclQualifier() == 0 && !IsParameter &&
Richard Smith20e883e2015-04-29 23:20:19 +00005808 PP.isMacroDefined("IBAction")) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005809 CodeCompletionBuilder Builder(Results.getAllocator(),
5810 Results.getCodeCompletionTUInfo(),
5811 CCP_CodePattern, CXAvailability_Available);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00005812 Builder.AddTypedTextChunk("IBAction");
Benjamin Kramerdb534a42012-03-26 16:57:36 +00005813 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00005814 Builder.AddPlaceholderChunk("selector");
Benjamin Kramerdb534a42012-03-26 16:57:36 +00005815 Builder.AddChunk(CodeCompletionString::CK_Colon);
5816 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00005817 Builder.AddTextChunk("id");
Benjamin Kramerdb534a42012-03-26 16:57:36 +00005818 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00005819 Builder.AddTextChunk("sender");
5820 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
5821 }
Douglas Gregored1f5972013-01-30 07:11:43 +00005822
5823 // If we're completing the return type, provide 'instancetype'.
5824 if (!IsParameter) {
5825 Results.AddResult(CodeCompletionResult("instancetype"));
5826 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005827
Douglas Gregor99fa2642010-08-24 01:06:58 +00005828 // Add various builtin type names and specifiers.
5829 AddOrdinaryNameResults(PCC_Type, S, *this, Results);
5830 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005831
Douglas Gregor99fa2642010-08-24 01:06:58 +00005832 // Add the various type names
5833 Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
5834 CodeCompletionDeclConsumer Consumer(Results, CurContext);
5835 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00005836 CodeCompleter->includeGlobals(),
5837 CodeCompleter->loadExternal());
5838
Douglas Gregor99fa2642010-08-24 01:06:58 +00005839 if (CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00005840 AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false);
Douglas Gregor99fa2642010-08-24 01:06:58 +00005841
Eric Liuf5ba09f2018-07-04 10:01:18 +00005842 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor99fa2642010-08-24 01:06:58 +00005843 Results.data(), Results.size());
5844}
5845
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00005846/// When we have an expression with type "id", we may assume
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005847/// that it has some more-specific class type based on knowledge of
5848/// common uses of Objective-C. This routine returns that class type,
5849/// or NULL if no better result could be determined.
5850static ObjCInterfaceDecl *GetAssumedMessageSendExprType(Expr *E) {
Douglas Gregored0b69d2010-09-15 16:23:04 +00005851 ObjCMessageExpr *Msg = dyn_cast_or_null<ObjCMessageExpr>(E);
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005852 if (!Msg)
Craig Topperc3ec1492014-05-26 06:22:03 +00005853 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005854
5855 Selector Sel = Msg->getSelector();
5856 if (Sel.isNull())
Craig Topperc3ec1492014-05-26 06:22:03 +00005857 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005858
5859 IdentifierInfo *Id = Sel.getIdentifierInfoForSlot(0);
5860 if (!Id)
Craig Topperc3ec1492014-05-26 06:22:03 +00005861 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005862
5863 ObjCMethodDecl *Method = Msg->getMethodDecl();
5864 if (!Method)
Craig Topperc3ec1492014-05-26 06:22:03 +00005865 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005866
5867 // Determine the class that we're sending the message to.
Craig Topperc3ec1492014-05-26 06:22:03 +00005868 ObjCInterfaceDecl *IFace = nullptr;
Douglas Gregor9a129192010-04-21 00:45:42 +00005869 switch (Msg->getReceiverKind()) {
5870 case ObjCMessageExpr::Class:
John McCall8b07ec22010-05-15 11:32:37 +00005871 if (const ObjCObjectType *ObjType
5872 = Msg->getClassReceiver()->getAs<ObjCObjectType>())
5873 IFace = ObjType->getInterface();
Douglas Gregor9a129192010-04-21 00:45:42 +00005874 break;
5875
5876 case ObjCMessageExpr::Instance: {
5877 QualType T = Msg->getInstanceReceiver()->getType();
5878 if (const ObjCObjectPointerType *Ptr = T->getAs<ObjCObjectPointerType>())
5879 IFace = Ptr->getInterfaceDecl();
5880 break;
5881 }
5882
5883 case ObjCMessageExpr::SuperInstance:
5884 case ObjCMessageExpr::SuperClass:
5885 break;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005886 }
5887
5888 if (!IFace)
Craig Topperc3ec1492014-05-26 06:22:03 +00005889 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005890
5891 ObjCInterfaceDecl *Super = IFace->getSuperClass();
5892 if (Method->isInstanceMethod())
5893 return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
5894 .Case("retain", IFace)
John McCall31168b02011-06-15 23:02:42 +00005895 .Case("strong", IFace)
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005896 .Case("autorelease", IFace)
5897 .Case("copy", IFace)
5898 .Case("copyWithZone", IFace)
5899 .Case("mutableCopy", IFace)
5900 .Case("mutableCopyWithZone", IFace)
5901 .Case("awakeFromCoder", IFace)
5902 .Case("replacementObjectFromCoder", IFace)
5903 .Case("class", IFace)
5904 .Case("classForCoder", IFace)
5905 .Case("superclass", Super)
Craig Topperc3ec1492014-05-26 06:22:03 +00005906 .Default(nullptr);
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005907
5908 return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
5909 .Case("new", IFace)
5910 .Case("alloc", IFace)
5911 .Case("allocWithZone", IFace)
5912 .Case("class", IFace)
5913 .Case("superclass", Super)
Craig Topperc3ec1492014-05-26 06:22:03 +00005914 .Default(nullptr);
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005915}
5916
Douglas Gregor6fc04132010-08-27 15:10:57 +00005917// Add a special completion for a message send to "super", which fills in the
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005918// most likely case of forwarding all of our arguments to the superclass
Douglas Gregor6fc04132010-08-27 15:10:57 +00005919// function.
5920///
5921/// \param S The semantic analysis object.
5922///
Dmitri Gribenkoadba9be2012-08-23 17:58:28 +00005923/// \param NeedSuperKeyword Whether we need to prefix this completion with
Douglas Gregor6fc04132010-08-27 15:10:57 +00005924/// the "super" keyword. Otherwise, we just need to provide the arguments.
5925///
5926/// \param SelIdents The identifiers in the selector that have already been
5927/// provided as arguments for a send to "super".
5928///
Douglas Gregor6fc04132010-08-27 15:10:57 +00005929/// \param Results The set of results to augment.
5930///
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005931/// \returns the Objective-C method declaration that would be invoked by
Douglas Gregor6fc04132010-08-27 15:10:57 +00005932/// this "super" completion. If NULL, no completion was added.
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005933static ObjCMethodDecl *AddSuperSendCompletion(
5934 Sema &S, bool NeedSuperKeyword,
5935 ArrayRef<IdentifierInfo *> SelIdents,
5936 ResultBuilder &Results) {
Douglas Gregor6fc04132010-08-27 15:10:57 +00005937 ObjCMethodDecl *CurMethod = S.getCurMethodDecl();
5938 if (!CurMethod)
Craig Topperc3ec1492014-05-26 06:22:03 +00005939 return nullptr;
5940
Douglas Gregor6fc04132010-08-27 15:10:57 +00005941 ObjCInterfaceDecl *Class = CurMethod->getClassInterface();
5942 if (!Class)
Craig Topperc3ec1492014-05-26 06:22:03 +00005943 return nullptr;
5944
Douglas Gregor6fc04132010-08-27 15:10:57 +00005945 // Try to find a superclass method with the same selector.
Craig Topperc3ec1492014-05-26 06:22:03 +00005946 ObjCMethodDecl *SuperMethod = nullptr;
Douglas Gregorb5f1e462011-02-16 00:51:18 +00005947 while ((Class = Class->getSuperClass()) && !SuperMethod) {
5948 // Check in the class
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005949 SuperMethod = Class->getMethod(CurMethod->getSelector(),
Douglas Gregor6fc04132010-08-27 15:10:57 +00005950 CurMethod->isInstanceMethod());
5951
Douglas Gregorb5f1e462011-02-16 00:51:18 +00005952 // Check in categories or class extensions.
5953 if (!SuperMethod) {
Aaron Ballman15063e12014-03-13 21:35:02 +00005954 for (const auto *Cat : Class->known_categories()) {
Douglas Gregor048fbfa2013-01-16 23:00:23 +00005955 if ((SuperMethod = Cat->getMethod(CurMethod->getSelector(),
Douglas Gregorb5f1e462011-02-16 00:51:18 +00005956 CurMethod->isInstanceMethod())))
5957 break;
Douglas Gregor048fbfa2013-01-16 23:00:23 +00005958 }
Douglas Gregorb5f1e462011-02-16 00:51:18 +00005959 }
5960 }
5961
Douglas Gregor6fc04132010-08-27 15:10:57 +00005962 if (!SuperMethod)
Craig Topperc3ec1492014-05-26 06:22:03 +00005963 return nullptr;
5964
Douglas Gregor6fc04132010-08-27 15:10:57 +00005965 // Check whether the superclass method has the same signature.
5966 if (CurMethod->param_size() != SuperMethod->param_size() ||
5967 CurMethod->isVariadic() != SuperMethod->isVariadic())
Craig Topperc3ec1492014-05-26 06:22:03 +00005968 return nullptr;
5969
Douglas Gregor6fc04132010-08-27 15:10:57 +00005970 for (ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin(),
5971 CurPEnd = CurMethod->param_end(),
5972 SuperP = SuperMethod->param_begin();
5973 CurP != CurPEnd; ++CurP, ++SuperP) {
5974 // Make sure the parameter types are compatible.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005975 if (!S.Context.hasSameUnqualifiedType((*CurP)->getType(),
Douglas Gregor6fc04132010-08-27 15:10:57 +00005976 (*SuperP)->getType()))
Craig Topperc3ec1492014-05-26 06:22:03 +00005977 return nullptr;
5978
Douglas Gregor6fc04132010-08-27 15:10:57 +00005979 // Make sure we have a parameter name to forward!
5980 if (!(*CurP)->getIdentifier())
Craig Topperc3ec1492014-05-26 06:22:03 +00005981 return nullptr;
Douglas Gregor6fc04132010-08-27 15:10:57 +00005982 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005983
Douglas Gregor6fc04132010-08-27 15:10:57 +00005984 // We have a superclass method. Now, form the send-to-super completion.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005985 CodeCompletionBuilder Builder(Results.getAllocator(),
5986 Results.getCodeCompletionTUInfo());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005987
Douglas Gregor6fc04132010-08-27 15:10:57 +00005988 // Give this completion a return type.
Douglas Gregorc3425b12015-07-07 06:20:19 +00005989 AddResultTypeChunk(S.Context, getCompletionPrintingPolicy(S), SuperMethod,
5990 Results.getCompletionContext().getBaseType(),
Douglas Gregor75acd922011-09-27 23:30:47 +00005991 Builder);
Douglas Gregor6fc04132010-08-27 15:10:57 +00005992
5993 // If we need the "super" keyword, add it (plus some spacing).
5994 if (NeedSuperKeyword) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005995 Builder.AddTypedTextChunk("super");
5996 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregor6fc04132010-08-27 15:10:57 +00005997 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005998
Douglas Gregor6fc04132010-08-27 15:10:57 +00005999 Selector Sel = CurMethod->getSelector();
6000 if (Sel.isUnarySelector()) {
6001 if (NeedSuperKeyword)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00006002 Builder.AddTextChunk(Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00006003 Sel.getNameForSlot(0)));
Douglas Gregor6fc04132010-08-27 15:10:57 +00006004 else
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00006005 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00006006 Sel.getNameForSlot(0)));
Douglas Gregor6fc04132010-08-27 15:10:57 +00006007 } else {
6008 ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin();
6009 for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I, ++CurP) {
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006010 if (I > SelIdents.size())
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006011 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006012
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006013 if (I < SelIdents.size())
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006014 Builder.AddInformativeChunk(
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00006015 Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00006016 Sel.getNameForSlot(I) + ":"));
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006017 else if (NeedSuperKeyword || I > SelIdents.size()) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006018 Builder.AddTextChunk(
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00006019 Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00006020 Sel.getNameForSlot(I) + ":"));
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00006021 Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006022 (*CurP)->getIdentifier()->getName()));
Douglas Gregor6fc04132010-08-27 15:10:57 +00006023 } else {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006024 Builder.AddTypedTextChunk(
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00006025 Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00006026 Sel.getNameForSlot(I) + ":"));
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00006027 Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006028 (*CurP)->getIdentifier()->getName()));
Douglas Gregor6fc04132010-08-27 15:10:57 +00006029 }
6030 }
6031 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006032
Douglas Gregor78254c82012-03-27 23:34:16 +00006033 Results.AddResult(CodeCompletionResult(Builder.TakeString(), SuperMethod,
6034 CCP_SuperCompletion));
Douglas Gregor6fc04132010-08-27 15:10:57 +00006035 return SuperMethod;
6036}
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006037
Douglas Gregora817a192010-05-27 23:06:34 +00006038void Sema::CodeCompleteObjCMessageReceiver(Scope *S) {
John McCall276321a2010-08-25 06:19:51 +00006039 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006040 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006041 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006042 CodeCompletionContext::CCC_ObjCMessageReceiver,
Richard Smith2bf7fdb2013-01-02 11:42:31 +00006043 getLangOpts().CPlusPlus11
Douglas Gregord8c61782012-02-15 15:34:24 +00006044 ? &ResultBuilder::IsObjCMessageReceiverOrLambdaCapture
6045 : &ResultBuilder::IsObjCMessageReceiver);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006046
Douglas Gregora817a192010-05-27 23:06:34 +00006047 CodeCompletionDeclConsumer Consumer(Results, CurContext);
6048 Results.EnterNewScope();
Douglas Gregor39982192010-08-15 06:18:01 +00006049 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00006050 CodeCompleter->includeGlobals(),
6051 CodeCompleter->loadExternal());
6052
Douglas Gregora817a192010-05-27 23:06:34 +00006053 // If we are in an Objective-C method inside a class that has a superclass,
6054 // add "super" as an option.
6055 if (ObjCMethodDecl *Method = getCurMethodDecl())
6056 if (ObjCInterfaceDecl *Iface = Method->getClassInterface())
Douglas Gregor6fc04132010-08-27 15:10:57 +00006057 if (Iface->getSuperClass()) {
Douglas Gregora817a192010-05-27 23:06:34 +00006058 Results.AddResult(Result("super"));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006059
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006060 AddSuperSendCompletion(*this, /*NeedSuperKeyword=*/true, None, Results);
Douglas Gregor6fc04132010-08-27 15:10:57 +00006061 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006062
Richard Smith2bf7fdb2013-01-02 11:42:31 +00006063 if (getLangOpts().CPlusPlus11)
Douglas Gregord8c61782012-02-15 15:34:24 +00006064 addThisCompletion(*this, Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006065
Douglas Gregora817a192010-05-27 23:06:34 +00006066 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006067
Douglas Gregora817a192010-05-27 23:06:34 +00006068 if (CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00006069 AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false);
Douglas Gregor50832e02010-09-20 22:39:41 +00006070 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006071 Results.data(), Results.size());
Douglas Gregora817a192010-05-27 23:06:34 +00006072}
6073
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006074void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006075 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006076 bool AtArgumentExpression) {
Craig Topperc3ec1492014-05-26 06:22:03 +00006077 ObjCInterfaceDecl *CDecl = nullptr;
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006078 if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
6079 // Figure out which interface we're in.
6080 CDecl = CurMethod->getClassInterface();
6081 if (!CDecl)
6082 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006083
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006084 // Find the superclass of this class.
6085 CDecl = CDecl->getSuperClass();
6086 if (!CDecl)
6087 return;
6088
6089 if (CurMethod->isInstanceMethod()) {
6090 // We are inside an instance method, which means that the message
6091 // send [super ...] is actually calling an instance method on the
Douglas Gregor392a84b2010-10-13 21:24:53 +00006092 // current object.
Craig Topperc3ec1492014-05-26 06:22:03 +00006093 return CodeCompleteObjCInstanceMessage(S, nullptr, SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006094 AtArgumentExpression,
Douglas Gregor392a84b2010-10-13 21:24:53 +00006095 CDecl);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006096 }
6097
6098 // Fall through to send to the superclass in CDecl.
6099 } else {
6100 // "super" may be the name of a type or variable. Figure out which
6101 // it is.
Argyrios Kyrtzidis3e56dd42013-03-14 22:56:43 +00006102 IdentifierInfo *Super = getSuperIdentifier();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006103 NamedDecl *ND = LookupSingleName(S, Super, SuperLoc,
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006104 LookupOrdinaryName);
6105 if ((CDecl = dyn_cast_or_null<ObjCInterfaceDecl>(ND))) {
6106 // "super" names an interface. Use it.
6107 } else if (TypeDecl *TD = dyn_cast_or_null<TypeDecl>(ND)) {
John McCall8b07ec22010-05-15 11:32:37 +00006108 if (const ObjCObjectType *Iface
6109 = Context.getTypeDeclType(TD)->getAs<ObjCObjectType>())
6110 CDecl = Iface->getInterface();
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006111 } else if (ND && isa<UnresolvedUsingTypenameDecl>(ND)) {
6112 // "super" names an unresolved type; we can't be more specific.
6113 } else {
6114 // Assume that "super" names some kind of value and parse that way.
6115 CXXScopeSpec SS;
Abramo Bagnara7945c982012-01-27 09:46:47 +00006116 SourceLocation TemplateKWLoc;
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006117 UnqualifiedId id;
6118 id.setIdentifier(Super, SuperLoc);
Abramo Bagnara7945c982012-01-27 09:46:47 +00006119 ExprResult SuperExpr = ActOnIdExpression(S, SS, TemplateKWLoc, id,
6120 false, false);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006121 return CodeCompleteObjCInstanceMessage(S, (Expr *)SuperExpr.get(),
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006122 SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006123 AtArgumentExpression);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006124 }
6125
6126 // Fall through
6127 }
6128
John McCallba7bf592010-08-24 05:47:05 +00006129 ParsedType Receiver;
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006130 if (CDecl)
John McCallba7bf592010-08-24 05:47:05 +00006131 Receiver = ParsedType::make(Context.getObjCInterfaceType(CDecl));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006132 return CodeCompleteObjCClassMessage(S, Receiver, SelIdents,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006133 AtArgumentExpression,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006134 /*IsSuper=*/true);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006135}
6136
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006137/// Given a set of code-completion results for the argument of a message
Douglas Gregor74661272010-09-21 00:03:25 +00006138/// send, determine the preferred type (if any) for that argument expression.
6139static QualType getPreferredArgumentTypeForMessageSend(ResultBuilder &Results,
6140 unsigned NumSelIdents) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006141 typedef CodeCompletionResult Result;
Douglas Gregor74661272010-09-21 00:03:25 +00006142 ASTContext &Context = Results.getSema().Context;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006143
Douglas Gregor74661272010-09-21 00:03:25 +00006144 QualType PreferredType;
6145 unsigned BestPriority = CCP_Unlikely * 2;
6146 Result *ResultsData = Results.data();
6147 for (unsigned I = 0, N = Results.size(); I != N; ++I) {
6148 Result &R = ResultsData[I];
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006149 if (R.Kind == Result::RK_Declaration &&
Douglas Gregor74661272010-09-21 00:03:25 +00006150 isa<ObjCMethodDecl>(R.Declaration)) {
6151 if (R.Priority <= BestPriority) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00006152 const ObjCMethodDecl *Method = cast<ObjCMethodDecl>(R.Declaration);
Douglas Gregor74661272010-09-21 00:03:25 +00006153 if (NumSelIdents <= Method->param_size()) {
Alp Toker03376dc2014-07-07 09:02:20 +00006154 QualType MyPreferredType = Method->parameters()[NumSelIdents - 1]
Douglas Gregor74661272010-09-21 00:03:25 +00006155 ->getType();
6156 if (R.Priority < BestPriority || PreferredType.isNull()) {
6157 BestPriority = R.Priority;
6158 PreferredType = MyPreferredType;
6159 } else if (!Context.hasSameUnqualifiedType(PreferredType,
6160 MyPreferredType)) {
6161 PreferredType = QualType();
6162 }
6163 }
6164 }
6165 }
6166 }
6167
6168 return PreferredType;
6169}
6170
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006171static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006172 ParsedType Receiver,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006173 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006174 bool AtArgumentExpression,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006175 bool IsSuper,
6176 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00006177 typedef CodeCompletionResult Result;
Craig Topperc3ec1492014-05-26 06:22:03 +00006178 ObjCInterfaceDecl *CDecl = nullptr;
6179
Douglas Gregor8ce33212009-11-17 17:59:40 +00006180 // If the given name refers to an interface type, retrieve the
6181 // corresponding declaration.
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006182 if (Receiver) {
Craig Topperc3ec1492014-05-26 06:22:03 +00006183 QualType T = SemaRef.GetTypeFromParser(Receiver, nullptr);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006184 if (!T.isNull())
John McCall8b07ec22010-05-15 11:32:37 +00006185 if (const ObjCObjectType *Interface = T->getAs<ObjCObjectType>())
6186 CDecl = Interface->getInterface();
Douglas Gregor8ce33212009-11-17 17:59:40 +00006187 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006188
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006189 // Add all of the factory methods in this Objective-C class, its protocols,
6190 // superclasses, categories, implementation, etc.
Steve Naroffeae65032009-11-07 02:08:14 +00006191 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006192
6193 // If this is a send-to-super, try to add the special "super" send
Douglas Gregor6fc04132010-08-27 15:10:57 +00006194 // completion.
6195 if (IsSuper) {
6196 if (ObjCMethodDecl *SuperMethod
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006197 = AddSuperSendCompletion(SemaRef, false, SelIdents, Results))
Douglas Gregor6fc04132010-08-27 15:10:57 +00006198 Results.Ignore(SuperMethod);
6199 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006200
Douglas Gregorc2cb2e22010-08-27 15:29:55 +00006201 // If we're inside an Objective-C method definition, prefer its selector to
6202 // others.
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006203 if (ObjCMethodDecl *CurMethod = SemaRef.getCurMethodDecl())
Douglas Gregorc2cb2e22010-08-27 15:29:55 +00006204 Results.setPreferredSelector(CurMethod->getSelector());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006205
Douglas Gregor1154e272010-09-16 16:06:31 +00006206 VisitedSelectorSet Selectors;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006207 if (CDecl)
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006208 AddObjCMethods(CDecl, false, MK_Any, SelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00006209 SemaRef.CurContext, Selectors, AtArgumentExpression,
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006210 Results);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006211 else {
Douglas Gregor6285f752010-04-06 16:40:00 +00006212 // We're messaging "id" as a type; provide all class/factory methods.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006213
Douglas Gregord720daf2010-04-06 17:30:22 +00006214 // If we have an external source, load the entire class method
Sebastian Redld44cd6a2010-08-18 23:57:06 +00006215 // pool from the AST file.
Axel Naumanndd433f02012-10-18 19:05:02 +00006216 if (SemaRef.getExternalSource()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006217 for (uint32_t I = 0,
Axel Naumanndd433f02012-10-18 19:05:02 +00006218 N = SemaRef.getExternalSource()->GetNumExternalSelectors();
John McCall75b960e2010-06-01 09:23:16 +00006219 I != N; ++I) {
Axel Naumanndd433f02012-10-18 19:05:02 +00006220 Selector Sel = SemaRef.getExternalSource()->GetExternalSelector(I);
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006221 if (Sel.isNull() || SemaRef.MethodPool.count(Sel))
Douglas Gregord720daf2010-04-06 17:30:22 +00006222 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006223
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006224 SemaRef.ReadMethodPool(Sel);
Douglas Gregord720daf2010-04-06 17:30:22 +00006225 }
6226 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006227
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006228 for (Sema::GlobalMethodPool::iterator M = SemaRef.MethodPool.begin(),
6229 MEnd = SemaRef.MethodPool.end();
Sebastian Redl75d8a322010-08-02 23:18:59 +00006230 M != MEnd; ++M) {
6231 for (ObjCMethodList *MethList = &M->second.second;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006232 MethList && MethList->getMethod();
Argyrios Kyrtzidisd3da6e02013-04-17 00:08:58 +00006233 MethList = MethList->getNext()) {
Nico Weber2e0c8f72014-12-27 03:58:08 +00006234 if (!isAcceptableObjCMethod(MethList->getMethod(), MK_Any, SelIdents))
Douglas Gregor6285f752010-04-06 16:40:00 +00006235 continue;
Craig Topperc3ec1492014-05-26 06:22:03 +00006236
Nico Weber2e0c8f72014-12-27 03:58:08 +00006237 Result R(MethList->getMethod(),
6238 Results.getBasePriority(MethList->getMethod()), nullptr);
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006239 R.StartParameter = SelIdents.size();
Douglas Gregor6285f752010-04-06 16:40:00 +00006240 R.AllParametersAreInformative = false;
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006241 Results.MaybeAddResult(R, SemaRef.CurContext);
Douglas Gregor6285f752010-04-06 16:40:00 +00006242 }
6243 }
6244 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006245
6246 Results.ExitScope();
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006247}
Douglas Gregor6285f752010-04-06 16:40:00 +00006248
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006249void Sema::CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006250 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006251 bool AtArgumentExpression,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006252 bool IsSuper) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006253
Douglas Gregor63745d52011-07-21 01:05:26 +00006254 QualType T = this->GetTypeFromParser(Receiver);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006255
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006256 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006257 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor63745d52011-07-21 01:05:26 +00006258 CodeCompletionContext(CodeCompletionContext::CCC_ObjCClassMessage,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006259 T, SelIdents));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006260
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006261 AddClassMessageCompletions(*this, S, Receiver, SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006262 AtArgumentExpression, IsSuper, Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006263
6264 // If we're actually at the argument expression (rather than prior to the
Douglas Gregor74661272010-09-21 00:03:25 +00006265 // selector), we're actually performing code completion for an expression.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006266 // Determine whether we have a single, best method. If so, we can
Douglas Gregor74661272010-09-21 00:03:25 +00006267 // code-complete the expression using the corresponding parameter type as
6268 // our preferred type, improving completion results.
6269 if (AtArgumentExpression) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006270 QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006271 SelIdents.size());
Douglas Gregor74661272010-09-21 00:03:25 +00006272 if (PreferredType.isNull())
6273 CodeCompleteOrdinaryName(S, PCC_Expression);
6274 else
6275 CodeCompleteExpression(S, PreferredType);
6276 return;
6277 }
6278
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006279 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor63745d52011-07-21 01:05:26 +00006280 Results.getCompletionContext(),
Douglas Gregor6fc04132010-08-27 15:10:57 +00006281 Results.data(), Results.size());
Steve Naroffeae65032009-11-07 02:08:14 +00006282}
6283
Richard Trieu2bd04012011-09-09 02:00:50 +00006284void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006285 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006286 bool AtArgumentExpression,
Douglas Gregor392a84b2010-10-13 21:24:53 +00006287 ObjCInterfaceDecl *Super) {
John McCall276321a2010-08-25 06:19:51 +00006288 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006289
Steve Naroffeae65032009-11-07 02:08:14 +00006290 Expr *RecExpr = static_cast<Expr *>(Receiver);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006291
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006292 // If necessary, apply function/array conversion to the receiver.
6293 // C99 6.7.5.3p[7,8].
John Wiegley01296292011-04-08 18:41:53 +00006294 if (RecExpr) {
6295 ExprResult Conv = DefaultFunctionArrayLvalueConversion(RecExpr);
6296 if (Conv.isInvalid()) // conversion failed. bail.
6297 return;
Nikola Smiljanic01a75982014-05-29 10:55:11 +00006298 RecExpr = Conv.get();
John Wiegley01296292011-04-08 18:41:53 +00006299 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006300 QualType ReceiverType = RecExpr? RecExpr->getType()
Douglas Gregor392a84b2010-10-13 21:24:53 +00006301 : Super? Context.getObjCObjectPointerType(
6302 Context.getObjCInterfaceType(Super))
6303 : Context.getObjCIdType();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006304
Douglas Gregordc520b02010-11-08 21:12:30 +00006305 // If we're messaging an expression with type "id" or "Class", check
6306 // whether we know something special about the receiver that allows
6307 // us to assume a more-specific receiver type.
Anders Carlsson382ba412014-02-28 19:07:22 +00006308 if (ReceiverType->isObjCIdType() || ReceiverType->isObjCClassType()) {
Douglas Gregordc520b02010-11-08 21:12:30 +00006309 if (ObjCInterfaceDecl *IFace = GetAssumedMessageSendExprType(RecExpr)) {
6310 if (ReceiverType->isObjCClassType())
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006311 return CodeCompleteObjCClassMessage(S,
Douglas Gregordc520b02010-11-08 21:12:30 +00006312 ParsedType::make(Context.getObjCInterfaceType(IFace)),
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006313 SelIdents,
Douglas Gregordc520b02010-11-08 21:12:30 +00006314 AtArgumentExpression, Super);
6315
6316 ReceiverType = Context.getObjCObjectPointerType(
6317 Context.getObjCInterfaceType(IFace));
6318 }
Anders Carlsson382ba412014-02-28 19:07:22 +00006319 } else if (RecExpr && getLangOpts().CPlusPlus) {
6320 ExprResult Conv = PerformContextuallyConvertToObjCPointer(RecExpr);
6321 if (Conv.isUsable()) {
Nikola Smiljanic01a75982014-05-29 10:55:11 +00006322 RecExpr = Conv.get();
Anders Carlsson382ba412014-02-28 19:07:22 +00006323 ReceiverType = RecExpr->getType();
6324 }
6325 }
Douglas Gregordc520b02010-11-08 21:12:30 +00006326
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006327 // Build the set of methods we can see.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006328 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006329 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor63745d52011-07-21 01:05:26 +00006330 CodeCompletionContext(CodeCompletionContext::CCC_ObjCInstanceMessage,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006331 ReceiverType, SelIdents));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006332
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006333 Results.EnterNewScope();
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006334
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006335 // If this is a send-to-super, try to add the special "super" send
Douglas Gregor6fc04132010-08-27 15:10:57 +00006336 // completion.
Douglas Gregor392a84b2010-10-13 21:24:53 +00006337 if (Super) {
Douglas Gregor6fc04132010-08-27 15:10:57 +00006338 if (ObjCMethodDecl *SuperMethod
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006339 = AddSuperSendCompletion(*this, false, SelIdents, Results))
Douglas Gregor6fc04132010-08-27 15:10:57 +00006340 Results.Ignore(SuperMethod);
6341 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006342
Douglas Gregorc2cb2e22010-08-27 15:29:55 +00006343 // If we're inside an Objective-C method definition, prefer its selector to
6344 // others.
6345 if (ObjCMethodDecl *CurMethod = getCurMethodDecl())
6346 Results.setPreferredSelector(CurMethod->getSelector());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006347
Douglas Gregor1154e272010-09-16 16:06:31 +00006348 // Keep track of the selectors we've already added.
6349 VisitedSelectorSet Selectors;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006350
Douglas Gregora3329fa2009-11-18 00:06:18 +00006351 // Handle messages to Class. This really isn't a message to an instance
6352 // method, so we treat it the same way we would treat a message send to a
6353 // class method.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006354 if (ReceiverType->isObjCClassType() ||
Douglas Gregora3329fa2009-11-18 00:06:18 +00006355 ReceiverType->isObjCQualifiedClassType()) {
6356 if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
6357 if (ObjCInterfaceDecl *ClassDecl = CurMethod->getClassInterface())
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006358 AddObjCMethods(ClassDecl, false, MK_Any, SelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00006359 CurContext, Selectors, AtArgumentExpression, Results);
Douglas Gregora3329fa2009-11-18 00:06:18 +00006360 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006361 }
Douglas Gregora3329fa2009-11-18 00:06:18 +00006362 // Handle messages to a qualified ID ("id<foo>").
6363 else if (const ObjCObjectPointerType *QualID
6364 = ReceiverType->getAsObjCQualifiedIdType()) {
6365 // Search protocols for instance methods.
Aaron Ballman83731462014-03-17 16:14:00 +00006366 for (auto *I : QualID->quals())
6367 AddObjCMethods(I, true, MK_Any, SelIdents, CurContext,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00006368 Selectors, AtArgumentExpression, Results);
Douglas Gregora3329fa2009-11-18 00:06:18 +00006369 }
6370 // Handle messages to a pointer to interface type.
6371 else if (const ObjCObjectPointerType *IFacePtr
6372 = ReceiverType->getAsObjCInterfacePointerType()) {
6373 // Search the class, its superclasses, etc., for instance methods.
Douglas Gregorc8537c52009-11-19 07:41:15 +00006374 AddObjCMethods(IFacePtr->getInterfaceDecl(), true, MK_Any, SelIdents,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006375 CurContext, Selectors, AtArgumentExpression,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00006376 Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006377
Douglas Gregora3329fa2009-11-18 00:06:18 +00006378 // Search protocols for instance methods.
Aaron Ballman83731462014-03-17 16:14:00 +00006379 for (auto *I : IFacePtr->quals())
6380 AddObjCMethods(I, true, MK_Any, SelIdents, CurContext,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00006381 Selectors, AtArgumentExpression, Results);
Douglas Gregora3329fa2009-11-18 00:06:18 +00006382 }
Douglas Gregor6285f752010-04-06 16:40:00 +00006383 // Handle messages to "id".
6384 else if (ReceiverType->isObjCIdType()) {
Douglas Gregord720daf2010-04-06 17:30:22 +00006385 // We're messaging "id", so provide all instance methods we know
6386 // about as code-completion results.
6387
6388 // If we have an external source, load the entire class method
Sebastian Redld44cd6a2010-08-18 23:57:06 +00006389 // pool from the AST file.
Douglas Gregord720daf2010-04-06 17:30:22 +00006390 if (ExternalSource) {
John McCall75b960e2010-06-01 09:23:16 +00006391 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
6392 I != N; ++I) {
6393 Selector Sel = ExternalSource->GetExternalSelector(I);
Sebastian Redl75d8a322010-08-02 23:18:59 +00006394 if (Sel.isNull() || MethodPool.count(Sel))
Douglas Gregord720daf2010-04-06 17:30:22 +00006395 continue;
6396
Sebastian Redl75d8a322010-08-02 23:18:59 +00006397 ReadMethodPool(Sel);
Douglas Gregord720daf2010-04-06 17:30:22 +00006398 }
6399 }
6400
Sebastian Redl75d8a322010-08-02 23:18:59 +00006401 for (GlobalMethodPool::iterator M = MethodPool.begin(),
6402 MEnd = MethodPool.end();
6403 M != MEnd; ++M) {
6404 for (ObjCMethodList *MethList = &M->second.first;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006405 MethList && MethList->getMethod();
Argyrios Kyrtzidisd3da6e02013-04-17 00:08:58 +00006406 MethList = MethList->getNext()) {
Nico Weber2e0c8f72014-12-27 03:58:08 +00006407 if (!isAcceptableObjCMethod(MethList->getMethod(), MK_Any, SelIdents))
Douglas Gregor6285f752010-04-06 16:40:00 +00006408 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006409
Nico Weber2e0c8f72014-12-27 03:58:08 +00006410 if (!Selectors.insert(MethList->getMethod()->getSelector()).second)
Douglas Gregor1154e272010-09-16 16:06:31 +00006411 continue;
Craig Topperc3ec1492014-05-26 06:22:03 +00006412
Nico Weber2e0c8f72014-12-27 03:58:08 +00006413 Result R(MethList->getMethod(),
6414 Results.getBasePriority(MethList->getMethod()), nullptr);
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006415 R.StartParameter = SelIdents.size();
Douglas Gregor6285f752010-04-06 16:40:00 +00006416 R.AllParametersAreInformative = false;
6417 Results.MaybeAddResult(R, CurContext);
6418 }
6419 }
6420 }
Steve Naroffeae65032009-11-07 02:08:14 +00006421 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006422
6423
6424 // If we're actually at the argument expression (rather than prior to the
Douglas Gregor74661272010-09-21 00:03:25 +00006425 // selector), we're actually performing code completion for an expression.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006426 // Determine whether we have a single, best method. If so, we can
Douglas Gregor74661272010-09-21 00:03:25 +00006427 // code-complete the expression using the corresponding parameter type as
6428 // our preferred type, improving completion results.
6429 if (AtArgumentExpression) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006430 QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006431 SelIdents.size());
Douglas Gregor74661272010-09-21 00:03:25 +00006432 if (PreferredType.isNull())
6433 CodeCompleteOrdinaryName(S, PCC_Expression);
6434 else
6435 CodeCompleteExpression(S, PreferredType);
6436 return;
6437 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006438
6439 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor63745d52011-07-21 01:05:26 +00006440 Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006441 Results.data(),Results.size());
Steve Naroffeae65032009-11-07 02:08:14 +00006442}
Douglas Gregorbaf69612009-11-18 04:19:12 +00006443
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006444void Sema::CodeCompleteObjCForCollection(Scope *S,
Douglas Gregor68762e72010-08-23 21:17:50 +00006445 DeclGroupPtrTy IterationVar) {
6446 CodeCompleteExpressionData Data;
6447 Data.ObjCCollection = true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006448
Douglas Gregor68762e72010-08-23 21:17:50 +00006449 if (IterationVar.getAsOpaquePtr()) {
Serge Pavlov9ddb76e2013-08-27 13:15:56 +00006450 DeclGroupRef DG = IterationVar.get();
Douglas Gregor68762e72010-08-23 21:17:50 +00006451 for (DeclGroupRef::iterator I = DG.begin(), End = DG.end(); I != End; ++I) {
6452 if (*I)
6453 Data.IgnoreDecls.push_back(*I);
6454 }
6455 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006456
Douglas Gregor68762e72010-08-23 21:17:50 +00006457 CodeCompleteExpression(S, Data);
6458}
6459
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006460void Sema::CodeCompleteObjCSelector(Scope *S,
6461 ArrayRef<IdentifierInfo *> SelIdents) {
Douglas Gregor67c692c2010-08-26 15:07:07 +00006462 // If we have an external source, load the entire class method
6463 // pool from the AST file.
6464 if (ExternalSource) {
6465 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
6466 I != N; ++I) {
6467 Selector Sel = ExternalSource->GetExternalSelector(I);
6468 if (Sel.isNull() || MethodPool.count(Sel))
6469 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006470
Douglas Gregor67c692c2010-08-26 15:07:07 +00006471 ReadMethodPool(Sel);
6472 }
6473 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006474
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006475 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006476 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006477 CodeCompletionContext::CCC_SelectorName);
Douglas Gregor67c692c2010-08-26 15:07:07 +00006478 Results.EnterNewScope();
6479 for (GlobalMethodPool::iterator M = MethodPool.begin(),
6480 MEnd = MethodPool.end();
6481 M != MEnd; ++M) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006482
Douglas Gregor67c692c2010-08-26 15:07:07 +00006483 Selector Sel = M->first;
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006484 if (!isAcceptableObjCSelector(Sel, MK_Any, SelIdents))
Douglas Gregor67c692c2010-08-26 15:07:07 +00006485 continue;
6486
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006487 CodeCompletionBuilder Builder(Results.getAllocator(),
6488 Results.getCodeCompletionTUInfo());
Douglas Gregor67c692c2010-08-26 15:07:07 +00006489 if (Sel.isUnarySelector()) {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00006490 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00006491 Sel.getNameForSlot(0)));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006492 Results.AddResult(Builder.TakeString());
Douglas Gregor67c692c2010-08-26 15:07:07 +00006493 continue;
6494 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006495
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00006496 std::string Accumulator;
Douglas Gregor67c692c2010-08-26 15:07:07 +00006497 for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I) {
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006498 if (I == SelIdents.size()) {
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00006499 if (!Accumulator.empty()) {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00006500 Builder.AddInformativeChunk(Builder.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006501 Accumulator));
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00006502 Accumulator.clear();
6503 }
6504 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006505
Benjamin Kramer632500c2011-07-26 16:59:25 +00006506 Accumulator += Sel.getNameForSlot(I);
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00006507 Accumulator += ':';
Douglas Gregor67c692c2010-08-26 15:07:07 +00006508 }
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00006509 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString( Accumulator));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006510 Results.AddResult(Builder.TakeString());
Douglas Gregor67c692c2010-08-26 15:07:07 +00006511 }
6512 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00006513
6514 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor67c692c2010-08-26 15:07:07 +00006515 Results.data(), Results.size());
6516}
6517
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006518/// Add all of the protocol declarations that we find in the given
Douglas Gregorbaf69612009-11-18 04:19:12 +00006519/// (translation unit) context.
6520static void AddProtocolResults(DeclContext *Ctx, DeclContext *CurContext,
Douglas Gregor5b4671c2009-11-18 04:49:41 +00006521 bool OnlyForwardDeclarations,
Douglas Gregorbaf69612009-11-18 04:19:12 +00006522 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00006523 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006524
Aaron Ballman629afae2014-03-07 19:56:05 +00006525 for (const auto *D : Ctx->decls()) {
Douglas Gregorbaf69612009-11-18 04:19:12 +00006526 // Record any protocols we find.
Aaron Ballman629afae2014-03-07 19:56:05 +00006527 if (const auto *Proto = dyn_cast<ObjCProtocolDecl>(D))
Douglas Gregore6e48b12012-01-01 19:29:29 +00006528 if (!OnlyForwardDeclarations || !Proto->hasDefinition())
Craig Topperc3ec1492014-05-26 06:22:03 +00006529 Results.AddResult(Result(Proto, Results.getBasePriority(Proto),nullptr),
6530 CurContext, nullptr, false);
Douglas Gregorbaf69612009-11-18 04:19:12 +00006531 }
6532}
6533
Craig Topper883dd332015-12-24 23:58:11 +00006534void Sema::CodeCompleteObjCProtocolReferences(
6535 ArrayRef<IdentifierLocPair> Protocols) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006536 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006537 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006538 CodeCompletionContext::CCC_ObjCProtocolName);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006539
Chandler Carruthede11632016-11-04 06:06:50 +00006540 if (CodeCompleter->includeGlobals()) {
Douglas Gregora3b23b02010-12-09 21:44:02 +00006541 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006542
Douglas Gregora3b23b02010-12-09 21:44:02 +00006543 // Tell the result set to ignore all of the protocols we have
6544 // already seen.
6545 // FIXME: This doesn't work when caching code-completion results.
Craig Topper883dd332015-12-24 23:58:11 +00006546 for (const IdentifierLocPair &Pair : Protocols)
6547 if (ObjCProtocolDecl *Protocol = LookupProtocol(Pair.first,
6548 Pair.second))
Douglas Gregora3b23b02010-12-09 21:44:02 +00006549 Results.Ignore(Protocol);
Douglas Gregorbaf69612009-11-18 04:19:12 +00006550
Douglas Gregora3b23b02010-12-09 21:44:02 +00006551 // Add all protocols.
6552 AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, false,
6553 Results);
Douglas Gregor5b4671c2009-11-18 04:49:41 +00006554
Douglas Gregora3b23b02010-12-09 21:44:02 +00006555 Results.ExitScope();
6556 }
Eric Liuf5ba09f2018-07-04 10:01:18 +00006557
6558 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6559 Results.data(), Results.size());
Douglas Gregor5b4671c2009-11-18 04:49:41 +00006560}
6561
6562void Sema::CodeCompleteObjCProtocolDecl(Scope *) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006563 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006564 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006565 CodeCompletionContext::CCC_ObjCProtocolName);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006566
Chandler Carruthede11632016-11-04 06:06:50 +00006567 if (CodeCompleter->includeGlobals()) {
Douglas Gregora3b23b02010-12-09 21:44:02 +00006568 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006569
Douglas Gregora3b23b02010-12-09 21:44:02 +00006570 // Add all protocols.
6571 AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, true,
6572 Results);
Douglas Gregorbaf69612009-11-18 04:19:12 +00006573
Douglas Gregora3b23b02010-12-09 21:44:02 +00006574 Results.ExitScope();
6575 }
Eric Liuf5ba09f2018-07-04 10:01:18 +00006576
6577 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6578 Results.data(), Results.size());
Douglas Gregorbaf69612009-11-18 04:19:12 +00006579}
Douglas Gregor49c22a72009-11-18 16:26:39 +00006580
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006581/// Add all of the Objective-C interface declarations that we find in
Douglas Gregor49c22a72009-11-18 16:26:39 +00006582/// the given (translation unit) context.
6583static void AddInterfaceResults(DeclContext *Ctx, DeclContext *CurContext,
6584 bool OnlyForwardDeclarations,
6585 bool OnlyUnimplemented,
6586 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00006587 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006588
Aaron Ballman629afae2014-03-07 19:56:05 +00006589 for (const auto *D : Ctx->decls()) {
Douglas Gregor1c283312010-08-11 12:19:30 +00006590 // Record any interfaces we find.
Aaron Ballman629afae2014-03-07 19:56:05 +00006591 if (const auto *Class = dyn_cast<ObjCInterfaceDecl>(D))
Douglas Gregordc9166c2011-12-15 20:29:51 +00006592 if ((!OnlyForwardDeclarations || !Class->hasDefinition()) &&
Douglas Gregor1c283312010-08-11 12:19:30 +00006593 (!OnlyUnimplemented || !Class->getImplementation()))
Craig Topperc3ec1492014-05-26 06:22:03 +00006594 Results.AddResult(Result(Class, Results.getBasePriority(Class),nullptr),
6595 CurContext, nullptr, false);
Douglas Gregor49c22a72009-11-18 16:26:39 +00006596 }
6597}
6598
Eric Liuf5ba09f2018-07-04 10:01:18 +00006599void Sema::CodeCompleteObjCInterfaceDecl(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006600 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006601 CodeCompleter->getCodeCompletionTUInfo(),
Eric Liuf5ba09f2018-07-04 10:01:18 +00006602 CodeCompletionContext::CCC_ObjCInterfaceName);
Douglas Gregor49c22a72009-11-18 16:26:39 +00006603 Results.EnterNewScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00006604
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006605 if (CodeCompleter->includeGlobals()) {
6606 // Add all classes.
6607 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
6608 false, Results);
6609 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006610
Douglas Gregor49c22a72009-11-18 16:26:39 +00006611 Results.ExitScope();
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006612
Eric Liuf5ba09f2018-07-04 10:01:18 +00006613 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6614 Results.data(), Results.size());
Douglas Gregor49c22a72009-11-18 16:26:39 +00006615}
6616
Douglas Gregorb2ccf012010-04-15 22:33:43 +00006617void Sema::CodeCompleteObjCSuperclass(Scope *S, IdentifierInfo *ClassName,
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006618 SourceLocation ClassNameLoc) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006619 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006620 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006621 CodeCompletionContext::CCC_ObjCInterfaceName);
Douglas Gregor49c22a72009-11-18 16:26:39 +00006622 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006623
Douglas Gregor49c22a72009-11-18 16:26:39 +00006624 // Make sure that we ignore the class we're currently defining.
6625 NamedDecl *CurClass
Douglas Gregorb2ccf012010-04-15 22:33:43 +00006626 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006627 if (CurClass && isa<ObjCInterfaceDecl>(CurClass))
Douglas Gregor49c22a72009-11-18 16:26:39 +00006628 Results.Ignore(CurClass);
6629
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006630 if (CodeCompleter->includeGlobals()) {
6631 // Add all classes.
6632 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
6633 false, Results);
6634 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006635
Douglas Gregor49c22a72009-11-18 16:26:39 +00006636 Results.ExitScope();
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006637
Eric Liuf5ba09f2018-07-04 10:01:18 +00006638 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6639 Results.data(), Results.size());
Douglas Gregor49c22a72009-11-18 16:26:39 +00006640}
6641
Eric Liuf5ba09f2018-07-04 10:01:18 +00006642void Sema::CodeCompleteObjCImplementationDecl(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006643 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006644 CodeCompleter->getCodeCompletionTUInfo(),
Eric Liuf5ba09f2018-07-04 10:01:18 +00006645 CodeCompletionContext::CCC_ObjCImplementation);
Douglas Gregor49c22a72009-11-18 16:26:39 +00006646 Results.EnterNewScope();
6647
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006648 if (CodeCompleter->includeGlobals()) {
6649 // Add all unimplemented classes.
6650 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
6651 true, Results);
6652 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006653
Douglas Gregor49c22a72009-11-18 16:26:39 +00006654 Results.ExitScope();
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006655
Eric Liuf5ba09f2018-07-04 10:01:18 +00006656 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6657 Results.data(), Results.size());
Douglas Gregor49c22a72009-11-18 16:26:39 +00006658}
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006659
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006660void Sema::CodeCompleteObjCInterfaceCategory(Scope *S,
Douglas Gregorb2ccf012010-04-15 22:33:43 +00006661 IdentifierInfo *ClassName,
6662 SourceLocation ClassNameLoc) {
John McCall276321a2010-08-25 06:19:51 +00006663 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006664
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006665 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006666 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor21325842011-07-07 16:03:39 +00006667 CodeCompletionContext::CCC_ObjCCategoryName);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006668
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006669 // Ignore any categories we find that have already been implemented by this
6670 // interface.
6671 llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
6672 NamedDecl *CurClass
Douglas Gregorb2ccf012010-04-15 22:33:43 +00006673 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006674 if (ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass)){
Aaron Ballman3fe486a2014-03-13 21:23:55 +00006675 for (const auto *Cat : Class->visible_categories())
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006676 CategoryNames.insert(Cat->getIdentifier());
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006677 }
6678
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006679 // Add all of the categories we know about.
6680 Results.EnterNewScope();
6681 TranslationUnitDecl *TU = Context.getTranslationUnitDecl();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006682 for (const auto *D : TU->decls())
Aaron Ballman629afae2014-03-07 19:56:05 +00006683 if (const auto *Category = dyn_cast<ObjCCategoryDecl>(D))
David Blaikie82e95a32014-11-19 07:49:47 +00006684 if (CategoryNames.insert(Category->getIdentifier()).second)
Craig Topperc3ec1492014-05-26 06:22:03 +00006685 Results.AddResult(Result(Category, Results.getBasePriority(Category),
6686 nullptr),
6687 CurContext, nullptr, false);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006688 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00006689
6690 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6691 Results.data(), Results.size());
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006692}
6693
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006694void Sema::CodeCompleteObjCImplementationCategory(Scope *S,
Douglas Gregorb2ccf012010-04-15 22:33:43 +00006695 IdentifierInfo *ClassName,
6696 SourceLocation ClassNameLoc) {
John McCall276321a2010-08-25 06:19:51 +00006697 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006698
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006699 // Find the corresponding interface. If we couldn't find the interface, the
6700 // program itself is ill-formed. However, we'll try to be helpful still by
6701 // providing the list of all of the categories we know about.
6702 NamedDecl *CurClass
Douglas Gregorb2ccf012010-04-15 22:33:43 +00006703 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006704 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass);
6705 if (!Class)
Douglas Gregorb2ccf012010-04-15 22:33:43 +00006706 return CodeCompleteObjCInterfaceCategory(S, ClassName, ClassNameLoc);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006707
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006708 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006709 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor21325842011-07-07 16:03:39 +00006710 CodeCompletionContext::CCC_ObjCCategoryName);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006711
6712 // Add all of the categories that have have corresponding interface
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006713 // declarations in this class and any of its superclasses, except for
6714 // already-implemented categories in the class itself.
6715 llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
6716 Results.EnterNewScope();
6717 bool IgnoreImplemented = true;
6718 while (Class) {
Aaron Ballman3fe486a2014-03-13 21:23:55 +00006719 for (const auto *Cat : Class->visible_categories()) {
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006720 if ((!IgnoreImplemented || !Cat->getImplementation()) &&
David Blaikie82e95a32014-11-19 07:49:47 +00006721 CategoryNames.insert(Cat->getIdentifier()).second)
Craig Topperc3ec1492014-05-26 06:22:03 +00006722 Results.AddResult(Result(Cat, Results.getBasePriority(Cat), nullptr),
6723 CurContext, nullptr, false);
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006724 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006725
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006726 Class = Class->getSuperClass();
6727 IgnoreImplemented = false;
6728 }
6729 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00006730
6731 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6732 Results.data(), Results.size());
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006733}
Douglas Gregor5d649882009-11-18 22:32:06 +00006734
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00006735void Sema::CodeCompleteObjCPropertyDefinition(Scope *S) {
Douglas Gregorc3425b12015-07-07 06:20:19 +00006736 CodeCompletionContext CCContext(CodeCompletionContext::CCC_Other);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006737 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006738 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorc3425b12015-07-07 06:20:19 +00006739 CCContext);
Douglas Gregor5d649882009-11-18 22:32:06 +00006740
6741 // Figure out where this @synthesize lives.
6742 ObjCContainerDecl *Container
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00006743 = dyn_cast_or_null<ObjCContainerDecl>(CurContext);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006744 if (!Container ||
6745 (!isa<ObjCImplementationDecl>(Container) &&
Douglas Gregor5d649882009-11-18 22:32:06 +00006746 !isa<ObjCCategoryImplDecl>(Container)))
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006747 return;
Douglas Gregor5d649882009-11-18 22:32:06 +00006748
6749 // Ignore any properties that have already been implemented.
Douglas Gregor9b4f3702012-06-12 13:44:08 +00006750 Container = getContainerDef(Container);
Aaron Ballman629afae2014-03-07 19:56:05 +00006751 for (const auto *D : Container->decls())
6752 if (const auto *PropertyImpl = dyn_cast<ObjCPropertyImplDecl>(D))
Douglas Gregor5d649882009-11-18 22:32:06 +00006753 Results.Ignore(PropertyImpl->getPropertyDecl());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006754
Douglas Gregor5d649882009-11-18 22:32:06 +00006755 // Add any properties that we find.
Douglas Gregorb888acf2010-12-09 23:01:55 +00006756 AddedPropertiesSet AddedProperties;
Douglas Gregor5d649882009-11-18 22:32:06 +00006757 Results.EnterNewScope();
6758 if (ObjCImplementationDecl *ClassImpl
6759 = dyn_cast<ObjCImplementationDecl>(Container))
Douglas Gregorc3425b12015-07-07 06:20:19 +00006760 AddObjCProperties(CCContext, ClassImpl->getClassInterface(), false,
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006761 /*AllowNullaryMethods=*/false, CurContext,
Douglas Gregorb888acf2010-12-09 23:01:55 +00006762 AddedProperties, Results);
Douglas Gregor5d649882009-11-18 22:32:06 +00006763 else
Douglas Gregorc3425b12015-07-07 06:20:19 +00006764 AddObjCProperties(CCContext,
6765 cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl(),
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006766 false, /*AllowNullaryMethods=*/false, CurContext,
Douglas Gregor95147142011-05-05 15:50:42 +00006767 AddedProperties, Results);
Douglas Gregor5d649882009-11-18 22:32:06 +00006768 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00006769
6770 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6771 Results.data(), Results.size());
Douglas Gregor5d649882009-11-18 22:32:06 +00006772}
6773
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006774void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S,
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00006775 IdentifierInfo *PropertyName) {
John McCall276321a2010-08-25 06:19:51 +00006776 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006777 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006778 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006779 CodeCompletionContext::CCC_Other);
Douglas Gregor5d649882009-11-18 22:32:06 +00006780
6781 // Figure out where this @synthesize lives.
6782 ObjCContainerDecl *Container
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00006783 = dyn_cast_or_null<ObjCContainerDecl>(CurContext);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006784 if (!Container ||
6785 (!isa<ObjCImplementationDecl>(Container) &&
Douglas Gregor5d649882009-11-18 22:32:06 +00006786 !isa<ObjCCategoryImplDecl>(Container)))
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006787 return;
6788
Douglas Gregor5d649882009-11-18 22:32:06 +00006789 // Figure out which interface we're looking into.
Craig Topperc3ec1492014-05-26 06:22:03 +00006790 ObjCInterfaceDecl *Class = nullptr;
Douglas Gregor5d649882009-11-18 22:32:06 +00006791 if (ObjCImplementationDecl *ClassImpl
Manman Ren5b786402016-01-28 18:49:28 +00006792 = dyn_cast<ObjCImplementationDecl>(Container))
Douglas Gregor5d649882009-11-18 22:32:06 +00006793 Class = ClassImpl->getClassInterface();
6794 else
6795 Class = cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl()
6796 ->getClassInterface();
6797
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006798 // Determine the type of the property we're synthesizing.
6799 QualType PropertyType = Context.getObjCIdType();
6800 if (Class) {
Manman Ren5b786402016-01-28 18:49:28 +00006801 if (ObjCPropertyDecl *Property = Class->FindPropertyDeclaration(
6802 PropertyName, ObjCPropertyQueryKind::OBJC_PR_query_instance)) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006803 PropertyType
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006804 = Property->getType().getNonReferenceType().getUnqualifiedType();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006805
6806 // Give preference to ivars
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006807 Results.setPreferredType(PropertyType);
6808 }
6809 }
6810
Douglas Gregor5d649882009-11-18 22:32:06 +00006811 // Add all of the instance variables in this class and its superclasses.
6812 Results.EnterNewScope();
Douglas Gregor331faa02011-04-18 14:13:53 +00006813 bool SawSimilarlyNamedIvar = false;
6814 std::string NameWithPrefix;
6815 NameWithPrefix += '_';
Benjamin Kramer632500c2011-07-26 16:59:25 +00006816 NameWithPrefix += PropertyName->getName();
Douglas Gregor331faa02011-04-18 14:13:53 +00006817 std::string NameWithSuffix = PropertyName->getName().str();
6818 NameWithSuffix += '_';
Douglas Gregor5d649882009-11-18 22:32:06 +00006819 for(; Class; Class = Class->getSuperClass()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006820 for (ObjCIvarDecl *Ivar = Class->all_declared_ivar_begin(); Ivar;
Douglas Gregor331faa02011-04-18 14:13:53 +00006821 Ivar = Ivar->getNextIvar()) {
Craig Topperc3ec1492014-05-26 06:22:03 +00006822 Results.AddResult(Result(Ivar, Results.getBasePriority(Ivar), nullptr),
6823 CurContext, nullptr, false);
6824
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006825 // Determine whether we've seen an ivar with a name similar to the
Douglas Gregor331faa02011-04-18 14:13:53 +00006826 // property.
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006827 if ((PropertyName == Ivar->getIdentifier() ||
Douglas Gregor331faa02011-04-18 14:13:53 +00006828 NameWithPrefix == Ivar->getName() ||
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006829 NameWithSuffix == Ivar->getName())) {
Douglas Gregor331faa02011-04-18 14:13:53 +00006830 SawSimilarlyNamedIvar = true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006831
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006832 // Reduce the priority of this result by one, to give it a slight
6833 // advantage over other results whose names don't match so closely.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006834 if (Results.size() &&
6835 Results.data()[Results.size() - 1].Kind
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006836 == CodeCompletionResult::RK_Declaration &&
6837 Results.data()[Results.size() - 1].Declaration == Ivar)
6838 Results.data()[Results.size() - 1].Priority--;
6839 }
Douglas Gregor331faa02011-04-18 14:13:53 +00006840 }
Douglas Gregor5d649882009-11-18 22:32:06 +00006841 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006842
Douglas Gregor331faa02011-04-18 14:13:53 +00006843 if (!SawSimilarlyNamedIvar) {
6844 // Create ivar result _propName, that the user can use to synthesize
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006845 // an ivar of the appropriate type.
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006846 unsigned Priority = CCP_MemberDeclaration + 1;
Douglas Gregor331faa02011-04-18 14:13:53 +00006847 typedef CodeCompletionResult Result;
6848 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006849 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo(),
6850 Priority,CXAvailability_Available);
Douglas Gregor331faa02011-04-18 14:13:53 +00006851
Douglas Gregor75acd922011-09-27 23:30:47 +00006852 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006853 Builder.AddResultTypeChunk(GetCompletionTypeString(PropertyType, Context,
Douglas Gregor75acd922011-09-27 23:30:47 +00006854 Policy, Allocator));
Douglas Gregor331faa02011-04-18 14:13:53 +00006855 Builder.AddTypedTextChunk(Allocator.CopyString(NameWithPrefix));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006856 Results.AddResult(Result(Builder.TakeString(), Priority,
Douglas Gregor331faa02011-04-18 14:13:53 +00006857 CXCursor_ObjCIvarDecl));
6858 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006859
Douglas Gregor5d649882009-11-18 22:32:06 +00006860 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00006861
6862 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6863 Results.data(), Results.size());
Douglas Gregor5d649882009-11-18 22:32:06 +00006864}
Douglas Gregor636a61e2010-04-07 00:21:17 +00006865
Douglas Gregor416b5752010-08-25 01:08:01 +00006866// Mapping from selectors to the methods that implement that selector, along
6867// with the "in original class" flag.
Benjamin Kramereb8c4462013-06-29 17:52:13 +00006868typedef llvm::DenseMap<
6869 Selector, llvm::PointerIntPair<ObjCMethodDecl *, 1, bool> > KnownMethodsMap;
Douglas Gregor636a61e2010-04-07 00:21:17 +00006870
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006871/// Find all of the methods that reside in the given container
Douglas Gregor636a61e2010-04-07 00:21:17 +00006872/// (and its superclasses, protocols, etc.) that meet the given
6873/// criteria. Insert those methods into the map of known methods,
6874/// indexed by selector so they can be easily found.
6875static void FindImplementableMethods(ASTContext &Context,
6876 ObjCContainerDecl *Container,
Alex Lorenzb8740422017-10-24 16:39:37 +00006877 Optional<bool> WantInstanceMethods,
Douglas Gregor636a61e2010-04-07 00:21:17 +00006878 QualType ReturnType,
Douglas Gregor416b5752010-08-25 01:08:01 +00006879 KnownMethodsMap &KnownMethods,
6880 bool InOriginalClass = true) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00006881 if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)) {
Douglas Gregor9b4f3702012-06-12 13:44:08 +00006882 // Make sure we have a definition; that's what we'll walk.
Douglas Gregorc0ac7d62011-12-15 05:27:12 +00006883 if (!IFace->hasDefinition())
6884 return;
Douglas Gregor9b4f3702012-06-12 13:44:08 +00006885
6886 IFace = IFace->getDefinition();
6887 Container = IFace;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006888
Douglas Gregor636a61e2010-04-07 00:21:17 +00006889 const ObjCList<ObjCProtocolDecl> &Protocols
6890 = IFace->getReferencedProtocols();
6891 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006892 E = Protocols.end();
Douglas Gregor636a61e2010-04-07 00:21:17 +00006893 I != E; ++I)
6894 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006895 KnownMethods, InOriginalClass);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006896
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006897 // Add methods from any class extensions and categories.
Aaron Ballman3fe486a2014-03-13 21:23:55 +00006898 for (auto *Cat : IFace->visible_categories()) {
6899 FindImplementableMethods(Context, Cat, WantInstanceMethods, ReturnType,
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006900 KnownMethods, false);
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006901 }
6902
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006903 // Visit the superclass.
6904 if (IFace->getSuperClass())
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006905 FindImplementableMethods(Context, IFace->getSuperClass(),
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006906 WantInstanceMethods, ReturnType,
6907 KnownMethods, false);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006908 }
6909
6910 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(Container)) {
6911 // Recurse into protocols.
6912 const ObjCList<ObjCProtocolDecl> &Protocols
6913 = Category->getReferencedProtocols();
6914 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006915 E = Protocols.end();
Douglas Gregor636a61e2010-04-07 00:21:17 +00006916 I != E; ++I)
6917 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006918 KnownMethods, InOriginalClass);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006919
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006920 // If this category is the original class, jump to the interface.
6921 if (InOriginalClass && Category->getClassInterface())
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006922 FindImplementableMethods(Context, Category->getClassInterface(),
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006923 WantInstanceMethods, ReturnType, KnownMethods,
6924 false);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006925 }
6926
6927 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Douglas Gregor9b4f3702012-06-12 13:44:08 +00006928 // Make sure we have a definition; that's what we'll walk.
6929 if (!Protocol->hasDefinition())
6930 return;
6931 Protocol = Protocol->getDefinition();
6932 Container = Protocol;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006933
Douglas Gregor9b4f3702012-06-12 13:44:08 +00006934 // Recurse into protocols.
6935 const ObjCList<ObjCProtocolDecl> &Protocols
6936 = Protocol->getReferencedProtocols();
6937 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006938 E = Protocols.end();
Douglas Gregor9b4f3702012-06-12 13:44:08 +00006939 I != E; ++I)
6940 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
6941 KnownMethods, false);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006942 }
6943
6944 // Add methods in this container. This operation occurs last because
6945 // we want the methods from this container to override any methods
6946 // we've previously seen with the same selector.
Aaron Ballmanaff18c02014-03-13 19:03:34 +00006947 for (auto *M : Container->methods()) {
Alex Lorenzb8740422017-10-24 16:39:37 +00006948 if (!WantInstanceMethods || M->isInstanceMethod() == *WantInstanceMethods) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00006949 if (!ReturnType.isNull() &&
Alp Toker314cc812014-01-25 16:55:45 +00006950 !Context.hasSameUnqualifiedType(ReturnType, M->getReturnType()))
Douglas Gregor636a61e2010-04-07 00:21:17 +00006951 continue;
6952
Benjamin Kramereb8c4462013-06-29 17:52:13 +00006953 KnownMethods[M->getSelector()] =
Aaron Ballmanaff18c02014-03-13 19:03:34 +00006954 KnownMethodsMap::mapped_type(M, InOriginalClass);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006955 }
6956 }
6957}
6958
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006959/// Add the parenthesized return or parameter type chunk to a code
Douglas Gregor669a25a2011-02-17 00:22:45 +00006960/// completion string.
6961static void AddObjCPassingTypeChunk(QualType Type,
Douglas Gregor29979142012-04-10 18:35:07 +00006962 unsigned ObjCDeclQuals,
Douglas Gregor669a25a2011-02-17 00:22:45 +00006963 ASTContext &Context,
Douglas Gregor75acd922011-09-27 23:30:47 +00006964 const PrintingPolicy &Policy,
Douglas Gregor669a25a2011-02-17 00:22:45 +00006965 CodeCompletionBuilder &Builder) {
6966 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregor86b42682015-06-19 18:27:52 +00006967 std::string Quals = formatObjCParamQualifiers(ObjCDeclQuals, Type);
Douglas Gregor29979142012-04-10 18:35:07 +00006968 if (!Quals.empty())
6969 Builder.AddTextChunk(Builder.getAllocator().CopyString(Quals));
Douglas Gregor75acd922011-09-27 23:30:47 +00006970 Builder.AddTextChunk(GetCompletionTypeString(Type, Context, Policy,
Douglas Gregor669a25a2011-02-17 00:22:45 +00006971 Builder.getAllocator()));
6972 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6973}
6974
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006975/// Determine whether the given class is or inherits from a class by
Douglas Gregor669a25a2011-02-17 00:22:45 +00006976/// the given name.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006977static bool InheritsFromClassNamed(ObjCInterfaceDecl *Class,
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006978 StringRef Name) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006979 if (!Class)
6980 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006981
Douglas Gregor669a25a2011-02-17 00:22:45 +00006982 if (Class->getIdentifier() && Class->getIdentifier()->getName() == Name)
6983 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006984
Douglas Gregor669a25a2011-02-17 00:22:45 +00006985 return InheritsFromClassNamed(Class->getSuperClass(), Name);
6986}
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006987
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006988/// Add code completions for Objective-C Key-Value Coding (KVC) and
Douglas Gregor669a25a2011-02-17 00:22:45 +00006989/// Key-Value Observing (KVO).
6990static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
6991 bool IsInstanceMethod,
6992 QualType ReturnType,
6993 ASTContext &Context,
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006994 VisitedSelectorSet &KnownSelectors,
Douglas Gregor669a25a2011-02-17 00:22:45 +00006995 ResultBuilder &Results) {
6996 IdentifierInfo *PropName = Property->getIdentifier();
6997 if (!PropName || PropName->getLength() == 0)
6998 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006999
Douglas Gregor75acd922011-09-27 23:30:47 +00007000 PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema());
7001
Douglas Gregor669a25a2011-02-17 00:22:45 +00007002 // Builder that will create each code completion.
7003 typedef CodeCompletionResult Result;
7004 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007005 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007006
Douglas Gregor669a25a2011-02-17 00:22:45 +00007007 // The selector table.
7008 SelectorTable &Selectors = Context.Selectors;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007009
Douglas Gregor669a25a2011-02-17 00:22:45 +00007010 // The property name, copied into the code completion allocation region
7011 // on demand.
7012 struct KeyHolder {
7013 CodeCompletionAllocator &Allocator;
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007014 StringRef Key;
Douglas Gregor669a25a2011-02-17 00:22:45 +00007015 const char *CopiedKey;
Craig Topperc3ec1492014-05-26 06:22:03 +00007016
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007017 KeyHolder(CodeCompletionAllocator &Allocator, StringRef Key)
Craig Topperc3ec1492014-05-26 06:22:03 +00007018 : Allocator(Allocator), Key(Key), CopiedKey(nullptr) {}
7019
Douglas Gregor669a25a2011-02-17 00:22:45 +00007020 operator const char *() {
7021 if (CopiedKey)
7022 return CopiedKey;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007023
Douglas Gregor669a25a2011-02-17 00:22:45 +00007024 return CopiedKey = Allocator.CopyString(Key);
7025 }
7026 } Key(Allocator, PropName->getName());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007027
Douglas Gregor669a25a2011-02-17 00:22:45 +00007028 // The uppercased name of the property name.
7029 std::string UpperKey = PropName->getName();
7030 if (!UpperKey.empty())
Jordan Rose4938f272013-02-09 10:09:43 +00007031 UpperKey[0] = toUppercase(UpperKey[0]);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007032
Douglas Gregor669a25a2011-02-17 00:22:45 +00007033 bool ReturnTypeMatchesProperty = ReturnType.isNull() ||
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007034 Context.hasSameUnqualifiedType(ReturnType.getNonReferenceType(),
Douglas Gregor669a25a2011-02-17 00:22:45 +00007035 Property->getType());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007036 bool ReturnTypeMatchesVoid
Douglas Gregor669a25a2011-02-17 00:22:45 +00007037 = ReturnType.isNull() || ReturnType->isVoidType();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007038
Douglas Gregor669a25a2011-02-17 00:22:45 +00007039 // Add the normal accessor -(type)key.
7040 if (IsInstanceMethod &&
David Blaikie82e95a32014-11-19 07:49:47 +00007041 KnownSelectors.insert(Selectors.getNullarySelector(PropName)).second &&
Douglas Gregor669a25a2011-02-17 00:22:45 +00007042 ReturnTypeMatchesProperty && !Property->getGetterMethodDecl()) {
7043 if (ReturnType.isNull())
Douglas Gregor29979142012-04-10 18:35:07 +00007044 AddObjCPassingTypeChunk(Property->getType(), /*Quals=*/0,
7045 Context, Policy, Builder);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007046
Douglas Gregor669a25a2011-02-17 00:22:45 +00007047 Builder.AddTypedTextChunk(Key);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007048 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007049 CXCursor_ObjCInstanceMethodDecl));
7050 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007051
Douglas Gregor669a25a2011-02-17 00:22:45 +00007052 // If we have an integral or boolean property (or the user has provided
7053 // an integral or boolean return type), add the accessor -(type)isKey.
7054 if (IsInstanceMethod &&
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007055 ((!ReturnType.isNull() &&
Douglas Gregor669a25a2011-02-17 00:22:45 +00007056 (ReturnType->isIntegerType() || ReturnType->isBooleanType())) ||
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007057 (ReturnType.isNull() &&
7058 (Property->getType()->isIntegerType() ||
Douglas Gregor669a25a2011-02-17 00:22:45 +00007059 Property->getType()->isBooleanType())))) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007060 std::string SelectorName = (Twine("is") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007061 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007062 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
7063 .second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007064 if (ReturnType.isNull()) {
7065 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7066 Builder.AddTextChunk("BOOL");
7067 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7068 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007069
Douglas Gregor669a25a2011-02-17 00:22:45 +00007070 Builder.AddTypedTextChunk(
7071 Allocator.CopyString(SelectorId->getName()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007072 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007073 CXCursor_ObjCInstanceMethodDecl));
7074 }
7075 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007076
Douglas Gregor669a25a2011-02-17 00:22:45 +00007077 // Add the normal mutator.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007078 if (IsInstanceMethod && ReturnTypeMatchesVoid &&
Douglas Gregor669a25a2011-02-17 00:22:45 +00007079 !Property->getSetterMethodDecl()) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007080 std::string SelectorName = (Twine("set") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007081 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007082 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007083 if (ReturnType.isNull()) {
7084 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7085 Builder.AddTextChunk("void");
7086 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7087 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007088
Douglas Gregor669a25a2011-02-17 00:22:45 +00007089 Builder.AddTypedTextChunk(
7090 Allocator.CopyString(SelectorId->getName()));
7091 Builder.AddTypedTextChunk(":");
Douglas Gregor29979142012-04-10 18:35:07 +00007092 AddObjCPassingTypeChunk(Property->getType(), /*Quals=*/0,
7093 Context, Policy, Builder);
Douglas Gregor669a25a2011-02-17 00:22:45 +00007094 Builder.AddTextChunk(Key);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007095 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007096 CXCursor_ObjCInstanceMethodDecl));
7097 }
7098 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007099
Douglas Gregor669a25a2011-02-17 00:22:45 +00007100 // Indexed and unordered accessors
7101 unsigned IndexedGetterPriority = CCP_CodePattern;
7102 unsigned IndexedSetterPriority = CCP_CodePattern;
7103 unsigned UnorderedGetterPriority = CCP_CodePattern;
7104 unsigned UnorderedSetterPriority = CCP_CodePattern;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007105 if (const ObjCObjectPointerType *ObjCPointer
Douglas Gregor669a25a2011-02-17 00:22:45 +00007106 = Property->getType()->getAs<ObjCObjectPointerType>()) {
7107 if (ObjCInterfaceDecl *IFace = ObjCPointer->getInterfaceDecl()) {
7108 // If this interface type is not provably derived from a known
7109 // collection, penalize the corresponding completions.
7110 if (!InheritsFromClassNamed(IFace, "NSMutableArray")) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007111 IndexedSetterPriority += CCD_ProbablyNotObjCCollection;
Douglas Gregor669a25a2011-02-17 00:22:45 +00007112 if (!InheritsFromClassNamed(IFace, "NSArray"))
7113 IndexedGetterPriority += CCD_ProbablyNotObjCCollection;
7114 }
7115
7116 if (!InheritsFromClassNamed(IFace, "NSMutableSet")) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007117 UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;
Douglas Gregor669a25a2011-02-17 00:22:45 +00007118 if (!InheritsFromClassNamed(IFace, "NSSet"))
7119 UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;
7120 }
7121 }
7122 } else {
7123 IndexedGetterPriority += CCD_ProbablyNotObjCCollection;
7124 IndexedSetterPriority += CCD_ProbablyNotObjCCollection;
7125 UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;
7126 UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;
7127 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007128
Douglas Gregor669a25a2011-02-17 00:22:45 +00007129 // Add -(NSUInteger)countOf<key>
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007130 if (IsInstanceMethod &&
Douglas Gregor669a25a2011-02-17 00:22:45 +00007131 (ReturnType.isNull() || ReturnType->isIntegerType())) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007132 std::string SelectorName = (Twine("countOf") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007133 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007134 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
7135 .second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007136 if (ReturnType.isNull()) {
7137 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7138 Builder.AddTextChunk("NSUInteger");
7139 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7140 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007141
Douglas Gregor669a25a2011-02-17 00:22:45 +00007142 Builder.AddTypedTextChunk(
7143 Allocator.CopyString(SelectorId->getName()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007144 Results.AddResult(Result(Builder.TakeString(),
7145 std::min(IndexedGetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007146 UnorderedGetterPriority),
7147 CXCursor_ObjCInstanceMethodDecl));
7148 }
7149 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007150
Douglas Gregor669a25a2011-02-17 00:22:45 +00007151 // Indexed getters
7152 // Add -(id)objectInKeyAtIndex:(NSUInteger)index
7153 if (IsInstanceMethod &&
7154 (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007155 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007156 = (Twine("objectIn") + UpperKey + "AtIndex").str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007157 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007158 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007159 if (ReturnType.isNull()) {
7160 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7161 Builder.AddTextChunk("id");
7162 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7163 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007164
Douglas Gregor669a25a2011-02-17 00:22:45 +00007165 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7166 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7167 Builder.AddTextChunk("NSUInteger");
7168 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7169 Builder.AddTextChunk("index");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007170 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007171 CXCursor_ObjCInstanceMethodDecl));
7172 }
7173 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007174
Douglas Gregor669a25a2011-02-17 00:22:45 +00007175 // Add -(NSArray *)keyAtIndexes:(NSIndexSet *)indexes
7176 if (IsInstanceMethod &&
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007177 (ReturnType.isNull() ||
Douglas Gregor669a25a2011-02-17 00:22:45 +00007178 (ReturnType->isObjCObjectPointerType() &&
7179 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
7180 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
7181 ->getName() == "NSArray"))) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007182 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007183 = (Twine(Property->getName()) + "AtIndexes").str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007184 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007185 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007186 if (ReturnType.isNull()) {
7187 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7188 Builder.AddTextChunk("NSArray *");
7189 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7190 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007191
Douglas Gregor669a25a2011-02-17 00:22:45 +00007192 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7193 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7194 Builder.AddTextChunk("NSIndexSet *");
7195 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7196 Builder.AddTextChunk("indexes");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007197 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007198 CXCursor_ObjCInstanceMethodDecl));
7199 }
7200 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007201
Douglas Gregor669a25a2011-02-17 00:22:45 +00007202 // Add -(void)getKey:(type **)buffer range:(NSRange)inRange
7203 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007204 std::string SelectorName = (Twine("get") + UpperKey).str();
Douglas Gregor669a25a2011-02-17 00:22:45 +00007205 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007206 &Context.Idents.get(SelectorName),
Douglas Gregor669a25a2011-02-17 00:22:45 +00007207 &Context.Idents.get("range")
7208 };
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007209
David Blaikie82e95a32014-11-19 07:49:47 +00007210 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007211 if (ReturnType.isNull()) {
7212 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7213 Builder.AddTextChunk("void");
7214 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7215 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007216
Douglas Gregor669a25a2011-02-17 00:22:45 +00007217 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7218 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7219 Builder.AddPlaceholderChunk("object-type");
7220 Builder.AddTextChunk(" **");
7221 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7222 Builder.AddTextChunk("buffer");
7223 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7224 Builder.AddTypedTextChunk("range:");
7225 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7226 Builder.AddTextChunk("NSRange");
7227 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7228 Builder.AddTextChunk("inRange");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007229 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007230 CXCursor_ObjCInstanceMethodDecl));
7231 }
7232 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007233
Douglas Gregor669a25a2011-02-17 00:22:45 +00007234 // Mutable indexed accessors
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007235
Douglas Gregor669a25a2011-02-17 00:22:45 +00007236 // - (void)insertObject:(type *)object inKeyAtIndex:(NSUInteger)index
7237 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007238 std::string SelectorName = (Twine("in") + UpperKey + "AtIndex").str();
Douglas Gregor669a25a2011-02-17 00:22:45 +00007239 IdentifierInfo *SelectorIds[2] = {
7240 &Context.Idents.get("insertObject"),
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007241 &Context.Idents.get(SelectorName)
Douglas Gregor669a25a2011-02-17 00:22:45 +00007242 };
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007243
David Blaikie82e95a32014-11-19 07:49:47 +00007244 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007245 if (ReturnType.isNull()) {
7246 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7247 Builder.AddTextChunk("void");
7248 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7249 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007250
Douglas Gregor669a25a2011-02-17 00:22:45 +00007251 Builder.AddTypedTextChunk("insertObject:");
7252 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7253 Builder.AddPlaceholderChunk("object-type");
7254 Builder.AddTextChunk(" *");
7255 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7256 Builder.AddTextChunk("object");
7257 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7258 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7259 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7260 Builder.AddPlaceholderChunk("NSUInteger");
7261 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7262 Builder.AddTextChunk("index");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007263 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007264 CXCursor_ObjCInstanceMethodDecl));
7265 }
7266 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007267
Douglas Gregor669a25a2011-02-17 00:22:45 +00007268 // - (void)insertKey:(NSArray *)array atIndexes:(NSIndexSet *)indexes
7269 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007270 std::string SelectorName = (Twine("insert") + UpperKey).str();
Douglas Gregor669a25a2011-02-17 00:22:45 +00007271 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007272 &Context.Idents.get(SelectorName),
Douglas Gregor669a25a2011-02-17 00:22:45 +00007273 &Context.Idents.get("atIndexes")
7274 };
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007275
David Blaikie82e95a32014-11-19 07:49:47 +00007276 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007277 if (ReturnType.isNull()) {
7278 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7279 Builder.AddTextChunk("void");
7280 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7281 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007282
Douglas Gregor669a25a2011-02-17 00:22:45 +00007283 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7284 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7285 Builder.AddTextChunk("NSArray *");
7286 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7287 Builder.AddTextChunk("array");
7288 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7289 Builder.AddTypedTextChunk("atIndexes:");
7290 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7291 Builder.AddPlaceholderChunk("NSIndexSet *");
7292 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7293 Builder.AddTextChunk("indexes");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007294 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007295 CXCursor_ObjCInstanceMethodDecl));
7296 }
7297 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007298
Douglas Gregor669a25a2011-02-17 00:22:45 +00007299 // -(void)removeObjectFromKeyAtIndex:(NSUInteger)index
7300 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007301 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007302 = (Twine("removeObjectFrom") + UpperKey + "AtIndex").str();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007303 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007304 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007305 if (ReturnType.isNull()) {
7306 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7307 Builder.AddTextChunk("void");
7308 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7309 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007310
Douglas Gregor669a25a2011-02-17 00:22:45 +00007311 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7312 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7313 Builder.AddTextChunk("NSUInteger");
7314 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7315 Builder.AddTextChunk("index");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007316 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007317 CXCursor_ObjCInstanceMethodDecl));
7318 }
7319 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007320
Douglas Gregor669a25a2011-02-17 00:22:45 +00007321 // -(void)removeKeyAtIndexes:(NSIndexSet *)indexes
7322 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007323 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007324 = (Twine("remove") + UpperKey + "AtIndexes").str();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007325 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007326 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007327 if (ReturnType.isNull()) {
7328 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7329 Builder.AddTextChunk("void");
7330 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7331 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007332
Douglas Gregor669a25a2011-02-17 00:22:45 +00007333 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7334 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7335 Builder.AddTextChunk("NSIndexSet *");
7336 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7337 Builder.AddTextChunk("indexes");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007338 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007339 CXCursor_ObjCInstanceMethodDecl));
7340 }
7341 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007342
Douglas Gregor669a25a2011-02-17 00:22:45 +00007343 // - (void)replaceObjectInKeyAtIndex:(NSUInteger)index withObject:(id)object
7344 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007345 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007346 = (Twine("replaceObjectIn") + UpperKey + "AtIndex").str();
Douglas Gregor669a25a2011-02-17 00:22:45 +00007347 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007348 &Context.Idents.get(SelectorName),
Douglas Gregor669a25a2011-02-17 00:22:45 +00007349 &Context.Idents.get("withObject")
7350 };
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007351
David Blaikie82e95a32014-11-19 07:49:47 +00007352 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007353 if (ReturnType.isNull()) {
7354 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7355 Builder.AddTextChunk("void");
7356 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7357 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007358
Douglas Gregor669a25a2011-02-17 00:22:45 +00007359 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7360 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7361 Builder.AddPlaceholderChunk("NSUInteger");
7362 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7363 Builder.AddTextChunk("index");
7364 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7365 Builder.AddTypedTextChunk("withObject:");
7366 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7367 Builder.AddTextChunk("id");
7368 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7369 Builder.AddTextChunk("object");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007370 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007371 CXCursor_ObjCInstanceMethodDecl));
7372 }
7373 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007374
Douglas Gregor669a25a2011-02-17 00:22:45 +00007375 // - (void)replaceKeyAtIndexes:(NSIndexSet *)indexes withKey:(NSArray *)array
7376 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007377 std::string SelectorName1
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007378 = (Twine("replace") + UpperKey + "AtIndexes").str();
7379 std::string SelectorName2 = (Twine("with") + UpperKey).str();
Douglas Gregor669a25a2011-02-17 00:22:45 +00007380 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007381 &Context.Idents.get(SelectorName1),
7382 &Context.Idents.get(SelectorName2)
Douglas Gregor669a25a2011-02-17 00:22:45 +00007383 };
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007384
David Blaikie82e95a32014-11-19 07:49:47 +00007385 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007386 if (ReturnType.isNull()) {
7387 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7388 Builder.AddTextChunk("void");
7389 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7390 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007391
Douglas Gregor669a25a2011-02-17 00:22:45 +00007392 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName1 + ":"));
7393 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7394 Builder.AddPlaceholderChunk("NSIndexSet *");
7395 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7396 Builder.AddTextChunk("indexes");
7397 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7398 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName2 + ":"));
7399 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7400 Builder.AddTextChunk("NSArray *");
7401 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7402 Builder.AddTextChunk("array");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007403 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007404 CXCursor_ObjCInstanceMethodDecl));
7405 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007406 }
7407
Douglas Gregor669a25a2011-02-17 00:22:45 +00007408 // Unordered getters
7409 // - (NSEnumerator *)enumeratorOfKey
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007410 if (IsInstanceMethod &&
7411 (ReturnType.isNull() ||
Douglas Gregor669a25a2011-02-17 00:22:45 +00007412 (ReturnType->isObjCObjectPointerType() &&
7413 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
7414 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
7415 ->getName() == "NSEnumerator"))) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007416 std::string SelectorName = (Twine("enumeratorOf") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007417 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007418 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
7419 .second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007420 if (ReturnType.isNull()) {
7421 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7422 Builder.AddTextChunk("NSEnumerator *");
7423 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7424 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007425
Douglas Gregor669a25a2011-02-17 00:22:45 +00007426 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007427 Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007428 CXCursor_ObjCInstanceMethodDecl));
7429 }
7430 }
7431
7432 // - (type *)memberOfKey:(type *)object
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007433 if (IsInstanceMethod &&
Douglas Gregor669a25a2011-02-17 00:22:45 +00007434 (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007435 std::string SelectorName = (Twine("memberOf") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007436 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007437 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007438 if (ReturnType.isNull()) {
7439 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7440 Builder.AddPlaceholderChunk("object-type");
7441 Builder.AddTextChunk(" *");
7442 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7443 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007444
Douglas Gregor669a25a2011-02-17 00:22:45 +00007445 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7446 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7447 if (ReturnType.isNull()) {
7448 Builder.AddPlaceholderChunk("object-type");
7449 Builder.AddTextChunk(" *");
7450 } else {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007451 Builder.AddTextChunk(GetCompletionTypeString(ReturnType, Context,
Douglas Gregor75acd922011-09-27 23:30:47 +00007452 Policy,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007453 Builder.getAllocator()));
7454 }
7455 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7456 Builder.AddTextChunk("object");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007457 Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007458 CXCursor_ObjCInstanceMethodDecl));
7459 }
7460 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007461
Douglas Gregor669a25a2011-02-17 00:22:45 +00007462 // Mutable unordered accessors
7463 // - (void)addKeyObject:(type *)object
7464 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007465 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007466 = (Twine("add") + UpperKey + Twine("Object")).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007467 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007468 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007469 if (ReturnType.isNull()) {
7470 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7471 Builder.AddTextChunk("void");
7472 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7473 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007474
Douglas Gregor669a25a2011-02-17 00:22:45 +00007475 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7476 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7477 Builder.AddPlaceholderChunk("object-type");
7478 Builder.AddTextChunk(" *");
7479 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7480 Builder.AddTextChunk("object");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007481 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007482 CXCursor_ObjCInstanceMethodDecl));
7483 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007484 }
Douglas Gregor669a25a2011-02-17 00:22:45 +00007485
7486 // - (void)addKey:(NSSet *)objects
7487 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007488 std::string SelectorName = (Twine("add") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007489 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007490 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007491 if (ReturnType.isNull()) {
7492 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7493 Builder.AddTextChunk("void");
7494 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7495 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007496
Douglas Gregor669a25a2011-02-17 00:22:45 +00007497 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7498 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7499 Builder.AddTextChunk("NSSet *");
7500 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7501 Builder.AddTextChunk("objects");
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 }
7506
Douglas Gregor669a25a2011-02-17 00:22:45 +00007507 // - (void)removeKeyObject:(type *)object
7508 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007509 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007510 = (Twine("remove") + UpperKey + Twine("Object")).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007511 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007512 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007513 if (ReturnType.isNull()) {
7514 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7515 Builder.AddTextChunk("void");
7516 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7517 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007518
Douglas Gregor669a25a2011-02-17 00:22:45 +00007519 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7520 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7521 Builder.AddPlaceholderChunk("object-type");
7522 Builder.AddTextChunk(" *");
7523 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7524 Builder.AddTextChunk("object");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007525 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007526 CXCursor_ObjCInstanceMethodDecl));
7527 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007528 }
7529
Douglas Gregor669a25a2011-02-17 00:22:45 +00007530 // - (void)removeKey:(NSSet *)objects
7531 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007532 std::string SelectorName = (Twine("remove") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007533 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007534 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007535 if (ReturnType.isNull()) {
7536 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7537 Builder.AddTextChunk("void");
7538 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7539 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007540
Douglas Gregor669a25a2011-02-17 00:22:45 +00007541 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7542 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7543 Builder.AddTextChunk("NSSet *");
7544 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7545 Builder.AddTextChunk("objects");
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 }
Douglas Gregor669a25a2011-02-17 00:22:45 +00007550
7551 // - (void)intersectKey:(NSSet *)objects
7552 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007553 std::string SelectorName = (Twine("intersect") + 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 }
7571
Douglas Gregor669a25a2011-02-17 00:22:45 +00007572 // Key-Value Observing
7573 // + (NSSet *)keyPathsForValuesAffectingKey
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007574 if (!IsInstanceMethod &&
7575 (ReturnType.isNull() ||
Douglas Gregor669a25a2011-02-17 00:22:45 +00007576 (ReturnType->isObjCObjectPointerType() &&
7577 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
7578 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
7579 ->getName() == "NSSet"))) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007580 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007581 = (Twine("keyPathsForValuesAffecting") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007582 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007583 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
7584 .second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007585 if (ReturnType.isNull()) {
7586 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Alex Lorenz71ecb072016-12-08 16:49:05 +00007587 Builder.AddTextChunk("NSSet<NSString *> *");
Douglas Gregor669a25a2011-02-17 00:22:45 +00007588 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7589 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007590
Douglas Gregor669a25a2011-02-17 00:22:45 +00007591 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007592 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Douglas Gregor857bcda2011-06-02 04:02:27 +00007593 CXCursor_ObjCClassMethodDecl));
7594 }
7595 }
7596
7597 // + (BOOL)automaticallyNotifiesObserversForKey
7598 if (!IsInstanceMethod &&
7599 (ReturnType.isNull() ||
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007600 ReturnType->isIntegerType() ||
Douglas Gregor857bcda2011-06-02 04:02:27 +00007601 ReturnType->isBooleanType())) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007602 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007603 = (Twine("automaticallyNotifiesObserversOf") + UpperKey).str();
Douglas Gregor857bcda2011-06-02 04:02:27 +00007604 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007605 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
7606 .second) {
Douglas Gregor857bcda2011-06-02 04:02:27 +00007607 if (ReturnType.isNull()) {
7608 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7609 Builder.AddTextChunk("BOOL");
7610 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7611 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007612
Douglas Gregor857bcda2011-06-02 04:02:27 +00007613 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007614 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Douglas Gregor857bcda2011-06-02 04:02:27 +00007615 CXCursor_ObjCClassMethodDecl));
Douglas Gregor669a25a2011-02-17 00:22:45 +00007616 }
7617 }
7618}
7619
Alex Lorenzb8740422017-10-24 16:39:37 +00007620void Sema::CodeCompleteObjCMethodDecl(Scope *S, Optional<bool> IsInstanceMethod,
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00007621 ParsedType ReturnTy) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00007622 // Determine the return type of the method we're declaring, if
7623 // provided.
7624 QualType ReturnType = GetTypeFromParser(ReturnTy);
Craig Topperc3ec1492014-05-26 06:22:03 +00007625 Decl *IDecl = nullptr;
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00007626 if (CurContext->isObjCContainer()) {
7627 ObjCContainerDecl *OCD = dyn_cast<ObjCContainerDecl>(CurContext);
George Burgess IV00f70bd2018-03-01 05:43:23 +00007628 IDecl = OCD;
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00007629 }
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007630 // Determine where we should start searching for methods.
Craig Topperc3ec1492014-05-26 06:22:03 +00007631 ObjCContainerDecl *SearchDecl = nullptr;
Douglas Gregor636a61e2010-04-07 00:21:17 +00007632 bool IsInImplementation = false;
John McCall48871652010-08-21 09:40:31 +00007633 if (Decl *D = IDecl) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00007634 if (ObjCImplementationDecl *Impl = dyn_cast<ObjCImplementationDecl>(D)) {
7635 SearchDecl = Impl->getClassInterface();
Douglas Gregor636a61e2010-04-07 00:21:17 +00007636 IsInImplementation = true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007637 } else if (ObjCCategoryImplDecl *CatImpl
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007638 = dyn_cast<ObjCCategoryImplDecl>(D)) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00007639 SearchDecl = CatImpl->getCategoryDecl();
Douglas Gregor636a61e2010-04-07 00:21:17 +00007640 IsInImplementation = true;
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007641 } else
Douglas Gregor636a61e2010-04-07 00:21:17 +00007642 SearchDecl = dyn_cast<ObjCContainerDecl>(D);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007643 }
7644
7645 if (!SearchDecl && S) {
Ted Kremenekc37877d2013-10-08 17:08:03 +00007646 if (DeclContext *DC = S->getEntity())
Douglas Gregor636a61e2010-04-07 00:21:17 +00007647 SearchDecl = dyn_cast<ObjCContainerDecl>(DC);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007648 }
7649
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007650 if (!SearchDecl) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007651 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00007652 CodeCompletionContext::CCC_Other,
Craig Topperc3ec1492014-05-26 06:22:03 +00007653 nullptr, 0);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007654 return;
7655 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007656
Douglas Gregor636a61e2010-04-07 00:21:17 +00007657 // Find all of the methods that we could declare/implement here.
7658 KnownMethodsMap KnownMethods;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007659 FindImplementableMethods(Context, SearchDecl, IsInstanceMethod,
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007660 ReturnType, KnownMethods);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007661
Douglas Gregor636a61e2010-04-07 00:21:17 +00007662 // Add declarations or definitions for each of the known methods.
John McCall276321a2010-08-25 06:19:51 +00007663 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007664 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007665 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007666 CodeCompletionContext::CCC_Other);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007667 Results.EnterNewScope();
Douglas Gregor75acd922011-09-27 23:30:47 +00007668 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007669 for (KnownMethodsMap::iterator M = KnownMethods.begin(),
Douglas Gregor636a61e2010-04-07 00:21:17 +00007670 MEnd = KnownMethods.end();
7671 M != MEnd; ++M) {
Benjamin Kramereb8c4462013-06-29 17:52:13 +00007672 ObjCMethodDecl *Method = M->second.getPointer();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007673 CodeCompletionBuilder Builder(Results.getAllocator(),
7674 Results.getCodeCompletionTUInfo());
Alex Lorenzb8740422017-10-24 16:39:37 +00007675
7676 // Add the '-'/'+' prefix if it wasn't provided yet.
7677 if (!IsInstanceMethod) {
7678 Builder.AddTextChunk(Method->isInstanceMethod() ? "-" : "+");
7679 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7680 }
7681
Douglas Gregor636a61e2010-04-07 00:21:17 +00007682 // If the result type was not already provided, add it to the
7683 // pattern as (type).
Argyrios Kyrtzidisf0917ab2015-07-24 17:00:19 +00007684 if (ReturnType.isNull()) {
7685 QualType ResTy = Method->getSendResultType().stripObjCKindOfType(Context);
7686 AttributedType::stripOuterNullability(ResTy);
7687 AddObjCPassingTypeChunk(ResTy,
Alp Toker314cc812014-01-25 16:55:45 +00007688 Method->getObjCDeclQualifier(), Context, Policy,
7689 Builder);
Argyrios Kyrtzidisf0917ab2015-07-24 17:00:19 +00007690 }
Douglas Gregor636a61e2010-04-07 00:21:17 +00007691
7692 Selector Sel = Method->getSelector();
7693
7694 // Add the first part of the selector to the pattern.
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00007695 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00007696 Sel.getNameForSlot(0)));
Douglas Gregor636a61e2010-04-07 00:21:17 +00007697
7698 // Add parameters to the pattern.
7699 unsigned I = 0;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007700 for (ObjCMethodDecl::param_iterator P = Method->param_begin(),
Douglas Gregor636a61e2010-04-07 00:21:17 +00007701 PEnd = Method->param_end();
7702 P != PEnd; (void)++P, ++I) {
7703 // Add the part of the selector name.
7704 if (I == 0)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007705 Builder.AddTypedTextChunk(":");
Douglas Gregor636a61e2010-04-07 00:21:17 +00007706 else if (I < Sel.getNumArgs()) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007707 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7708 Builder.AddTypedTextChunk(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00007709 Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":"));
Douglas Gregor636a61e2010-04-07 00:21:17 +00007710 } else
7711 break;
7712
7713 // Add the parameter type.
Douglas Gregor86b42682015-06-19 18:27:52 +00007714 QualType ParamType;
7715 if ((*P)->getObjCDeclQualifier() & Decl::OBJC_TQ_CSNullability)
7716 ParamType = (*P)->getType();
7717 else
7718 ParamType = (*P)->getOriginalType();
Douglas Gregor9b7b3e92015-07-07 06:20:27 +00007719 ParamType = ParamType.substObjCTypeArgs(Context, {},
7720 ObjCSubstitutionContext::Parameter);
Argyrios Kyrtzidisf0917ab2015-07-24 17:00:19 +00007721 AttributedType::stripOuterNullability(ParamType);
Douglas Gregor86b42682015-06-19 18:27:52 +00007722 AddObjCPassingTypeChunk(ParamType,
Douglas Gregor29979142012-04-10 18:35:07 +00007723 (*P)->getObjCDeclQualifier(),
7724 Context, Policy,
Douglas Gregor75acd922011-09-27 23:30:47 +00007725 Builder);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007726
Douglas Gregor636a61e2010-04-07 00:21:17 +00007727 if (IdentifierInfo *Id = (*P)->getIdentifier())
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007728 Builder.AddTextChunk(Builder.getAllocator().CopyString( Id->getName()));
Douglas Gregor636a61e2010-04-07 00:21:17 +00007729 }
7730
7731 if (Method->isVariadic()) {
7732 if (Method->param_size() > 0)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007733 Builder.AddChunk(CodeCompletionString::CK_Comma);
7734 Builder.AddTextChunk("...");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007735 }
Douglas Gregor636a61e2010-04-07 00:21:17 +00007736
Douglas Gregord37c59d2010-05-28 00:57:46 +00007737 if (IsInImplementation && Results.includeCodePatterns()) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00007738 // We will be defining the method here, so add a compound statement.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007739 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7740 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
7741 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
Alp Toker314cc812014-01-25 16:55:45 +00007742 if (!Method->getReturnType()->isVoidType()) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00007743 // If the result type is not void, add a return clause.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007744 Builder.AddTextChunk("return");
7745 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7746 Builder.AddPlaceholderChunk("expression");
7747 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007748 } else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007749 Builder.AddPlaceholderChunk("statements");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007750
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007751 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
7752 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007753 }
7754
Douglas Gregor416b5752010-08-25 01:08:01 +00007755 unsigned Priority = CCP_CodePattern;
Benjamin Kramereb8c4462013-06-29 17:52:13 +00007756 if (!M->second.getInt())
Douglas Gregor416b5752010-08-25 01:08:01 +00007757 Priority += CCD_InBaseClass;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007758
Douglas Gregor78254c82012-03-27 23:34:16 +00007759 Results.AddResult(Result(Builder.TakeString(), Method, Priority));
Douglas Gregor636a61e2010-04-07 00:21:17 +00007760 }
7761
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007762 // Add Key-Value-Coding and Key-Value-Observing accessor methods for all of
Douglas Gregor669a25a2011-02-17 00:22:45 +00007763 // the properties in this class and its categories.
David Blaikiebbafb8a2012-03-11 07:00:24 +00007764 if (Context.getLangOpts().ObjC2) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007765 SmallVector<ObjCContainerDecl *, 4> Containers;
Douglas Gregor669a25a2011-02-17 00:22:45 +00007766 Containers.push_back(SearchDecl);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007767
Douglas Gregord4a8ced2011-05-04 23:50:46 +00007768 VisitedSelectorSet KnownSelectors;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007769 for (KnownMethodsMap::iterator M = KnownMethods.begin(),
Douglas Gregord4a8ced2011-05-04 23:50:46 +00007770 MEnd = KnownMethods.end();
7771 M != MEnd; ++M)
7772 KnownSelectors.insert(M->first);
7773
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007774
Douglas Gregor669a25a2011-02-17 00:22:45 +00007775 ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(SearchDecl);
7776 if (!IFace)
7777 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(SearchDecl))
7778 IFace = Category->getClassInterface();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007779
Aaron Ballman3fe486a2014-03-13 21:23:55 +00007780 if (IFace)
7781 for (auto *Cat : IFace->visible_categories())
7782 Containers.push_back(Cat);
Alex Lorenzb8740422017-10-24 16:39:37 +00007783
7784 if (IsInstanceMethod) {
7785 for (unsigned I = 0, N = Containers.size(); I != N; ++I)
7786 for (auto *P : Containers[I]->instance_properties())
7787 AddObjCKeyValueCompletions(P, *IsInstanceMethod, ReturnType, Context,
7788 KnownSelectors, Results);
7789 }
Douglas Gregor669a25a2011-02-17 00:22:45 +00007790 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007791
Douglas Gregor636a61e2010-04-07 00:21:17 +00007792 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00007793
7794 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
7795 Results.data(), Results.size());
Douglas Gregor636a61e2010-04-07 00:21:17 +00007796}
Douglas Gregor95887f92010-07-08 23:20:03 +00007797
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007798void Sema::CodeCompleteObjCMethodDeclSelector(Scope *S,
Douglas Gregor95887f92010-07-08 23:20:03 +00007799 bool IsInstanceMethod,
Douglas Gregor45879692010-07-08 23:37:41 +00007800 bool AtParameterName,
John McCallba7bf592010-08-24 05:47:05 +00007801 ParsedType ReturnTy,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00007802 ArrayRef<IdentifierInfo *> SelIdents) {
Douglas Gregor95887f92010-07-08 23:20:03 +00007803 // If we have an external source, load the entire class method
Sebastian Redld44cd6a2010-08-18 23:57:06 +00007804 // pool from the AST file.
Douglas Gregor95887f92010-07-08 23:20:03 +00007805 if (ExternalSource) {
7806 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
7807 I != N; ++I) {
7808 Selector Sel = ExternalSource->GetExternalSelector(I);
Sebastian Redl75d8a322010-08-02 23:18:59 +00007809 if (Sel.isNull() || MethodPool.count(Sel))
Douglas Gregor95887f92010-07-08 23:20:03 +00007810 continue;
Sebastian Redl75d8a322010-08-02 23:18:59 +00007811
7812 ReadMethodPool(Sel);
Douglas Gregor95887f92010-07-08 23:20:03 +00007813 }
7814 }
7815
7816 // Build the set of methods we can see.
John McCall276321a2010-08-25 06:19:51 +00007817 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007818 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007819 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007820 CodeCompletionContext::CCC_Other);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007821
Douglas Gregor95887f92010-07-08 23:20:03 +00007822 if (ReturnTy)
7823 Results.setPreferredType(GetTypeFromParser(ReturnTy).getNonReferenceType());
Sebastian Redl75d8a322010-08-02 23:18:59 +00007824
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007825 Results.EnterNewScope();
Sebastian Redl75d8a322010-08-02 23:18:59 +00007826 for (GlobalMethodPool::iterator M = MethodPool.begin(),
7827 MEnd = MethodPool.end();
7828 M != MEnd; ++M) {
7829 for (ObjCMethodList *MethList = IsInstanceMethod ? &M->second.first :
7830 &M->second.second;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007831 MethList && MethList->getMethod();
Argyrios Kyrtzidisd3da6e02013-04-17 00:08:58 +00007832 MethList = MethList->getNext()) {
Nico Weber2e0c8f72014-12-27 03:58:08 +00007833 if (!isAcceptableObjCMethod(MethList->getMethod(), MK_Any, SelIdents))
Douglas Gregor95887f92010-07-08 23:20:03 +00007834 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007835
Douglas Gregor45879692010-07-08 23:37:41 +00007836 if (AtParameterName) {
7837 // Suggest parameter names we've seen before.
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00007838 unsigned NumSelIdents = SelIdents.size();
Nico Weber2e0c8f72014-12-27 03:58:08 +00007839 if (NumSelIdents &&
7840 NumSelIdents <= MethList->getMethod()->param_size()) {
7841 ParmVarDecl *Param =
7842 MethList->getMethod()->parameters()[NumSelIdents - 1];
Douglas Gregor45879692010-07-08 23:37:41 +00007843 if (Param->getIdentifier()) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007844 CodeCompletionBuilder Builder(Results.getAllocator(),
7845 Results.getCodeCompletionTUInfo());
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00007846 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007847 Param->getIdentifier()->getName()));
7848 Results.AddResult(Builder.TakeString());
Douglas Gregor45879692010-07-08 23:37:41 +00007849 }
7850 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007851
Douglas Gregor45879692010-07-08 23:37:41 +00007852 continue;
7853 }
Craig Topperc3ec1492014-05-26 06:22:03 +00007854
Nico Weber2e0c8f72014-12-27 03:58:08 +00007855 Result R(MethList->getMethod(),
7856 Results.getBasePriority(MethList->getMethod()), nullptr);
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00007857 R.StartParameter = SelIdents.size();
Douglas Gregor95887f92010-07-08 23:20:03 +00007858 R.AllParametersAreInformative = false;
7859 R.DeclaringEntity = true;
7860 Results.MaybeAddResult(R, CurContext);
7861 }
7862 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007863
Douglas Gregor95887f92010-07-08 23:20:03 +00007864 Results.ExitScope();
Alex Lorenz847fda12017-01-03 11:56:40 +00007865
7866 if (!AtParameterName && !SelIdents.empty() &&
7867 SelIdents.front()->getName().startswith("init")) {
7868 for (const auto &M : PP.macros()) {
7869 if (M.first->getName() != "NS_DESIGNATED_INITIALIZER")
7870 continue;
7871 Results.EnterNewScope();
7872 CodeCompletionBuilder Builder(Results.getAllocator(),
7873 Results.getCodeCompletionTUInfo());
7874 Builder.AddTypedTextChunk(
7875 Builder.getAllocator().CopyString(M.first->getName()));
7876 Results.AddResult(CodeCompletionResult(Builder.TakeString(), CCP_Macro,
7877 CXCursor_MacroDefinition));
7878 Results.ExitScope();
7879 }
7880 }
7881
Eric Liuf5ba09f2018-07-04 10:01:18 +00007882 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
7883 Results.data(), Results.size());
Douglas Gregor95887f92010-07-08 23:20:03 +00007884}
Douglas Gregorb14904c2010-08-13 22:48:40 +00007885
Douglas Gregorec00a262010-08-24 22:20:20 +00007886void Sema::CodeCompletePreprocessorDirective(bool InConditional) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007887 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007888 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00007889 CodeCompletionContext::CCC_PreprocessorDirective);
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007890 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007891
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007892 // #if <condition>
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007893 CodeCompletionBuilder Builder(Results.getAllocator(),
7894 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007895 Builder.AddTypedTextChunk("if");
7896 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7897 Builder.AddPlaceholderChunk("condition");
7898 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007899
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007900 // #ifdef <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007901 Builder.AddTypedTextChunk("ifdef");
7902 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7903 Builder.AddPlaceholderChunk("macro");
7904 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007905
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007906 // #ifndef <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007907 Builder.AddTypedTextChunk("ifndef");
7908 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7909 Builder.AddPlaceholderChunk("macro");
7910 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007911
7912 if (InConditional) {
7913 // #elif <condition>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007914 Builder.AddTypedTextChunk("elif");
7915 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7916 Builder.AddPlaceholderChunk("condition");
7917 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007918
7919 // #else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007920 Builder.AddTypedTextChunk("else");
7921 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007922
7923 // #endif
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007924 Builder.AddTypedTextChunk("endif");
7925 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007926 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007927
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007928 // #include "header"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007929 Builder.AddTypedTextChunk("include");
7930 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7931 Builder.AddTextChunk("\"");
7932 Builder.AddPlaceholderChunk("header");
7933 Builder.AddTextChunk("\"");
7934 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007935
7936 // #include <header>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007937 Builder.AddTypedTextChunk("include");
7938 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7939 Builder.AddTextChunk("<");
7940 Builder.AddPlaceholderChunk("header");
7941 Builder.AddTextChunk(">");
7942 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007943
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007944 // #define <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007945 Builder.AddTypedTextChunk("define");
7946 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7947 Builder.AddPlaceholderChunk("macro");
7948 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007949
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007950 // #define <macro>(<args>)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007951 Builder.AddTypedTextChunk("define");
7952 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7953 Builder.AddPlaceholderChunk("macro");
7954 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7955 Builder.AddPlaceholderChunk("args");
7956 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7957 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007958
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007959 // #undef <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007960 Builder.AddTypedTextChunk("undef");
7961 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7962 Builder.AddPlaceholderChunk("macro");
7963 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007964
7965 // #line <number>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007966 Builder.AddTypedTextChunk("line");
7967 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7968 Builder.AddPlaceholderChunk("number");
7969 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007970
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007971 // #line <number> "filename"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007972 Builder.AddTypedTextChunk("line");
7973 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7974 Builder.AddPlaceholderChunk("number");
7975 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7976 Builder.AddTextChunk("\"");
7977 Builder.AddPlaceholderChunk("filename");
7978 Builder.AddTextChunk("\"");
7979 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007980
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007981 // #error <message>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007982 Builder.AddTypedTextChunk("error");
7983 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7984 Builder.AddPlaceholderChunk("message");
7985 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007986
7987 // #pragma <arguments>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007988 Builder.AddTypedTextChunk("pragma");
7989 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7990 Builder.AddPlaceholderChunk("arguments");
7991 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007992
David Blaikiebbafb8a2012-03-11 07:00:24 +00007993 if (getLangOpts().ObjC1) {
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007994 // #import "header"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007995 Builder.AddTypedTextChunk("import");
7996 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7997 Builder.AddTextChunk("\"");
7998 Builder.AddPlaceholderChunk("header");
7999 Builder.AddTextChunk("\"");
8000 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008001
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008002 // #import <header>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008003 Builder.AddTypedTextChunk("import");
8004 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8005 Builder.AddTextChunk("<");
8006 Builder.AddPlaceholderChunk("header");
8007 Builder.AddTextChunk(">");
8008 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008009 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008010
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008011 // #include_next "header"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008012 Builder.AddTypedTextChunk("include_next");
8013 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8014 Builder.AddTextChunk("\"");
8015 Builder.AddPlaceholderChunk("header");
8016 Builder.AddTextChunk("\"");
8017 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008018
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008019 // #include_next <header>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008020 Builder.AddTypedTextChunk("include_next");
8021 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8022 Builder.AddTextChunk("<");
8023 Builder.AddPlaceholderChunk("header");
8024 Builder.AddTextChunk(">");
8025 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008026
8027 // #warning <message>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008028 Builder.AddTypedTextChunk("warning");
8029 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8030 Builder.AddPlaceholderChunk("message");
8031 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008032
8033 // Note: #ident and #sccs are such crazy anachronisms that we don't provide
8034 // completions for them. And __include_macros is a Clang-internal extension
8035 // that we don't want to encourage anyone to use.
8036
8037 // FIXME: we don't support #assert or #unassert, so don't suggest them.
8038 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00008039
8040 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008041 Results.data(), Results.size());
8042}
8043
8044void Sema::CodeCompleteInPreprocessorConditionalExclusion(Scope *S) {
Douglas Gregorec00a262010-08-24 22:20:20 +00008045 CodeCompleteOrdinaryName(S,
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008046 S->getFnParent()? Sema::PCC_RecoveryInFunction
John McCallfaf5fb42010-08-26 23:41:50 +00008047 : Sema::PCC_Namespace);
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008048}
8049
Douglas Gregorec00a262010-08-24 22:20:20 +00008050void Sema::CodeCompletePreprocessorMacroName(bool IsDefinition) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008051 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008052 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00008053 IsDefinition? CodeCompletionContext::CCC_MacroName
8054 : CodeCompletionContext::CCC_MacroNameUse);
Douglas Gregor12785102010-08-24 20:21:13 +00008055 if (!IsDefinition && (!CodeCompleter || CodeCompleter->includeMacros())) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008056 // Add just the names of macros, not their arguments.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008057 CodeCompletionBuilder Builder(Results.getAllocator(),
8058 Results.getCodeCompletionTUInfo());
Douglas Gregor12785102010-08-24 20:21:13 +00008059 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008060 for (Preprocessor::macro_iterator M = PP.macro_begin(),
Douglas Gregor12785102010-08-24 20:21:13 +00008061 MEnd = PP.macro_end();
8062 M != MEnd; ++M) {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00008063 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008064 M->first->getName()));
Argyrios Kyrtzidis5c8b1cd2012-09-27 00:24:09 +00008065 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
8066 CCP_CodePattern,
8067 CXCursor_MacroDefinition));
Douglas Gregor12785102010-08-24 20:21:13 +00008068 }
8069 Results.ExitScope();
8070 } else if (IsDefinition) {
8071 // FIXME: Can we detect when the user just wrote an include guard above?
8072 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008073
Douglas Gregor0ac41382010-09-23 23:01:17 +00008074 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008075 Results.data(), Results.size());
Douglas Gregor12785102010-08-24 20:21:13 +00008076}
8077
Douglas Gregorec00a262010-08-24 22:20:20 +00008078void Sema::CodeCompletePreprocessorExpression() {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008079 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008080 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00008081 CodeCompletionContext::CCC_PreprocessorExpression);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008082
Douglas Gregorec00a262010-08-24 22:20:20 +00008083 if (!CodeCompleter || CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00008084 AddMacroResults(PP, Results,
8085 CodeCompleter ? CodeCompleter->loadExternal() : false,
8086 true);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008087
Douglas Gregorec00a262010-08-24 22:20:20 +00008088 // defined (<macro>)
8089 Results.EnterNewScope();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008090 CodeCompletionBuilder Builder(Results.getAllocator(),
8091 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008092 Builder.AddTypedTextChunk("defined");
8093 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8094 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
8095 Builder.AddPlaceholderChunk("macro");
8096 Builder.AddChunk(CodeCompletionString::CK_RightParen);
8097 Results.AddResult(Builder.TakeString());
Douglas Gregorec00a262010-08-24 22:20:20 +00008098 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00008099
8100 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
8101 Results.data(), Results.size());
Douglas Gregorec00a262010-08-24 22:20:20 +00008102}
8103
8104void Sema::CodeCompletePreprocessorMacroArgument(Scope *S,
8105 IdentifierInfo *Macro,
8106 MacroInfo *MacroInfo,
8107 unsigned Argument) {
8108 // FIXME: In the future, we could provide "overload" results, much like we
8109 // do for function calls.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008110
Argyrios Kyrtzidis75f6cd22011-08-18 19:41:28 +00008111 // Now just ignore this. There will be another code-completion callback
8112 // for the expanded tokens.
Douglas Gregorec00a262010-08-24 22:20:20 +00008113}
8114
Sam McCall3d8051a2018-09-18 08:40:41 +00008115// This handles completion inside an #include filename, e.g. #include <foo/ba
8116// We look for the directory "foo" under each directory on the include path,
8117// list its files, and reassemble the appropriate #include.
8118void Sema::CodeCompleteIncludedFile(llvm::StringRef Dir, bool Angled) {
8119 // RelDir should use /, but unescaped \ is possible on windows!
8120 // Our completions will normalize to / for simplicity, this case is rare.
8121 std::string RelDir = llvm::sys::path::convert_to_slash(Dir);
8122 // We need the native slashes for the actual file system interactions.
8123 SmallString<128> NativeRelDir = StringRef(RelDir);
8124 llvm::sys::path::native(NativeRelDir);
8125 auto FS = getSourceManager().getFileManager().getVirtualFileSystem();
8126
8127 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
8128 CodeCompleter->getCodeCompletionTUInfo(),
8129 CodeCompletionContext::CCC_IncludedFile);
8130 llvm::DenseSet<StringRef> SeenResults; // To deduplicate results.
8131
8132 // Helper: adds one file or directory completion result.
8133 auto AddCompletion = [&](StringRef Filename, bool IsDirectory) {
8134 SmallString<64> TypedChunk = Filename;
8135 // Directory completion is up to the slash, e.g. <sys/
8136 TypedChunk.push_back(IsDirectory ? '/' : Angled ? '>' : '"');
8137 auto R = SeenResults.insert(TypedChunk);
8138 if (R.second) { // New completion
8139 const char *InternedTyped = Results.getAllocator().CopyString(TypedChunk);
8140 *R.first = InternedTyped; // Avoid dangling StringRef.
8141 CodeCompletionBuilder Builder(CodeCompleter->getAllocator(),
8142 CodeCompleter->getCodeCompletionTUInfo());
8143 Builder.AddTypedTextChunk(InternedTyped);
8144 // The result is a "Pattern", which is pretty opaque.
8145 // We may want to include the real filename to allow smart ranking.
8146 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
8147 }
8148 };
8149
8150 // Helper: scans IncludeDir for nice files, and adds results for each.
8151 auto AddFilesFromIncludeDir = [&](StringRef IncludeDir, bool IsSystem) {
8152 llvm::SmallString<128> Dir = IncludeDir;
8153 if (!NativeRelDir.empty())
8154 llvm::sys::path::append(Dir, NativeRelDir);
8155
8156 std::error_code EC;
8157 unsigned Count = 0;
8158 for (auto It = FS->dir_begin(Dir, EC);
Jonas Devliegherefc514902018-10-10 13:27:25 +00008159 !EC && It != llvm::vfs::directory_iterator(); It.increment(EC)) {
Sam McCall3d8051a2018-09-18 08:40:41 +00008160 if (++Count == 2500) // If we happen to hit a huge directory,
8161 break; // bail out early so we're not too slow.
8162 StringRef Filename = llvm::sys::path::filename(It->path());
8163 switch (It->type()) {
8164 case llvm::sys::fs::file_type::directory_file:
8165 AddCompletion(Filename, /*IsDirectory=*/true);
8166 break;
8167 case llvm::sys::fs::file_type::regular_file:
8168 // Only files that really look like headers. (Except in system dirs).
8169 if (!IsSystem) {
8170 // Header extensions from Types.def, which we can't depend on here.
8171 if (!(Filename.endswith_lower(".h") ||
8172 Filename.endswith_lower(".hh") ||
8173 Filename.endswith_lower(".hpp") ||
8174 Filename.endswith_lower(".inc")))
8175 break;
8176 }
8177 AddCompletion(Filename, /*IsDirectory=*/false);
8178 break;
8179 default:
8180 break;
8181 }
8182 }
8183 };
8184
8185 // Helper: adds results relative to IncludeDir, if possible.
8186 auto AddFilesFromDirLookup = [&](const DirectoryLookup &IncludeDir,
8187 bool IsSystem) {
8188 llvm::SmallString<128> Dir;
8189 switch (IncludeDir.getLookupType()) {
8190 case DirectoryLookup::LT_HeaderMap:
8191 // header maps are not (currently) enumerable.
8192 break;
8193 case DirectoryLookup::LT_NormalDir:
8194 AddFilesFromIncludeDir(IncludeDir.getDir()->getName(), IsSystem);
8195 break;
8196 case DirectoryLookup::LT_Framework:
8197 AddFilesFromIncludeDir(IncludeDir.getFrameworkDir()->getName(), IsSystem);
8198 break;
8199 }
8200 };
8201
8202 // Finally with all our helpers, we can scan the include path.
8203 // Do this in standard order so deduplication keeps the right file.
8204 // (In case we decide to add more details to the results later).
8205 const auto &S = PP.getHeaderSearchInfo();
8206 using llvm::make_range;
8207 if (!Angled) {
8208 // The current directory is on the include path for "quoted" includes.
8209 auto *CurFile = PP.getCurrentFileLexer()->getFileEntry();
8210 if (CurFile && CurFile->getDir())
8211 AddFilesFromIncludeDir(CurFile->getDir()->getName(), false);
8212 for (const auto &D : make_range(S.quoted_dir_begin(), S.quoted_dir_end()))
8213 AddFilesFromDirLookup(D, false);
8214 }
8215 for (const auto &D : make_range(S.angled_dir_begin(), S.angled_dir_end()))
Sam McCall3e4f5eb2018-10-01 11:56:42 +00008216 AddFilesFromDirLookup(D, false);
Sam McCall3d8051a2018-09-18 08:40:41 +00008217 for (const auto &D : make_range(S.system_dir_begin(), S.system_dir_end()))
8218 AddFilesFromDirLookup(D, true);
8219
8220 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
8221 Results.data(), Results.size());
8222}
8223
Douglas Gregor11583702010-08-25 17:04:25 +00008224void Sema::CodeCompleteNaturalLanguage() {
Douglas Gregor11583702010-08-25 17:04:25 +00008225 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregorea736372010-08-25 17:10:00 +00008226 CodeCompletionContext::CCC_NaturalLanguage,
Craig Topperc3ec1492014-05-26 06:22:03 +00008227 nullptr, 0);
Douglas Gregor11583702010-08-25 17:04:25 +00008228}
8229
Alex Lorenzf7f6f822017-05-09 16:05:04 +00008230void Sema::CodeCompleteAvailabilityPlatformName() {
8231 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
8232 CodeCompleter->getCodeCompletionTUInfo(),
8233 CodeCompletionContext::CCC_Other);
8234 Results.EnterNewScope();
8235 static const char *Platforms[] = {"macOS", "iOS", "watchOS", "tvOS"};
8236 for (const char *Platform : llvm::makeArrayRef(Platforms)) {
8237 Results.AddResult(CodeCompletionResult(Platform));
8238 Results.AddResult(CodeCompletionResult(Results.getAllocator().CopyString(
8239 Twine(Platform) + "ApplicationExtension")));
8240 }
8241 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00008242 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
8243 Results.data(), Results.size());
Alex Lorenzf7f6f822017-05-09 16:05:04 +00008244}
8245
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00008246void Sema::GatherGlobalCodeCompletions(CodeCompletionAllocator &Allocator,
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008247 CodeCompletionTUInfo &CCTUInfo,
Chris Lattner0e62c1c2011-07-23 10:55:15 +00008248 SmallVectorImpl<CodeCompletionResult> &Results) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008249 ResultBuilder Builder(*this, Allocator, CCTUInfo,
8250 CodeCompletionContext::CCC_Recovery);
Douglas Gregor39982192010-08-15 06:18:01 +00008251 if (!CodeCompleter || CodeCompleter->includeGlobals()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008252 CodeCompletionDeclConsumer Consumer(Builder,
Douglas Gregor39982192010-08-15 06:18:01 +00008253 Context.getTranslationUnitDecl());
Sam McCallbb2cf632018-01-12 14:51:47 +00008254 LookupVisibleDecls(Context.getTranslationUnitDecl(), LookupAnyName,
8255 Consumer,
8256 !CodeCompleter || CodeCompleter->loadExternal());
Douglas Gregor39982192010-08-15 06:18:01 +00008257 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008258
Douglas Gregorb14904c2010-08-13 22:48:40 +00008259 if (!CodeCompleter || CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00008260 AddMacroResults(PP, Builder,
8261 CodeCompleter ? CodeCompleter->loadExternal() : false,
8262 true);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008263
Douglas Gregorb14904c2010-08-13 22:48:40 +00008264 Results.clear();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008265 Results.insert(Results.end(),
Douglas Gregorb14904c2010-08-13 22:48:40 +00008266 Builder.data(), Builder.data() + Builder.size());
8267}