blob: 9beefc05a2c20c1a95504cdf7a48b5be2ab3e234 [file] [log] [blame]
Douglas Gregor2436e712009-09-17 21:32:03 +00001//===---------------- SemaCodeComplete.cpp - Code Completion ----*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file defines the code-completion semantic actions.
11//
12//===----------------------------------------------------------------------===//
Ilya Biryukov4e7a6fe2017-09-22 19:07:37 +000013#include "clang/AST/DeclCXX.h"
John McCallde6836a2010-08-24 07:21:54 +000014#include "clang/AST/DeclObjC.h"
Douglas Gregorf2510672009-09-21 19:57:38 +000015#include "clang/AST/ExprCXX.h"
Douglas Gregor8ce33212009-11-17 17:59:40 +000016#include "clang/AST/ExprObjC.h"
Ilya Biryukovb5da91c2017-11-08 10:39:09 +000017#include "clang/AST/QualTypeNames.h"
Jordan Rose4938f272013-02-09 10:09:43 +000018#include "clang/Basic/CharInfo.h"
Douglas Gregor07f43572012-01-29 18:15:03 +000019#include "clang/Lex/HeaderSearch.h"
Douglas Gregorf329c7c2009-10-30 16:50:04 +000020#include "clang/Lex/MacroInfo.h"
21#include "clang/Lex/Preprocessor.h"
Chandler Carruth3a022472012-12-04 09:13:33 +000022#include "clang/Sema/CodeCompleteConsumer.h"
Chandler Carruth3a022472012-12-04 09:13:33 +000023#include "clang/Sema/Lookup.h"
24#include "clang/Sema/Overload.h"
25#include "clang/Sema/Scope.h"
26#include "clang/Sema/ScopeInfo.h"
Ilya Biryukov4e7a6fe2017-09-22 19:07:37 +000027#include "clang/Sema/SemaInternal.h"
Douglas Gregor1154e272010-09-16 16:06:31 +000028#include "llvm/ADT/DenseSet.h"
Benjamin Kramere0513cb2012-01-30 16:17:39 +000029#include "llvm/ADT/SmallBitVector.h"
Douglas Gregor3545ff42009-09-21 16:56:56 +000030#include "llvm/ADT/SmallPtrSet.h"
Benjamin Kramer49038022012-02-04 13:45:25 +000031#include "llvm/ADT/SmallString.h"
Douglas Gregore6688e62009-09-28 03:51:44 +000032#include "llvm/ADT/StringExtras.h"
Douglas Gregor9d2ddb22010-04-06 19:22:33 +000033#include "llvm/ADT/StringSwitch.h"
Douglas Gregor67c692c2010-08-26 15:07:07 +000034#include "llvm/ADT/Twine.h"
Douglas Gregor3545ff42009-09-21 16:56:56 +000035#include <list>
36#include <map>
37#include <vector>
Douglas Gregor2436e712009-09-17 21:32:03 +000038
39using namespace clang;
John McCallaab3e412010-08-25 08:40:02 +000040using namespace sema;
Douglas Gregor2436e712009-09-17 21:32:03 +000041
Douglas Gregor3545ff42009-09-21 16:56:56 +000042namespace {
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000043 /// A container of code-completion results.
Douglas Gregor3545ff42009-09-21 16:56:56 +000044 class ResultBuilder {
45 public:
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000046 /// The type of a name-lookup filter, which can be provided to the
Douglas Gregor3545ff42009-09-21 16:56:56 +000047 /// name-lookup routines to specify which declarations should be included in
48 /// the result set (when it returns true) and which declarations should be
49 /// filtered out (returns false).
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +000050 typedef bool (ResultBuilder::*LookupFilter)(const NamedDecl *) const;
Ivan Donchevskii13d90542017-10-27 11:05:40 +000051
John McCall276321a2010-08-25 06:19:51 +000052 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +000053
Douglas Gregor3545ff42009-09-21 16:56:56 +000054 private:
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000055 /// The actual results we have found.
Douglas Gregor3545ff42009-09-21 16:56:56 +000056 std::vector<Result> Results;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +000057
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000058 /// A record of all of the declarations we have found and placed
Douglas Gregor3545ff42009-09-21 16:56:56 +000059 /// into the result set, used to ensure that no declaration ever gets into
60 /// the result set twice.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +000061 llvm::SmallPtrSet<const Decl*, 16> AllDeclsFound;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +000062
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +000063 typedef std::pair<const NamedDecl *, unsigned> DeclIndexPair;
Douglas Gregor05e7ca32009-12-06 20:23:50 +000064
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000065 /// An entry in the shadow map, which is optimized to store
Douglas Gregor05e7ca32009-12-06 20:23:50 +000066 /// a single (declaration, index) mapping (the common case) but
67 /// can also store a list of (declaration, index) mappings.
68 class ShadowMapEntry {
Chris Lattner0e62c1c2011-07-23 10:55:15 +000069 typedef SmallVector<DeclIndexPair, 4> DeclIndexPairVector;
Douglas Gregor05e7ca32009-12-06 20:23:50 +000070
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000071 /// Contains either the solitary NamedDecl * or a vector
Douglas Gregor05e7ca32009-12-06 20:23:50 +000072 /// of (declaration, index) pairs.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +000073 llvm::PointerUnion<const NamedDecl *, DeclIndexPairVector*> DeclOrVector;
Douglas Gregor05e7ca32009-12-06 20:23:50 +000074
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000075 /// When the entry contains a single declaration, this is
Douglas Gregor05e7ca32009-12-06 20:23:50 +000076 /// the index associated with that entry.
77 unsigned SingleDeclIndex;
78
79 public:
80 ShadowMapEntry() : DeclOrVector(), SingleDeclIndex(0) { }
81
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +000082 void Add(const NamedDecl *ND, unsigned Index) {
Douglas Gregor05e7ca32009-12-06 20:23:50 +000083 if (DeclOrVector.isNull()) {
84 // 0 - > 1 elements: just set the single element information.
85 DeclOrVector = ND;
86 SingleDeclIndex = Index;
87 return;
88 }
89
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +000090 if (const NamedDecl *PrevND =
91 DeclOrVector.dyn_cast<const NamedDecl *>()) {
Douglas Gregor05e7ca32009-12-06 20:23:50 +000092 // 1 -> 2 elements: create the vector of results and push in the
93 // existing declaration.
94 DeclIndexPairVector *Vec = new DeclIndexPairVector;
95 Vec->push_back(DeclIndexPair(PrevND, SingleDeclIndex));
96 DeclOrVector = Vec;
97 }
98
99 // Add the new element to the end of the vector.
100 DeclOrVector.get<DeclIndexPairVector*>()->push_back(
101 DeclIndexPair(ND, Index));
102 }
103
104 void Destroy() {
105 if (DeclIndexPairVector *Vec
106 = DeclOrVector.dyn_cast<DeclIndexPairVector *>()) {
107 delete Vec;
Craig Topperc3ec1492014-05-26 06:22:03 +0000108 DeclOrVector = ((NamedDecl *)nullptr);
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000109 }
110 }
111
112 // Iteration.
113 class iterator;
114 iterator begin() const;
115 iterator end() const;
116 };
117
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000118 /// A mapping from declaration names to the declarations that have
Douglas Gregor3545ff42009-09-21 16:56:56 +0000119 /// this name within a particular scope and their index within the list of
120 /// results.
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000121 typedef llvm::DenseMap<DeclarationName, ShadowMapEntry> ShadowMap;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000122
123 /// The semantic analysis object for which results are being
Douglas Gregor3545ff42009-09-21 16:56:56 +0000124 /// produced.
125 Sema &SemaRef;
Douglas Gregorb278aaf2011-02-01 19:23:04 +0000126
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000127 /// The allocator used to allocate new code-completion strings.
Douglas Gregorbcbf46c2011-02-01 22:57:45 +0000128 CodeCompletionAllocator &Allocator;
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +0000129
130 CodeCompletionTUInfo &CCTUInfo;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000131
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000132 /// If non-NULL, a filter function used to remove any code-completion
Douglas Gregor3545ff42009-09-21 16:56:56 +0000133 /// results that are not desirable.
134 LookupFilter Filter;
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000135
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000136 /// Whether we should allow declarations as
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000137 /// nested-name-specifiers that would otherwise be filtered out.
138 bool AllowNestedNameSpecifiers;
139
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000140 /// If set, the type that we would prefer our resulting value
Douglas Gregor7aa6b222010-05-30 01:49:25 +0000141 /// declarations to have.
142 ///
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000143 /// Closely matching the preferred type gives a boost to a result's
Douglas Gregor7aa6b222010-05-30 01:49:25 +0000144 /// priority.
145 CanQualType PreferredType;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000146
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000147 /// A list of shadow maps, which is used to model name hiding at
Douglas Gregor3545ff42009-09-21 16:56:56 +0000148 /// different levels of, e.g., the inheritance hierarchy.
149 std::list<ShadowMap> ShadowMaps;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000150
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000151 /// If we're potentially referring to a C++ member function, the set
Douglas Gregor9be0ed42010-08-26 16:36:48 +0000152 /// of qualifiers applied to the object type.
153 Qualifiers ObjectTypeQualifiers;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000154
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000155 /// Whether the \p ObjectTypeQualifiers field is active.
Douglas Gregor9be0ed42010-08-26 16:36:48 +0000156 bool HasObjectTypeQualifiers;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000157
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000158 /// The selector that we prefer.
Douglas Gregorc2cb2e22010-08-27 15:29:55 +0000159 Selector PreferredSelector;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000160
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000161 /// The completion context in which we are gathering results.
Douglas Gregor50832e02010-09-20 22:39:41 +0000162 CodeCompletionContext CompletionContext;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000163
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000164 /// If we are in an instance method definition, the \@implementation
Douglas Gregor05fcf842010-11-02 20:36:02 +0000165 /// object.
166 ObjCImplementationDecl *ObjCImplementation;
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000167
Douglas Gregor50832e02010-09-20 22:39:41 +0000168 void AdjustResultPriorityForDecl(Result &R);
Douglas Gregor95887f92010-07-08 23:20:03 +0000169
Douglas Gregor0212fd72010-09-21 16:06:22 +0000170 void MaybeAddConstructorResults(Result R);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000171
Douglas Gregor3545ff42009-09-21 16:56:56 +0000172 public:
Douglas Gregorbcbf46c2011-02-01 22:57:45 +0000173 explicit ResultBuilder(Sema &SemaRef, CodeCompletionAllocator &Allocator,
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +0000174 CodeCompletionTUInfo &CCTUInfo,
Douglas Gregor0ac41382010-09-23 23:01:17 +0000175 const CodeCompletionContext &CompletionContext,
Craig Topperc3ec1492014-05-26 06:22:03 +0000176 LookupFilter Filter = nullptr)
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +0000177 : SemaRef(SemaRef), Allocator(Allocator), CCTUInfo(CCTUInfo),
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000178 Filter(Filter),
179 AllowNestedNameSpecifiers(false), HasObjectTypeQualifiers(false),
Douglas Gregor05fcf842010-11-02 20:36:02 +0000180 CompletionContext(CompletionContext),
Craig Topperc3ec1492014-05-26 06:22:03 +0000181 ObjCImplementation(nullptr)
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000182 {
183 // If this is an Objective-C instance method definition, dig out the
Douglas Gregor05fcf842010-11-02 20:36:02 +0000184 // corresponding implementation.
185 switch (CompletionContext.getKind()) {
186 case CodeCompletionContext::CCC_Expression:
187 case CodeCompletionContext::CCC_ObjCMessageReceiver:
188 case CodeCompletionContext::CCC_ParenthesizedExpression:
189 case CodeCompletionContext::CCC_Statement:
190 case CodeCompletionContext::CCC_Recovery:
191 if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl())
192 if (Method->isInstanceMethod())
193 if (ObjCInterfaceDecl *Interface = Method->getClassInterface())
194 ObjCImplementation = Interface->getImplementation();
195 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000196
Douglas Gregor05fcf842010-11-02 20:36:02 +0000197 default:
198 break;
199 }
200 }
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000201
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000202 /// Determine the priority for a reference to the given declaration.
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000203 unsigned getBasePriority(const NamedDecl *D);
204
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000205 /// Whether we should include code patterns in the completion
Douglas Gregorf64acca2010-05-25 21:41:55 +0000206 /// results.
207 bool includeCodePatterns() const {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000208 return SemaRef.CodeCompleter &&
Douglas Gregorac322ec2010-08-27 21:18:54 +0000209 SemaRef.CodeCompleter->includeCodePatterns();
Douglas Gregorf64acca2010-05-25 21:41:55 +0000210 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000211
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000212 /// Set the filter used for code-completion results.
Douglas Gregor3545ff42009-09-21 16:56:56 +0000213 void setFilter(LookupFilter Filter) {
214 this->Filter = Filter;
215 }
Craig Topperc3ec1492014-05-26 06:22:03 +0000216
217 Result *data() { return Results.empty()? nullptr : &Results.front(); }
Douglas Gregor3545ff42009-09-21 16:56:56 +0000218 unsigned size() const { return Results.size(); }
219 bool empty() const { return Results.empty(); }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000220
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000221 /// Specify the preferred type.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000222 void setPreferredType(QualType T) {
223 PreferredType = SemaRef.Context.getCanonicalType(T);
Douglas Gregor7aa6b222010-05-30 01:49:25 +0000224 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000225
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000226 /// Set the cv-qualifiers on the object type, for us in filtering
Douglas Gregor9be0ed42010-08-26 16:36:48 +0000227 /// calls to member functions.
228 ///
229 /// When there are qualifiers in this set, they will be used to filter
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000230 /// out member functions that aren't available (because there will be a
Douglas Gregor9be0ed42010-08-26 16:36:48 +0000231 /// cv-qualifier mismatch) or prefer functions with an exact qualifier
232 /// match.
233 void setObjectTypeQualifiers(Qualifiers Quals) {
234 ObjectTypeQualifiers = Quals;
235 HasObjectTypeQualifiers = true;
236 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000237
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000238 /// Set the preferred selector.
Douglas Gregorc2cb2e22010-08-27 15:29:55 +0000239 ///
240 /// When an Objective-C method declaration result is added, and that
241 /// method's selector matches this preferred selector, we give that method
242 /// a slight priority boost.
243 void setPreferredSelector(Selector Sel) {
244 PreferredSelector = Sel;
245 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000246
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000247 /// Retrieve the code-completion context for which results are
Douglas Gregor50832e02010-09-20 22:39:41 +0000248 /// being collected.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000249 const CodeCompletionContext &getCompletionContext() const {
250 return CompletionContext;
Douglas Gregor50832e02010-09-20 22:39:41 +0000251 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000252
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000253 /// Specify whether nested-name-specifiers are allowed.
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000254 void allowNestedNameSpecifiers(bool Allow = true) {
255 AllowNestedNameSpecifiers = Allow;
256 }
257
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000258 /// Return the semantic analysis object for which we are collecting
Douglas Gregor74661272010-09-21 00:03:25 +0000259 /// code completion results.
260 Sema &getSema() const { return SemaRef; }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000261
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000262 /// Retrieve the allocator used to allocate code completion strings.
Douglas Gregorbcbf46c2011-02-01 22:57:45 +0000263 CodeCompletionAllocator &getAllocator() const { return Allocator; }
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +0000264
265 CodeCompletionTUInfo &getCodeCompletionTUInfo() const { return CCTUInfo; }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000266
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000267 /// Determine whether the given declaration is at all interesting
Douglas Gregor7c208612010-01-14 00:20:49 +0000268 /// as a code-completion result.
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000269 ///
270 /// \param ND the declaration that we are inspecting.
271 ///
272 /// \param AsNestedNameSpecifier will be set true if this declaration is
273 /// only interesting when it is a nested-name-specifier.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000274 bool isInterestingDecl(const NamedDecl *ND,
275 bool &AsNestedNameSpecifier) const;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000276
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000277 /// Check whether the result is hidden by the Hiding declaration.
Douglas Gregore0717ab2010-01-14 00:41:07 +0000278 ///
279 /// \returns true if the result is hidden and cannot be found, false if
280 /// the hidden result could still be found. When false, \p R may be
281 /// modified to describe how the result can be found (e.g., via extra
282 /// qualification).
283 bool CheckHiddenResult(Result &R, DeclContext *CurContext,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000284 const NamedDecl *Hiding);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000285
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000286 /// Add a new result to this result set (if it isn't already in one
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000287 /// of the shadow maps), or replace an existing result (for, e.g., a
Douglas Gregor3545ff42009-09-21 16:56:56 +0000288 /// redeclaration).
Douglas Gregor2af2f672009-09-21 20:12:40 +0000289 ///
Douglas Gregord8c61782012-02-15 15:34:24 +0000290 /// \param R the result to add (if it is unique).
Douglas Gregor2af2f672009-09-21 20:12:40 +0000291 ///
Douglas Gregord8c61782012-02-15 15:34:24 +0000292 /// \param CurContext the context in which this result will be named.
Craig Topperc3ec1492014-05-26 06:22:03 +0000293 void MaybeAddResult(Result R, DeclContext *CurContext = nullptr);
294
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000295 /// Add a new result to this result set, where we already know
Yaron Keren8fbe43982014-11-14 18:33:42 +0000296 /// the hiding declaration (if any).
Douglas Gregorc580c522010-01-14 01:09:38 +0000297 ///
298 /// \param R the result to add (if it is unique).
299 ///
300 /// \param CurContext the context in which this result will be named.
301 ///
302 /// \param Hiding the declaration that hides the result.
Douglas Gregor09bbc652010-01-14 15:47:35 +0000303 ///
304 /// \param InBaseClass whether the result was found in a base
305 /// class of the searched context.
306 void AddResult(Result R, DeclContext *CurContext, NamedDecl *Hiding,
307 bool InBaseClass);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000308
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000309 /// Add a new non-declaration result to this result set.
Douglas Gregor78a21012010-01-14 16:01:26 +0000310 void AddResult(Result R);
311
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000312 /// Enter into a new scope.
Douglas Gregor3545ff42009-09-21 16:56:56 +0000313 void EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000314
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000315 /// Exit from the current scope.
Douglas Gregor3545ff42009-09-21 16:56:56 +0000316 void ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000317
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000318 /// Ignore this declaration, if it is seen again.
Dmitri Gribenko6cfb1532013-02-14 13:53:30 +0000319 void Ignore(const Decl *D) { AllDeclsFound.insert(D->getCanonicalDecl()); }
Douglas Gregorbaf69612009-11-18 04:19:12 +0000320
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000321 /// Add a visited context.
Haojian Wu10d95c52018-01-17 14:29:25 +0000322 void addVisitedContext(DeclContext *Ctx) {
323 CompletionContext.addVisitedContext(Ctx);
324 }
325
Douglas Gregor3545ff42009-09-21 16:56:56 +0000326 /// \name Name lookup predicates
327 ///
328 /// These predicates can be passed to the name lookup functions to filter the
329 /// results of name lookup. All of the predicates have the same type, so that
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000330 ///
Douglas Gregor3545ff42009-09-21 16:56:56 +0000331 //@{
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000332 bool IsOrdinaryName(const NamedDecl *ND) const;
333 bool IsOrdinaryNonTypeName(const NamedDecl *ND) const;
334 bool IsIntegralConstantValue(const NamedDecl *ND) const;
335 bool IsOrdinaryNonValueName(const NamedDecl *ND) const;
336 bool IsNestedNameSpecifier(const NamedDecl *ND) const;
337 bool IsEnum(const NamedDecl *ND) const;
338 bool IsClassOrStruct(const NamedDecl *ND) const;
339 bool IsUnion(const NamedDecl *ND) const;
340 bool IsNamespace(const NamedDecl *ND) const;
341 bool IsNamespaceOrAlias(const NamedDecl *ND) const;
342 bool IsType(const NamedDecl *ND) const;
343 bool IsMember(const NamedDecl *ND) const;
344 bool IsObjCIvar(const NamedDecl *ND) const;
345 bool IsObjCMessageReceiver(const NamedDecl *ND) const;
346 bool IsObjCMessageReceiverOrLambdaCapture(const NamedDecl *ND) const;
347 bool IsObjCCollection(const NamedDecl *ND) const;
348 bool IsImpossibleToSatisfy(const NamedDecl *ND) const;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000349 //@}
350 };
Alexander Kornienkoab9db512015-06-22 23:07:51 +0000351}
Douglas Gregor3545ff42009-09-21 16:56:56 +0000352
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000353class ResultBuilder::ShadowMapEntry::iterator {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000354 llvm::PointerUnion<const NamedDecl *, const DeclIndexPair *> DeclOrIterator;
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000355 unsigned SingleDeclIndex;
356
357public:
358 typedef DeclIndexPair value_type;
359 typedef value_type reference;
360 typedef std::ptrdiff_t difference_type;
361 typedef std::input_iterator_tag iterator_category;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000362
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000363 class pointer {
364 DeclIndexPair Value;
365
366 public:
367 pointer(const DeclIndexPair &Value) : Value(Value) { }
368
369 const DeclIndexPair *operator->() const {
370 return &Value;
371 }
372 };
Craig Topperc3ec1492014-05-26 06:22:03 +0000373
374 iterator() : DeclOrIterator((NamedDecl *)nullptr), SingleDeclIndex(0) {}
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000375
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000376 iterator(const NamedDecl *SingleDecl, unsigned Index)
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000377 : DeclOrIterator(SingleDecl), SingleDeclIndex(Index) { }
378
379 iterator(const DeclIndexPair *Iterator)
380 : DeclOrIterator(Iterator), SingleDeclIndex(0) { }
381
382 iterator &operator++() {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000383 if (DeclOrIterator.is<const NamedDecl *>()) {
Craig Topperc3ec1492014-05-26 06:22:03 +0000384 DeclOrIterator = (NamedDecl *)nullptr;
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000385 SingleDeclIndex = 0;
386 return *this;
387 }
388
389 const DeclIndexPair *I = DeclOrIterator.get<const DeclIndexPair*>();
390 ++I;
391 DeclOrIterator = I;
392 return *this;
393 }
394
Chris Lattner9795b392010-09-04 18:12:20 +0000395 /*iterator operator++(int) {
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000396 iterator tmp(*this);
397 ++(*this);
398 return tmp;
Chris Lattner9795b392010-09-04 18:12:20 +0000399 }*/
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000400
401 reference operator*() const {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000402 if (const NamedDecl *ND = DeclOrIterator.dyn_cast<const NamedDecl *>())
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000403 return reference(ND, SingleDeclIndex);
404
Douglas Gregor94bb5e82009-12-06 21:27:58 +0000405 return *DeclOrIterator.get<const DeclIndexPair*>();
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000406 }
407
408 pointer operator->() const {
409 return pointer(**this);
410 }
411
412 friend bool operator==(const iterator &X, const iterator &Y) {
Douglas Gregor94bb5e82009-12-06 21:27:58 +0000413 return X.DeclOrIterator.getOpaqueValue()
414 == Y.DeclOrIterator.getOpaqueValue() &&
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000415 X.SingleDeclIndex == Y.SingleDeclIndex;
416 }
417
418 friend bool operator!=(const iterator &X, const iterator &Y) {
Douglas Gregor94bb5e82009-12-06 21:27:58 +0000419 return !(X == Y);
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000420 }
421};
422
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000423ResultBuilder::ShadowMapEntry::iterator
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000424ResultBuilder::ShadowMapEntry::begin() const {
425 if (DeclOrVector.isNull())
426 return iterator();
427
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000428 if (const NamedDecl *ND = DeclOrVector.dyn_cast<const NamedDecl *>())
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000429 return iterator(ND, SingleDeclIndex);
430
431 return iterator(DeclOrVector.get<DeclIndexPairVector *>()->begin());
432}
433
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000434ResultBuilder::ShadowMapEntry::iterator
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000435ResultBuilder::ShadowMapEntry::end() const {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000436 if (DeclOrVector.is<const NamedDecl *>() || DeclOrVector.isNull())
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000437 return iterator();
438
439 return iterator(DeclOrVector.get<DeclIndexPairVector *>()->end());
440}
441
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000442/// Compute the qualification required to get from the current context
Douglas Gregor2af2f672009-09-21 20:12:40 +0000443/// (\p CurContext) to the target context (\p TargetContext).
444///
445/// \param Context the AST context in which the qualification will be used.
446///
447/// \param CurContext the context where an entity is being named, which is
448/// typically based on the current scope.
449///
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000450/// \param TargetContext the context in which the named entity actually
Douglas Gregor2af2f672009-09-21 20:12:40 +0000451/// resides.
452///
453/// \returns a nested name specifier that refers into the target context, or
454/// NULL if no qualification is needed.
455static NestedNameSpecifier *
456getRequiredQualification(ASTContext &Context,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000457 const DeclContext *CurContext,
458 const DeclContext *TargetContext) {
459 SmallVector<const DeclContext *, 4> TargetParents;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000460
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000461 for (const DeclContext *CommonAncestor = TargetContext;
Douglas Gregor2af2f672009-09-21 20:12:40 +0000462 CommonAncestor && !CommonAncestor->Encloses(CurContext);
463 CommonAncestor = CommonAncestor->getLookupParent()) {
464 if (CommonAncestor->isTransparentContext() ||
465 CommonAncestor->isFunctionOrMethod())
466 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000467
Douglas Gregor2af2f672009-09-21 20:12:40 +0000468 TargetParents.push_back(CommonAncestor);
469 }
Craig Topperc3ec1492014-05-26 06:22:03 +0000470
471 NestedNameSpecifier *Result = nullptr;
Douglas Gregor2af2f672009-09-21 20:12:40 +0000472 while (!TargetParents.empty()) {
Robert Wilhelm25284cc2013-08-23 16:11:15 +0000473 const DeclContext *Parent = TargetParents.pop_back_val();
474
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000475 if (const NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Parent)) {
Douglas Gregor68762e72010-08-23 21:17:50 +0000476 if (!Namespace->getIdentifier())
477 continue;
478
Douglas Gregor2af2f672009-09-21 20:12:40 +0000479 Result = NestedNameSpecifier::Create(Context, Result, Namespace);
Douglas Gregor68762e72010-08-23 21:17:50 +0000480 }
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000481 else if (const TagDecl *TD = dyn_cast<TagDecl>(Parent))
Douglas Gregor2af2f672009-09-21 20:12:40 +0000482 Result = NestedNameSpecifier::Create(Context, Result,
483 false,
484 Context.getTypeDeclType(TD).getTypePtr());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000485 }
Douglas Gregor2af2f672009-09-21 20:12:40 +0000486 return Result;
487}
488
Alp Toker034bbd52014-06-30 01:33:53 +0000489/// Determine whether \p Id is a name reserved for the implementation (C99
490/// 7.1.3, C++ [lib.global.names]).
Argyrios Kyrtzidis5d8006d2016-07-01 01:17:02 +0000491static bool isReservedName(const IdentifierInfo *Id,
492 bool doubleUnderscoreOnly = false) {
Alp Toker034bbd52014-06-30 01:33:53 +0000493 if (Id->getLength() < 2)
494 return false;
495 const char *Name = Id->getNameStart();
496 return Name[0] == '_' &&
Argyrios Kyrtzidis5d8006d2016-07-01 01:17:02 +0000497 (Name[1] == '_' || (Name[1] >= 'A' && Name[1] <= 'Z' &&
498 !doubleUnderscoreOnly));
499}
500
501// Some declarations have reserved names that we don't want to ever show.
502// Filter out names reserved for the implementation if they come from a
503// system header.
504static bool shouldIgnoreDueToReservedName(const NamedDecl *ND, Sema &SemaRef) {
505 const IdentifierInfo *Id = ND->getIdentifier();
506 if (!Id)
507 return false;
508
509 // Ignore reserved names for compiler provided decls.
510 if (isReservedName(Id) && ND->getLocation().isInvalid())
511 return true;
512
513 // For system headers ignore only double-underscore names.
514 // This allows for system headers providing private symbols with a single
515 // underscore.
516 if (isReservedName(Id, /*doubleUnderscoreOnly=*/true) &&
517 SemaRef.SourceMgr.isInSystemHeader(
518 SemaRef.SourceMgr.getSpellingLoc(ND->getLocation())))
519 return true;
520
521 return false;
Alp Toker034bbd52014-06-30 01:33:53 +0000522}
523
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000524bool ResultBuilder::isInterestingDecl(const NamedDecl *ND,
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000525 bool &AsNestedNameSpecifier) const {
526 AsNestedNameSpecifier = false;
527
Richard Smithf2005d32015-12-29 23:34:32 +0000528 auto *Named = ND;
Douglas Gregor7c208612010-01-14 00:20:49 +0000529 ND = ND->getUnderlyingDecl();
Douglas Gregor58acf322009-10-09 22:16:47 +0000530
531 // Skip unnamed entities.
Douglas Gregor7c208612010-01-14 00:20:49 +0000532 if (!ND->getDeclName())
533 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000534
Douglas Gregor3545ff42009-09-21 16:56:56 +0000535 // Friend declarations and declarations introduced due to friends are never
536 // added as results.
Richard Smith6eece292015-01-15 02:27:20 +0000537 if (ND->getFriendObjectKind() == Decl::FOK_Undeclared)
Douglas Gregor7c208612010-01-14 00:20:49 +0000538 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000539
Douglas Gregor99fe2ad2009-12-11 17:31:05 +0000540 // Class template (partial) specializations are never added as results.
Douglas Gregor7c208612010-01-14 00:20:49 +0000541 if (isa<ClassTemplateSpecializationDecl>(ND) ||
542 isa<ClassTemplatePartialSpecializationDecl>(ND))
543 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000544
Douglas Gregor99fe2ad2009-12-11 17:31:05 +0000545 // Using declarations themselves are never added as results.
Douglas Gregor7c208612010-01-14 00:20:49 +0000546 if (isa<UsingDecl>(ND))
547 return false;
Argyrios Kyrtzidis5d8006d2016-07-01 01:17:02 +0000548
549 if (shouldIgnoreDueToReservedName(ND, SemaRef))
550 return false;
Douglas Gregor2927c0c2010-11-09 03:59:40 +0000551
Douglas Gregor59cab552010-08-16 23:05:20 +0000552 if (Filter == &ResultBuilder::IsNestedNameSpecifier ||
Richard Smithf2005d32015-12-29 23:34:32 +0000553 (isa<NamespaceDecl>(ND) &&
Douglas Gregor59cab552010-08-16 23:05:20 +0000554 Filter != &ResultBuilder::IsNamespace &&
Douglas Gregor0ac41382010-09-23 23:01:17 +0000555 Filter != &ResultBuilder::IsNamespaceOrAlias &&
Craig Topperc3ec1492014-05-26 06:22:03 +0000556 Filter != nullptr))
Douglas Gregor59cab552010-08-16 23:05:20 +0000557 AsNestedNameSpecifier = true;
558
Douglas Gregor3545ff42009-09-21 16:56:56 +0000559 // Filter out any unwanted results.
Richard Smithf2005d32015-12-29 23:34:32 +0000560 if (Filter && !(this->*Filter)(Named)) {
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000561 // Check whether it is interesting as a nested-name-specifier.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000562 if (AllowNestedNameSpecifiers && SemaRef.getLangOpts().CPlusPlus &&
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000563 IsNestedNameSpecifier(ND) &&
564 (Filter != &ResultBuilder::IsMember ||
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000565 (isa<CXXRecordDecl>(ND) &&
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000566 cast<CXXRecordDecl>(ND)->isInjectedClassName()))) {
567 AsNestedNameSpecifier = true;
568 return true;
569 }
570
Douglas Gregor7c208612010-01-14 00:20:49 +0000571 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000572 }
Douglas Gregor7c208612010-01-14 00:20:49 +0000573 // ... then it must be interesting!
574 return true;
575}
576
Douglas Gregore0717ab2010-01-14 00:41:07 +0000577bool ResultBuilder::CheckHiddenResult(Result &R, DeclContext *CurContext,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000578 const NamedDecl *Hiding) {
Douglas Gregore0717ab2010-01-14 00:41:07 +0000579 // In C, there is no way to refer to a hidden name.
580 // FIXME: This isn't true; we can find a tag name hidden by an ordinary
581 // name if we introduce the tag type.
David Blaikiebbafb8a2012-03-11 07:00:24 +0000582 if (!SemaRef.getLangOpts().CPlusPlus)
Douglas Gregore0717ab2010-01-14 00:41:07 +0000583 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000584
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000585 const DeclContext *HiddenCtx =
586 R.Declaration->getDeclContext()->getRedeclContext();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000587
Douglas Gregore0717ab2010-01-14 00:41:07 +0000588 // There is no way to qualify a name declared in a function or method.
589 if (HiddenCtx->isFunctionOrMethod())
590 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000591
Sebastian Redl50c68252010-08-31 00:36:30 +0000592 if (HiddenCtx == Hiding->getDeclContext()->getRedeclContext())
Douglas Gregore0717ab2010-01-14 00:41:07 +0000593 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000594
Douglas Gregore0717ab2010-01-14 00:41:07 +0000595 // We can refer to the result with the appropriate qualification. Do it.
596 R.Hidden = true;
597 R.QualifierIsInformative = false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000598
Douglas Gregore0717ab2010-01-14 00:41:07 +0000599 if (!R.Qualifier)
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000600 R.Qualifier = getRequiredQualification(SemaRef.Context,
601 CurContext,
Douglas Gregore0717ab2010-01-14 00:41:07 +0000602 R.Declaration->getDeclContext());
603 return false;
604}
605
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000606/// A simplified classification of types used to determine whether two
Douglas Gregor95887f92010-07-08 23:20:03 +0000607/// types are "similar enough" when adjusting priorities.
Douglas Gregor6e240332010-08-16 16:18:59 +0000608SimplifiedTypeClass clang::getSimplifiedTypeClass(CanQualType T) {
Douglas Gregor95887f92010-07-08 23:20:03 +0000609 switch (T->getTypeClass()) {
610 case Type::Builtin:
611 switch (cast<BuiltinType>(T)->getKind()) {
612 case BuiltinType::Void:
613 return STC_Void;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000614
Douglas Gregor95887f92010-07-08 23:20:03 +0000615 case BuiltinType::NullPtr:
616 return STC_Pointer;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000617
Douglas Gregor95887f92010-07-08 23:20:03 +0000618 case BuiltinType::Overload:
619 case BuiltinType::Dependent:
Douglas Gregor95887f92010-07-08 23:20:03 +0000620 return STC_Other;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000621
Douglas Gregor95887f92010-07-08 23:20:03 +0000622 case BuiltinType::ObjCId:
623 case BuiltinType::ObjCClass:
624 case BuiltinType::ObjCSel:
625 return STC_ObjectiveC;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000626
Douglas Gregor95887f92010-07-08 23:20:03 +0000627 default:
628 return STC_Arithmetic;
629 }
David Blaikie8a40f702012-01-17 06:56:22 +0000630
Douglas Gregor95887f92010-07-08 23:20:03 +0000631 case Type::Complex:
632 return STC_Arithmetic;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000633
Douglas Gregor95887f92010-07-08 23:20:03 +0000634 case Type::Pointer:
635 return STC_Pointer;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000636
Douglas Gregor95887f92010-07-08 23:20:03 +0000637 case Type::BlockPointer:
638 return STC_Block;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000639
Douglas Gregor95887f92010-07-08 23:20:03 +0000640 case Type::LValueReference:
641 case Type::RValueReference:
642 return getSimplifiedTypeClass(T->getAs<ReferenceType>()->getPointeeType());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000643
Douglas Gregor95887f92010-07-08 23:20:03 +0000644 case Type::ConstantArray:
645 case Type::IncompleteArray:
646 case Type::VariableArray:
647 case Type::DependentSizedArray:
648 return STC_Array;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000649
Douglas Gregor95887f92010-07-08 23:20:03 +0000650 case Type::DependentSizedExtVector:
651 case Type::Vector:
652 case Type::ExtVector:
653 return STC_Arithmetic;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000654
Douglas Gregor95887f92010-07-08 23:20:03 +0000655 case Type::FunctionProto:
656 case Type::FunctionNoProto:
657 return STC_Function;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000658
Douglas Gregor95887f92010-07-08 23:20:03 +0000659 case Type::Record:
660 return STC_Record;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000661
Douglas Gregor95887f92010-07-08 23:20:03 +0000662 case Type::Enum:
663 return STC_Arithmetic;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000664
Douglas Gregor95887f92010-07-08 23:20:03 +0000665 case Type::ObjCObject:
666 case Type::ObjCInterface:
667 case Type::ObjCObjectPointer:
668 return STC_ObjectiveC;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000669
Douglas Gregor95887f92010-07-08 23:20:03 +0000670 default:
671 return STC_Other;
672 }
673}
674
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000675/// Get the type that a given expression will have if this declaration
Douglas Gregor95887f92010-07-08 23:20:03 +0000676/// is used as an expression in its "typical" code-completion form.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000677QualType clang::getDeclUsageType(ASTContext &C, const NamedDecl *ND) {
George Burgess IV00f70bd2018-03-01 05:43:23 +0000678 ND = ND->getUnderlyingDecl();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000679
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000680 if (const TypeDecl *Type = dyn_cast<TypeDecl>(ND))
Douglas Gregor95887f92010-07-08 23:20:03 +0000681 return C.getTypeDeclType(Type);
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000682 if (const ObjCInterfaceDecl *Iface = dyn_cast<ObjCInterfaceDecl>(ND))
Douglas Gregor95887f92010-07-08 23:20:03 +0000683 return C.getObjCInterfaceType(Iface);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000684
Douglas Gregor95887f92010-07-08 23:20:03 +0000685 QualType T;
Alp Tokera2794f92014-01-22 07:29:52 +0000686 if (const FunctionDecl *Function = ND->getAsFunction())
Douglas Gregor603d81b2010-07-13 08:18:22 +0000687 T = Function->getCallResultType();
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000688 else if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND))
Douglas Gregor603d81b2010-07-13 08:18:22 +0000689 T = Method->getSendResultType();
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000690 else if (const EnumConstantDecl *Enumerator = dyn_cast<EnumConstantDecl>(ND))
Douglas Gregor95887f92010-07-08 23:20:03 +0000691 T = C.getTypeDeclType(cast<EnumDecl>(Enumerator->getDeclContext()));
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000692 else if (const ObjCPropertyDecl *Property = dyn_cast<ObjCPropertyDecl>(ND))
Douglas Gregor95887f92010-07-08 23:20:03 +0000693 T = Property->getType();
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000694 else if (const ValueDecl *Value = dyn_cast<ValueDecl>(ND))
Douglas Gregor95887f92010-07-08 23:20:03 +0000695 T = Value->getType();
696 else
697 return QualType();
Douglas Gregoraf670a82011-04-14 20:33:34 +0000698
699 // Dig through references, function pointers, and block pointers to
700 // get down to the likely type of an expression when the entity is
701 // used.
702 do {
703 if (const ReferenceType *Ref = T->getAs<ReferenceType>()) {
704 T = Ref->getPointeeType();
705 continue;
706 }
707
708 if (const PointerType *Pointer = T->getAs<PointerType>()) {
709 if (Pointer->getPointeeType()->isFunctionType()) {
710 T = Pointer->getPointeeType();
711 continue;
712 }
713
714 break;
715 }
716
717 if (const BlockPointerType *Block = T->getAs<BlockPointerType>()) {
718 T = Block->getPointeeType();
719 continue;
720 }
721
722 if (const FunctionType *Function = T->getAs<FunctionType>()) {
Alp Toker314cc812014-01-25 16:55:45 +0000723 T = Function->getReturnType();
Douglas Gregoraf670a82011-04-14 20:33:34 +0000724 continue;
725 }
726
727 break;
728 } while (true);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000729
Douglas Gregoraf670a82011-04-14 20:33:34 +0000730 return T;
Douglas Gregor95887f92010-07-08 23:20:03 +0000731}
732
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000733unsigned ResultBuilder::getBasePriority(const NamedDecl *ND) {
734 if (!ND)
735 return CCP_Unlikely;
736
737 // Context-based decisions.
Richard Smith541b38b2013-09-20 01:15:31 +0000738 const DeclContext *LexicalDC = ND->getLexicalDeclContext();
739 if (LexicalDC->isFunctionOrMethod()) {
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000740 // _cmd is relatively rare
741 if (const ImplicitParamDecl *ImplicitParam =
742 dyn_cast<ImplicitParamDecl>(ND))
743 if (ImplicitParam->getIdentifier() &&
744 ImplicitParam->getIdentifier()->isStr("_cmd"))
745 return CCP_ObjC_cmd;
746
747 return CCP_LocalDeclaration;
748 }
Richard Smith541b38b2013-09-20 01:15:31 +0000749
750 const DeclContext *DC = ND->getDeclContext()->getRedeclContext();
Ilya Biryukov4e7a6fe2017-09-22 19:07:37 +0000751 if (DC->isRecord() || isa<ObjCContainerDecl>(DC)) {
752 // Explicit destructor calls are very rare.
753 if (isa<CXXDestructorDecl>(ND))
754 return CCP_Unlikely;
755 // Explicit operator and conversion function calls are also very rare.
756 auto DeclNameKind = ND->getDeclName().getNameKind();
757 if (DeclNameKind == DeclarationName::CXXOperatorName ||
758 DeclNameKind == DeclarationName::CXXLiteralOperatorName ||
759 DeclNameKind == DeclarationName::CXXConversionFunctionName)
760 return CCP_Unlikely;
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000761 return CCP_MemberDeclaration;
Ilya Biryukov4e7a6fe2017-09-22 19:07:37 +0000762 }
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000763
764 // Content-based decisions.
765 if (isa<EnumConstantDecl>(ND))
766 return CCP_Constant;
767
Douglas Gregor52e0de42013-01-31 05:03:46 +0000768 // Use CCP_Type for type declarations unless we're in a statement, Objective-C
769 // message receiver, or parenthesized expression context. There, it's as
770 // likely that the user will want to write a type as other declarations.
771 if ((isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND)) &&
772 !(CompletionContext.getKind() == CodeCompletionContext::CCC_Statement ||
773 CompletionContext.getKind()
774 == CodeCompletionContext::CCC_ObjCMessageReceiver ||
775 CompletionContext.getKind()
776 == CodeCompletionContext::CCC_ParenthesizedExpression))
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000777 return CCP_Type;
778
779 return CCP_Declaration;
780}
781
Douglas Gregor50832e02010-09-20 22:39:41 +0000782void ResultBuilder::AdjustResultPriorityForDecl(Result &R) {
783 // If this is an Objective-C method declaration whose selector matches our
784 // preferred selector, give it a priority boost.
785 if (!PreferredSelector.isNull())
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000786 if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(R.Declaration))
Douglas Gregor50832e02010-09-20 22:39:41 +0000787 if (PreferredSelector == Method->getSelector())
788 R.Priority += CCD_SelectorMatch;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000789
Douglas Gregor50832e02010-09-20 22:39:41 +0000790 // If we have a preferred type, adjust the priority for results with exactly-
791 // matching or nearly-matching types.
792 if (!PreferredType.isNull()) {
793 QualType T = getDeclUsageType(SemaRef.Context, R.Declaration);
794 if (!T.isNull()) {
795 CanQualType TC = SemaRef.Context.getCanonicalType(T);
796 // Check for exactly-matching types (modulo qualifiers).
797 if (SemaRef.Context.hasSameUnqualifiedType(PreferredType, TC))
798 R.Priority /= CCF_ExactTypeMatch;
799 // Check for nearly-matching types, based on classification of each.
800 else if ((getSimplifiedTypeClass(PreferredType)
Douglas Gregor95887f92010-07-08 23:20:03 +0000801 == getSimplifiedTypeClass(TC)) &&
Douglas Gregor50832e02010-09-20 22:39:41 +0000802 !(PreferredType->isEnumeralType() && TC->isEnumeralType()))
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000803 R.Priority /= CCF_SimilarTypeMatch;
Douglas Gregor50832e02010-09-20 22:39:41 +0000804 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000805 }
Douglas Gregor95887f92010-07-08 23:20:03 +0000806}
807
Douglas Gregor0212fd72010-09-21 16:06:22 +0000808void ResultBuilder::MaybeAddConstructorResults(Result R) {
David Blaikiebbafb8a2012-03-11 07:00:24 +0000809 if (!SemaRef.getLangOpts().CPlusPlus || !R.Declaration ||
Douglas Gregor0212fd72010-09-21 16:06:22 +0000810 !CompletionContext.wantConstructorResults())
811 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000812
Douglas Gregor0212fd72010-09-21 16:06:22 +0000813 ASTContext &Context = SemaRef.Context;
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000814 const NamedDecl *D = R.Declaration;
Craig Topperc3ec1492014-05-26 06:22:03 +0000815 const CXXRecordDecl *Record = nullptr;
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000816 if (const ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(D))
Douglas Gregor0212fd72010-09-21 16:06:22 +0000817 Record = ClassTemplate->getTemplatedDecl();
818 else if ((Record = dyn_cast<CXXRecordDecl>(D))) {
819 // Skip specializations and partial specializations.
820 if (isa<ClassTemplateSpecializationDecl>(Record))
821 return;
822 } else {
823 // There are no constructors here.
824 return;
825 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000826
Douglas Gregor0212fd72010-09-21 16:06:22 +0000827 Record = Record->getDefinition();
828 if (!Record)
829 return;
830
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000831
Douglas Gregor0212fd72010-09-21 16:06:22 +0000832 QualType RecordTy = Context.getTypeDeclType(Record);
833 DeclarationName ConstructorName
834 = Context.DeclarationNames.getCXXConstructorName(
835 Context.getCanonicalType(RecordTy));
Richard Smithcf4bdde2015-02-21 02:45:19 +0000836 DeclContext::lookup_result Ctors = Record->lookup(ConstructorName);
837 for (DeclContext::lookup_iterator I = Ctors.begin(),
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000838 E = Ctors.end();
839 I != E; ++I) {
David Blaikieff7d47a2012-12-19 00:45:41 +0000840 R.Declaration = *I;
Douglas Gregor0212fd72010-09-21 16:06:22 +0000841 R.CursorKind = getCursorKindForDecl(R.Declaration);
842 Results.push_back(R);
843 }
844}
845
Sam McCall63c59722018-01-22 20:44:47 +0000846static bool isConstructor(const Decl *ND) {
847 if (const auto *Tmpl = dyn_cast<FunctionTemplateDecl>(ND))
848 ND = Tmpl->getTemplatedDecl();
849 return isa<CXXConstructorDecl>(ND);
850}
851
Douglas Gregor7c208612010-01-14 00:20:49 +0000852void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) {
853 assert(!ShadowMaps.empty() && "Must enter into a results scope");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000854
Douglas Gregor7c208612010-01-14 00:20:49 +0000855 if (R.Kind != Result::RK_Declaration) {
856 // For non-declaration results, just add the result.
857 Results.push_back(R);
858 return;
859 }
860
861 // Look through using declarations.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000862 if (const UsingShadowDecl *Using =
863 dyn_cast<UsingShadowDecl>(R.Declaration)) {
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000864 MaybeAddResult(Result(Using->getTargetDecl(),
865 getBasePriority(Using->getTargetDecl()),
866 R.Qualifier),
867 CurContext);
Douglas Gregor7c208612010-01-14 00:20:49 +0000868 return;
869 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000870
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000871 const Decl *CanonDecl = R.Declaration->getCanonicalDecl();
Douglas Gregor7c208612010-01-14 00:20:49 +0000872 unsigned IDNS = CanonDecl->getIdentifierNamespace();
873
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000874 bool AsNestedNameSpecifier = false;
875 if (!isInterestingDecl(R.Declaration, AsNestedNameSpecifier))
Douglas Gregor7c208612010-01-14 00:20:49 +0000876 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000877
Douglas Gregor0212fd72010-09-21 16:06:22 +0000878 // C++ constructors are never found by name lookup.
Sam McCall63c59722018-01-22 20:44:47 +0000879 if (isConstructor(R.Declaration))
Douglas Gregor0212fd72010-09-21 16:06:22 +0000880 return;
881
Douglas Gregor3545ff42009-09-21 16:56:56 +0000882 ShadowMap &SMap = ShadowMaps.back();
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000883 ShadowMapEntry::iterator I, IEnd;
884 ShadowMap::iterator NamePos = SMap.find(R.Declaration->getDeclName());
885 if (NamePos != SMap.end()) {
886 I = NamePos->second.begin();
887 IEnd = NamePos->second.end();
888 }
889
890 for (; I != IEnd; ++I) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000891 const NamedDecl *ND = I->first;
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000892 unsigned Index = I->second;
Douglas Gregor3545ff42009-09-21 16:56:56 +0000893 if (ND->getCanonicalDecl() == CanonDecl) {
894 // This is a redeclaration. Always pick the newer declaration.
Douglas Gregor3545ff42009-09-21 16:56:56 +0000895 Results[Index].Declaration = R.Declaration;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000896
Douglas Gregor3545ff42009-09-21 16:56:56 +0000897 // We're done.
898 return;
899 }
900 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000901
Douglas Gregor3545ff42009-09-21 16:56:56 +0000902 // This is a new declaration in this scope. However, check whether this
903 // declaration name is hidden by a similarly-named declaration in an outer
904 // scope.
905 std::list<ShadowMap>::iterator SM, SMEnd = ShadowMaps.end();
906 --SMEnd;
907 for (SM = ShadowMaps.begin(); SM != SMEnd; ++SM) {
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000908 ShadowMapEntry::iterator I, IEnd;
909 ShadowMap::iterator NamePos = SM->find(R.Declaration->getDeclName());
910 if (NamePos != SM->end()) {
911 I = NamePos->second.begin();
912 IEnd = NamePos->second.end();
913 }
914 for (; I != IEnd; ++I) {
Douglas Gregor3545ff42009-09-21 16:56:56 +0000915 // A tag declaration does not hide a non-tag declaration.
John McCalle87beb22010-04-23 18:46:30 +0000916 if (I->first->hasTagIdentifierNamespace() &&
Richard Smith541b38b2013-09-20 01:15:31 +0000917 (IDNS & (Decl::IDNS_Member | Decl::IDNS_Ordinary |
918 Decl::IDNS_LocalExtern | Decl::IDNS_ObjCProtocol)))
Douglas Gregor3545ff42009-09-21 16:56:56 +0000919 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000920
Douglas Gregor3545ff42009-09-21 16:56:56 +0000921 // Protocols are in distinct namespaces from everything else.
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000922 if (((I->first->getIdentifierNamespace() & Decl::IDNS_ObjCProtocol)
Douglas Gregor3545ff42009-09-21 16:56:56 +0000923 || (IDNS & Decl::IDNS_ObjCProtocol)) &&
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000924 I->first->getIdentifierNamespace() != IDNS)
Douglas Gregor3545ff42009-09-21 16:56:56 +0000925 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000926
Douglas Gregor3545ff42009-09-21 16:56:56 +0000927 // The newly-added result is hidden by an entry in the shadow map.
Douglas Gregore0717ab2010-01-14 00:41:07 +0000928 if (CheckHiddenResult(R, CurContext, I->first))
Douglas Gregor3545ff42009-09-21 16:56:56 +0000929 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000930
Douglas Gregor3545ff42009-09-21 16:56:56 +0000931 break;
932 }
933 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000934
Douglas Gregor3545ff42009-09-21 16:56:56 +0000935 // Make sure that any given declaration only shows up in the result set once.
David Blaikie82e95a32014-11-19 07:49:47 +0000936 if (!AllDeclsFound.insert(CanonDecl).second)
Douglas Gregor3545ff42009-09-21 16:56:56 +0000937 return;
Douglas Gregorc2cb2e22010-08-27 15:29:55 +0000938
Douglas Gregore412a5a2009-09-23 22:26:46 +0000939 // If the filter is for nested-name-specifiers, then this result starts a
940 // nested-name-specifier.
Douglas Gregora2db7932010-05-26 22:00:08 +0000941 if (AsNestedNameSpecifier) {
Douglas Gregore412a5a2009-09-23 22:26:46 +0000942 R.StartsNestedNameSpecifier = true;
Douglas Gregora2db7932010-05-26 22:00:08 +0000943 R.Priority = CCP_NestedNameSpecifier;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000944 } else
Douglas Gregor50832e02010-09-20 22:39:41 +0000945 AdjustResultPriorityForDecl(R);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000946
Douglas Gregor5bf52692009-09-22 23:15:58 +0000947 // If this result is supposed to have an informative qualifier, add one.
Douglas Gregore412a5a2009-09-23 22:26:46 +0000948 if (R.QualifierIsInformative && !R.Qualifier &&
949 !R.StartsNestedNameSpecifier) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000950 const DeclContext *Ctx = R.Declaration->getDeclContext();
951 if (const NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Ctx))
Craig Topperc3ec1492014-05-26 06:22:03 +0000952 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, nullptr,
953 Namespace);
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000954 else if (const TagDecl *Tag = dyn_cast<TagDecl>(Ctx))
Craig Topperc3ec1492014-05-26 06:22:03 +0000955 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, nullptr,
956 false, SemaRef.Context.getTypeDeclType(Tag).getTypePtr());
Douglas Gregor5bf52692009-09-22 23:15:58 +0000957 else
958 R.QualifierIsInformative = false;
959 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000960
Douglas Gregor3545ff42009-09-21 16:56:56 +0000961 // Insert this result into the set of results and into the current shadow
962 // map.
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000963 SMap[R.Declaration->getDeclName()].Add(R.Declaration, Results.size());
Douglas Gregor3545ff42009-09-21 16:56:56 +0000964 Results.push_back(R);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000965
Douglas Gregor0212fd72010-09-21 16:06:22 +0000966 if (!AsNestedNameSpecifier)
967 MaybeAddConstructorResults(R);
Douglas Gregor3545ff42009-09-21 16:56:56 +0000968}
969
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000970void ResultBuilder::AddResult(Result R, DeclContext *CurContext,
Douglas Gregor09bbc652010-01-14 15:47:35 +0000971 NamedDecl *Hiding, bool InBaseClass = false) {
Douglas Gregor78a21012010-01-14 16:01:26 +0000972 if (R.Kind != Result::RK_Declaration) {
973 // For non-declaration results, just add the result.
974 Results.push_back(R);
975 return;
976 }
977
Douglas Gregorc580c522010-01-14 01:09:38 +0000978 // Look through using declarations.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000979 if (const UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(R.Declaration)) {
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000980 AddResult(Result(Using->getTargetDecl(),
981 getBasePriority(Using->getTargetDecl()),
982 R.Qualifier),
983 CurContext, Hiding);
Douglas Gregorc580c522010-01-14 01:09:38 +0000984 return;
985 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000986
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000987 bool AsNestedNameSpecifier = false;
988 if (!isInterestingDecl(R.Declaration, AsNestedNameSpecifier))
Douglas Gregorc580c522010-01-14 01:09:38 +0000989 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000990
Douglas Gregor0212fd72010-09-21 16:06:22 +0000991 // C++ constructors are never found by name lookup.
Sam McCall63c59722018-01-22 20:44:47 +0000992 if (isConstructor(R.Declaration))
Douglas Gregor0212fd72010-09-21 16:06:22 +0000993 return;
994
Douglas Gregorc580c522010-01-14 01:09:38 +0000995 if (Hiding && CheckHiddenResult(R, CurContext, Hiding))
996 return;
Nick Lewyckyc3921482012-04-03 21:44:08 +0000997
Douglas Gregorc580c522010-01-14 01:09:38 +0000998 // Make sure that any given declaration only shows up in the result set once.
David Blaikie82e95a32014-11-19 07:49:47 +0000999 if (!AllDeclsFound.insert(R.Declaration->getCanonicalDecl()).second)
Douglas Gregorc580c522010-01-14 01:09:38 +00001000 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001001
Douglas Gregorc580c522010-01-14 01:09:38 +00001002 // If the filter is for nested-name-specifiers, then this result starts a
1003 // nested-name-specifier.
Douglas Gregora2db7932010-05-26 22:00:08 +00001004 if (AsNestedNameSpecifier) {
Douglas Gregorc580c522010-01-14 01:09:38 +00001005 R.StartsNestedNameSpecifier = true;
Douglas Gregora2db7932010-05-26 22:00:08 +00001006 R.Priority = CCP_NestedNameSpecifier;
1007 }
Douglas Gregor09bbc652010-01-14 15:47:35 +00001008 else if (Filter == &ResultBuilder::IsMember && !R.Qualifier && InBaseClass &&
1009 isa<CXXRecordDecl>(R.Declaration->getDeclContext()
Sebastian Redl50c68252010-08-31 00:36:30 +00001010 ->getRedeclContext()))
Douglas Gregor09bbc652010-01-14 15:47:35 +00001011 R.QualifierIsInformative = true;
1012
Douglas Gregorc580c522010-01-14 01:09:38 +00001013 // If this result is supposed to have an informative qualifier, add one.
1014 if (R.QualifierIsInformative && !R.Qualifier &&
1015 !R.StartsNestedNameSpecifier) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001016 const DeclContext *Ctx = R.Declaration->getDeclContext();
1017 if (const NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Ctx))
Craig Topperc3ec1492014-05-26 06:22:03 +00001018 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, nullptr,
1019 Namespace);
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001020 else if (const TagDecl *Tag = dyn_cast<TagDecl>(Ctx))
Craig Topperc3ec1492014-05-26 06:22:03 +00001021 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, nullptr, false,
Douglas Gregor6ae4c522010-01-14 03:21:49 +00001022 SemaRef.Context.getTypeDeclType(Tag).getTypePtr());
Douglas Gregorc580c522010-01-14 01:09:38 +00001023 else
1024 R.QualifierIsInformative = false;
1025 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001026
Douglas Gregora2db7932010-05-26 22:00:08 +00001027 // Adjust the priority if this result comes from a base class.
1028 if (InBaseClass)
1029 R.Priority += CCD_InBaseClass;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001030
Douglas Gregor50832e02010-09-20 22:39:41 +00001031 AdjustResultPriorityForDecl(R);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001032
Douglas Gregor9be0ed42010-08-26 16:36:48 +00001033 if (HasObjectTypeQualifiers)
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001034 if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(R.Declaration))
Douglas Gregor9be0ed42010-08-26 16:36:48 +00001035 if (Method->isInstance()) {
1036 Qualifiers MethodQuals
1037 = Qualifiers::fromCVRMask(Method->getTypeQualifiers());
1038 if (ObjectTypeQualifiers == MethodQuals)
1039 R.Priority += CCD_ObjectQualifierMatch;
1040 else if (ObjectTypeQualifiers - MethodQuals) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001041 // The method cannot be invoked, because doing so would drop
Douglas Gregor9be0ed42010-08-26 16:36:48 +00001042 // qualifiers.
1043 return;
1044 }
1045 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001046
Douglas Gregorc580c522010-01-14 01:09:38 +00001047 // Insert this result into the set of results.
1048 Results.push_back(R);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001049
Douglas Gregor0212fd72010-09-21 16:06:22 +00001050 if (!AsNestedNameSpecifier)
1051 MaybeAddConstructorResults(R);
Douglas Gregorc580c522010-01-14 01:09:38 +00001052}
1053
Douglas Gregor78a21012010-01-14 16:01:26 +00001054void ResultBuilder::AddResult(Result R) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001055 assert(R.Kind != Result::RK_Declaration &&
Douglas Gregor78a21012010-01-14 16:01:26 +00001056 "Declaration results need more context");
1057 Results.push_back(R);
1058}
1059
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001060/// Enter into a new scope.
Benjamin Kramer3204b152015-05-29 19:42:19 +00001061void ResultBuilder::EnterNewScope() { ShadowMaps.emplace_back(); }
Douglas Gregor3545ff42009-09-21 16:56:56 +00001062
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001063/// Exit from the current scope.
Douglas Gregor3545ff42009-09-21 16:56:56 +00001064void ResultBuilder::ExitScope() {
Douglas Gregor05e7ca32009-12-06 20:23:50 +00001065 for (ShadowMap::iterator E = ShadowMaps.back().begin(),
1066 EEnd = ShadowMaps.back().end();
1067 E != EEnd;
1068 ++E)
1069 E->second.Destroy();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001070
Douglas Gregor3545ff42009-09-21 16:56:56 +00001071 ShadowMaps.pop_back();
1072}
1073
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001074/// Determines whether this given declaration will be found by
Douglas Gregor9d64c5e2009-09-21 20:51:25 +00001075/// ordinary name lookup.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001076bool ResultBuilder::IsOrdinaryName(const NamedDecl *ND) const {
George Burgess IV00f70bd2018-03-01 05:43:23 +00001077 ND = ND->getUnderlyingDecl();
Douglas Gregor70febae2010-05-28 00:49:12 +00001078
Richard Smith541b38b2013-09-20 01:15:31 +00001079 // If name lookup finds a local extern declaration, then we are in a
1080 // context where it behaves like an ordinary name.
1081 unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_LocalExtern;
David Blaikiebbafb8a2012-03-11 07:00:24 +00001082 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregor9858ed52010-06-15 20:26:51 +00001083 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member;
David Blaikiebbafb8a2012-03-11 07:00:24 +00001084 else if (SemaRef.getLangOpts().ObjC1) {
Douglas Gregor05fcf842010-11-02 20:36:02 +00001085 if (isa<ObjCIvarDecl>(ND))
1086 return true;
Douglas Gregor05fcf842010-11-02 20:36:02 +00001087 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001088
Douglas Gregor9d64c5e2009-09-21 20:51:25 +00001089 return ND->getIdentifierNamespace() & IDNS;
1090}
1091
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001092/// Determines whether this given declaration will be found by
Douglas Gregor70febae2010-05-28 00:49:12 +00001093/// ordinary name lookup but is not a type name.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001094bool ResultBuilder::IsOrdinaryNonTypeName(const NamedDecl *ND) const {
George Burgess IV00f70bd2018-03-01 05:43:23 +00001095 ND = ND->getUnderlyingDecl();
Alex Lorenzf3df1f72017-11-14 01:46:24 +00001096 if (isa<TypeDecl>(ND))
Douglas Gregor70febae2010-05-28 00:49:12 +00001097 return false;
Alex Lorenzf3df1f72017-11-14 01:46:24 +00001098 // Objective-C interfaces names are not filtered by this method because they
1099 // can be used in a class property expression. We can still filter out
1100 // @class declarations though.
1101 if (const auto *ID = dyn_cast<ObjCInterfaceDecl>(ND)) {
1102 if (!ID->getDefinition())
1103 return false;
1104 }
1105
Richard Smith541b38b2013-09-20 01:15:31 +00001106 unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_LocalExtern;
David Blaikiebbafb8a2012-03-11 07:00:24 +00001107 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregor9858ed52010-06-15 20:26:51 +00001108 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member;
David Blaikiebbafb8a2012-03-11 07:00:24 +00001109 else if (SemaRef.getLangOpts().ObjC1) {
Douglas Gregor05fcf842010-11-02 20:36:02 +00001110 if (isa<ObjCIvarDecl>(ND))
1111 return true;
Douglas Gregor05fcf842010-11-02 20:36:02 +00001112 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001113
Douglas Gregor70febae2010-05-28 00:49:12 +00001114 return ND->getIdentifierNamespace() & IDNS;
1115}
1116
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001117bool ResultBuilder::IsIntegralConstantValue(const NamedDecl *ND) const {
Douglas Gregor85b50632010-07-28 21:50:18 +00001118 if (!IsOrdinaryNonTypeName(ND))
1119 return 0;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001120
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001121 if (const ValueDecl *VD = dyn_cast<ValueDecl>(ND->getUnderlyingDecl()))
Douglas Gregor85b50632010-07-28 21:50:18 +00001122 if (VD->getType()->isIntegralOrEnumerationType())
1123 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001124
Douglas Gregor85b50632010-07-28 21:50:18 +00001125 return false;
1126}
1127
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001128/// Determines whether this given declaration will be found by
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001129/// ordinary name lookup.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001130bool ResultBuilder::IsOrdinaryNonValueName(const NamedDecl *ND) const {
George Burgess IV00f70bd2018-03-01 05:43:23 +00001131 ND = ND->getUnderlyingDecl();
Douglas Gregor70febae2010-05-28 00:49:12 +00001132
Richard Smith541b38b2013-09-20 01:15:31 +00001133 unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_LocalExtern;
David Blaikiebbafb8a2012-03-11 07:00:24 +00001134 if (SemaRef.getLangOpts().CPlusPlus)
John McCalle87beb22010-04-23 18:46:30 +00001135 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001136
1137 return (ND->getIdentifierNamespace() & IDNS) &&
1138 !isa<ValueDecl>(ND) && !isa<FunctionTemplateDecl>(ND) &&
Douglas Gregor70febae2010-05-28 00:49:12 +00001139 !isa<ObjCPropertyDecl>(ND);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001140}
1141
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001142/// Determines whether the given declaration is suitable as the
Douglas Gregor3545ff42009-09-21 16:56:56 +00001143/// start of a C++ nested-name-specifier, e.g., a class or namespace.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001144bool ResultBuilder::IsNestedNameSpecifier(const NamedDecl *ND) const {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001145 // Allow us to find class templates, too.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001146 if (const ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
Douglas Gregor3545ff42009-09-21 16:56:56 +00001147 ND = ClassTemplate->getTemplatedDecl();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001148
Douglas Gregor3545ff42009-09-21 16:56:56 +00001149 return SemaRef.isAcceptableNestedNameSpecifier(ND);
1150}
1151
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001152/// Determines whether the given declaration is an enumeration.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001153bool ResultBuilder::IsEnum(const NamedDecl *ND) const {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001154 return isa<EnumDecl>(ND);
1155}
1156
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001157/// Determines whether the given declaration is a class or struct.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001158bool ResultBuilder::IsClassOrStruct(const NamedDecl *ND) const {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001159 // Allow us to find class templates, too.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001160 if (const ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
Douglas Gregor3545ff42009-09-21 16:56:56 +00001161 ND = ClassTemplate->getTemplatedDecl();
Joao Matosdc86f942012-08-31 18:45:21 +00001162
1163 // For purposes of this check, interfaces match too.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001164 if (const RecordDecl *RD = dyn_cast<RecordDecl>(ND))
Abramo Bagnara6150c882010-05-11 21:36:43 +00001165 return RD->getTagKind() == TTK_Class ||
Joao Matosdc86f942012-08-31 18:45:21 +00001166 RD->getTagKind() == TTK_Struct ||
1167 RD->getTagKind() == TTK_Interface;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001168
Douglas Gregor3545ff42009-09-21 16:56:56 +00001169 return false;
1170}
1171
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001172/// Determines whether the given declaration is a union.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001173bool ResultBuilder::IsUnion(const NamedDecl *ND) const {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001174 // Allow us to find class templates, too.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001175 if (const ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
Douglas Gregor3545ff42009-09-21 16:56:56 +00001176 ND = ClassTemplate->getTemplatedDecl();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001177
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001178 if (const RecordDecl *RD = dyn_cast<RecordDecl>(ND))
Abramo Bagnara6150c882010-05-11 21:36:43 +00001179 return RD->getTagKind() == TTK_Union;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001180
Douglas Gregor3545ff42009-09-21 16:56:56 +00001181 return false;
1182}
1183
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001184/// Determines whether the given declaration is a namespace.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001185bool ResultBuilder::IsNamespace(const NamedDecl *ND) const {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001186 return isa<NamespaceDecl>(ND);
1187}
1188
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001189/// Determines whether the given declaration is a namespace or
Douglas Gregor3545ff42009-09-21 16:56:56 +00001190/// namespace alias.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001191bool ResultBuilder::IsNamespaceOrAlias(const NamedDecl *ND) const {
Richard Smithf2005d32015-12-29 23:34:32 +00001192 return isa<NamespaceDecl>(ND->getUnderlyingDecl());
Douglas Gregor3545ff42009-09-21 16:56:56 +00001193}
1194
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001195/// Determines whether the given declaration is a type.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001196bool ResultBuilder::IsType(const NamedDecl *ND) const {
Richard Smithf2005d32015-12-29 23:34:32 +00001197 ND = ND->getUnderlyingDecl();
Douglas Gregor99fa2642010-08-24 01:06:58 +00001198 return isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND);
Douglas Gregor3545ff42009-09-21 16:56:56 +00001199}
1200
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001201/// Determines which members of a class should be visible via
Douglas Gregor99fe2ad2009-12-11 17:31:05 +00001202/// "." or "->". Only value declarations, nested name specifiers, and
1203/// using declarations thereof should show up.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001204bool ResultBuilder::IsMember(const NamedDecl *ND) const {
Richard Smithf2005d32015-12-29 23:34:32 +00001205 ND = ND->getUnderlyingDecl();
Douglas Gregor70788392009-12-11 18:14:22 +00001206 return isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND) ||
Richard Smithf2005d32015-12-29 23:34:32 +00001207 isa<ObjCPropertyDecl>(ND);
Douglas Gregore412a5a2009-09-23 22:26:46 +00001208}
1209
Douglas Gregora817a192010-05-27 23:06:34 +00001210static bool isObjCReceiverType(ASTContext &C, QualType T) {
1211 T = C.getCanonicalType(T);
1212 switch (T->getTypeClass()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001213 case Type::ObjCObject:
Douglas Gregora817a192010-05-27 23:06:34 +00001214 case Type::ObjCInterface:
1215 case Type::ObjCObjectPointer:
1216 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001217
Douglas Gregora817a192010-05-27 23:06:34 +00001218 case Type::Builtin:
1219 switch (cast<BuiltinType>(T)->getKind()) {
1220 case BuiltinType::ObjCId:
1221 case BuiltinType::ObjCClass:
1222 case BuiltinType::ObjCSel:
1223 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001224
Douglas Gregora817a192010-05-27 23:06:34 +00001225 default:
1226 break;
1227 }
1228 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001229
Douglas Gregora817a192010-05-27 23:06:34 +00001230 default:
1231 break;
1232 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001233
David Blaikiebbafb8a2012-03-11 07:00:24 +00001234 if (!C.getLangOpts().CPlusPlus)
Douglas Gregora817a192010-05-27 23:06:34 +00001235 return false;
1236
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001237 // FIXME: We could perform more analysis here to determine whether a
Douglas Gregora817a192010-05-27 23:06:34 +00001238 // particular class type has any conversions to Objective-C types. For now,
1239 // just accept all class types.
1240 return T->isDependentType() || T->isRecordType();
1241}
1242
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001243bool ResultBuilder::IsObjCMessageReceiver(const NamedDecl *ND) const {
Douglas Gregora817a192010-05-27 23:06:34 +00001244 QualType T = getDeclUsageType(SemaRef.Context, ND);
1245 if (T.isNull())
1246 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001247
Douglas Gregora817a192010-05-27 23:06:34 +00001248 T = SemaRef.Context.getBaseElementType(T);
1249 return isObjCReceiverType(SemaRef.Context, T);
1250}
1251
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001252bool ResultBuilder::IsObjCMessageReceiverOrLambdaCapture(const NamedDecl *ND) const {
Douglas Gregord8c61782012-02-15 15:34:24 +00001253 if (IsObjCMessageReceiver(ND))
1254 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001255
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001256 const VarDecl *Var = dyn_cast<VarDecl>(ND);
Douglas Gregord8c61782012-02-15 15:34:24 +00001257 if (!Var)
1258 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001259
Douglas Gregord8c61782012-02-15 15:34:24 +00001260 return Var->hasLocalStorage() && !Var->hasAttr<BlocksAttr>();
1261}
1262
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001263bool ResultBuilder::IsObjCCollection(const NamedDecl *ND) const {
David Blaikiebbafb8a2012-03-11 07:00:24 +00001264 if ((SemaRef.getLangOpts().CPlusPlus && !IsOrdinaryName(ND)) ||
1265 (!SemaRef.getLangOpts().CPlusPlus && !IsOrdinaryNonTypeName(ND)))
Douglas Gregor68762e72010-08-23 21:17:50 +00001266 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001267
Douglas Gregor68762e72010-08-23 21:17:50 +00001268 QualType T = getDeclUsageType(SemaRef.Context, ND);
1269 if (T.isNull())
1270 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001271
Douglas Gregor68762e72010-08-23 21:17:50 +00001272 T = SemaRef.Context.getBaseElementType(T);
1273 return T->isObjCObjectType() || T->isObjCObjectPointerType() ||
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001274 T->isObjCIdType() ||
David Blaikiebbafb8a2012-03-11 07:00:24 +00001275 (SemaRef.getLangOpts().CPlusPlus && T->isRecordType());
Douglas Gregor68762e72010-08-23 21:17:50 +00001276}
Douglas Gregora817a192010-05-27 23:06:34 +00001277
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001278bool ResultBuilder::IsImpossibleToSatisfy(const NamedDecl *ND) const {
Douglas Gregor0ac41382010-09-23 23:01:17 +00001279 return false;
1280}
1281
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001282/// Determines whether the given declaration is an Objective-C
Douglas Gregor2b8162b2010-01-14 16:08:12 +00001283/// instance variable.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001284bool ResultBuilder::IsObjCIvar(const NamedDecl *ND) const {
Douglas Gregor2b8162b2010-01-14 16:08:12 +00001285 return isa<ObjCIvarDecl>(ND);
1286}
1287
Douglas Gregorc580c522010-01-14 01:09:38 +00001288namespace {
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001289 /// Visible declaration consumer that adds a code-completion result
Douglas Gregorc580c522010-01-14 01:09:38 +00001290 /// for each visible declaration.
1291 class CodeCompletionDeclConsumer : public VisibleDeclConsumer {
1292 ResultBuilder &Results;
1293 DeclContext *CurContext;
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00001294 std::vector<FixItHint> FixIts;
Haojian Wu10d95c52018-01-17 14:29:25 +00001295
Douglas Gregorc580c522010-01-14 01:09:38 +00001296 public:
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00001297 CodeCompletionDeclConsumer(
1298 ResultBuilder &Results, DeclContext *CurContext,
1299 std::vector<FixItHint> FixIts = std::vector<FixItHint>())
1300 : Results(Results), CurContext(CurContext), FixIts(std::move(FixIts)) {}
Craig Toppere14c0f82014-03-12 04:55:44 +00001301
1302 void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx,
1303 bool InBaseClass) override {
Erik Verbruggen2e657ff2011-10-06 07:27:49 +00001304 bool Accessible = true;
Douglas Gregor03ba1882011-11-03 16:51:37 +00001305 if (Ctx)
1306 Accessible = Results.getSema().IsSimplyAccessible(ND, Ctx);
Craig Topperc3ec1492014-05-26 06:22:03 +00001307
1308 ResultBuilder::Result Result(ND, Results.getBasePriority(ND), nullptr,
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00001309 false, Accessible, FixIts);
Erik Verbruggen2e657ff2011-10-06 07:27:49 +00001310 Results.AddResult(Result, CurContext, Hiding, InBaseClass);
Douglas Gregorc580c522010-01-14 01:09:38 +00001311 }
Haojian Wu10d95c52018-01-17 14:29:25 +00001312
1313 void EnteredContext(DeclContext* Ctx) override {
1314 Results.addVisitedContext(Ctx);
1315 }
Douglas Gregorc580c522010-01-14 01:09:38 +00001316 };
Alexander Kornienkoab9db512015-06-22 23:07:51 +00001317}
Douglas Gregorc580c522010-01-14 01:09:38 +00001318
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001319/// Add type specifiers for the current language as keyword results.
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001320static void AddTypeSpecifierResults(const LangOptions &LangOpts,
Douglas Gregor3545ff42009-09-21 16:56:56 +00001321 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00001322 typedef CodeCompletionResult Result;
Douglas Gregora2db7932010-05-26 22:00:08 +00001323 Results.AddResult(Result("short", CCP_Type));
1324 Results.AddResult(Result("long", CCP_Type));
1325 Results.AddResult(Result("signed", CCP_Type));
1326 Results.AddResult(Result("unsigned", CCP_Type));
1327 Results.AddResult(Result("void", CCP_Type));
1328 Results.AddResult(Result("char", CCP_Type));
1329 Results.AddResult(Result("int", CCP_Type));
1330 Results.AddResult(Result("float", CCP_Type));
1331 Results.AddResult(Result("double", CCP_Type));
1332 Results.AddResult(Result("enum", CCP_Type));
1333 Results.AddResult(Result("struct", CCP_Type));
1334 Results.AddResult(Result("union", CCP_Type));
1335 Results.AddResult(Result("const", CCP_Type));
1336 Results.AddResult(Result("volatile", CCP_Type));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001337
Douglas Gregor3545ff42009-09-21 16:56:56 +00001338 if (LangOpts.C99) {
1339 // C99-specific
Douglas Gregora2db7932010-05-26 22:00:08 +00001340 Results.AddResult(Result("_Complex", CCP_Type));
1341 Results.AddResult(Result("_Imaginary", CCP_Type));
1342 Results.AddResult(Result("_Bool", CCP_Type));
1343 Results.AddResult(Result("restrict", CCP_Type));
Douglas Gregor3545ff42009-09-21 16:56:56 +00001344 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001345
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00001346 CodeCompletionBuilder Builder(Results.getAllocator(),
1347 Results.getCodeCompletionTUInfo());
Douglas Gregor3545ff42009-09-21 16:56:56 +00001348 if (LangOpts.CPlusPlus) {
1349 // C++-specific
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001350 Results.AddResult(Result("bool", CCP_Type +
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00001351 (LangOpts.ObjC1? CCD_bool_in_ObjC : 0)));
Douglas Gregora2db7932010-05-26 22:00:08 +00001352 Results.AddResult(Result("class", CCP_Type));
1353 Results.AddResult(Result("wchar_t", CCP_Type));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001354
Douglas Gregorf4c33342010-05-28 00:22:41 +00001355 // typename qualified-id
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001356 Builder.AddTypedTextChunk("typename");
1357 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1358 Builder.AddPlaceholderChunk("qualifier");
1359 Builder.AddTextChunk("::");
1360 Builder.AddPlaceholderChunk("name");
1361 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001362
Richard Smith2bf7fdb2013-01-02 11:42:31 +00001363 if (LangOpts.CPlusPlus11) {
Douglas Gregora2db7932010-05-26 22:00:08 +00001364 Results.AddResult(Result("auto", CCP_Type));
1365 Results.AddResult(Result("char16_t", CCP_Type));
1366 Results.AddResult(Result("char32_t", CCP_Type));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001367
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001368 Builder.AddTypedTextChunk("decltype");
1369 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1370 Builder.AddPlaceholderChunk("expression");
1371 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1372 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor3545ff42009-09-21 16:56:56 +00001373 }
Alex Lorenz46eed9d2017-02-13 23:35:59 +00001374 } else
1375 Results.AddResult(Result("__auto_type", CCP_Type));
1376
Richard Smith7b301e22018-05-24 21:51:52 +00001377 // GNU keywords
1378 if (LangOpts.GNUKeywords) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001379 // FIXME: Enable when we actually support decimal floating point.
Douglas Gregor78a21012010-01-14 16:01:26 +00001380 // Results.AddResult(Result("_Decimal32"));
1381 // Results.AddResult(Result("_Decimal64"));
1382 // Results.AddResult(Result("_Decimal128"));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001383
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001384 Builder.AddTypedTextChunk("typeof");
1385 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1386 Builder.AddPlaceholderChunk("expression");
1387 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00001388
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001389 Builder.AddTypedTextChunk("typeof");
1390 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1391 Builder.AddPlaceholderChunk("type");
1392 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1393 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor3545ff42009-09-21 16:56:56 +00001394 }
Douglas Gregor86b42682015-06-19 18:27:52 +00001395
1396 // Nullability
Douglas Gregoraea7afd2015-06-24 22:02:08 +00001397 Results.AddResult(Result("_Nonnull", CCP_Type));
1398 Results.AddResult(Result("_Null_unspecified", CCP_Type));
1399 Results.AddResult(Result("_Nullable", CCP_Type));
Douglas Gregor3545ff42009-09-21 16:56:56 +00001400}
1401
John McCallfaf5fb42010-08-26 23:41:50 +00001402static void AddStorageSpecifiers(Sema::ParserCompletionContext CCC,
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001403 const LangOptions &LangOpts,
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001404 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00001405 typedef CodeCompletionResult Result;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001406 // Note: we don't suggest either "auto" or "register", because both
1407 // are pointless as storage specifiers. Elsewhere, we suggest "auto"
1408 // in C++0x as a type specifier.
Douglas Gregor78a21012010-01-14 16:01:26 +00001409 Results.AddResult(Result("extern"));
1410 Results.AddResult(Result("static"));
Alex Lorenz8f4d3992017-02-13 23:19:40 +00001411
1412 if (LangOpts.CPlusPlus11) {
1413 CodeCompletionAllocator &Allocator = Results.getAllocator();
1414 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
1415
1416 // alignas
1417 Builder.AddTypedTextChunk("alignas");
1418 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1419 Builder.AddPlaceholderChunk("expression");
1420 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1421 Results.AddResult(Result(Builder.TakeString()));
1422
1423 Results.AddResult(Result("constexpr"));
1424 Results.AddResult(Result("thread_local"));
1425 }
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001426}
1427
John McCallfaf5fb42010-08-26 23:41:50 +00001428static void AddFunctionSpecifiers(Sema::ParserCompletionContext CCC,
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001429 const LangOptions &LangOpts,
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001430 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00001431 typedef CodeCompletionResult Result;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001432 switch (CCC) {
John McCallfaf5fb42010-08-26 23:41:50 +00001433 case Sema::PCC_Class:
1434 case Sema::PCC_MemberTemplate:
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001435 if (LangOpts.CPlusPlus) {
Douglas Gregor78a21012010-01-14 16:01:26 +00001436 Results.AddResult(Result("explicit"));
1437 Results.AddResult(Result("friend"));
1438 Results.AddResult(Result("mutable"));
1439 Results.AddResult(Result("virtual"));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001440 }
Adrian Prantlf3b3ccd2017-12-19 22:06:11 +00001441 LLVM_FALLTHROUGH;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001442
John McCallfaf5fb42010-08-26 23:41:50 +00001443 case Sema::PCC_ObjCInterface:
1444 case Sema::PCC_ObjCImplementation:
1445 case Sema::PCC_Namespace:
1446 case Sema::PCC_Template:
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001447 if (LangOpts.CPlusPlus || LangOpts.C99)
Douglas Gregor78a21012010-01-14 16:01:26 +00001448 Results.AddResult(Result("inline"));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001449 break;
1450
John McCallfaf5fb42010-08-26 23:41:50 +00001451 case Sema::PCC_ObjCInstanceVariableList:
1452 case Sema::PCC_Expression:
1453 case Sema::PCC_Statement:
1454 case Sema::PCC_ForInit:
1455 case Sema::PCC_Condition:
1456 case Sema::PCC_RecoveryInFunction:
1457 case Sema::PCC_Type:
Douglas Gregor5e35d592010-09-14 23:59:36 +00001458 case Sema::PCC_ParenthesizedExpression:
Douglas Gregor80039242011-02-15 20:33:25 +00001459 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001460 break;
1461 }
1462}
1463
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001464static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt);
1465static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt);
1466static void AddObjCVisibilityResults(const LangOptions &LangOpts,
Douglas Gregor48d46252010-01-13 21:54:15 +00001467 ResultBuilder &Results,
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001468 bool NeedAt);
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001469static void AddObjCImplementationResults(const LangOptions &LangOpts,
Douglas Gregorf1934162010-01-13 21:24:21 +00001470 ResultBuilder &Results,
1471 bool NeedAt);
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001472static void AddObjCInterfaceResults(const LangOptions &LangOpts,
Douglas Gregorf1934162010-01-13 21:24:21 +00001473 ResultBuilder &Results,
1474 bool NeedAt);
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001475static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt);
Douglas Gregorf1934162010-01-13 21:24:21 +00001476
Douglas Gregorf4c33342010-05-28 00:22:41 +00001477static void AddTypedefResult(ResultBuilder &Results) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00001478 CodeCompletionBuilder Builder(Results.getAllocator(),
1479 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001480 Builder.AddTypedTextChunk("typedef");
1481 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1482 Builder.AddPlaceholderChunk("type");
1483 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1484 Builder.AddPlaceholderChunk("name");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001485 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00001486}
1487
John McCallfaf5fb42010-08-26 23:41:50 +00001488static bool WantTypesInContext(Sema::ParserCompletionContext CCC,
Douglas Gregor70febae2010-05-28 00:49:12 +00001489 const LangOptions &LangOpts) {
Douglas Gregor70febae2010-05-28 00:49:12 +00001490 switch (CCC) {
John McCallfaf5fb42010-08-26 23:41:50 +00001491 case Sema::PCC_Namespace:
1492 case Sema::PCC_Class:
1493 case Sema::PCC_ObjCInstanceVariableList:
1494 case Sema::PCC_Template:
1495 case Sema::PCC_MemberTemplate:
1496 case Sema::PCC_Statement:
1497 case Sema::PCC_RecoveryInFunction:
1498 case Sema::PCC_Type:
Douglas Gregor5e35d592010-09-14 23:59:36 +00001499 case Sema::PCC_ParenthesizedExpression:
Douglas Gregor80039242011-02-15 20:33:25 +00001500 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregor70febae2010-05-28 00:49:12 +00001501 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001502
John McCallfaf5fb42010-08-26 23:41:50 +00001503 case Sema::PCC_Expression:
1504 case Sema::PCC_Condition:
Douglas Gregor5e35d592010-09-14 23:59:36 +00001505 return LangOpts.CPlusPlus;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001506
Douglas Gregor5e35d592010-09-14 23:59:36 +00001507 case Sema::PCC_ObjCInterface:
1508 case Sema::PCC_ObjCImplementation:
Douglas Gregor70febae2010-05-28 00:49:12 +00001509 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001510
John McCallfaf5fb42010-08-26 23:41:50 +00001511 case Sema::PCC_ForInit:
Douglas Gregor5e35d592010-09-14 23:59:36 +00001512 return LangOpts.CPlusPlus || LangOpts.ObjC1 || LangOpts.C99;
Douglas Gregor70febae2010-05-28 00:49:12 +00001513 }
David Blaikie8a40f702012-01-17 06:56:22 +00001514
1515 llvm_unreachable("Invalid ParserCompletionContext!");
Douglas Gregor70febae2010-05-28 00:49:12 +00001516}
1517
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00001518static PrintingPolicy getCompletionPrintingPolicy(const ASTContext &Context,
1519 const Preprocessor &PP) {
1520 PrintingPolicy Policy = Sema::getPrintingPolicy(Context, PP);
Douglas Gregore5c79d52011-10-18 21:20:17 +00001521 Policy.AnonymousTagLocations = false;
1522 Policy.SuppressStrongLifetime = true;
Douglas Gregor2e10cf92011-11-03 00:16:13 +00001523 Policy.SuppressUnwrittenScope = true;
Ilya Biryukovb5da91c2017-11-08 10:39:09 +00001524 Policy.SuppressScope = true;
Douglas Gregore5c79d52011-10-18 21:20:17 +00001525 return Policy;
1526}
1527
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001528/// Retrieve a printing policy suitable for code completion.
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00001529static PrintingPolicy getCompletionPrintingPolicy(Sema &S) {
1530 return getCompletionPrintingPolicy(S.Context, S.PP);
1531}
1532
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001533/// Retrieve the string representation of the given type as a string
Douglas Gregore5c79d52011-10-18 21:20:17 +00001534/// that has the appropriate lifetime for code completion.
1535///
1536/// This routine provides a fast path where we provide constant strings for
1537/// common type names.
1538static const char *GetCompletionTypeString(QualType T,
1539 ASTContext &Context,
1540 const PrintingPolicy &Policy,
1541 CodeCompletionAllocator &Allocator) {
1542 if (!T.getLocalQualifiers()) {
1543 // Built-in type names are constant strings.
1544 if (const BuiltinType *BT = dyn_cast<BuiltinType>(T))
Argyrios Kyrtzidisbbff3da2012-05-05 04:20:28 +00001545 return BT->getNameAsCString(Policy);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001546
Douglas Gregore5c79d52011-10-18 21:20:17 +00001547 // Anonymous tag types are constant strings.
1548 if (const TagType *TagT = dyn_cast<TagType>(T))
1549 if (TagDecl *Tag = TagT->getDecl())
John McCall5ea95772013-03-09 00:54:27 +00001550 if (!Tag->hasNameForLinkage()) {
Douglas Gregore5c79d52011-10-18 21:20:17 +00001551 switch (Tag->getTagKind()) {
1552 case TTK_Struct: return "struct <anonymous>";
Joao Matosdc86f942012-08-31 18:45:21 +00001553 case TTK_Interface: return "__interface <anonymous>";
1554 case TTK_Class: return "class <anonymous>";
Douglas Gregore5c79d52011-10-18 21:20:17 +00001555 case TTK_Union: return "union <anonymous>";
1556 case TTK_Enum: return "enum <anonymous>";
1557 }
1558 }
1559 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001560
Douglas Gregore5c79d52011-10-18 21:20:17 +00001561 // Slow path: format the type as a string.
1562 std::string Result;
1563 T.getAsStringInternal(Result, Policy);
1564 return Allocator.CopyString(Result);
1565}
1566
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001567/// Add a completion for "this", if we're in a member function.
Douglas Gregord8c61782012-02-15 15:34:24 +00001568static void addThisCompletion(Sema &S, ResultBuilder &Results) {
1569 QualType ThisTy = S.getCurrentThisType();
1570 if (ThisTy.isNull())
1571 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001572
Douglas Gregord8c61782012-02-15 15:34:24 +00001573 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00001574 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Douglas Gregord8c61782012-02-15 15:34:24 +00001575 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001576 Builder.AddResultTypeChunk(GetCompletionTypeString(ThisTy,
1577 S.Context,
Douglas Gregord8c61782012-02-15 15:34:24 +00001578 Policy,
1579 Allocator));
1580 Builder.AddTypedTextChunk("this");
Joao Matosdc86f942012-08-31 18:45:21 +00001581 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
Douglas Gregord8c61782012-02-15 15:34:24 +00001582}
1583
Alex Lorenz8f4d3992017-02-13 23:19:40 +00001584static void AddStaticAssertResult(CodeCompletionBuilder &Builder,
1585 ResultBuilder &Results,
1586 const LangOptions &LangOpts) {
1587 if (!LangOpts.CPlusPlus11)
1588 return;
1589
1590 Builder.AddTypedTextChunk("static_assert");
1591 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1592 Builder.AddPlaceholderChunk("expression");
1593 Builder.AddChunk(CodeCompletionString::CK_Comma);
1594 Builder.AddPlaceholderChunk("message");
1595 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1596 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
1597}
1598
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001599/// Add language constructs that show up for "ordinary" names.
John McCallfaf5fb42010-08-26 23:41:50 +00001600static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001601 Scope *S,
1602 Sema &SemaRef,
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001603 ResultBuilder &Results) {
Douglas Gregore5c79d52011-10-18 21:20:17 +00001604 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00001605 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001606
John McCall276321a2010-08-25 06:19:51 +00001607 typedef CodeCompletionResult Result;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001608 switch (CCC) {
John McCallfaf5fb42010-08-26 23:41:50 +00001609 case Sema::PCC_Namespace:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001610 if (SemaRef.getLangOpts().CPlusPlus) {
Douglas Gregorf4c33342010-05-28 00:22:41 +00001611 if (Results.includeCodePatterns()) {
1612 // namespace <identifier> { declarations }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001613 Builder.AddTypedTextChunk("namespace");
1614 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1615 Builder.AddPlaceholderChunk("identifier");
1616 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1617 Builder.AddPlaceholderChunk("declarations");
1618 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1619 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1620 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00001621 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001622
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001623 // namespace identifier = identifier ;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001624 Builder.AddTypedTextChunk("namespace");
1625 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1626 Builder.AddPlaceholderChunk("name");
1627 Builder.AddChunk(CodeCompletionString::CK_Equal);
1628 Builder.AddPlaceholderChunk("namespace");
1629 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001630
1631 // Using directives
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001632 Builder.AddTypedTextChunk("using");
1633 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1634 Builder.AddTextChunk("namespace");
1635 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1636 Builder.AddPlaceholderChunk("identifier");
1637 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001638
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001639 // asm(string-literal)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001640 Builder.AddTypedTextChunk("asm");
1641 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1642 Builder.AddPlaceholderChunk("string-literal");
1643 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1644 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001645
Douglas Gregorf4c33342010-05-28 00:22:41 +00001646 if (Results.includeCodePatterns()) {
1647 // Explicit template instantiation
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001648 Builder.AddTypedTextChunk("template");
1649 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1650 Builder.AddPlaceholderChunk("declaration");
1651 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00001652 }
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001653 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001654
David Blaikiebbafb8a2012-03-11 07:00:24 +00001655 if (SemaRef.getLangOpts().ObjC1)
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001656 AddObjCTopLevelResults(Results, true);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001657
Douglas Gregorf4c33342010-05-28 00:22:41 +00001658 AddTypedefResult(Results);
Adrian Prantlf3b3ccd2017-12-19 22:06:11 +00001659 LLVM_FALLTHROUGH;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001660
John McCallfaf5fb42010-08-26 23:41:50 +00001661 case Sema::PCC_Class:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001662 if (SemaRef.getLangOpts().CPlusPlus) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001663 // Using declaration
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001664 Builder.AddTypedTextChunk("using");
1665 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1666 Builder.AddPlaceholderChunk("qualifier");
1667 Builder.AddTextChunk("::");
1668 Builder.AddPlaceholderChunk("name");
1669 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001670
Douglas Gregorf4c33342010-05-28 00:22:41 +00001671 // using typename qualifier::name (only in a dependent context)
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001672 if (SemaRef.CurContext->isDependentContext()) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001673 Builder.AddTypedTextChunk("using");
1674 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1675 Builder.AddTextChunk("typename");
1676 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1677 Builder.AddPlaceholderChunk("qualifier");
1678 Builder.AddTextChunk("::");
1679 Builder.AddPlaceholderChunk("name");
1680 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001681 }
1682
Alex Lorenz8f4d3992017-02-13 23:19:40 +00001683 AddStaticAssertResult(Builder, Results, SemaRef.getLangOpts());
1684
John McCallfaf5fb42010-08-26 23:41:50 +00001685 if (CCC == Sema::PCC_Class) {
Douglas Gregorf4c33342010-05-28 00:22:41 +00001686 AddTypedefResult(Results);
1687
Erik Verbruggen6524c052017-10-24 13:46:58 +00001688 bool IsNotInheritanceScope =
1689 !(S->getFlags() & Scope::ClassInheritanceScope);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001690 // public:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001691 Builder.AddTypedTextChunk("public");
Erik Verbruggen6524c052017-10-24 13:46:58 +00001692 if (IsNotInheritanceScope && Results.includeCodePatterns())
Douglas Gregor9489cdf2012-04-10 17:56:28 +00001693 Builder.AddChunk(CodeCompletionString::CK_Colon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001694 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001695
1696 // protected:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001697 Builder.AddTypedTextChunk("protected");
Erik Verbruggen6524c052017-10-24 13:46:58 +00001698 if (IsNotInheritanceScope && Results.includeCodePatterns())
Douglas Gregor9489cdf2012-04-10 17:56:28 +00001699 Builder.AddChunk(CodeCompletionString::CK_Colon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001700 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001701
1702 // private:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001703 Builder.AddTypedTextChunk("private");
Erik Verbruggen6524c052017-10-24 13:46:58 +00001704 if (IsNotInheritanceScope && Results.includeCodePatterns())
Douglas Gregor9489cdf2012-04-10 17:56:28 +00001705 Builder.AddChunk(CodeCompletionString::CK_Colon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001706 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001707 }
1708 }
Adrian Prantlf3b3ccd2017-12-19 22:06:11 +00001709 LLVM_FALLTHROUGH;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001710
John McCallfaf5fb42010-08-26 23:41:50 +00001711 case Sema::PCC_Template:
1712 case Sema::PCC_MemberTemplate:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001713 if (SemaRef.getLangOpts().CPlusPlus && Results.includeCodePatterns()) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001714 // template < parameters >
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001715 Builder.AddTypedTextChunk("template");
1716 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1717 Builder.AddPlaceholderChunk("parameters");
1718 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1719 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001720 }
1721
David Blaikiebbafb8a2012-03-11 07:00:24 +00001722 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
1723 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001724 break;
1725
John McCallfaf5fb42010-08-26 23:41:50 +00001726 case Sema::PCC_ObjCInterface:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001727 AddObjCInterfaceResults(SemaRef.getLangOpts(), Results, true);
1728 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
1729 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregorf1934162010-01-13 21:24:21 +00001730 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001731
John McCallfaf5fb42010-08-26 23:41:50 +00001732 case Sema::PCC_ObjCImplementation:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001733 AddObjCImplementationResults(SemaRef.getLangOpts(), Results, true);
1734 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
1735 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregorf1934162010-01-13 21:24:21 +00001736 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001737
John McCallfaf5fb42010-08-26 23:41:50 +00001738 case Sema::PCC_ObjCInstanceVariableList:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001739 AddObjCVisibilityResults(SemaRef.getLangOpts(), Results, true);
Douglas Gregor48d46252010-01-13 21:54:15 +00001740 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001741
John McCallfaf5fb42010-08-26 23:41:50 +00001742 case Sema::PCC_RecoveryInFunction:
1743 case Sema::PCC_Statement: {
Douglas Gregorf4c33342010-05-28 00:22:41 +00001744 AddTypedefResult(Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001745
David Blaikiebbafb8a2012-03-11 07:00:24 +00001746 if (SemaRef.getLangOpts().CPlusPlus && Results.includeCodePatterns() &&
1747 SemaRef.getLangOpts().CXXExceptions) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001748 Builder.AddTypedTextChunk("try");
1749 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1750 Builder.AddPlaceholderChunk("statements");
1751 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1752 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1753 Builder.AddTextChunk("catch");
1754 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1755 Builder.AddPlaceholderChunk("declaration");
1756 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1757 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1758 Builder.AddPlaceholderChunk("statements");
1759 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1760 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1761 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001762 }
David Blaikiebbafb8a2012-03-11 07:00:24 +00001763 if (SemaRef.getLangOpts().ObjC1)
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001764 AddObjCStatementResults(Results, true);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001765
Douglas Gregorf64acca2010-05-25 21:41:55 +00001766 if (Results.includeCodePatterns()) {
1767 // if (condition) { statements }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001768 Builder.AddTypedTextChunk("if");
1769 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00001770 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001771 Builder.AddPlaceholderChunk("condition");
Douglas Gregorf64acca2010-05-25 21:41:55 +00001772 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001773 Builder.AddPlaceholderChunk("expression");
1774 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1775 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1776 Builder.AddPlaceholderChunk("statements");
1777 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1778 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1779 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001780
Douglas Gregorf64acca2010-05-25 21:41:55 +00001781 // switch (condition) { }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001782 Builder.AddTypedTextChunk("switch");
1783 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00001784 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001785 Builder.AddPlaceholderChunk("condition");
Douglas Gregorf64acca2010-05-25 21:41:55 +00001786 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001787 Builder.AddPlaceholderChunk("expression");
1788 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1789 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1790 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1791 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1792 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf64acca2010-05-25 21:41:55 +00001793 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001794
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001795 // Switch-specific statements.
John McCallaab3e412010-08-25 08:40:02 +00001796 if (!SemaRef.getCurFunction()->SwitchStack.empty()) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001797 // case expression:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001798 Builder.AddTypedTextChunk("case");
1799 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1800 Builder.AddPlaceholderChunk("expression");
1801 Builder.AddChunk(CodeCompletionString::CK_Colon);
1802 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001803
1804 // default:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001805 Builder.AddTypedTextChunk("default");
1806 Builder.AddChunk(CodeCompletionString::CK_Colon);
1807 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001808 }
1809
Douglas Gregorf64acca2010-05-25 21:41:55 +00001810 if (Results.includeCodePatterns()) {
1811 /// while (condition) { statements }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001812 Builder.AddTypedTextChunk("while");
1813 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00001814 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001815 Builder.AddPlaceholderChunk("condition");
Douglas Gregorf64acca2010-05-25 21:41:55 +00001816 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001817 Builder.AddPlaceholderChunk("expression");
1818 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1819 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1820 Builder.AddPlaceholderChunk("statements");
1821 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1822 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1823 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf64acca2010-05-25 21:41:55 +00001824
1825 // do { statements } while ( expression );
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001826 Builder.AddTypedTextChunk("do");
1827 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1828 Builder.AddPlaceholderChunk("statements");
1829 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1830 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1831 Builder.AddTextChunk("while");
1832 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1833 Builder.AddPlaceholderChunk("expression");
1834 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1835 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001836
Douglas Gregorf64acca2010-05-25 21:41:55 +00001837 // for ( for-init-statement ; condition ; expression ) { statements }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001838 Builder.AddTypedTextChunk("for");
1839 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00001840 if (SemaRef.getLangOpts().CPlusPlus || SemaRef.getLangOpts().C99)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001841 Builder.AddPlaceholderChunk("init-statement");
Douglas Gregorf64acca2010-05-25 21:41:55 +00001842 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001843 Builder.AddPlaceholderChunk("init-expression");
1844 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
1845 Builder.AddPlaceholderChunk("condition");
1846 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
1847 Builder.AddPlaceholderChunk("inc-expression");
1848 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1849 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1850 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1851 Builder.AddPlaceholderChunk("statements");
1852 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1853 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1854 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf64acca2010-05-25 21:41:55 +00001855 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001856
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001857 if (S->getContinueParent()) {
1858 // continue ;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001859 Builder.AddTypedTextChunk("continue");
1860 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001861 }
1862
1863 if (S->getBreakParent()) {
1864 // break ;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001865 Builder.AddTypedTextChunk("break");
1866 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001867 }
1868
1869 // "return expression ;" or "return ;", depending on whether we
1870 // know the function is void or not.
1871 bool isVoid = false;
1872 if (FunctionDecl *Function = dyn_cast<FunctionDecl>(SemaRef.CurContext))
Alp Toker314cc812014-01-25 16:55:45 +00001873 isVoid = Function->getReturnType()->isVoidType();
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001874 else if (ObjCMethodDecl *Method
1875 = dyn_cast<ObjCMethodDecl>(SemaRef.CurContext))
Alp Toker314cc812014-01-25 16:55:45 +00001876 isVoid = Method->getReturnType()->isVoidType();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001877 else if (SemaRef.getCurBlock() &&
Douglas Gregor9a28e842010-03-01 23:15:13 +00001878 !SemaRef.getCurBlock()->ReturnType.isNull())
1879 isVoid = SemaRef.getCurBlock()->ReturnType->isVoidType();
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001880 Builder.AddTypedTextChunk("return");
Douglas Gregor44272ca2010-02-18 04:06:48 +00001881 if (!isVoid) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001882 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1883 Builder.AddPlaceholderChunk("expression");
Douglas Gregor44272ca2010-02-18 04:06:48 +00001884 }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001885 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001886
Douglas Gregorf4c33342010-05-28 00:22:41 +00001887 // goto identifier ;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001888 Builder.AddTypedTextChunk("goto");
1889 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1890 Builder.AddPlaceholderChunk("label");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001891 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001892
Douglas Gregorf4c33342010-05-28 00:22:41 +00001893 // Using directives
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001894 Builder.AddTypedTextChunk("using");
1895 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1896 Builder.AddTextChunk("namespace");
1897 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1898 Builder.AddPlaceholderChunk("identifier");
1899 Results.AddResult(Result(Builder.TakeString()));
Alex Lorenz8f4d3992017-02-13 23:19:40 +00001900
1901 AddStaticAssertResult(Builder, Results, SemaRef.getLangOpts());
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001902 }
Galina Kistanovabe3ba9da2017-06-07 06:31:55 +00001903 LLVM_FALLTHROUGH;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001904
1905 // Fall through (for statement expressions).
John McCallfaf5fb42010-08-26 23:41:50 +00001906 case Sema::PCC_ForInit:
1907 case Sema::PCC_Condition:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001908 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001909 // Fall through: conditions and statements can have expressions.
Galina Kistanova33399112017-06-03 06:35:06 +00001910 LLVM_FALLTHROUGH;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001911
Douglas Gregor5e35d592010-09-14 23:59:36 +00001912 case Sema::PCC_ParenthesizedExpression:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001913 if (SemaRef.getLangOpts().ObjCAutoRefCount &&
John McCall31168b02011-06-15 23:02:42 +00001914 CCC == Sema::PCC_ParenthesizedExpression) {
1915 // (__bridge <type>)<expression>
1916 Builder.AddTypedTextChunk("__bridge");
1917 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1918 Builder.AddPlaceholderChunk("type");
1919 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1920 Builder.AddPlaceholderChunk("expression");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001921 Results.AddResult(Result(Builder.TakeString()));
John McCall31168b02011-06-15 23:02:42 +00001922
1923 // (__bridge_transfer <Objective-C type>)<expression>
1924 Builder.AddTypedTextChunk("__bridge_transfer");
1925 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1926 Builder.AddPlaceholderChunk("Objective-C type");
1927 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1928 Builder.AddPlaceholderChunk("expression");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001929 Results.AddResult(Result(Builder.TakeString()));
John McCall31168b02011-06-15 23:02:42 +00001930
1931 // (__bridge_retained <CF type>)<expression>
1932 Builder.AddTypedTextChunk("__bridge_retained");
1933 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1934 Builder.AddPlaceholderChunk("CF type");
1935 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1936 Builder.AddPlaceholderChunk("expression");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001937 Results.AddResult(Result(Builder.TakeString()));
John McCall31168b02011-06-15 23:02:42 +00001938 }
1939 // Fall through
Galina Kistanova33399112017-06-03 06:35:06 +00001940 LLVM_FALLTHROUGH;
John McCall31168b02011-06-15 23:02:42 +00001941
John McCallfaf5fb42010-08-26 23:41:50 +00001942 case Sema::PCC_Expression: {
David Blaikiebbafb8a2012-03-11 07:00:24 +00001943 if (SemaRef.getLangOpts().CPlusPlus) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001944 // 'this', if we're in a non-static member function.
Douglas Gregord8c61782012-02-15 15:34:24 +00001945 addThisCompletion(SemaRef, Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001946
Douglas Gregore5c79d52011-10-18 21:20:17 +00001947 // true
1948 Builder.AddResultTypeChunk("bool");
1949 Builder.AddTypedTextChunk("true");
1950 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001951
Douglas Gregore5c79d52011-10-18 21:20:17 +00001952 // false
1953 Builder.AddResultTypeChunk("bool");
1954 Builder.AddTypedTextChunk("false");
1955 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001956
David Blaikiebbafb8a2012-03-11 07:00:24 +00001957 if (SemaRef.getLangOpts().RTTI) {
Douglas Gregorc05f6572011-04-12 02:47:21 +00001958 // dynamic_cast < type-id > ( expression )
1959 Builder.AddTypedTextChunk("dynamic_cast");
1960 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1961 Builder.AddPlaceholderChunk("type");
1962 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1963 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1964 Builder.AddPlaceholderChunk("expression");
1965 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001966 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc05f6572011-04-12 02:47:21 +00001967 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001968
Douglas Gregorf4c33342010-05-28 00:22:41 +00001969 // static_cast < type-id > ( expression )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001970 Builder.AddTypedTextChunk("static_cast");
1971 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1972 Builder.AddPlaceholderChunk("type");
1973 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1974 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1975 Builder.AddPlaceholderChunk("expression");
1976 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001977 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001978
Douglas Gregorf4c33342010-05-28 00:22:41 +00001979 // reinterpret_cast < type-id > ( expression )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001980 Builder.AddTypedTextChunk("reinterpret_cast");
1981 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1982 Builder.AddPlaceholderChunk("type");
1983 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1984 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1985 Builder.AddPlaceholderChunk("expression");
1986 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001987 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001988
Douglas Gregorf4c33342010-05-28 00:22:41 +00001989 // const_cast < type-id > ( expression )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001990 Builder.AddTypedTextChunk("const_cast");
1991 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1992 Builder.AddPlaceholderChunk("type");
1993 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1994 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1995 Builder.AddPlaceholderChunk("expression");
1996 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001997 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001998
David Blaikiebbafb8a2012-03-11 07:00:24 +00001999 if (SemaRef.getLangOpts().RTTI) {
Douglas Gregorc05f6572011-04-12 02:47:21 +00002000 // typeid ( expression-or-type )
Douglas Gregore5c79d52011-10-18 21:20:17 +00002001 Builder.AddResultTypeChunk("std::type_info");
Douglas Gregorc05f6572011-04-12 02:47:21 +00002002 Builder.AddTypedTextChunk("typeid");
2003 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2004 Builder.AddPlaceholderChunk("expression-or-type");
2005 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002006 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc05f6572011-04-12 02:47:21 +00002007 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002008
Douglas Gregorf4c33342010-05-28 00:22:41 +00002009 // new T ( ... )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002010 Builder.AddTypedTextChunk("new");
2011 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2012 Builder.AddPlaceholderChunk("type");
2013 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2014 Builder.AddPlaceholderChunk("expressions");
2015 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002016 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002017
Douglas Gregorf4c33342010-05-28 00:22:41 +00002018 // new T [ ] ( ... )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002019 Builder.AddTypedTextChunk("new");
2020 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2021 Builder.AddPlaceholderChunk("type");
2022 Builder.AddChunk(CodeCompletionString::CK_LeftBracket);
2023 Builder.AddPlaceholderChunk("size");
2024 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
2025 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2026 Builder.AddPlaceholderChunk("expressions");
2027 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002028 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002029
Douglas Gregorf4c33342010-05-28 00:22:41 +00002030 // delete expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00002031 Builder.AddResultTypeChunk("void");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002032 Builder.AddTypedTextChunk("delete");
2033 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2034 Builder.AddPlaceholderChunk("expression");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002035 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002036
Douglas Gregorf4c33342010-05-28 00:22:41 +00002037 // delete [] expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00002038 Builder.AddResultTypeChunk("void");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002039 Builder.AddTypedTextChunk("delete");
2040 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2041 Builder.AddChunk(CodeCompletionString::CK_LeftBracket);
2042 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
2043 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2044 Builder.AddPlaceholderChunk("expression");
2045 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002046
David Blaikiebbafb8a2012-03-11 07:00:24 +00002047 if (SemaRef.getLangOpts().CXXExceptions) {
Douglas Gregorc05f6572011-04-12 02:47:21 +00002048 // throw expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00002049 Builder.AddResultTypeChunk("void");
Douglas Gregorc05f6572011-04-12 02:47:21 +00002050 Builder.AddTypedTextChunk("throw");
2051 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2052 Builder.AddPlaceholderChunk("expression");
2053 Results.AddResult(Result(Builder.TakeString()));
2054 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002055
Douglas Gregora2db7932010-05-26 22:00:08 +00002056 // FIXME: Rethrow?
Douglas Gregor4205fef2011-10-18 16:29:03 +00002057
Richard Smith2bf7fdb2013-01-02 11:42:31 +00002058 if (SemaRef.getLangOpts().CPlusPlus11) {
Douglas Gregor4205fef2011-10-18 16:29:03 +00002059 // nullptr
Douglas Gregore5c79d52011-10-18 21:20:17 +00002060 Builder.AddResultTypeChunk("std::nullptr_t");
Douglas Gregor4205fef2011-10-18 16:29:03 +00002061 Builder.AddTypedTextChunk("nullptr");
2062 Results.AddResult(Result(Builder.TakeString()));
2063
2064 // alignof
Douglas Gregore5c79d52011-10-18 21:20:17 +00002065 Builder.AddResultTypeChunk("size_t");
Douglas Gregor4205fef2011-10-18 16:29:03 +00002066 Builder.AddTypedTextChunk("alignof");
2067 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2068 Builder.AddPlaceholderChunk("type");
2069 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2070 Results.AddResult(Result(Builder.TakeString()));
2071
2072 // noexcept
Douglas Gregore5c79d52011-10-18 21:20:17 +00002073 Builder.AddResultTypeChunk("bool");
Douglas Gregor4205fef2011-10-18 16:29:03 +00002074 Builder.AddTypedTextChunk("noexcept");
2075 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2076 Builder.AddPlaceholderChunk("expression");
2077 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2078 Results.AddResult(Result(Builder.TakeString()));
2079
2080 // sizeof... expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00002081 Builder.AddResultTypeChunk("size_t");
Douglas Gregor4205fef2011-10-18 16:29:03 +00002082 Builder.AddTypedTextChunk("sizeof...");
2083 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2084 Builder.AddPlaceholderChunk("parameter-pack");
2085 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2086 Results.AddResult(Result(Builder.TakeString()));
2087 }
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002088 }
2089
David Blaikiebbafb8a2012-03-11 07:00:24 +00002090 if (SemaRef.getLangOpts().ObjC1) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002091 // Add "super", if we're in an Objective-C class with a superclass.
Ted Kremenek305a0a72010-05-31 21:43:10 +00002092 if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl()) {
2093 // The interface can be NULL.
2094 if (ObjCInterfaceDecl *ID = Method->getClassInterface())
Douglas Gregore5c79d52011-10-18 21:20:17 +00002095 if (ID->getSuperClass()) {
2096 std::string SuperType;
2097 SuperType = ID->getSuperClass()->getNameAsString();
2098 if (Method->isInstanceMethod())
2099 SuperType += " *";
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002100
Douglas Gregore5c79d52011-10-18 21:20:17 +00002101 Builder.AddResultTypeChunk(Allocator.CopyString(SuperType));
2102 Builder.AddTypedTextChunk("super");
2103 Results.AddResult(Result(Builder.TakeString()));
2104 }
Ted Kremenek305a0a72010-05-31 21:43:10 +00002105 }
2106
Douglas Gregorf98e6a22010-01-13 23:51:12 +00002107 AddObjCExpressionResults(Results, true);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002108 }
2109
Jordan Rose58d54722012-06-30 21:33:57 +00002110 if (SemaRef.getLangOpts().C11) {
2111 // _Alignof
2112 Builder.AddResultTypeChunk("size_t");
Richard Smith20e883e2015-04-29 23:20:19 +00002113 if (SemaRef.PP.isMacroDefined("alignof"))
Jordan Rose58d54722012-06-30 21:33:57 +00002114 Builder.AddTypedTextChunk("alignof");
2115 else
2116 Builder.AddTypedTextChunk("_Alignof");
2117 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2118 Builder.AddPlaceholderChunk("type");
2119 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2120 Results.AddResult(Result(Builder.TakeString()));
2121 }
2122
Douglas Gregorf4c33342010-05-28 00:22:41 +00002123 // sizeof expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00002124 Builder.AddResultTypeChunk("size_t");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002125 Builder.AddTypedTextChunk("sizeof");
2126 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2127 Builder.AddPlaceholderChunk("expression-or-type");
2128 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2129 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002130 break;
2131 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002132
John McCallfaf5fb42010-08-26 23:41:50 +00002133 case Sema::PCC_Type:
Douglas Gregor80039242011-02-15 20:33:25 +00002134 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregor99fa2642010-08-24 01:06:58 +00002135 break;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002136 }
2137
David Blaikiebbafb8a2012-03-11 07:00:24 +00002138 if (WantTypesInContext(CCC, SemaRef.getLangOpts()))
2139 AddTypeSpecifierResults(SemaRef.getLangOpts(), Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002140
David Blaikiebbafb8a2012-03-11 07:00:24 +00002141 if (SemaRef.getLangOpts().CPlusPlus && CCC != Sema::PCC_Type)
Douglas Gregor78a21012010-01-14 16:01:26 +00002142 Results.AddResult(Result("operator"));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002143}
2144
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002145/// If the given declaration has an associated type, add it as a result
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002146/// type chunk.
2147static void AddResultTypeChunk(ASTContext &Context,
Douglas Gregor75acd922011-09-27 23:30:47 +00002148 const PrintingPolicy &Policy,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002149 const NamedDecl *ND,
Douglas Gregorc3425b12015-07-07 06:20:19 +00002150 QualType BaseType,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002151 CodeCompletionBuilder &Result) {
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002152 if (!ND)
2153 return;
Douglas Gregor0212fd72010-09-21 16:06:22 +00002154
2155 // Skip constructors and conversion functions, which have their return types
2156 // built into their names.
Sam McCall63c59722018-01-22 20:44:47 +00002157 if (isConstructor(ND) || isa<CXXConversionDecl>(ND))
Douglas Gregor0212fd72010-09-21 16:06:22 +00002158 return;
2159
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002160 // Determine the type of the declaration (if it has a type).
Alp Tokera2794f92014-01-22 07:29:52 +00002161 QualType T;
2162 if (const FunctionDecl *Function = ND->getAsFunction())
Alp Toker314cc812014-01-25 16:55:45 +00002163 T = Function->getReturnType();
Douglas Gregorc3425b12015-07-07 06:20:19 +00002164 else if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND)) {
2165 if (!BaseType.isNull())
2166 T = Method->getSendResultType(BaseType);
2167 else
2168 T = Method->getReturnType();
Ilya Biryukovb5da91c2017-11-08 10:39:09 +00002169 } else if (const EnumConstantDecl *Enumerator = dyn_cast<EnumConstantDecl>(ND)) {
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002170 T = Context.getTypeDeclType(cast<TypeDecl>(Enumerator->getDeclContext()));
Ilya Biryukovb5da91c2017-11-08 10:39:09 +00002171 T = clang::TypeName::getFullyQualifiedType(T, Context);
2172 } else if (isa<UnresolvedUsingValueDecl>(ND)) {
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002173 /* Do nothing: ignore unresolved using declarations*/
Douglas Gregorc3425b12015-07-07 06:20:19 +00002174 } else if (const ObjCIvarDecl *Ivar = dyn_cast<ObjCIvarDecl>(ND)) {
2175 if (!BaseType.isNull())
2176 T = Ivar->getUsageType(BaseType);
2177 else
2178 T = Ivar->getType();
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002179 } else if (const ValueDecl *Value = dyn_cast<ValueDecl>(ND)) {
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002180 T = Value->getType();
Douglas Gregorc3425b12015-07-07 06:20:19 +00002181 } else if (const ObjCPropertyDecl *Property = dyn_cast<ObjCPropertyDecl>(ND)) {
2182 if (!BaseType.isNull())
2183 T = Property->getUsageType(BaseType);
2184 else
2185 T = Property->getType();
2186 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002187
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002188 if (T.isNull() || Context.hasSameType(T, Context.DependentTy))
2189 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002190
Douglas Gregor75acd922011-09-27 23:30:47 +00002191 Result.AddResultTypeChunk(GetCompletionTypeString(T, Context, Policy,
Douglas Gregor304f9b02011-02-01 21:15:40 +00002192 Result.getAllocator()));
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002193}
2194
Richard Smith20e883e2015-04-29 23:20:19 +00002195static void MaybeAddSentinel(Preprocessor &PP,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002196 const NamedDecl *FunctionOrMethod,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002197 CodeCompletionBuilder &Result) {
Douglas Gregordbb71db2010-08-23 23:51:41 +00002198 if (SentinelAttr *Sentinel = FunctionOrMethod->getAttr<SentinelAttr>())
2199 if (Sentinel->getSentinel() == 0) {
Richard Smith20e883e2015-04-29 23:20:19 +00002200 if (PP.getLangOpts().ObjC1 && PP.isMacroDefined("nil"))
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002201 Result.AddTextChunk(", nil");
Richard Smith20e883e2015-04-29 23:20:19 +00002202 else if (PP.isMacroDefined("NULL"))
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002203 Result.AddTextChunk(", NULL");
Douglas Gregordbb71db2010-08-23 23:51:41 +00002204 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002205 Result.AddTextChunk(", (void*)0");
Douglas Gregordbb71db2010-08-23 23:51:41 +00002206 }
2207}
2208
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002209static std::string formatObjCParamQualifiers(unsigned ObjCQuals,
Douglas Gregor86b42682015-06-19 18:27:52 +00002210 QualType &Type) {
Douglas Gregor8f08d742011-07-30 07:55:26 +00002211 std::string Result;
2212 if (ObjCQuals & Decl::OBJC_TQ_In)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002213 Result += "in ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002214 else if (ObjCQuals & Decl::OBJC_TQ_Inout)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002215 Result += "inout ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002216 else if (ObjCQuals & Decl::OBJC_TQ_Out)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002217 Result += "out ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002218 if (ObjCQuals & Decl::OBJC_TQ_Bycopy)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002219 Result += "bycopy ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002220 else if (ObjCQuals & Decl::OBJC_TQ_Byref)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002221 Result += "byref ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002222 if (ObjCQuals & Decl::OBJC_TQ_Oneway)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002223 Result += "oneway ";
Douglas Gregor86b42682015-06-19 18:27:52 +00002224 if (ObjCQuals & Decl::OBJC_TQ_CSNullability) {
2225 if (auto nullability = AttributedType::stripOuterNullability(Type)) {
2226 switch (*nullability) {
2227 case NullabilityKind::NonNull:
2228 Result += "nonnull ";
2229 break;
2230
2231 case NullabilityKind::Nullable:
2232 Result += "nullable ";
2233 break;
2234
2235 case NullabilityKind::Unspecified:
2236 Result += "null_unspecified ";
2237 break;
2238 }
2239 }
2240 }
Douglas Gregor8f08d742011-07-30 07:55:26 +00002241 return Result;
2242}
2243
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002244/// Tries to find the most appropriate type location for an Objective-C
Alex Lorenza1951202016-10-18 10:35:27 +00002245/// block placeholder.
2246///
2247/// This function ignores things like typedefs and qualifiers in order to
2248/// present the most relevant and accurate block placeholders in code completion
2249/// results.
2250static void findTypeLocationForBlockDecl(const TypeSourceInfo *TSInfo,
2251 FunctionTypeLoc &Block,
2252 FunctionProtoTypeLoc &BlockProto,
2253 bool SuppressBlock = false) {
2254 if (!TSInfo)
2255 return;
2256 TypeLoc TL = TSInfo->getTypeLoc().getUnqualifiedLoc();
2257 while (true) {
2258 // Look through typedefs.
2259 if (!SuppressBlock) {
2260 if (TypedefTypeLoc TypedefTL = TL.getAs<TypedefTypeLoc>()) {
2261 if (TypeSourceInfo *InnerTSInfo =
2262 TypedefTL.getTypedefNameDecl()->getTypeSourceInfo()) {
2263 TL = InnerTSInfo->getTypeLoc().getUnqualifiedLoc();
2264 continue;
2265 }
2266 }
2267
2268 // Look through qualified types
2269 if (QualifiedTypeLoc QualifiedTL = TL.getAs<QualifiedTypeLoc>()) {
2270 TL = QualifiedTL.getUnqualifiedLoc();
2271 continue;
2272 }
2273
2274 if (AttributedTypeLoc AttrTL = TL.getAs<AttributedTypeLoc>()) {
2275 TL = AttrTL.getModifiedLoc();
2276 continue;
2277 }
2278 }
2279
2280 // Try to get the function prototype behind the block pointer type,
2281 // then we're done.
2282 if (BlockPointerTypeLoc BlockPtr = TL.getAs<BlockPointerTypeLoc>()) {
2283 TL = BlockPtr.getPointeeLoc().IgnoreParens();
2284 Block = TL.getAs<FunctionTypeLoc>();
2285 BlockProto = TL.getAs<FunctionProtoTypeLoc>();
2286 }
2287 break;
2288 }
2289}
2290
Alex Lorenz920ae142016-10-18 10:38:58 +00002291static std::string
2292formatBlockPlaceholder(const PrintingPolicy &Policy, const NamedDecl *BlockDecl,
2293 FunctionTypeLoc &Block, FunctionProtoTypeLoc &BlockProto,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002294 bool SuppressBlockName = false,
Alex Lorenz920ae142016-10-18 10:38:58 +00002295 bool SuppressBlock = false,
2296 Optional<ArrayRef<QualType>> ObjCSubsts = None);
2297
Richard Smith20e883e2015-04-29 23:20:19 +00002298static std::string FormatFunctionParameter(const PrintingPolicy &Policy,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002299 const ParmVarDecl *Param,
Douglas Gregord793e7c2011-10-18 04:23:19 +00002300 bool SuppressName = false,
Douglas Gregorc3425b12015-07-07 06:20:19 +00002301 bool SuppressBlock = false,
2302 Optional<ArrayRef<QualType>> ObjCSubsts = None) {
Douglas Gregore90dd002010-08-24 16:15:59 +00002303 bool ObjCMethodParam = isa<ObjCMethodDecl>(Param->getDeclContext());
2304 if (Param->getType()->isDependentType() ||
2305 !Param->getType()->isBlockPointerType()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002306 // The argument for a dependent or non-block parameter is a placeholder
Douglas Gregore90dd002010-08-24 16:15:59 +00002307 // containing that parameter's type.
2308 std::string Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002309
Douglas Gregor981a0c42010-08-29 19:47:46 +00002310 if (Param->getIdentifier() && !ObjCMethodParam && !SuppressName)
Douglas Gregore90dd002010-08-24 16:15:59 +00002311 Result = Param->getIdentifier()->getName();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002312
Douglas Gregor86b42682015-06-19 18:27:52 +00002313 QualType Type = Param->getType();
Douglas Gregorc3425b12015-07-07 06:20:19 +00002314 if (ObjCSubsts)
2315 Type = Type.substObjCTypeArgs(Param->getASTContext(), *ObjCSubsts,
2316 ObjCSubstitutionContext::Parameter);
Douglas Gregore90dd002010-08-24 16:15:59 +00002317 if (ObjCMethodParam) {
Douglas Gregor86b42682015-06-19 18:27:52 +00002318 Result = "(" + formatObjCParamQualifiers(Param->getObjCDeclQualifier(),
2319 Type);
2320 Result += Type.getAsString(Policy) + ")";
Douglas Gregor981a0c42010-08-29 19:47:46 +00002321 if (Param->getIdentifier() && !SuppressName)
Douglas Gregore90dd002010-08-24 16:15:59 +00002322 Result += Param->getIdentifier()->getName();
Douglas Gregor86b42682015-06-19 18:27:52 +00002323 } else {
2324 Type.getAsStringInternal(Result, Policy);
Douglas Gregore90dd002010-08-24 16:15:59 +00002325 }
2326 return Result;
2327 }
Alex Lorenza1951202016-10-18 10:35:27 +00002328
Douglas Gregore90dd002010-08-24 16:15:59 +00002329 // The argument for a block pointer parameter is a block literal with
2330 // the appropriate type.
David Blaikie6adc78e2013-02-18 22:06:02 +00002331 FunctionTypeLoc Block;
2332 FunctionProtoTypeLoc BlockProto;
Alex Lorenza1951202016-10-18 10:35:27 +00002333 findTypeLocationForBlockDecl(Param->getTypeSourceInfo(), Block, BlockProto,
2334 SuppressBlock);
Alex Lorenz6bf4a582017-03-13 15:43:42 +00002335 // Try to retrieve the block type information from the property if this is a
2336 // parameter in a setter.
2337 if (!Block && ObjCMethodParam &&
2338 cast<ObjCMethodDecl>(Param->getDeclContext())->isPropertyAccessor()) {
2339 if (const auto *PD = cast<ObjCMethodDecl>(Param->getDeclContext())
2340 ->findPropertyDecl(/*CheckOverrides=*/false))
2341 findTypeLocationForBlockDecl(PD->getTypeSourceInfo(), Block, BlockProto,
2342 SuppressBlock);
2343 }
Douglas Gregore90dd002010-08-24 16:15:59 +00002344
2345 if (!Block) {
2346 // We were unable to find a FunctionProtoTypeLoc with parameter names
2347 // for the block; just use the parameter type as a placeholder.
2348 std::string Result;
Douglas Gregord793e7c2011-10-18 04:23:19 +00002349 if (!ObjCMethodParam && Param->getIdentifier())
2350 Result = Param->getIdentifier()->getName();
2351
Douglas Gregor86b42682015-06-19 18:27:52 +00002352 QualType Type = Param->getType().getUnqualifiedType();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002353
Douglas Gregore90dd002010-08-24 16:15:59 +00002354 if (ObjCMethodParam) {
Alex Lorenz01bcfc12016-11-23 16:28:34 +00002355 Result = Type.getAsString(Policy);
2356 std::string Quals =
2357 formatObjCParamQualifiers(Param->getObjCDeclQualifier(), Type);
2358 if (!Quals.empty())
2359 Result = "(" + Quals + " " + Result + ")";
2360 if (Result.back() != ')')
2361 Result += " ";
Douglas Gregore90dd002010-08-24 16:15:59 +00002362 if (Param->getIdentifier())
2363 Result += Param->getIdentifier()->getName();
Douglas Gregor86b42682015-06-19 18:27:52 +00002364 } else {
2365 Type.getAsStringInternal(Result, Policy);
Douglas Gregore90dd002010-08-24 16:15:59 +00002366 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002367
Douglas Gregore90dd002010-08-24 16:15:59 +00002368 return Result;
2369 }
Alex Lorenz01bcfc12016-11-23 16:28:34 +00002370
Douglas Gregore90dd002010-08-24 16:15:59 +00002371 // We have the function prototype behind the block pointer type, as it was
2372 // written in the source.
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002373 return formatBlockPlaceholder(Policy, Param, Block, BlockProto,
2374 /*SuppressBlockName=*/false, SuppressBlock,
Alex Lorenz920ae142016-10-18 10:38:58 +00002375 ObjCSubsts);
2376}
2377
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002378/// Returns a placeholder string that corresponds to an Objective-C block
Alex Lorenz920ae142016-10-18 10:38:58 +00002379/// declaration.
2380///
2381/// \param BlockDecl A declaration with an Objective-C block type.
2382///
2383/// \param Block The most relevant type location for that block type.
2384///
Alexander Kornienko2a8c18d2018-04-06 15:14:32 +00002385/// \param SuppressBlockName Determines whether or not the name of the block
Alex Lorenz920ae142016-10-18 10:38:58 +00002386/// declaration is included in the resulting string.
2387static std::string
2388formatBlockPlaceholder(const PrintingPolicy &Policy, const NamedDecl *BlockDecl,
2389 FunctionTypeLoc &Block, FunctionProtoTypeLoc &BlockProto,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002390 bool SuppressBlockName, bool SuppressBlock,
Alex Lorenz920ae142016-10-18 10:38:58 +00002391 Optional<ArrayRef<QualType>> ObjCSubsts) {
Douglas Gregor67da50e2010-09-08 22:47:51 +00002392 std::string Result;
Alp Toker314cc812014-01-25 16:55:45 +00002393 QualType ResultType = Block.getTypePtr()->getReturnType();
Douglas Gregorc3425b12015-07-07 06:20:19 +00002394 if (ObjCSubsts)
Alex Lorenz920ae142016-10-18 10:38:58 +00002395 ResultType =
2396 ResultType.substObjCTypeArgs(BlockDecl->getASTContext(), *ObjCSubsts,
2397 ObjCSubstitutionContext::Result);
Douglas Gregord793e7c2011-10-18 04:23:19 +00002398 if (!ResultType->isVoidType() || SuppressBlock)
John McCall31168b02011-06-15 23:02:42 +00002399 ResultType.getAsStringInternal(Result, Policy);
Douglas Gregord793e7c2011-10-18 04:23:19 +00002400
2401 // Format the parameter list.
2402 std::string Params;
Alp Tokerb3fd5cf2014-01-21 00:32:38 +00002403 if (!BlockProto || Block.getNumParams() == 0) {
David Blaikie6adc78e2013-02-18 22:06:02 +00002404 if (BlockProto && BlockProto.getTypePtr()->isVariadic())
Douglas Gregord793e7c2011-10-18 04:23:19 +00002405 Params = "(...)";
Douglas Gregoraf25cfa2010-10-02 23:49:58 +00002406 else
Douglas Gregord793e7c2011-10-18 04:23:19 +00002407 Params = "(void)";
Douglas Gregor67da50e2010-09-08 22:47:51 +00002408 } else {
Douglas Gregord793e7c2011-10-18 04:23:19 +00002409 Params += "(";
Alp Tokerb3fd5cf2014-01-21 00:32:38 +00002410 for (unsigned I = 0, N = Block.getNumParams(); I != N; ++I) {
Douglas Gregor67da50e2010-09-08 22:47:51 +00002411 if (I)
Douglas Gregord793e7c2011-10-18 04:23:19 +00002412 Params += ", ";
Richard Smith20e883e2015-04-29 23:20:19 +00002413 Params += FormatFunctionParameter(Policy, Block.getParam(I),
Alp Tokerb3fd5cf2014-01-21 00:32:38 +00002414 /*SuppressName=*/false,
Alex Lorenz920ae142016-10-18 10:38:58 +00002415 /*SuppressBlock=*/true, ObjCSubsts);
Alp Tokerb3fd5cf2014-01-21 00:32:38 +00002416
David Blaikie6adc78e2013-02-18 22:06:02 +00002417 if (I == N - 1 && BlockProto.getTypePtr()->isVariadic())
Douglas Gregord793e7c2011-10-18 04:23:19 +00002418 Params += ", ...";
Douglas Gregor67da50e2010-09-08 22:47:51 +00002419 }
Douglas Gregord793e7c2011-10-18 04:23:19 +00002420 Params += ")";
Douglas Gregor400f5972010-08-31 05:13:43 +00002421 }
Alex Lorenz920ae142016-10-18 10:38:58 +00002422
Douglas Gregord793e7c2011-10-18 04:23:19 +00002423 if (SuppressBlock) {
2424 // Format as a parameter.
2425 Result = Result + " (^";
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002426 if (!SuppressBlockName && BlockDecl->getIdentifier())
Alex Lorenz920ae142016-10-18 10:38:58 +00002427 Result += BlockDecl->getIdentifier()->getName();
Douglas Gregord793e7c2011-10-18 04:23:19 +00002428 Result += ")";
2429 Result += Params;
2430 } else {
2431 // Format as a block literal argument.
2432 Result = '^' + Result;
2433 Result += Params;
Alex Lorenz920ae142016-10-18 10:38:58 +00002434
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002435 if (!SuppressBlockName && BlockDecl->getIdentifier())
Alex Lorenz920ae142016-10-18 10:38:58 +00002436 Result += BlockDecl->getIdentifier()->getName();
Douglas Gregord793e7c2011-10-18 04:23:19 +00002437 }
Alex Lorenz920ae142016-10-18 10:38:58 +00002438
Douglas Gregore90dd002010-08-24 16:15:59 +00002439 return Result;
2440}
2441
Erik Verbruggen11338c52017-07-19 10:45:40 +00002442static std::string GetDefaultValueString(const ParmVarDecl *Param,
2443 const SourceManager &SM,
2444 const LangOptions &LangOpts) {
Ilya Biryukovb6d1ec82017-07-21 09:24:00 +00002445 const SourceRange SrcRange = Param->getDefaultArgRange();
Erik Verbruggen11338c52017-07-19 10:45:40 +00002446 CharSourceRange CharSrcRange = CharSourceRange::getTokenRange(SrcRange);
2447 bool Invalid = CharSrcRange.isInvalid();
2448 if (Invalid)
2449 return "";
2450 StringRef srcText = Lexer::getSourceText(CharSrcRange, SM, LangOpts, &Invalid);
2451 if (Invalid)
2452 return "";
2453
2454 if (srcText.empty() || srcText == "=") {
2455 // Lexer can't determine the value.
2456 // This happens if the code is incorrect (for example class is forward declared).
2457 return "";
2458 }
Erik Verbruggen797980e2017-07-19 11:15:36 +00002459 std::string DefValue(srcText.str());
Erik Verbruggen11338c52017-07-19 10:45:40 +00002460 // FIXME: remove this check if the Lexer::getSourceText value is fixed and
2461 // this value always has (or always does not have) '=' in front of it
2462 if (DefValue.at(0) != '=') {
2463 // If we don't have '=' in front of value.
2464 // Lexer returns built-in types values without '=' and user-defined types values with it.
2465 return " = " + DefValue;
2466 }
2467 return " " + DefValue;
2468}
2469
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002470/// Add function parameter chunks to the given code completion string.
Richard Smith20e883e2015-04-29 23:20:19 +00002471static void AddFunctionParameterChunks(Preprocessor &PP,
Douglas Gregor75acd922011-09-27 23:30:47 +00002472 const PrintingPolicy &Policy,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002473 const FunctionDecl *Function,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002474 CodeCompletionBuilder &Result,
2475 unsigned Start = 0,
2476 bool InOptional = false) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002477 bool FirstParameter = true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002478
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002479 for (unsigned P = Start, N = Function->getNumParams(); P != N; ++P) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002480 const ParmVarDecl *Param = Function->getParamDecl(P);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002481
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002482 if (Param->hasDefaultArg() && !InOptional) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002483 // When we see an optional default argument, put that argument and
2484 // the remaining default arguments into a new, optional string.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00002485 CodeCompletionBuilder Opt(Result.getAllocator(),
2486 Result.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002487 if (!FirstParameter)
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002488 Opt.AddChunk(CodeCompletionString::CK_Comma);
Richard Smith20e883e2015-04-29 23:20:19 +00002489 AddFunctionParameterChunks(PP, Policy, Function, Opt, P, true);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002490 Result.AddOptionalChunk(Opt.TakeString());
2491 break;
Douglas Gregor3545ff42009-09-21 16:56:56 +00002492 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002493
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002494 if (FirstParameter)
2495 FirstParameter = false;
2496 else
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002497 Result.AddChunk(CodeCompletionString::CK_Comma);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002498
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002499 InOptional = false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002500
Douglas Gregor3545ff42009-09-21 16:56:56 +00002501 // Format the placeholder string.
Richard Smith20e883e2015-04-29 23:20:19 +00002502 std::string PlaceholderStr = FormatFunctionParameter(Policy, Param);
Erik Verbruggen11338c52017-07-19 10:45:40 +00002503 if (Param->hasDefaultArg())
2504 PlaceholderStr += GetDefaultValueString(Param, PP.getSourceManager(), PP.getLangOpts());
Richard Smith20e883e2015-04-29 23:20:19 +00002505
Douglas Gregor400f5972010-08-31 05:13:43 +00002506 if (Function->isVariadic() && P == N - 1)
2507 PlaceholderStr += ", ...";
2508
Douglas Gregor3545ff42009-09-21 16:56:56 +00002509 // Add the placeholder string.
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002510 Result.AddPlaceholderChunk(
2511 Result.getAllocator().CopyString(PlaceholderStr));
Douglas Gregor3545ff42009-09-21 16:56:56 +00002512 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002513
2514 if (const FunctionProtoType *Proto
Douglas Gregorba449032009-09-22 21:42:17 +00002515 = Function->getType()->getAs<FunctionProtoType>())
Douglas Gregordbb71db2010-08-23 23:51:41 +00002516 if (Proto->isVariadic()) {
Alp Toker9cacbab2014-01-20 20:26:09 +00002517 if (Proto->getNumParams() == 0)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002518 Result.AddPlaceholderChunk("...");
Douglas Gregordbb71db2010-08-23 23:51:41 +00002519
Richard Smith20e883e2015-04-29 23:20:19 +00002520 MaybeAddSentinel(PP, Function, Result);
Douglas Gregordbb71db2010-08-23 23:51:41 +00002521 }
Douglas Gregor3545ff42009-09-21 16:56:56 +00002522}
2523
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002524/// Add template parameter chunks to the given code completion string.
Douglas Gregor3545ff42009-09-21 16:56:56 +00002525static void AddTemplateParameterChunks(ASTContext &Context,
Douglas Gregor75acd922011-09-27 23:30:47 +00002526 const PrintingPolicy &Policy,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002527 const TemplateDecl *Template,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002528 CodeCompletionBuilder &Result,
2529 unsigned MaxParameters = 0,
2530 unsigned Start = 0,
2531 bool InDefaultArg = false) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002532 bool FirstParameter = true;
Richard Smith6eece292015-01-15 02:27:20 +00002533
2534 // Prefer to take the template parameter names from the first declaration of
2535 // the template.
2536 Template = cast<TemplateDecl>(Template->getCanonicalDecl());
2537
Douglas Gregor3545ff42009-09-21 16:56:56 +00002538 TemplateParameterList *Params = Template->getTemplateParameters();
2539 TemplateParameterList::iterator PEnd = Params->end();
2540 if (MaxParameters)
2541 PEnd = Params->begin() + MaxParameters;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002542 for (TemplateParameterList::iterator P = Params->begin() + Start;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002543 P != PEnd; ++P) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002544 bool HasDefaultArg = false;
2545 std::string PlaceholderStr;
2546 if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*P)) {
2547 if (TTP->wasDeclaredWithTypename())
2548 PlaceholderStr = "typename";
2549 else
2550 PlaceholderStr = "class";
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002551
Douglas Gregor3545ff42009-09-21 16:56:56 +00002552 if (TTP->getIdentifier()) {
2553 PlaceholderStr += ' ';
2554 PlaceholderStr += TTP->getIdentifier()->getName();
2555 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002556
Douglas Gregor3545ff42009-09-21 16:56:56 +00002557 HasDefaultArg = TTP->hasDefaultArgument();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002558 } else if (NonTypeTemplateParmDecl *NTTP
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002559 = dyn_cast<NonTypeTemplateParmDecl>(*P)) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002560 if (NTTP->getIdentifier())
2561 PlaceholderStr = NTTP->getIdentifier()->getName();
John McCall31168b02011-06-15 23:02:42 +00002562 NTTP->getType().getAsStringInternal(PlaceholderStr, Policy);
Douglas Gregor3545ff42009-09-21 16:56:56 +00002563 HasDefaultArg = NTTP->hasDefaultArgument();
2564 } else {
2565 assert(isa<TemplateTemplateParmDecl>(*P));
2566 TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*P);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002567
Douglas Gregor3545ff42009-09-21 16:56:56 +00002568 // Since putting the template argument list into the placeholder would
2569 // be very, very long, we just use an abbreviation.
2570 PlaceholderStr = "template<...> class";
2571 if (TTP->getIdentifier()) {
2572 PlaceholderStr += ' ';
2573 PlaceholderStr += TTP->getIdentifier()->getName();
2574 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002575
Douglas Gregor3545ff42009-09-21 16:56:56 +00002576 HasDefaultArg = TTP->hasDefaultArgument();
2577 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002578
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002579 if (HasDefaultArg && !InDefaultArg) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002580 // When we see an optional default argument, put that argument and
2581 // the remaining default arguments into a new, optional string.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00002582 CodeCompletionBuilder Opt(Result.getAllocator(),
2583 Result.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002584 if (!FirstParameter)
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002585 Opt.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor75acd922011-09-27 23:30:47 +00002586 AddTemplateParameterChunks(Context, Policy, Template, Opt, MaxParameters,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002587 P - Params->begin(), true);
2588 Result.AddOptionalChunk(Opt.TakeString());
2589 break;
Douglas Gregor3545ff42009-09-21 16:56:56 +00002590 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002591
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002592 InDefaultArg = false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002593
Douglas Gregor3545ff42009-09-21 16:56:56 +00002594 if (FirstParameter)
2595 FirstParameter = false;
2596 else
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002597 Result.AddChunk(CodeCompletionString::CK_Comma);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002598
Douglas Gregor3545ff42009-09-21 16:56:56 +00002599 // Add the placeholder string.
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002600 Result.AddPlaceholderChunk(
2601 Result.getAllocator().CopyString(PlaceholderStr));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002602 }
Douglas Gregor3545ff42009-09-21 16:56:56 +00002603}
2604
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002605/// Add a qualifier to the given code-completion string, if the
Douglas Gregorf2510672009-09-21 19:57:38 +00002606/// provided nested-name-specifier is non-NULL.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002607static void
2608AddQualifierToCompletionString(CodeCompletionBuilder &Result,
2609 NestedNameSpecifier *Qualifier,
Douglas Gregor0f622362009-12-11 18:44:16 +00002610 bool QualifierIsInformative,
Douglas Gregor75acd922011-09-27 23:30:47 +00002611 ASTContext &Context,
2612 const PrintingPolicy &Policy) {
Douglas Gregorf2510672009-09-21 19:57:38 +00002613 if (!Qualifier)
2614 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002615
Douglas Gregorf2510672009-09-21 19:57:38 +00002616 std::string PrintedNNS;
2617 {
2618 llvm::raw_string_ostream OS(PrintedNNS);
Douglas Gregor75acd922011-09-27 23:30:47 +00002619 Qualifier->print(OS, Policy);
Douglas Gregorf2510672009-09-21 19:57:38 +00002620 }
Douglas Gregor5bf52692009-09-22 23:15:58 +00002621 if (QualifierIsInformative)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002622 Result.AddInformativeChunk(Result.getAllocator().CopyString(PrintedNNS));
Douglas Gregor5bf52692009-09-22 23:15:58 +00002623 else
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002624 Result.AddTextChunk(Result.getAllocator().CopyString(PrintedNNS));
Douglas Gregorf2510672009-09-21 19:57:38 +00002625}
2626
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002627static void
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002628AddFunctionTypeQualsToCompletionString(CodeCompletionBuilder &Result,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002629 const FunctionDecl *Function) {
Douglas Gregor0f622362009-12-11 18:44:16 +00002630 const FunctionProtoType *Proto
2631 = Function->getType()->getAs<FunctionProtoType>();
2632 if (!Proto || !Proto->getTypeQuals())
2633 return;
2634
Douglas Gregor304f9b02011-02-01 21:15:40 +00002635 // FIXME: Add ref-qualifier!
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002636
Douglas Gregor304f9b02011-02-01 21:15:40 +00002637 // Handle single qualifiers without copying
2638 if (Proto->getTypeQuals() == Qualifiers::Const) {
2639 Result.AddInformativeChunk(" const");
2640 return;
2641 }
2642
2643 if (Proto->getTypeQuals() == Qualifiers::Volatile) {
2644 Result.AddInformativeChunk(" volatile");
2645 return;
2646 }
2647
2648 if (Proto->getTypeQuals() == Qualifiers::Restrict) {
2649 Result.AddInformativeChunk(" restrict");
2650 return;
2651 }
2652
2653 // Handle multiple qualifiers.
Douglas Gregor0f622362009-12-11 18:44:16 +00002654 std::string QualsStr;
David Blaikief5697e52012-08-10 00:55:35 +00002655 if (Proto->isConst())
Douglas Gregor0f622362009-12-11 18:44:16 +00002656 QualsStr += " const";
David Blaikief5697e52012-08-10 00:55:35 +00002657 if (Proto->isVolatile())
Douglas Gregor0f622362009-12-11 18:44:16 +00002658 QualsStr += " volatile";
David Blaikief5697e52012-08-10 00:55:35 +00002659 if (Proto->isRestrict())
Douglas Gregor0f622362009-12-11 18:44:16 +00002660 QualsStr += " restrict";
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002661 Result.AddInformativeChunk(Result.getAllocator().CopyString(QualsStr));
Douglas Gregor0f622362009-12-11 18:44:16 +00002662}
2663
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002664/// Add the name of the given declaration
Douglas Gregor75acd922011-09-27 23:30:47 +00002665static void AddTypedNameChunk(ASTContext &Context, const PrintingPolicy &Policy,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002666 const NamedDecl *ND,
2667 CodeCompletionBuilder &Result) {
Douglas Gregor0212fd72010-09-21 16:06:22 +00002668 DeclarationName Name = ND->getDeclName();
2669 if (!Name)
2670 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002671
Douglas Gregor0212fd72010-09-21 16:06:22 +00002672 switch (Name.getNameKind()) {
Douglas Gregor304f9b02011-02-01 21:15:40 +00002673 case DeclarationName::CXXOperatorName: {
Craig Topperc3ec1492014-05-26 06:22:03 +00002674 const char *OperatorName = nullptr;
Douglas Gregor304f9b02011-02-01 21:15:40 +00002675 switch (Name.getCXXOverloadedOperator()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002676 case OO_None:
Douglas Gregor304f9b02011-02-01 21:15:40 +00002677 case OO_Conditional:
2678 case NUM_OVERLOADED_OPERATORS:
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002679 OperatorName = "operator";
Douglas Gregor304f9b02011-02-01 21:15:40 +00002680 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002681
Douglas Gregor304f9b02011-02-01 21:15:40 +00002682#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
2683 case OO_##Name: OperatorName = "operator" Spelling; break;
2684#define OVERLOADED_OPERATOR_MULTI(Name,Spelling,Unary,Binary,MemberOnly)
2685#include "clang/Basic/OperatorKinds.def"
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002686
Douglas Gregor304f9b02011-02-01 21:15:40 +00002687 case OO_New: OperatorName = "operator new"; break;
2688 case OO_Delete: OperatorName = "operator delete"; break;
2689 case OO_Array_New: OperatorName = "operator new[]"; break;
2690 case OO_Array_Delete: OperatorName = "operator delete[]"; break;
2691 case OO_Call: OperatorName = "operator()"; break;
2692 case OO_Subscript: OperatorName = "operator[]"; break;
2693 }
2694 Result.AddTypedTextChunk(OperatorName);
2695 break;
2696 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002697
Douglas Gregor0212fd72010-09-21 16:06:22 +00002698 case DeclarationName::Identifier:
2699 case DeclarationName::CXXConversionFunctionName:
Douglas Gregor0212fd72010-09-21 16:06:22 +00002700 case DeclarationName::CXXDestructorName:
2701 case DeclarationName::CXXLiteralOperatorName:
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002702 Result.AddTypedTextChunk(
2703 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor0212fd72010-09-21 16:06:22 +00002704 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002705
Richard Smith35845152017-02-07 01:37:30 +00002706 case DeclarationName::CXXDeductionGuideName:
Douglas Gregor0212fd72010-09-21 16:06:22 +00002707 case DeclarationName::CXXUsingDirective:
2708 case DeclarationName::ObjCZeroArgSelector:
2709 case DeclarationName::ObjCOneArgSelector:
2710 case DeclarationName::ObjCMultiArgSelector:
2711 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002712
Douglas Gregor0212fd72010-09-21 16:06:22 +00002713 case DeclarationName::CXXConstructorName: {
Craig Topperc3ec1492014-05-26 06:22:03 +00002714 CXXRecordDecl *Record = nullptr;
Douglas Gregor0212fd72010-09-21 16:06:22 +00002715 QualType Ty = Name.getCXXNameType();
2716 if (const RecordType *RecordTy = Ty->getAs<RecordType>())
2717 Record = cast<CXXRecordDecl>(RecordTy->getDecl());
2718 else if (const InjectedClassNameType *InjectedTy
2719 = Ty->getAs<InjectedClassNameType>())
2720 Record = InjectedTy->getDecl();
2721 else {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002722 Result.AddTypedTextChunk(
2723 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor0212fd72010-09-21 16:06:22 +00002724 break;
2725 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002726
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002727 Result.AddTypedTextChunk(
2728 Result.getAllocator().CopyString(Record->getNameAsString()));
Douglas Gregor0212fd72010-09-21 16:06:22 +00002729 if (ClassTemplateDecl *Template = Record->getDescribedClassTemplate()) {
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002730 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Douglas Gregor75acd922011-09-27 23:30:47 +00002731 AddTemplateParameterChunks(Context, Policy, Template, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002732 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregor0212fd72010-09-21 16:06:22 +00002733 }
2734 break;
2735 }
2736 }
2737}
2738
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002739CodeCompletionString *CodeCompletionResult::CreateCodeCompletionString(Sema &S,
Douglas Gregorc3425b12015-07-07 06:20:19 +00002740 const CodeCompletionContext &CCContext,
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00002741 CodeCompletionAllocator &Allocator,
Dmitri Gribenko3292d062012-07-02 17:35:10 +00002742 CodeCompletionTUInfo &CCTUInfo,
2743 bool IncludeBriefComments) {
Douglas Gregorc3425b12015-07-07 06:20:19 +00002744 return CreateCodeCompletionString(S.Context, S.PP, CCContext, Allocator,
2745 CCTUInfo, IncludeBriefComments);
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002746}
2747
Eric Liu00f43c92018-07-06 09:43:57 +00002748CodeCompletionString *CodeCompletionResult::CreateCodeCompletionStringForMacro(
2749 Preprocessor &PP, CodeCompletionAllocator &Allocator,
2750 CodeCompletionTUInfo &CCTUInfo) {
2751 assert(Kind == RK_Macro);
2752 CodeCompletionBuilder Result(Allocator, CCTUInfo, Priority, Availability);
2753 const MacroInfo *MI = PP.getMacroInfo(Macro);
2754 Result.AddTypedTextChunk(Result.getAllocator().CopyString(Macro->getName()));
2755
2756 if (!MI || !MI->isFunctionLike())
2757 return Result.TakeString();
2758
2759 // Format a function-like macro with placeholders for the arguments.
2760 Result.AddChunk(CodeCompletionString::CK_LeftParen);
2761 MacroInfo::param_iterator A = MI->param_begin(), AEnd = MI->param_end();
2762
2763 // C99 variadic macros add __VA_ARGS__ at the end. Skip it.
2764 if (MI->isC99Varargs()) {
2765 --AEnd;
2766
2767 if (A == AEnd) {
2768 Result.AddPlaceholderChunk("...");
2769 }
2770 }
2771
2772 for (MacroInfo::param_iterator A = MI->param_begin(); A != AEnd; ++A) {
2773 if (A != MI->param_begin())
2774 Result.AddChunk(CodeCompletionString::CK_Comma);
2775
2776 if (MI->isVariadic() && (A + 1) == AEnd) {
2777 SmallString<32> Arg = (*A)->getName();
2778 if (MI->isC99Varargs())
2779 Arg += ", ...";
2780 else
2781 Arg += "...";
2782 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg));
2783 break;
2784 }
2785
2786 // Non-variadic macros are simple.
2787 Result.AddPlaceholderChunk(
2788 Result.getAllocator().CopyString((*A)->getName()));
2789 }
2790 Result.AddChunk(CodeCompletionString::CK_RightParen);
2791 return Result.TakeString();
2792}
2793
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002794/// If possible, create a new code completion string for the given
Douglas Gregor3545ff42009-09-21 16:56:56 +00002795/// result.
2796///
2797/// \returns Either a new, heap-allocated code completion string describing
2798/// how to use this result, or NULL to indicate that the string or name of the
2799/// result is all that is needed.
2800CodeCompletionString *
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002801CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx,
2802 Preprocessor &PP,
Douglas Gregorc3425b12015-07-07 06:20:19 +00002803 const CodeCompletionContext &CCContext,
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00002804 CodeCompletionAllocator &Allocator,
Dmitri Gribenko3292d062012-07-02 17:35:10 +00002805 CodeCompletionTUInfo &CCTUInfo,
2806 bool IncludeBriefComments) {
Eric Liu00f43c92018-07-06 09:43:57 +00002807 if (Kind == RK_Macro)
2808 return CreateCodeCompletionStringForMacro(PP, Allocator, CCTUInfo);
2809
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00002810 CodeCompletionBuilder Result(Allocator, CCTUInfo, Priority, Availability);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002811
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002812 PrintingPolicy Policy = getCompletionPrintingPolicy(Ctx, PP);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002813 if (Kind == RK_Pattern) {
2814 Pattern->Priority = Priority;
2815 Pattern->Availability = Availability;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002816
Douglas Gregor78254c82012-03-27 23:34:16 +00002817 if (Declaration) {
2818 Result.addParentContext(Declaration->getDeclContext());
Douglas Gregor78254c82012-03-27 23:34:16 +00002819 Pattern->ParentName = Result.getParentName();
Ilya Biryukova3f955b2018-05-16 12:30:01 +00002820 if (const RawComment *RC =
2821 getPatternCompletionComment(Ctx, Declaration)) {
2822 Result.addBriefComment(RC->getBriefText(Ctx));
2823 Pattern->BriefComment = Result.getBriefComment();
2824 }
Douglas Gregor78254c82012-03-27 23:34:16 +00002825 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002826
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002827 return Pattern;
2828 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002829
Douglas Gregorf09935f2009-12-01 05:55:20 +00002830 if (Kind == RK_Keyword) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002831 Result.AddTypedTextChunk(Keyword);
2832 return Result.TakeString();
Douglas Gregorf09935f2009-12-01 05:55:20 +00002833 }
Douglas Gregorf64acca2010-05-25 21:41:55 +00002834 assert(Kind == RK_Declaration && "Missed a result kind?");
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002835 const NamedDecl *ND = Declaration;
Douglas Gregor78254c82012-03-27 23:34:16 +00002836 Result.addParentContext(ND->getDeclContext());
Dmitri Gribenko3292d062012-07-02 17:35:10 +00002837
2838 if (IncludeBriefComments) {
2839 // Add documentation comment, if it exists.
Ilya Biryukova3f955b2018-05-16 12:30:01 +00002840 if (const RawComment *RC = getCompletionComment(Ctx, Declaration)) {
Dmitri Gribenko3292d062012-07-02 17:35:10 +00002841 Result.addBriefComment(RC->getBriefText(Ctx));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002842 }
Dmitri Gribenko3292d062012-07-02 17:35:10 +00002843 }
2844
Douglas Gregor9eb77012009-11-07 00:00:49 +00002845 if (StartsNestedNameSpecifier) {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002846 Result.AddTypedTextChunk(
2847 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002848 Result.AddTextChunk("::");
2849 return Result.TakeString();
Douglas Gregor9eb77012009-11-07 00:00:49 +00002850 }
Erik Verbruggen98ea7f62011-10-14 15:31:08 +00002851
Aaron Ballmanbe22bcb2014-03-10 17:08:28 +00002852 for (const auto *I : ND->specific_attrs<AnnotateAttr>())
2853 Result.AddAnnotation(Result.getAllocator().CopyString(I->getAnnotation()));
Aaron Ballmanb97112e2014-03-08 22:19:01 +00002854
Douglas Gregorc3425b12015-07-07 06:20:19 +00002855 AddResultTypeChunk(Ctx, Policy, ND, CCContext.getBaseType(), Result);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002856
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002857 if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(ND)) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002858 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002859 Ctx, Policy);
2860 AddTypedNameChunk(Ctx, Policy, ND, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002861 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Richard Smith20e883e2015-04-29 23:20:19 +00002862 AddFunctionParameterChunks(PP, Policy, Function, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002863 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor0f622362009-12-11 18:44:16 +00002864 AddFunctionTypeQualsToCompletionString(Result, Function);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002865 return Result.TakeString();
Douglas Gregor3545ff42009-09-21 16:56:56 +00002866 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002867
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002868 if (const FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND)) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002869 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002870 Ctx, Policy);
Douglas Gregor3545ff42009-09-21 16:56:56 +00002871 FunctionDecl *Function = FunTmpl->getTemplatedDecl();
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002872 AddTypedNameChunk(Ctx, Policy, Function, Result);
Douglas Gregor0212fd72010-09-21 16:06:22 +00002873
Douglas Gregor3545ff42009-09-21 16:56:56 +00002874 // Figure out which template parameters are deduced (or have default
2875 // arguments).
Benjamin Kramere0513cb2012-01-30 16:17:39 +00002876 llvm::SmallBitVector Deduced;
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002877 Sema::MarkDeducedTemplateParameters(Ctx, FunTmpl, Deduced);
Douglas Gregor3545ff42009-09-21 16:56:56 +00002878 unsigned LastDeducibleArgument;
2879 for (LastDeducibleArgument = Deduced.size(); LastDeducibleArgument > 0;
2880 --LastDeducibleArgument) {
2881 if (!Deduced[LastDeducibleArgument - 1]) {
2882 // C++0x: Figure out if the template argument has a default. If so,
2883 // the user doesn't need to type this argument.
2884 // FIXME: We need to abstract template parameters better!
2885 bool HasDefaultArg = false;
2886 NamedDecl *Param = FunTmpl->getTemplateParameters()->getParam(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002887 LastDeducibleArgument - 1);
Douglas Gregor3545ff42009-09-21 16:56:56 +00002888 if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param))
2889 HasDefaultArg = TTP->hasDefaultArgument();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002890 else if (NonTypeTemplateParmDecl *NTTP
Douglas Gregor3545ff42009-09-21 16:56:56 +00002891 = dyn_cast<NonTypeTemplateParmDecl>(Param))
2892 HasDefaultArg = NTTP->hasDefaultArgument();
2893 else {
2894 assert(isa<TemplateTemplateParmDecl>(Param));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002895 HasDefaultArg
Douglas Gregor9eb77012009-11-07 00:00:49 +00002896 = cast<TemplateTemplateParmDecl>(Param)->hasDefaultArgument();
Douglas Gregor3545ff42009-09-21 16:56:56 +00002897 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002898
Douglas Gregor3545ff42009-09-21 16:56:56 +00002899 if (!HasDefaultArg)
2900 break;
2901 }
2902 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002903
Douglas Gregor3545ff42009-09-21 16:56:56 +00002904 if (LastDeducibleArgument) {
2905 // Some of the function template arguments cannot be deduced from a
2906 // function call, so we introduce an explicit template argument list
2907 // containing all of the arguments up to the first deducible argument.
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002908 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002909 AddTemplateParameterChunks(Ctx, Policy, FunTmpl, Result,
Douglas Gregor3545ff42009-09-21 16:56:56 +00002910 LastDeducibleArgument);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002911 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregor3545ff42009-09-21 16:56:56 +00002912 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002913
Douglas Gregor3545ff42009-09-21 16:56:56 +00002914 // Add the function parameters
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002915 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Richard Smith20e883e2015-04-29 23:20:19 +00002916 AddFunctionParameterChunks(PP, Policy, Function, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002917 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor0f622362009-12-11 18:44:16 +00002918 AddFunctionTypeQualsToCompletionString(Result, Function);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002919 return Result.TakeString();
Douglas Gregor3545ff42009-09-21 16:56:56 +00002920 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002921
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002922 if (const TemplateDecl *Template = dyn_cast<TemplateDecl>(ND)) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002923 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002924 Ctx, Policy);
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002925 Result.AddTypedTextChunk(
2926 Result.getAllocator().CopyString(Template->getNameAsString()));
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002927 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002928 AddTemplateParameterChunks(Ctx, Policy, Template, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002929 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002930 return Result.TakeString();
Douglas Gregor3545ff42009-09-21 16:56:56 +00002931 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002932
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002933 if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND)) {
Douglas Gregord3c5d792009-11-17 16:44:22 +00002934 Selector Sel = Method->getSelector();
2935 if (Sel.isUnarySelector()) {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002936 Result.AddTypedTextChunk(Result.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00002937 Sel.getNameForSlot(0)));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002938 return Result.TakeString();
Douglas Gregord3c5d792009-11-17 16:44:22 +00002939 }
2940
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00002941 std::string SelName = Sel.getNameForSlot(0).str();
Douglas Gregor1b605f72009-11-19 01:08:35 +00002942 SelName += ':';
2943 if (StartParameter == 0)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002944 Result.AddTypedTextChunk(Result.getAllocator().CopyString(SelName));
Douglas Gregor1b605f72009-11-19 01:08:35 +00002945 else {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002946 Result.AddInformativeChunk(Result.getAllocator().CopyString(SelName));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002947
Douglas Gregor1b605f72009-11-19 01:08:35 +00002948 // If there is only one parameter, and we're past it, add an empty
2949 // typed-text chunk since there is nothing to type.
2950 if (Method->param_size() == 1)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002951 Result.AddTypedTextChunk("");
Douglas Gregor1b605f72009-11-19 01:08:35 +00002952 }
Douglas Gregord3c5d792009-11-17 16:44:22 +00002953 unsigned Idx = 0;
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002954 for (ObjCMethodDecl::param_const_iterator P = Method->param_begin(),
2955 PEnd = Method->param_end();
Douglas Gregord3c5d792009-11-17 16:44:22 +00002956 P != PEnd; (void)++P, ++Idx) {
2957 if (Idx > 0) {
Douglas Gregor1b605f72009-11-19 01:08:35 +00002958 std::string Keyword;
2959 if (Idx > StartParameter)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002960 Result.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregord3c5d792009-11-17 16:44:22 +00002961 if (IdentifierInfo *II = Sel.getIdentifierInfoForSlot(Idx))
Benjamin Kramer632500c2011-07-26 16:59:25 +00002962 Keyword += II->getName();
Douglas Gregord3c5d792009-11-17 16:44:22 +00002963 Keyword += ":";
Douglas Gregor95887f92010-07-08 23:20:03 +00002964 if (Idx < StartParameter || AllParametersAreInformative)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002965 Result.AddInformativeChunk(Result.getAllocator().CopyString(Keyword));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002966 else
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002967 Result.AddTypedTextChunk(Result.getAllocator().CopyString(Keyword));
Douglas Gregord3c5d792009-11-17 16:44:22 +00002968 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002969
Douglas Gregor1b605f72009-11-19 01:08:35 +00002970 // If we're before the starting parameter, skip the placeholder.
2971 if (Idx < StartParameter)
2972 continue;
Douglas Gregord3c5d792009-11-17 16:44:22 +00002973
2974 std::string Arg;
Douglas Gregorc3425b12015-07-07 06:20:19 +00002975 QualType ParamType = (*P)->getType();
2976 Optional<ArrayRef<QualType>> ObjCSubsts;
2977 if (!CCContext.getBaseType().isNull())
2978 ObjCSubsts = CCContext.getBaseType()->getObjCSubstitutions(Method);
2979
2980 if (ParamType->isBlockPointerType() && !DeclaringEntity)
2981 Arg = FormatFunctionParameter(Policy, *P, true,
2982 /*SuppressBlock=*/false,
2983 ObjCSubsts);
Douglas Gregore90dd002010-08-24 16:15:59 +00002984 else {
Douglas Gregorc3425b12015-07-07 06:20:19 +00002985 if (ObjCSubsts)
2986 ParamType = ParamType.substObjCTypeArgs(Ctx, *ObjCSubsts,
2987 ObjCSubstitutionContext::Parameter);
Douglas Gregor86b42682015-06-19 18:27:52 +00002988 Arg = "(" + formatObjCParamQualifiers((*P)->getObjCDeclQualifier(),
Douglas Gregorc3425b12015-07-07 06:20:19 +00002989 ParamType);
2990 Arg += ParamType.getAsString(Policy) + ")";
Douglas Gregore90dd002010-08-24 16:15:59 +00002991 if (IdentifierInfo *II = (*P)->getIdentifier())
Douglas Gregor981a0c42010-08-29 19:47:46 +00002992 if (DeclaringEntity || AllParametersAreInformative)
Benjamin Kramer632500c2011-07-26 16:59:25 +00002993 Arg += II->getName();
Douglas Gregore90dd002010-08-24 16:15:59 +00002994 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002995
Douglas Gregor400f5972010-08-31 05:13:43 +00002996 if (Method->isVariadic() && (P + 1) == PEnd)
2997 Arg += ", ...";
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002998
Douglas Gregor95887f92010-07-08 23:20:03 +00002999 if (DeclaringEntity)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003000 Result.AddTextChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregor95887f92010-07-08 23:20:03 +00003001 else if (AllParametersAreInformative)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003002 Result.AddInformativeChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregorc8537c52009-11-19 07:41:15 +00003003 else
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003004 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregord3c5d792009-11-17 16:44:22 +00003005 }
3006
Douglas Gregor04c5f972009-12-23 00:21:46 +00003007 if (Method->isVariadic()) {
Douglas Gregor400f5972010-08-31 05:13:43 +00003008 if (Method->param_size() == 0) {
3009 if (DeclaringEntity)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003010 Result.AddTextChunk(", ...");
Douglas Gregor400f5972010-08-31 05:13:43 +00003011 else if (AllParametersAreInformative)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003012 Result.AddInformativeChunk(", ...");
Douglas Gregor400f5972010-08-31 05:13:43 +00003013 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003014 Result.AddPlaceholderChunk(", ...");
Douglas Gregor400f5972010-08-31 05:13:43 +00003015 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003016
Richard Smith20e883e2015-04-29 23:20:19 +00003017 MaybeAddSentinel(PP, Method, Result);
Douglas Gregor04c5f972009-12-23 00:21:46 +00003018 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003019
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003020 return Result.TakeString();
Douglas Gregord3c5d792009-11-17 16:44:22 +00003021 }
3022
Douglas Gregorf09935f2009-12-01 05:55:20 +00003023 if (Qualifier)
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003024 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003025 Ctx, Policy);
Douglas Gregorf09935f2009-12-01 05:55:20 +00003026
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003027 Result.AddTypedTextChunk(
3028 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003029 return Result.TakeString();
Douglas Gregor3545ff42009-09-21 16:56:56 +00003030}
3031
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003032const RawComment *clang::getCompletionComment(const ASTContext &Ctx,
3033 const NamedDecl *ND) {
3034 if (!ND)
3035 return nullptr;
3036 if (auto *RC = Ctx.getRawCommentForAnyRedecl(ND))
3037 return RC;
3038
3039 // Try to find comment from a property for ObjC methods.
3040 const ObjCMethodDecl *M = dyn_cast<ObjCMethodDecl>(ND);
3041 if (!M)
3042 return nullptr;
3043 const ObjCPropertyDecl *PDecl = M->findPropertyDecl();
3044 if (!PDecl)
3045 return nullptr;
3046
3047 return Ctx.getRawCommentForAnyRedecl(PDecl);
3048}
3049
3050const RawComment *clang::getPatternCompletionComment(const ASTContext &Ctx,
3051 const NamedDecl *ND) {
3052 const ObjCMethodDecl *M = dyn_cast_or_null<ObjCMethodDecl>(ND);
3053 if (!M || !M->isPropertyAccessor())
3054 return nullptr;
3055
3056 // Provide code completion comment for self.GetterName where
3057 // GetterName is the getter method for a property with name
3058 // different from the property name (declared via a property
3059 // getter attribute.
3060 const ObjCPropertyDecl *PDecl = M->findPropertyDecl();
3061 if (!PDecl)
3062 return nullptr;
3063 if (PDecl->getGetterName() == M->getSelector() &&
3064 PDecl->getIdentifier() != M->getIdentifier()) {
3065 if (auto *RC = Ctx.getRawCommentForAnyRedecl(M))
3066 return RC;
3067 if (auto *RC = Ctx.getRawCommentForAnyRedecl(PDecl))
3068 return RC;
3069 }
3070 return nullptr;
3071}
3072
3073const RawComment *clang::getParameterComment(
3074 const ASTContext &Ctx,
3075 const CodeCompleteConsumer::OverloadCandidate &Result,
3076 unsigned ArgIndex) {
3077 auto FDecl = Result.getFunction();
3078 if (!FDecl)
3079 return nullptr;
3080 if (ArgIndex < FDecl->getNumParams())
3081 return Ctx.getRawCommentForAnyRedecl(FDecl->getParamDecl(ArgIndex));
3082 return nullptr;
3083}
3084
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003085/// Add function overload parameter chunks to the given code completion
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003086/// string.
3087static void AddOverloadParameterChunks(ASTContext &Context,
3088 const PrintingPolicy &Policy,
3089 const FunctionDecl *Function,
3090 const FunctionProtoType *Prototype,
3091 CodeCompletionBuilder &Result,
3092 unsigned CurrentArg,
3093 unsigned Start = 0,
3094 bool InOptional = false) {
3095 bool FirstParameter = true;
3096 unsigned NumParams = Function ? Function->getNumParams()
3097 : Prototype->getNumParams();
3098
3099 for (unsigned P = Start; P != NumParams; ++P) {
3100 if (Function && Function->getParamDecl(P)->hasDefaultArg() && !InOptional) {
3101 // When we see an optional default argument, put that argument and
3102 // the remaining default arguments into a new, optional string.
3103 CodeCompletionBuilder Opt(Result.getAllocator(),
3104 Result.getCodeCompletionTUInfo());
3105 if (!FirstParameter)
3106 Opt.AddChunk(CodeCompletionString::CK_Comma);
3107 // Optional sections are nested.
3108 AddOverloadParameterChunks(Context, Policy, Function, Prototype, Opt,
3109 CurrentArg, P, /*InOptional=*/true);
3110 Result.AddOptionalChunk(Opt.TakeString());
3111 return;
3112 }
3113
3114 if (FirstParameter)
3115 FirstParameter = false;
3116 else
3117 Result.AddChunk(CodeCompletionString::CK_Comma);
3118
3119 InOptional = false;
3120
3121 // Format the placeholder string.
3122 std::string Placeholder;
Erik Verbruggen11338c52017-07-19 10:45:40 +00003123 if (Function) {
3124 const ParmVarDecl *Param = Function->getParamDecl(P);
3125 Placeholder = FormatFunctionParameter(Policy, Param);
3126 if (Param->hasDefaultArg())
3127 Placeholder += GetDefaultValueString(Param, Context.getSourceManager(), Context.getLangOpts());
3128 } else {
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003129 Placeholder = Prototype->getParamType(P).getAsString(Policy);
Erik Verbruggen11338c52017-07-19 10:45:40 +00003130 }
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003131
3132 if (P == CurrentArg)
3133 Result.AddCurrentParameterChunk(
3134 Result.getAllocator().CopyString(Placeholder));
3135 else
3136 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Placeholder));
3137 }
3138
3139 if (Prototype && Prototype->isVariadic()) {
3140 CodeCompletionBuilder Opt(Result.getAllocator(),
3141 Result.getCodeCompletionTUInfo());
3142 if (!FirstParameter)
3143 Opt.AddChunk(CodeCompletionString::CK_Comma);
3144
3145 if (CurrentArg < NumParams)
3146 Opt.AddPlaceholderChunk("...");
3147 else
3148 Opt.AddCurrentParameterChunk("...");
3149
3150 Result.AddOptionalChunk(Opt.TakeString());
3151 }
3152}
3153
Douglas Gregorf0f51982009-09-23 00:34:09 +00003154CodeCompletionString *
3155CodeCompleteConsumer::OverloadCandidate::CreateSignatureString(
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003156 unsigned CurrentArg, Sema &S,
3157 CodeCompletionAllocator &Allocator,
3158 CodeCompletionTUInfo &CCTUInfo,
3159 bool IncludeBriefComments) const {
Douglas Gregor75acd922011-09-27 23:30:47 +00003160 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
John McCall31168b02011-06-15 23:02:42 +00003161
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003162 // FIXME: Set priority, availability appropriately.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003163 CodeCompletionBuilder Result(Allocator,CCTUInfo, 1, CXAvailability_Available);
Douglas Gregorf0f51982009-09-23 00:34:09 +00003164 FunctionDecl *FDecl = getFunction();
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003165 const FunctionProtoType *Proto
Douglas Gregorf0f51982009-09-23 00:34:09 +00003166 = dyn_cast<FunctionProtoType>(getFunctionType());
3167 if (!FDecl && !Proto) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003168 // Function without a prototype. Just give the return type and a
Douglas Gregorf0f51982009-09-23 00:34:09 +00003169 // highlighted ellipsis.
3170 const FunctionType *FT = getFunctionType();
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003171 Result.AddResultTypeChunk(Result.getAllocator().CopyString(
3172 FT->getReturnType().getAsString(Policy)));
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003173 Result.AddChunk(CodeCompletionString::CK_LeftParen);
3174 Result.AddChunk(CodeCompletionString::CK_CurrentParameter, "...");
3175 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003176 return Result.TakeString();
Douglas Gregorf0f51982009-09-23 00:34:09 +00003177 }
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003178
3179 if (FDecl) {
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003180 if (IncludeBriefComments) {
3181 if (auto RC = getParameterComment(S.getASTContext(), *this, CurrentArg))
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003182 Result.addBriefComment(RC->getBriefText(S.getASTContext()));
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003183 }
Douglas Gregorc3425b12015-07-07 06:20:19 +00003184 AddResultTypeChunk(S.Context, Policy, FDecl, QualType(), Result);
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003185 Result.AddTextChunk(
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003186 Result.getAllocator().CopyString(FDecl->getNameAsString()));
3187 } else {
3188 Result.AddResultTypeChunk(
3189 Result.getAllocator().CopyString(
Alp Toker314cc812014-01-25 16:55:45 +00003190 Proto->getReturnType().getAsString(Policy)));
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003191 }
Alp Toker314cc812014-01-25 16:55:45 +00003192
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003193 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003194 AddOverloadParameterChunks(S.getASTContext(), Policy, FDecl, Proto, Result,
3195 CurrentArg);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003196 Result.AddChunk(CodeCompletionString::CK_RightParen);
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003197
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003198 return Result.TakeString();
Douglas Gregorf0f51982009-09-23 00:34:09 +00003199}
3200
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003201unsigned clang::getMacroUsagePriority(StringRef MacroName,
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00003202 const LangOptions &LangOpts,
Douglas Gregor6e240332010-08-16 16:18:59 +00003203 bool PreferredTypeIsPointer) {
3204 unsigned Priority = CCP_Macro;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003205
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00003206 // Treat the "nil", "Nil" and "NULL" macros as null pointer constants.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003207 if (MacroName.equals("nil") || MacroName.equals("NULL") ||
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00003208 MacroName.equals("Nil")) {
Douglas Gregor6e240332010-08-16 16:18:59 +00003209 Priority = CCP_Constant;
3210 if (PreferredTypeIsPointer)
3211 Priority = Priority / CCF_SimilarTypeMatch;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003212 }
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00003213 // Treat "YES", "NO", "true", and "false" as constants.
3214 else if (MacroName.equals("YES") || MacroName.equals("NO") ||
3215 MacroName.equals("true") || MacroName.equals("false"))
3216 Priority = CCP_Constant;
3217 // Treat "bool" as a type.
3218 else if (MacroName.equals("bool"))
3219 Priority = CCP_Type + (LangOpts.ObjC1? CCD_bool_in_ObjC : 0);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003220
3221
Douglas Gregor6e240332010-08-16 16:18:59 +00003222 return Priority;
3223}
3224
Dmitri Gribenkobdc80de2013-01-11 20:32:41 +00003225CXCursorKind clang::getCursorKindForDecl(const Decl *D) {
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003226 if (!D)
3227 return CXCursor_UnexposedDecl;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003228
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003229 switch (D->getKind()) {
3230 case Decl::Enum: return CXCursor_EnumDecl;
3231 case Decl::EnumConstant: return CXCursor_EnumConstantDecl;
3232 case Decl::Field: return CXCursor_FieldDecl;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003233 case Decl::Function:
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003234 return CXCursor_FunctionDecl;
3235 case Decl::ObjCCategory: return CXCursor_ObjCCategoryDecl;
3236 case Decl::ObjCCategoryImpl: return CXCursor_ObjCCategoryImplDecl;
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003237 case Decl::ObjCImplementation: return CXCursor_ObjCImplementationDecl;
Douglas Gregordeafd0b2011-12-27 22:43:10 +00003238
Argyrios Kyrtzidis3698cef2012-01-24 21:39:26 +00003239 case Decl::ObjCInterface: return CXCursor_ObjCInterfaceDecl;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003240 case Decl::ObjCIvar: return CXCursor_ObjCIvarDecl;
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003241 case Decl::ObjCMethod:
3242 return cast<ObjCMethodDecl>(D)->isInstanceMethod()
3243 ? CXCursor_ObjCInstanceMethodDecl : CXCursor_ObjCClassMethodDecl;
3244 case Decl::CXXMethod: return CXCursor_CXXMethod;
3245 case Decl::CXXConstructor: return CXCursor_Constructor;
3246 case Decl::CXXDestructor: return CXCursor_Destructor;
3247 case Decl::CXXConversion: return CXCursor_ConversionFunction;
3248 case Decl::ObjCProperty: return CXCursor_ObjCPropertyDecl;
Argyrios Kyrtzidis3698cef2012-01-24 21:39:26 +00003249 case Decl::ObjCProtocol: return CXCursor_ObjCProtocolDecl;
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003250 case Decl::ParmVar: return CXCursor_ParmDecl;
3251 case Decl::Typedef: return CXCursor_TypedefDecl;
Richard Smithdda56e42011-04-15 14:24:37 +00003252 case Decl::TypeAlias: return CXCursor_TypeAliasDecl;
Sergey Kalinichev8f3b1872015-11-15 13:48:32 +00003253 case Decl::TypeAliasTemplate: return CXCursor_TypeAliasTemplateDecl;
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003254 case Decl::Var: return CXCursor_VarDecl;
3255 case Decl::Namespace: return CXCursor_Namespace;
3256 case Decl::NamespaceAlias: return CXCursor_NamespaceAlias;
3257 case Decl::TemplateTypeParm: return CXCursor_TemplateTypeParameter;
3258 case Decl::NonTypeTemplateParm:return CXCursor_NonTypeTemplateParameter;
3259 case Decl::TemplateTemplateParm:return CXCursor_TemplateTemplateParameter;
3260 case Decl::FunctionTemplate: return CXCursor_FunctionTemplate;
3261 case Decl::ClassTemplate: return CXCursor_ClassTemplate;
Argyrios Kyrtzidis12afd702011-09-30 17:58:23 +00003262 case Decl::AccessSpec: return CXCursor_CXXAccessSpecifier;
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003263 case Decl::ClassTemplatePartialSpecialization:
3264 return CXCursor_ClassTemplatePartialSpecialization;
3265 case Decl::UsingDirective: return CXCursor_UsingDirective;
Olivier Goffart81978012016-06-09 16:15:55 +00003266 case Decl::StaticAssert: return CXCursor_StaticAssert;
Olivier Goffartd211c642016-11-04 06:29:27 +00003267 case Decl::Friend: return CXCursor_FriendDecl;
Douglas Gregor3e653b32012-04-30 23:41:16 +00003268 case Decl::TranslationUnit: return CXCursor_TranslationUnit;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003269
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003270 case Decl::Using:
3271 case Decl::UnresolvedUsingValue:
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003272 case Decl::UnresolvedUsingTypename:
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003273 return CXCursor_UsingDeclaration;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003274
Douglas Gregor4cd65962011-06-03 23:08:58 +00003275 case Decl::ObjCPropertyImpl:
3276 switch (cast<ObjCPropertyImplDecl>(D)->getPropertyImplementation()) {
3277 case ObjCPropertyImplDecl::Dynamic:
3278 return CXCursor_ObjCDynamicDecl;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003279
Douglas Gregor4cd65962011-06-03 23:08:58 +00003280 case ObjCPropertyImplDecl::Synthesize:
3281 return CXCursor_ObjCSynthesizeDecl;
3282 }
Argyrios Kyrtzidis50e5b1d2012-10-05 00:22:24 +00003283
3284 case Decl::Import:
3285 return CXCursor_ModuleImportDecl;
Douglas Gregor85f3f952015-07-07 03:57:15 +00003286
3287 case Decl::ObjCTypeParam: return CXCursor_TemplateTypeParameter;
3288
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003289 default:
Dmitri Gribenkobdc80de2013-01-11 20:32:41 +00003290 if (const TagDecl *TD = dyn_cast<TagDecl>(D)) {
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003291 switch (TD->getTagKind()) {
Joao Matosdc86f942012-08-31 18:45:21 +00003292 case TTK_Interface: // fall through
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003293 case TTK_Struct: return CXCursor_StructDecl;
3294 case TTK_Class: return CXCursor_ClassDecl;
3295 case TTK_Union: return CXCursor_UnionDecl;
3296 case TTK_Enum: return CXCursor_EnumDecl;
3297 }
3298 }
3299 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003300
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003301 return CXCursor_UnexposedDecl;
3302}
3303
Douglas Gregor55b037b2010-07-08 20:55:51 +00003304static void AddMacroResults(Preprocessor &PP, ResultBuilder &Results,
Douglas Gregor8cb17462012-10-09 16:01:50 +00003305 bool IncludeUndefined,
Douglas Gregor55b037b2010-07-08 20:55:51 +00003306 bool TargetTypeIsPointer = false) {
John McCall276321a2010-08-25 06:19:51 +00003307 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003308
Douglas Gregorf329c7c2009-10-30 16:50:04 +00003309 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003310
3311 for (Preprocessor::macro_iterator M = PP.macro_begin(),
Douglas Gregor9eb77012009-11-07 00:00:49 +00003312 MEnd = PP.macro_end();
Douglas Gregor55b037b2010-07-08 20:55:51 +00003313 M != MEnd; ++M) {
Richard Smith20e883e2015-04-29 23:20:19 +00003314 auto MD = PP.getMacroDefinition(M->first);
3315 if (IncludeUndefined || MD) {
3316 if (MacroInfo *MI = MD.getMacroInfo())
Argyrios Kyrtzidis9ef53ce2014-04-09 18:21:23 +00003317 if (MI->isUsedForHeaderGuard())
3318 continue;
3319
Douglas Gregor8cb17462012-10-09 16:01:50 +00003320 Results.AddResult(Result(M->first,
Douglas Gregor6e240332010-08-16 16:18:59 +00003321 getMacroUsagePriority(M->first->getName(),
David Blaikiebbafb8a2012-03-11 07:00:24 +00003322 PP.getLangOpts(),
Douglas Gregor6e240332010-08-16 16:18:59 +00003323 TargetTypeIsPointer)));
Argyrios Kyrtzidis9ef53ce2014-04-09 18:21:23 +00003324 }
Douglas Gregor55b037b2010-07-08 20:55:51 +00003325 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003326
Douglas Gregorf329c7c2009-10-30 16:50:04 +00003327 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003328
Douglas Gregorf329c7c2009-10-30 16:50:04 +00003329}
3330
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003331static void AddPrettyFunctionResults(const LangOptions &LangOpts,
Douglas Gregorce0e8562010-08-23 21:54:33 +00003332 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00003333 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003334
Douglas Gregorce0e8562010-08-23 21:54:33 +00003335 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003336
Douglas Gregorce0e8562010-08-23 21:54:33 +00003337 Results.AddResult(Result("__PRETTY_FUNCTION__", CCP_Constant));
3338 Results.AddResult(Result("__FUNCTION__", CCP_Constant));
Richard Smith2bf7fdb2013-01-02 11:42:31 +00003339 if (LangOpts.C99 || LangOpts.CPlusPlus11)
Douglas Gregorce0e8562010-08-23 21:54:33 +00003340 Results.AddResult(Result("__func__", CCP_Constant));
3341 Results.ExitScope();
3342}
3343
Daniel Dunbar242ea9a2009-11-13 08:58:20 +00003344static void HandleCodeCompleteResults(Sema *S,
3345 CodeCompleteConsumer *CodeCompleter,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003346 CodeCompletionContext Context,
John McCall276321a2010-08-25 06:19:51 +00003347 CodeCompletionResult *Results,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003348 unsigned NumResults) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00003349 if (CodeCompleter)
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003350 CodeCompleter->ProcessCodeCompleteResults(*S, Context, Results, NumResults);
Douglas Gregor3545ff42009-09-21 16:56:56 +00003351}
3352
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003353static enum CodeCompletionContext::Kind mapCodeCompletionContext(Sema &S,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003354 Sema::ParserCompletionContext PCC) {
3355 switch (PCC) {
John McCallfaf5fb42010-08-26 23:41:50 +00003356 case Sema::PCC_Namespace:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003357 return CodeCompletionContext::CCC_TopLevel;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003358
John McCallfaf5fb42010-08-26 23:41:50 +00003359 case Sema::PCC_Class:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003360 return CodeCompletionContext::CCC_ClassStructUnion;
3361
John McCallfaf5fb42010-08-26 23:41:50 +00003362 case Sema::PCC_ObjCInterface:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003363 return CodeCompletionContext::CCC_ObjCInterface;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003364
John McCallfaf5fb42010-08-26 23:41:50 +00003365 case Sema::PCC_ObjCImplementation:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003366 return CodeCompletionContext::CCC_ObjCImplementation;
3367
John McCallfaf5fb42010-08-26 23:41:50 +00003368 case Sema::PCC_ObjCInstanceVariableList:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003369 return CodeCompletionContext::CCC_ObjCIvarList;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003370
John McCallfaf5fb42010-08-26 23:41:50 +00003371 case Sema::PCC_Template:
3372 case Sema::PCC_MemberTemplate:
Douglas Gregor0ac41382010-09-23 23:01:17 +00003373 if (S.CurContext->isFileContext())
3374 return CodeCompletionContext::CCC_TopLevel;
David Blaikie8a40f702012-01-17 06:56:22 +00003375 if (S.CurContext->isRecord())
Douglas Gregor0ac41382010-09-23 23:01:17 +00003376 return CodeCompletionContext::CCC_ClassStructUnion;
David Blaikie8a40f702012-01-17 06:56:22 +00003377 return CodeCompletionContext::CCC_Other;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003378
John McCallfaf5fb42010-08-26 23:41:50 +00003379 case Sema::PCC_RecoveryInFunction:
Douglas Gregor0ac41382010-09-23 23:01:17 +00003380 return CodeCompletionContext::CCC_Recovery;
Douglas Gregorc769d6e2010-10-18 22:01:46 +00003381
John McCallfaf5fb42010-08-26 23:41:50 +00003382 case Sema::PCC_ForInit:
David Blaikiebbafb8a2012-03-11 07:00:24 +00003383 if (S.getLangOpts().CPlusPlus || S.getLangOpts().C99 ||
3384 S.getLangOpts().ObjC1)
Douglas Gregorc769d6e2010-10-18 22:01:46 +00003385 return CodeCompletionContext::CCC_ParenthesizedExpression;
3386 else
3387 return CodeCompletionContext::CCC_Expression;
3388
3389 case Sema::PCC_Expression:
John McCallfaf5fb42010-08-26 23:41:50 +00003390 case Sema::PCC_Condition:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003391 return CodeCompletionContext::CCC_Expression;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003392
John McCallfaf5fb42010-08-26 23:41:50 +00003393 case Sema::PCC_Statement:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003394 return CodeCompletionContext::CCC_Statement;
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003395
John McCallfaf5fb42010-08-26 23:41:50 +00003396 case Sema::PCC_Type:
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003397 return CodeCompletionContext::CCC_Type;
Douglas Gregor5e35d592010-09-14 23:59:36 +00003398
3399 case Sema::PCC_ParenthesizedExpression:
3400 return CodeCompletionContext::CCC_ParenthesizedExpression;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003401
Douglas Gregor80039242011-02-15 20:33:25 +00003402 case Sema::PCC_LocalDeclarationSpecifiers:
3403 return CodeCompletionContext::CCC_Type;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003404 }
David Blaikie8a40f702012-01-17 06:56:22 +00003405
3406 llvm_unreachable("Invalid ParserCompletionContext!");
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003407}
3408
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003409/// If we're in a C++ virtual member function, add completion results
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003410/// that invoke the functions we override, since it's common to invoke the
Douglas Gregorac322ec2010-08-27 21:18:54 +00003411/// overridden function as well as adding new functionality.
3412///
3413/// \param S The semantic analysis object for which we are generating results.
3414///
3415/// \param InContext This context in which the nested-name-specifier preceding
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003416/// the code-completion point
Douglas Gregorac322ec2010-08-27 21:18:54 +00003417static void MaybeAddOverrideCalls(Sema &S, DeclContext *InContext,
3418 ResultBuilder &Results) {
3419 // Look through blocks.
3420 DeclContext *CurContext = S.CurContext;
3421 while (isa<BlockDecl>(CurContext))
3422 CurContext = CurContext->getParent();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003423
3424
Douglas Gregorac322ec2010-08-27 21:18:54 +00003425 CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(CurContext);
3426 if (!Method || !Method->isVirtual())
3427 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003428
3429 // We need to have names for all of the parameters, if we're going to
Douglas Gregorac322ec2010-08-27 21:18:54 +00003430 // generate a forwarding call.
David Majnemer59f77922016-06-24 04:05:48 +00003431 for (auto P : Method->parameters())
Aaron Ballman43b68be2014-03-07 17:50:17 +00003432 if (!P->getDeclName())
Douglas Gregorac322ec2010-08-27 21:18:54 +00003433 return;
Douglas Gregorac322ec2010-08-27 21:18:54 +00003434
Douglas Gregor75acd922011-09-27 23:30:47 +00003435 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
Benjamin Krameracfa3392017-12-17 23:52:45 +00003436 for (const CXXMethodDecl *Overridden : Method->overridden_methods()) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003437 CodeCompletionBuilder Builder(Results.getAllocator(),
3438 Results.getCodeCompletionTUInfo());
Douglas Gregorac322ec2010-08-27 21:18:54 +00003439 if (Overridden->getCanonicalDecl() == Method->getCanonicalDecl())
3440 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003441
Douglas Gregorac322ec2010-08-27 21:18:54 +00003442 // If we need a nested-name-specifier, add one now.
3443 if (!InContext) {
3444 NestedNameSpecifier *NNS
3445 = getRequiredQualification(S.Context, CurContext,
3446 Overridden->getDeclContext());
3447 if (NNS) {
3448 std::string Str;
3449 llvm::raw_string_ostream OS(Str);
Douglas Gregor75acd922011-09-27 23:30:47 +00003450 NNS->print(OS, Policy);
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003451 Builder.AddTextChunk(Results.getAllocator().CopyString(OS.str()));
Douglas Gregorac322ec2010-08-27 21:18:54 +00003452 }
3453 } else if (!InContext->Equals(Overridden->getDeclContext()))
3454 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003455
3456 Builder.AddTypedTextChunk(Results.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003457 Overridden->getNameAsString()));
3458 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregorac322ec2010-08-27 21:18:54 +00003459 bool FirstParam = true;
David Majnemer59f77922016-06-24 04:05:48 +00003460 for (auto P : Method->parameters()) {
Douglas Gregorac322ec2010-08-27 21:18:54 +00003461 if (FirstParam)
3462 FirstParam = false;
3463 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003464 Builder.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregorac322ec2010-08-27 21:18:54 +00003465
Aaron Ballman43b68be2014-03-07 17:50:17 +00003466 Builder.AddPlaceholderChunk(
3467 Results.getAllocator().CopyString(P->getIdentifier()->getName()));
Douglas Gregorac322ec2010-08-27 21:18:54 +00003468 }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003469 Builder.AddChunk(CodeCompletionString::CK_RightParen);
3470 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregorac322ec2010-08-27 21:18:54 +00003471 CCP_SuperCompletion,
Douglas Gregor78254c82012-03-27 23:34:16 +00003472 CXCursor_CXXMethod,
3473 CXAvailability_Available,
3474 Overridden));
Douglas Gregorac322ec2010-08-27 21:18:54 +00003475 Results.Ignore(Overridden);
3476 }
3477}
3478
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003479void Sema::CodeCompleteModuleImport(SourceLocation ImportLoc,
Douglas Gregor07f43572012-01-29 18:15:03 +00003480 ModuleIdPath Path) {
3481 typedef CodeCompletionResult Result;
3482 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003483 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor07f43572012-01-29 18:15:03 +00003484 CodeCompletionContext::CCC_Other);
3485 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003486
Douglas Gregor07f43572012-01-29 18:15:03 +00003487 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003488 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Douglas Gregor07f43572012-01-29 18:15:03 +00003489 typedef CodeCompletionResult Result;
3490 if (Path.empty()) {
3491 // Enumerate all top-level modules.
Dmitri Gribenkof8579502013-01-12 19:30:44 +00003492 SmallVector<Module *, 8> Modules;
Douglas Gregor07f43572012-01-29 18:15:03 +00003493 PP.getHeaderSearchInfo().collectAllModules(Modules);
3494 for (unsigned I = 0, N = Modules.size(); I != N; ++I) {
3495 Builder.AddTypedTextChunk(
3496 Builder.getAllocator().CopyString(Modules[I]->Name));
3497 Results.AddResult(Result(Builder.TakeString(),
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003498 CCP_Declaration,
Argyrios Kyrtzidis345d05f2013-05-29 18:50:15 +00003499 CXCursor_ModuleImportDecl,
Douglas Gregor07f43572012-01-29 18:15:03 +00003500 Modules[I]->isAvailable()
3501 ? CXAvailability_Available
3502 : CXAvailability_NotAvailable));
3503 }
Daniel Jasper07e6c402013-08-05 20:26:17 +00003504 } else if (getLangOpts().Modules) {
Douglas Gregor07f43572012-01-29 18:15:03 +00003505 // Load the named module.
3506 Module *Mod = PP.getModuleLoader().loadModule(ImportLoc, Path,
3507 Module::AllVisible,
3508 /*IsInclusionDirective=*/false);
3509 // Enumerate submodules.
3510 if (Mod) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003511 for (Module::submodule_iterator Sub = Mod->submodule_begin(),
Douglas Gregor07f43572012-01-29 18:15:03 +00003512 SubEnd = Mod->submodule_end();
3513 Sub != SubEnd; ++Sub) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003514
Douglas Gregor07f43572012-01-29 18:15:03 +00003515 Builder.AddTypedTextChunk(
3516 Builder.getAllocator().CopyString((*Sub)->Name));
3517 Results.AddResult(Result(Builder.TakeString(),
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003518 CCP_Declaration,
Argyrios Kyrtzidis345d05f2013-05-29 18:50:15 +00003519 CXCursor_ModuleImportDecl,
Douglas Gregor07f43572012-01-29 18:15:03 +00003520 (*Sub)->isAvailable()
3521 ? CXAvailability_Available
3522 : CXAvailability_NotAvailable));
3523 }
3524 }
3525 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003526 Results.ExitScope();
Douglas Gregor07f43572012-01-29 18:15:03 +00003527 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
3528 Results.data(),Results.size());
3529}
3530
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003531void Sema::CodeCompleteOrdinaryName(Scope *S,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003532 ParserCompletionContext CompletionContext) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003533 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003534 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00003535 mapCodeCompletionContext(*this, CompletionContext));
Douglas Gregorac322ec2010-08-27 21:18:54 +00003536 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003537
Douglas Gregor504a6ae2010-01-10 23:08:15 +00003538 // Determine how to filter results, e.g., so that the names of
3539 // values (functions, enumerators, function templates, etc.) are
3540 // only allowed where we can have an expression.
3541 switch (CompletionContext) {
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003542 case PCC_Namespace:
3543 case PCC_Class:
3544 case PCC_ObjCInterface:
3545 case PCC_ObjCImplementation:
3546 case PCC_ObjCInstanceVariableList:
3547 case PCC_Template:
3548 case PCC_MemberTemplate:
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003549 case PCC_Type:
Douglas Gregor80039242011-02-15 20:33:25 +00003550 case PCC_LocalDeclarationSpecifiers:
Douglas Gregor504a6ae2010-01-10 23:08:15 +00003551 Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
3552 break;
3553
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003554 case PCC_Statement:
Douglas Gregor5e35d592010-09-14 23:59:36 +00003555 case PCC_ParenthesizedExpression:
Douglas Gregor4d755e82010-08-24 23:58:17 +00003556 case PCC_Expression:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003557 case PCC_ForInit:
3558 case PCC_Condition:
David Blaikiebbafb8a2012-03-11 07:00:24 +00003559 if (WantTypesInContext(CompletionContext, getLangOpts()))
Douglas Gregor70febae2010-05-28 00:49:12 +00003560 Results.setFilter(&ResultBuilder::IsOrdinaryName);
3561 else
3562 Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003563
David Blaikiebbafb8a2012-03-11 07:00:24 +00003564 if (getLangOpts().CPlusPlus)
Craig Topperc3ec1492014-05-26 06:22:03 +00003565 MaybeAddOverrideCalls(*this, /*InContext=*/nullptr, Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00003566 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003567
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003568 case PCC_RecoveryInFunction:
Douglas Gregor6da3db42010-05-25 05:58:43 +00003569 // Unfiltered
3570 break;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00003571 }
3572
Douglas Gregor9be0ed42010-08-26 16:36:48 +00003573 // If we are in a C++ non-static member function, check the qualifiers on
3574 // the member function to filter/prioritize the results list.
3575 if (CXXMethodDecl *CurMethod = dyn_cast<CXXMethodDecl>(CurContext))
3576 if (CurMethod->isInstance())
3577 Results.setObjectTypeQualifiers(
3578 Qualifiers::fromCVRMask(CurMethod->getTypeQualifiers()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003579
Douglas Gregorc580c522010-01-14 01:09:38 +00003580 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00003581 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00003582 CodeCompleter->includeGlobals(),
3583 CodeCompleter->loadExternal());
Douglas Gregor92253692009-12-07 09:54:55 +00003584
Douglas Gregorf98e6a22010-01-13 23:51:12 +00003585 AddOrdinaryNameResults(CompletionContext, S, *this, Results);
Douglas Gregor92253692009-12-07 09:54:55 +00003586 Results.ExitScope();
3587
Douglas Gregorce0e8562010-08-23 21:54:33 +00003588 switch (CompletionContext) {
Douglas Gregor5e35d592010-09-14 23:59:36 +00003589 case PCC_ParenthesizedExpression:
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003590 case PCC_Expression:
3591 case PCC_Statement:
3592 case PCC_RecoveryInFunction:
3593 if (S->getFnParent())
Craig Topper12126262015-11-15 17:27:57 +00003594 AddPrettyFunctionResults(getLangOpts(), Results);
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003595 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003596
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003597 case PCC_Namespace:
3598 case PCC_Class:
3599 case PCC_ObjCInterface:
3600 case PCC_ObjCImplementation:
3601 case PCC_ObjCInstanceVariableList:
3602 case PCC_Template:
3603 case PCC_MemberTemplate:
3604 case PCC_ForInit:
3605 case PCC_Condition:
3606 case PCC_Type:
Douglas Gregor80039242011-02-15 20:33:25 +00003607 case PCC_LocalDeclarationSpecifiers:
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003608 break;
Douglas Gregorce0e8562010-08-23 21:54:33 +00003609 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003610
Douglas Gregor9eb77012009-11-07 00:00:49 +00003611 if (CodeCompleter->includeMacros())
Douglas Gregor8cb17462012-10-09 16:01:50 +00003612 AddMacroResults(PP, Results, false);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003613
Douglas Gregor50832e02010-09-20 22:39:41 +00003614 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003615 Results.data(),Results.size());
Douglas Gregor9d64c5e2009-09-21 20:51:25 +00003616}
3617
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003618static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003619 ParsedType Receiver,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00003620 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00003621 bool AtArgumentExpression,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003622 bool IsSuper,
3623 ResultBuilder &Results);
3624
3625void Sema::CodeCompleteDeclSpec(Scope *S, DeclSpec &DS,
3626 bool AllowNonIdentifiers,
3627 bool AllowNestedNameSpecifiers) {
John McCall276321a2010-08-25 06:19:51 +00003628 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003629 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003630 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00003631 AllowNestedNameSpecifiers
3632 ? CodeCompletionContext::CCC_PotentiallyQualifiedName
3633 : CodeCompletionContext::CCC_Name);
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003634 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003635
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003636 // Type qualifiers can come after names.
3637 Results.AddResult(Result("const"));
3638 Results.AddResult(Result("volatile"));
David Blaikiebbafb8a2012-03-11 07:00:24 +00003639 if (getLangOpts().C99)
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003640 Results.AddResult(Result("restrict"));
3641
David Blaikiebbafb8a2012-03-11 07:00:24 +00003642 if (getLangOpts().CPlusPlus) {
Alex Lorenz8f4d3992017-02-13 23:19:40 +00003643 if (getLangOpts().CPlusPlus11 &&
3644 (DS.getTypeSpecType() == DeclSpec::TST_class ||
3645 DS.getTypeSpecType() == DeclSpec::TST_struct))
3646 Results.AddResult("final");
3647
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003648 if (AllowNonIdentifiers) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003649 Results.AddResult(Result("operator"));
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003650 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003651
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003652 // Add nested-name-specifiers.
3653 if (AllowNestedNameSpecifiers) {
3654 Results.allowNestedNameSpecifiers();
Douglas Gregor0ac41382010-09-23 23:01:17 +00003655 Results.setFilter(&ResultBuilder::IsImpossibleToSatisfy);
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003656 CodeCompletionDeclConsumer Consumer(Results, CurContext);
3657 LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00003658 CodeCompleter->includeGlobals(),
3659 CodeCompleter->loadExternal());
Craig Topperc3ec1492014-05-26 06:22:03 +00003660 Results.setFilter(nullptr);
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003661 }
3662 }
3663 Results.ExitScope();
3664
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003665 // If we're in a context where we might have an expression (rather than a
3666 // declaration), and what we've seen so far is an Objective-C type that could
3667 // be a receiver of a class message, this may be a class message send with
3668 // the initial opening bracket '[' missing. Add appropriate completions.
3669 if (AllowNonIdentifiers && !AllowNestedNameSpecifiers &&
Richard Smithb4a9e862013-04-12 22:46:28 +00003670 DS.getParsedSpecifiers() == DeclSpec::PQ_TypeSpecifier &&
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003671 DS.getTypeSpecType() == DeclSpec::TST_typename &&
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003672 DS.getTypeSpecComplex() == DeclSpec::TSC_unspecified &&
3673 DS.getTypeSpecSign() == DeclSpec::TSS_unspecified &&
Richard Smithb4a9e862013-04-12 22:46:28 +00003674 !DS.isTypeAltiVecVector() &&
3675 S &&
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003676 (S->getFlags() & Scope::DeclScope) != 0 &&
3677 (S->getFlags() & (Scope::ClassScope | Scope::TemplateParamScope |
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003678 Scope::FunctionPrototypeScope |
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003679 Scope::AtCatchScope)) == 0) {
3680 ParsedType T = DS.getRepAsType();
3681 if (!T.get().isNull() && T.get()->isObjCObjectOrInterfaceType())
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00003682 AddClassMessageCompletions(*this, S, T, None, false, false, Results);
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003683 }
3684
Douglas Gregor56ccce02010-08-24 04:59:56 +00003685 // Note that we intentionally suppress macro results here, since we do not
3686 // encourage using macros to produce the names of entities.
3687
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003688 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0ac41382010-09-23 23:01:17 +00003689 Results.getCompletionContext(),
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003690 Results.data(), Results.size());
3691}
3692
Douglas Gregor68762e72010-08-23 21:17:50 +00003693struct Sema::CodeCompleteExpressionData {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003694 CodeCompleteExpressionData(QualType PreferredType = QualType())
Douglas Gregor68762e72010-08-23 21:17:50 +00003695 : PreferredType(PreferredType), IntegralConstantExpression(false),
3696 ObjCCollection(false) { }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003697
Douglas Gregor68762e72010-08-23 21:17:50 +00003698 QualType PreferredType;
3699 bool IntegralConstantExpression;
3700 bool ObjCCollection;
Chris Lattner0e62c1c2011-07-23 10:55:15 +00003701 SmallVector<Decl *, 4> IgnoreDecls;
Douglas Gregor68762e72010-08-23 21:17:50 +00003702};
3703
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003704/// Perform code-completion in an expression context when we know what
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003705/// type we're looking for.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003706void Sema::CodeCompleteExpression(Scope *S,
Douglas Gregor68762e72010-08-23 21:17:50 +00003707 const CodeCompleteExpressionData &Data) {
Eric Liuf5ba09f2018-07-04 10:01:18 +00003708 ResultBuilder Results(
3709 *this, CodeCompleter->getAllocator(),
3710 CodeCompleter->getCodeCompletionTUInfo(),
3711 CodeCompletionContext(CodeCompletionContext::CCC_Expression,
3712 Data.PreferredType));
Douglas Gregor68762e72010-08-23 21:17:50 +00003713 if (Data.ObjCCollection)
3714 Results.setFilter(&ResultBuilder::IsObjCCollection);
3715 else if (Data.IntegralConstantExpression)
Douglas Gregor85b50632010-07-28 21:50:18 +00003716 Results.setFilter(&ResultBuilder::IsIntegralConstantValue);
David Blaikiebbafb8a2012-03-11 07:00:24 +00003717 else if (WantTypesInContext(PCC_Expression, getLangOpts()))
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003718 Results.setFilter(&ResultBuilder::IsOrdinaryName);
3719 else
3720 Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
Douglas Gregor68762e72010-08-23 21:17:50 +00003721
3722 if (!Data.PreferredType.isNull())
3723 Results.setPreferredType(Data.PreferredType.getNonReferenceType());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003724
Douglas Gregor68762e72010-08-23 21:17:50 +00003725 // Ignore any declarations that we were told that we don't care about.
3726 for (unsigned I = 0, N = Data.IgnoreDecls.size(); I != N; ++I)
3727 Results.Ignore(Data.IgnoreDecls[I]);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003728
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003729 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00003730 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00003731 CodeCompleter->includeGlobals(),
3732 CodeCompleter->loadExternal());
3733
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003734 Results.EnterNewScope();
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003735 AddOrdinaryNameResults(PCC_Expression, S, *this, Results);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003736 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003737
Douglas Gregor55b037b2010-07-08 20:55:51 +00003738 bool PreferredTypeIsPointer = false;
Douglas Gregor68762e72010-08-23 21:17:50 +00003739 if (!Data.PreferredType.isNull())
3740 PreferredTypeIsPointer = Data.PreferredType->isAnyPointerType()
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003741 || Data.PreferredType->isMemberPointerType()
Douglas Gregor68762e72010-08-23 21:17:50 +00003742 || Data.PreferredType->isBlockPointerType();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003743
3744 if (S->getFnParent() &&
3745 !Data.ObjCCollection &&
Douglas Gregorce0e8562010-08-23 21:54:33 +00003746 !Data.IntegralConstantExpression)
Craig Topper12126262015-11-15 17:27:57 +00003747 AddPrettyFunctionResults(getLangOpts(), Results);
Douglas Gregorce0e8562010-08-23 21:54:33 +00003748
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003749 if (CodeCompleter->includeMacros())
Douglas Gregor8cb17462012-10-09 16:01:50 +00003750 AddMacroResults(PP, Results, false, PreferredTypeIsPointer);
Eric Liuf5ba09f2018-07-04 10:01:18 +00003751 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
3752 Results.data(), Results.size());
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003753}
3754
Douglas Gregoreda7e542010-09-18 01:28:11 +00003755void Sema::CodeCompletePostfixExpression(Scope *S, ExprResult E) {
3756 if (E.isInvalid())
3757 CodeCompleteOrdinaryName(S, PCC_RecoveryInFunction);
David Blaikiebbafb8a2012-03-11 07:00:24 +00003758 else if (getLangOpts().ObjC1)
Nikola Smiljanic01a75982014-05-29 10:55:11 +00003759 CodeCompleteObjCInstanceMessage(S, E.get(), None, false);
Douglas Gregored0b69d2010-09-15 16:23:04 +00003760}
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003761
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003762/// The set of properties that have already been added, referenced by
Douglas Gregorb888acf2010-12-09 23:01:55 +00003763/// property name.
3764typedef llvm::SmallPtrSet<IdentifierInfo*, 16> AddedPropertiesSet;
3765
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003766/// Retrieve the container definition, if any?
Douglas Gregor9b4f3702012-06-12 13:44:08 +00003767static ObjCContainerDecl *getContainerDef(ObjCContainerDecl *Container) {
3768 if (ObjCInterfaceDecl *Interface = dyn_cast<ObjCInterfaceDecl>(Container)) {
3769 if (Interface->hasDefinition())
3770 return Interface->getDefinition();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003771
Douglas Gregor9b4f3702012-06-12 13:44:08 +00003772 return Interface;
3773 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003774
Douglas Gregor9b4f3702012-06-12 13:44:08 +00003775 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
3776 if (Protocol->hasDefinition())
3777 return Protocol->getDefinition();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003778
Douglas Gregor9b4f3702012-06-12 13:44:08 +00003779 return Protocol;
3780 }
3781 return Container;
3782}
3783
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003784/// Adds a block invocation code completion result for the given block
Alex Lorenzbaef8022016-11-09 13:43:18 +00003785/// declaration \p BD.
3786static void AddObjCBlockCall(ASTContext &Context, const PrintingPolicy &Policy,
3787 CodeCompletionBuilder &Builder,
3788 const NamedDecl *BD,
3789 const FunctionTypeLoc &BlockLoc,
3790 const FunctionProtoTypeLoc &BlockProtoLoc) {
3791 Builder.AddResultTypeChunk(
3792 GetCompletionTypeString(BlockLoc.getReturnLoc().getType(), Context,
3793 Policy, Builder.getAllocator()));
3794
3795 AddTypedNameChunk(Context, Policy, BD, Builder);
3796 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
3797
3798 if (BlockProtoLoc && BlockProtoLoc.getTypePtr()->isVariadic()) {
3799 Builder.AddPlaceholderChunk("...");
3800 } else {
3801 for (unsigned I = 0, N = BlockLoc.getNumParams(); I != N; ++I) {
3802 if (I)
3803 Builder.AddChunk(CodeCompletionString::CK_Comma);
3804
3805 // Format the placeholder string.
3806 std::string PlaceholderStr =
3807 FormatFunctionParameter(Policy, BlockLoc.getParam(I));
3808
3809 if (I == N - 1 && BlockProtoLoc &&
3810 BlockProtoLoc.getTypePtr()->isVariadic())
3811 PlaceholderStr += ", ...";
3812
3813 // Add the placeholder string.
3814 Builder.AddPlaceholderChunk(
3815 Builder.getAllocator().CopyString(PlaceholderStr));
3816 }
3817 }
3818
3819 Builder.AddChunk(CodeCompletionString::CK_RightParen);
3820}
3821
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003822static void AddObjCProperties(
3823 const CodeCompletionContext &CCContext, ObjCContainerDecl *Container,
3824 bool AllowCategories, bool AllowNullaryMethods, DeclContext *CurContext,
3825 AddedPropertiesSet &AddedProperties, ResultBuilder &Results,
3826 bool IsBaseExprStatement = false, bool IsClassProperty = false) {
John McCall276321a2010-08-25 06:19:51 +00003827 typedef CodeCompletionResult Result;
Douglas Gregor9291bad2009-11-18 01:29:26 +00003828
Douglas Gregor9b4f3702012-06-12 13:44:08 +00003829 // Retrieve the definition.
3830 Container = getContainerDef(Container);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003831
Douglas Gregor9291bad2009-11-18 01:29:26 +00003832 // Add properties in this container.
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003833 const auto AddProperty = [&](const ObjCPropertyDecl *P) {
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003834 if (!AddedProperties.insert(P->getIdentifier()).second)
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003835 return;
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003836
Alex Lorenzbaef8022016-11-09 13:43:18 +00003837 // FIXME: Provide block invocation completion for non-statement
3838 // expressions.
3839 if (!P->getType().getTypePtr()->isBlockPointerType() ||
3840 !IsBaseExprStatement) {
3841 Results.MaybeAddResult(Result(P, Results.getBasePriority(P), nullptr),
3842 CurContext);
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003843 return;
Alex Lorenzbaef8022016-11-09 13:43:18 +00003844 }
3845
3846 // Block setter and invocation completion is provided only when we are able
3847 // to find the FunctionProtoTypeLoc with parameter names for the block.
3848 FunctionTypeLoc BlockLoc;
3849 FunctionProtoTypeLoc BlockProtoLoc;
3850 findTypeLocationForBlockDecl(P->getTypeSourceInfo(), BlockLoc,
3851 BlockProtoLoc);
3852 if (!BlockLoc) {
3853 Results.MaybeAddResult(Result(P, Results.getBasePriority(P), nullptr),
3854 CurContext);
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003855 return;
Alex Lorenzbaef8022016-11-09 13:43:18 +00003856 }
3857
3858 // The default completion result for block properties should be the block
3859 // invocation completion when the base expression is a statement.
3860 CodeCompletionBuilder Builder(Results.getAllocator(),
3861 Results.getCodeCompletionTUInfo());
3862 AddObjCBlockCall(Container->getASTContext(),
3863 getCompletionPrintingPolicy(Results.getSema()), Builder, P,
3864 BlockLoc, BlockProtoLoc);
3865 Results.MaybeAddResult(
3866 Result(Builder.TakeString(), P, Results.getBasePriority(P)),
3867 CurContext);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003868
3869 // Provide additional block setter completion iff the base expression is a
Alex Lorenzbaef8022016-11-09 13:43:18 +00003870 // statement and the block property is mutable.
3871 if (!P->isReadOnly()) {
3872 CodeCompletionBuilder Builder(Results.getAllocator(),
3873 Results.getCodeCompletionTUInfo());
3874 AddResultTypeChunk(Container->getASTContext(),
3875 getCompletionPrintingPolicy(Results.getSema()), P,
3876 CCContext.getBaseType(), Builder);
3877 Builder.AddTypedTextChunk(
3878 Results.getAllocator().CopyString(P->getName()));
3879 Builder.AddChunk(CodeCompletionString::CK_Equal);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003880
Alex Lorenzbaef8022016-11-09 13:43:18 +00003881 std::string PlaceholderStr = formatBlockPlaceholder(
3882 getCompletionPrintingPolicy(Results.getSema()), P, BlockLoc,
3883 BlockProtoLoc, /*SuppressBlockName=*/true);
3884 // Add the placeholder string.
3885 Builder.AddPlaceholderChunk(
3886 Builder.getAllocator().CopyString(PlaceholderStr));
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003887
Alex Lorenz6e0f3932017-01-06 12:00:44 +00003888 // When completing blocks properties that return void the default
3889 // property completion result should show up before the setter,
3890 // otherwise the setter completion should show up before the default
3891 // property completion, as we normally want to use the result of the
3892 // call.
Alex Lorenzbaef8022016-11-09 13:43:18 +00003893 Results.MaybeAddResult(
3894 Result(Builder.TakeString(), P,
Alex Lorenz6e0f3932017-01-06 12:00:44 +00003895 Results.getBasePriority(P) +
3896 (BlockLoc.getTypePtr()->getReturnType()->isVoidType()
3897 ? CCD_BlockPropertySetter
3898 : -CCD_BlockPropertySetter)),
Alex Lorenzbaef8022016-11-09 13:43:18 +00003899 CurContext);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003900 }
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003901 };
3902
3903 if (IsClassProperty) {
3904 for (const auto *P : Container->class_properties())
3905 AddProperty(P);
3906 } else {
3907 for (const auto *P : Container->instance_properties())
3908 AddProperty(P);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003909 }
Craig Topperc3ec1492014-05-26 06:22:03 +00003910
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003911 // Add nullary methods or implicit class properties
Douglas Gregor95147142011-05-05 15:50:42 +00003912 if (AllowNullaryMethods) {
3913 ASTContext &Context = Container->getASTContext();
Douglas Gregor75acd922011-09-27 23:30:47 +00003914 PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema());
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003915 // Adds a method result
3916 const auto AddMethod = [&](const ObjCMethodDecl *M) {
3917 IdentifierInfo *Name = M->getSelector().getIdentifierInfoForSlot(0);
3918 if (!Name)
3919 return;
3920 if (!AddedProperties.insert(Name).second)
3921 return;
3922 CodeCompletionBuilder Builder(Results.getAllocator(),
3923 Results.getCodeCompletionTUInfo());
3924 AddResultTypeChunk(Context, Policy, M, CCContext.getBaseType(), Builder);
3925 Builder.AddTypedTextChunk(
3926 Results.getAllocator().CopyString(Name->getName()));
3927 Results.MaybeAddResult(
3928 Result(Builder.TakeString(), M,
3929 CCP_MemberDeclaration + CCD_MethodAsProperty),
3930 CurContext);
3931 };
3932
3933 if (IsClassProperty) {
3934 for (const auto *M : Container->methods()) {
3935 // Gather the class method that can be used as implicit property
3936 // getters. Methods with arguments or methods that return void aren't
3937 // added to the results as they can't be used as a getter.
3938 if (!M->getSelector().isUnarySelector() ||
3939 M->getReturnType()->isVoidType() || M->isInstanceMethod())
3940 continue;
3941 AddMethod(M);
3942 }
3943 } else {
3944 for (auto *M : Container->methods()) {
3945 if (M->getSelector().isUnarySelector())
3946 AddMethod(M);
3947 }
Douglas Gregor95147142011-05-05 15:50:42 +00003948 }
3949 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003950
Douglas Gregor9291bad2009-11-18 01:29:26 +00003951 // Add properties in referenced protocols.
3952 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Aaron Ballman0f6e64d2014-03-13 22:58:06 +00003953 for (auto *P : Protocol->protocols())
Douglas Gregorc3425b12015-07-07 06:20:19 +00003954 AddObjCProperties(CCContext, P, AllowCategories, AllowNullaryMethods,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003955 CurContext, AddedProperties, Results,
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003956 IsBaseExprStatement, IsClassProperty);
Douglas Gregor9291bad2009-11-18 01:29:26 +00003957 } else if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)){
Douglas Gregor5d649882009-11-18 22:32:06 +00003958 if (AllowCategories) {
3959 // Look through categories.
Aaron Ballman15063e12014-03-13 21:35:02 +00003960 for (auto *Cat : IFace->known_categories())
Douglas Gregorc3425b12015-07-07 06:20:19 +00003961 AddObjCProperties(CCContext, Cat, AllowCategories, AllowNullaryMethods,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003962 CurContext, AddedProperties, Results,
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003963 IsBaseExprStatement, IsClassProperty);
Douglas Gregor5d649882009-11-18 22:32:06 +00003964 }
Aaron Ballman15063e12014-03-13 21:35:02 +00003965
Douglas Gregor9291bad2009-11-18 01:29:26 +00003966 // Look through protocols.
Aaron Ballmana9f49e32014-03-13 20:55:22 +00003967 for (auto *I : IFace->all_referenced_protocols())
Douglas Gregorc3425b12015-07-07 06:20:19 +00003968 AddObjCProperties(CCContext, I, AllowCategories, AllowNullaryMethods,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003969 CurContext, AddedProperties, Results,
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003970 IsBaseExprStatement, IsClassProperty);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003971
Douglas Gregor9291bad2009-11-18 01:29:26 +00003972 // Look in the superclass.
3973 if (IFace->getSuperClass())
Douglas Gregorc3425b12015-07-07 06:20:19 +00003974 AddObjCProperties(CCContext, IFace->getSuperClass(), AllowCategories,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003975 AllowNullaryMethods, CurContext, AddedProperties,
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003976 Results, IsBaseExprStatement, IsClassProperty);
Douglas Gregor9291bad2009-11-18 01:29:26 +00003977 } else if (const ObjCCategoryDecl *Category
3978 = dyn_cast<ObjCCategoryDecl>(Container)) {
3979 // Look through protocols.
Aaron Ballman19a41762014-03-14 12:55:57 +00003980 for (auto *P : Category->protocols())
Douglas Gregorc3425b12015-07-07 06:20:19 +00003981 AddObjCProperties(CCContext, P, AllowCategories, AllowNullaryMethods,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003982 CurContext, AddedProperties, Results,
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003983 IsBaseExprStatement, IsClassProperty);
Douglas Gregor9291bad2009-11-18 01:29:26 +00003984 }
3985}
3986
Alex Lorenz0fe0d982017-05-11 13:41:00 +00003987static void AddRecordMembersCompletionResults(Sema &SemaRef,
3988 ResultBuilder &Results, Scope *S,
3989 QualType BaseType,
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00003990 RecordDecl *RD,
3991 Optional<FixItHint> AccessOpFixIt) {
Alex Lorenz0fe0d982017-05-11 13:41:00 +00003992 // Indicate that we are performing a member access, and the cv-qualifiers
3993 // for the base object type.
3994 Results.setObjectTypeQualifiers(BaseType.getQualifiers());
3995
3996 // Access to a C/C++ class, struct, or union.
3997 Results.allowNestedNameSpecifiers();
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00003998 std::vector<FixItHint> FixIts;
3999 if (AccessOpFixIt)
4000 FixIts.emplace_back(AccessOpFixIt.getValue());
4001 CodeCompletionDeclConsumer Consumer(Results, SemaRef.CurContext, std::move(FixIts));
Alex Lorenz0fe0d982017-05-11 13:41:00 +00004002 SemaRef.LookupVisibleDecls(RD, Sema::LookupMemberName, Consumer,
Alex Lorenze6afa392017-05-11 13:48:57 +00004003 SemaRef.CodeCompleter->includeGlobals(),
Sam McCallbb2cf632018-01-12 14:51:47 +00004004 /*IncludeDependentBases=*/true,
4005 SemaRef.CodeCompleter->loadExternal());
Alex Lorenz0fe0d982017-05-11 13:41:00 +00004006
4007 if (SemaRef.getLangOpts().CPlusPlus) {
4008 if (!Results.empty()) {
4009 // The "template" keyword can follow "->" or "." in the grammar.
4010 // However, we only want to suggest the template keyword if something
4011 // is dependent.
4012 bool IsDependent = BaseType->isDependentType();
4013 if (!IsDependent) {
4014 for (Scope *DepScope = S; DepScope; DepScope = DepScope->getParent())
4015 if (DeclContext *Ctx = DepScope->getEntity()) {
4016 IsDependent = Ctx->isDependentContext();
4017 break;
4018 }
4019 }
4020
4021 if (IsDependent)
4022 Results.AddResult(CodeCompletionResult("template"));
4023 }
4024 }
4025}
4026
Douglas Gregor1cc88a92012-01-23 15:59:30 +00004027void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base,
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004028 Expr *OtherOpBase,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004029 SourceLocation OpLoc, bool IsArrow,
4030 bool IsBaseExprStatement) {
Douglas Gregor1cc88a92012-01-23 15:59:30 +00004031 if (!Base || !CodeCompleter)
Douglas Gregor2436e712009-09-17 21:32:03 +00004032 return;
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004033
Douglas Gregor1cc88a92012-01-23 15:59:30 +00004034 ExprResult ConvertedBase = PerformMemberExprBaseConversion(Base, IsArrow);
4035 if (ConvertedBase.isInvalid())
4036 return;
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004037 QualType ConvertedBaseType = ConvertedBase.get()->getType();
4038
4039 enum CodeCompletionContext::Kind contextKind;
Douglas Gregor3545ff42009-09-21 16:56:56 +00004040
4041 if (IsArrow) {
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004042 if (const PointerType *Ptr = ConvertedBaseType->getAs<PointerType>())
4043 ConvertedBaseType = Ptr->getPointeeType();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004044 }
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004045
Douglas Gregor21325842011-07-07 16:03:39 +00004046 if (IsArrow) {
4047 contextKind = CodeCompletionContext::CCC_ArrowMemberAccess;
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004048 } else {
4049 if (ConvertedBaseType->isObjCObjectPointerType() ||
4050 ConvertedBaseType->isObjCObjectOrInterfaceType()) {
Douglas Gregor21325842011-07-07 16:03:39 +00004051 contextKind = CodeCompletionContext::CCC_ObjCPropertyAccess;
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004052 } else {
Douglas Gregor21325842011-07-07 16:03:39 +00004053 contextKind = CodeCompletionContext::CCC_DotMemberAccess;
4054 }
4055 }
Douglas Gregorc3425b12015-07-07 06:20:19 +00004056
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004057 CodeCompletionContext CCContext(contextKind, ConvertedBaseType);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004058 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004059 CodeCompleter->getCodeCompletionTUInfo(), CCContext,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004060 &ResultBuilder::IsMember);
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004061
4062 auto DoCompletion = [&](Expr *Base, bool IsArrow, Optional<FixItHint> AccessOpFixIt) -> bool {
4063 if (!Base)
4064 return false;
4065
4066 ExprResult ConvertedBase = PerformMemberExprBaseConversion(Base, IsArrow);
4067 if (ConvertedBase.isInvalid())
4068 return false;
4069 Base = ConvertedBase.get();
4070
4071 QualType BaseType = Base->getType();
4072
4073 if (IsArrow) {
4074 if (const PointerType *Ptr = BaseType->getAs<PointerType>())
4075 BaseType = Ptr->getPointeeType();
4076 else if (BaseType->isObjCObjectPointerType())
4077 /*Do nothing*/;
4078 else
4079 return false;
4080 }
4081
4082 if (const RecordType *Record = BaseType->getAs<RecordType>()) {
4083 AddRecordMembersCompletionResults(*this, Results, S, BaseType,
4084 Record->getDecl(),
4085 std::move(AccessOpFixIt));
4086 } else if (const auto *TST =
4087 BaseType->getAs<TemplateSpecializationType>()) {
4088 TemplateName TN = TST->getTemplateName();
4089 if (const auto *TD =
4090 dyn_cast_or_null<ClassTemplateDecl>(TN.getAsTemplateDecl())) {
4091 CXXRecordDecl *RD = TD->getTemplatedDecl();
4092 AddRecordMembersCompletionResults(*this, Results, S, BaseType, RD,
4093 std::move(AccessOpFixIt));
4094 }
4095 } else if (const auto *ICNT = BaseType->getAs<InjectedClassNameType>()) {
4096 if (auto *RD = ICNT->getDecl())
4097 AddRecordMembersCompletionResults(*this, Results, S, BaseType, RD,
4098 std::move(AccessOpFixIt));
4099 } else if (!IsArrow && BaseType->isObjCObjectPointerType()) {
4100 // Objective-C property reference.
4101 AddedPropertiesSet AddedProperties;
4102
4103 if (const ObjCObjectPointerType *ObjCPtr =
4104 BaseType->getAsObjCInterfacePointerType()) {
4105 // Add property results based on our interface.
4106 assert(ObjCPtr && "Non-NULL pointer guaranteed above!");
4107 AddObjCProperties(CCContext, ObjCPtr->getInterfaceDecl(), true,
4108 /*AllowNullaryMethods=*/true, CurContext,
4109 AddedProperties, Results, IsBaseExprStatement);
4110 }
4111
4112 // Add properties from the protocols in a qualified interface.
4113 for (auto *I : BaseType->getAs<ObjCObjectPointerType>()->quals())
4114 AddObjCProperties(CCContext, I, true, /*AllowNullaryMethods=*/true,
4115 CurContext, AddedProperties, Results,
4116 IsBaseExprStatement);
4117 } else if ((IsArrow && BaseType->isObjCObjectPointerType()) ||
4118 (!IsArrow && BaseType->isObjCObjectType())) {
4119 // Objective-C instance variable access.
4120 ObjCInterfaceDecl *Class = nullptr;
4121 if (const ObjCObjectPointerType *ObjCPtr =
4122 BaseType->getAs<ObjCObjectPointerType>())
4123 Class = ObjCPtr->getInterfaceDecl();
4124 else
4125 Class = BaseType->getAs<ObjCObjectType>()->getInterface();
4126
4127 // Add all ivars from this class and its superclasses.
4128 if (Class) {
4129 CodeCompletionDeclConsumer Consumer(Results, CurContext);
4130 Results.setFilter(&ResultBuilder::IsObjCIvar);
4131 LookupVisibleDecls(
4132 Class, LookupMemberName, Consumer, CodeCompleter->includeGlobals(),
4133 /*IncludeDependentBases=*/false, CodeCompleter->loadExternal());
4134 }
4135 }
4136
4137 // FIXME: How do we cope with isa?
4138 return true;
4139 };
4140
Douglas Gregor9291bad2009-11-18 01:29:26 +00004141 Results.EnterNewScope();
Alex Lorenz06cfa992016-10-12 11:40:15 +00004142
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004143 bool CompletionSucceded = DoCompletion(Base, IsArrow, None);
4144 if (CodeCompleter->includeFixIts()) {
4145 const CharSourceRange OpRange =
4146 CharSourceRange::getTokenRange(OpLoc, OpLoc);
4147 CompletionSucceded |= DoCompletion(
4148 OtherOpBase, !IsArrow,
4149 FixItHint::CreateReplacement(OpRange, IsArrow ? "." : "->"));
Douglas Gregor3545ff42009-09-21 16:56:56 +00004150 }
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004151
Douglas Gregor9291bad2009-11-18 01:29:26 +00004152 Results.ExitScope();
Daniel Dunbar242ea9a2009-11-13 08:58:20 +00004153
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004154 if (!CompletionSucceded)
4155 return;
4156
Daniel Dunbar242ea9a2009-11-13 08:58:20 +00004157 // Hand off the results found for code completion.
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004158 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4159 Results.data(), Results.size());
Douglas Gregor2436e712009-09-17 21:32:03 +00004160}
4161
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004162void Sema::CodeCompleteObjCClassPropertyRefExpr(Scope *S,
4163 IdentifierInfo &ClassName,
4164 SourceLocation ClassNameLoc,
4165 bool IsBaseExprStatement) {
4166 IdentifierInfo *ClassNamePtr = &ClassName;
4167 ObjCInterfaceDecl *IFace = getObjCInterfaceDecl(ClassNamePtr, ClassNameLoc);
4168 if (!IFace)
4169 return;
4170 CodeCompletionContext CCContext(
4171 CodeCompletionContext::CCC_ObjCPropertyAccess);
4172 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4173 CodeCompleter->getCodeCompletionTUInfo(), CCContext,
4174 &ResultBuilder::IsMember);
4175 Results.EnterNewScope();
4176 AddedPropertiesSet AddedProperties;
4177 AddObjCProperties(CCContext, IFace, true,
4178 /*AllowNullaryMethods=*/true, CurContext, AddedProperties,
4179 Results, IsBaseExprStatement,
4180 /*IsClassProperty=*/true);
4181 Results.ExitScope();
4182 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4183 Results.data(), Results.size());
4184}
4185
Faisal Vali090da2d2018-01-01 18:23:28 +00004186void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) {
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004187 if (!CodeCompleter)
4188 return;
Craig Topperc3ec1492014-05-26 06:22:03 +00004189
4190 ResultBuilder::LookupFilter Filter = nullptr;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004191 enum CodeCompletionContext::Kind ContextKind
4192 = CodeCompletionContext::CCC_Other;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004193 switch ((DeclSpec::TST)TagSpec) {
4194 case DeclSpec::TST_enum:
Douglas Gregor3545ff42009-09-21 16:56:56 +00004195 Filter = &ResultBuilder::IsEnum;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004196 ContextKind = CodeCompletionContext::CCC_EnumTag;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004197 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004198
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004199 case DeclSpec::TST_union:
Douglas Gregor3545ff42009-09-21 16:56:56 +00004200 Filter = &ResultBuilder::IsUnion;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004201 ContextKind = CodeCompletionContext::CCC_UnionTag;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004202 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004203
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004204 case DeclSpec::TST_struct:
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004205 case DeclSpec::TST_class:
Joao Matosdc86f942012-08-31 18:45:21 +00004206 case DeclSpec::TST_interface:
Douglas Gregor3545ff42009-09-21 16:56:56 +00004207 Filter = &ResultBuilder::IsClassOrStruct;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004208 ContextKind = CodeCompletionContext::CCC_ClassOrStructTag;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004209 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004210
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004211 default:
David Blaikie83d382b2011-09-23 05:06:16 +00004212 llvm_unreachable("Unknown type specifier kind in CodeCompleteTag");
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004213 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004214
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004215 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4216 CodeCompleter->getCodeCompletionTUInfo(), ContextKind);
Douglas Gregora6e2edc2010-01-14 03:27:13 +00004217 CodeCompletionDeclConsumer Consumer(Results, CurContext);
John McCalle87beb22010-04-23 18:46:30 +00004218
4219 // First pass: look for tags.
4220 Results.setFilter(Filter);
Douglas Gregor39982192010-08-15 06:18:01 +00004221 LookupVisibleDecls(S, LookupTagName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00004222 CodeCompleter->includeGlobals(),
4223 CodeCompleter->loadExternal());
John McCalle87beb22010-04-23 18:46:30 +00004224
Douglas Gregor39982192010-08-15 06:18:01 +00004225 if (CodeCompleter->includeGlobals()) {
4226 // Second pass: look for nested name specifiers.
4227 Results.setFilter(&ResultBuilder::IsNestedNameSpecifier);
Sam McCallbb2cf632018-01-12 14:51:47 +00004228 LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer,
4229 CodeCompleter->includeGlobals(),
4230 CodeCompleter->loadExternal());
Douglas Gregor39982192010-08-15 06:18:01 +00004231 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004232
Douglas Gregor0ac41382010-09-23 23:01:17 +00004233 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004234 Results.data(),Results.size());
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004235}
4236
Alex Lorenz8f4d3992017-02-13 23:19:40 +00004237static void AddTypeQualifierResults(DeclSpec &DS, ResultBuilder &Results,
4238 const LangOptions &LangOpts) {
4239 if (!(DS.getTypeQualifiers() & DeclSpec::TQ_const))
4240 Results.AddResult("const");
4241 if (!(DS.getTypeQualifiers() & DeclSpec::TQ_volatile))
4242 Results.AddResult("volatile");
4243 if (LangOpts.C99 && !(DS.getTypeQualifiers() & DeclSpec::TQ_restrict))
4244 Results.AddResult("restrict");
4245 if (LangOpts.C11 && !(DS.getTypeQualifiers() & DeclSpec::TQ_atomic))
4246 Results.AddResult("_Atomic");
4247 if (LangOpts.MSVCCompat && !(DS.getTypeQualifiers() & DeclSpec::TQ_unaligned))
4248 Results.AddResult("__unaligned");
4249}
4250
Douglas Gregor28c78432010-08-27 17:35:51 +00004251void Sema::CodeCompleteTypeQualifiers(DeclSpec &DS) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004252 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004253 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004254 CodeCompletionContext::CCC_TypeQualifiers);
Douglas Gregor28c78432010-08-27 17:35:51 +00004255 Results.EnterNewScope();
Alex Lorenz8f4d3992017-02-13 23:19:40 +00004256 AddTypeQualifierResults(DS, Results, LangOpts);
Douglas Gregor28c78432010-08-27 17:35:51 +00004257 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004258 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004259 Results.getCompletionContext(),
Douglas Gregor28c78432010-08-27 17:35:51 +00004260 Results.data(), Results.size());
4261}
4262
Alex Lorenz8f4d3992017-02-13 23:19:40 +00004263void Sema::CodeCompleteFunctionQualifiers(DeclSpec &DS, Declarator &D,
4264 const VirtSpecifiers *VS) {
4265 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4266 CodeCompleter->getCodeCompletionTUInfo(),
4267 CodeCompletionContext::CCC_TypeQualifiers);
4268 Results.EnterNewScope();
4269 AddTypeQualifierResults(DS, Results, LangOpts);
4270 if (LangOpts.CPlusPlus11) {
4271 Results.AddResult("noexcept");
Faisal Vali421b2d12017-12-29 05:41:00 +00004272 if (D.getContext() == DeclaratorContext::MemberContext &&
4273 !D.isCtorOrDtor() && !D.isStaticMember()) {
Alex Lorenz8f4d3992017-02-13 23:19:40 +00004274 if (!VS || !VS->isFinalSpecified())
4275 Results.AddResult("final");
4276 if (!VS || !VS->isOverrideSpecified())
4277 Results.AddResult("override");
4278 }
4279 }
4280 Results.ExitScope();
4281 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4282 Results.data(), Results.size());
4283}
4284
Benjamin Kramer72dae622016-02-18 15:30:24 +00004285void Sema::CodeCompleteBracketDeclarator(Scope *S) {
4286 CodeCompleteExpression(S, QualType(getASTContext().getSizeType()));
4287}
4288
Douglas Gregord328d572009-09-21 18:10:23 +00004289void Sema::CodeCompleteCase(Scope *S) {
John McCallaab3e412010-08-25 08:40:02 +00004290 if (getCurFunction()->SwitchStack.empty() || !CodeCompleter)
Douglas Gregord328d572009-09-21 18:10:23 +00004291 return;
John McCall5939b162011-08-06 07:30:58 +00004292
John McCallaab3e412010-08-25 08:40:02 +00004293 SwitchStmt *Switch = getCurFunction()->SwitchStack.back();
John McCall5939b162011-08-06 07:30:58 +00004294 QualType type = Switch->getCond()->IgnoreImplicit()->getType();
4295 if (!type->isEnumeralType()) {
4296 CodeCompleteExpressionData Data(type);
Douglas Gregor68762e72010-08-23 21:17:50 +00004297 Data.IntegralConstantExpression = true;
4298 CodeCompleteExpression(S, Data);
Douglas Gregord328d572009-09-21 18:10:23 +00004299 return;
Douglas Gregor85b50632010-07-28 21:50:18 +00004300 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004301
Douglas Gregord328d572009-09-21 18:10:23 +00004302 // Code-complete the cases of a switch statement over an enumeration type
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004303 // by providing the list of
John McCall5939b162011-08-06 07:30:58 +00004304 EnumDecl *Enum = type->castAs<EnumType>()->getDecl();
Douglas Gregor9b4f3702012-06-12 13:44:08 +00004305 if (EnumDecl *Def = Enum->getDefinition())
4306 Enum = Def;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004307
Douglas Gregord328d572009-09-21 18:10:23 +00004308 // Determine which enumerators we have already seen in the switch statement.
4309 // FIXME: Ideally, we would also be able to look *past* the code-completion
4310 // token, in case we are code-completing in the middle of the switch and not
4311 // at the end. However, we aren't able to do so at the moment.
4312 llvm::SmallPtrSet<EnumConstantDecl *, 8> EnumeratorsSeen;
Craig Topperc3ec1492014-05-26 06:22:03 +00004313 NestedNameSpecifier *Qualifier = nullptr;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004314 for (SwitchCase *SC = Switch->getSwitchCaseList(); SC;
Douglas Gregord328d572009-09-21 18:10:23 +00004315 SC = SC->getNextSwitchCase()) {
4316 CaseStmt *Case = dyn_cast<CaseStmt>(SC);
4317 if (!Case)
4318 continue;
4319
4320 Expr *CaseVal = Case->getLHS()->IgnoreParenCasts();
4321 if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CaseVal))
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004322 if (EnumConstantDecl *Enumerator
Douglas Gregord328d572009-09-21 18:10:23 +00004323 = dyn_cast<EnumConstantDecl>(DRE->getDecl())) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004324 // We look into the AST of the case statement to determine which
4325 // enumerator was named. Alternatively, we could compute the value of
Douglas Gregord328d572009-09-21 18:10:23 +00004326 // the integral constant expression, then compare it against the
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004327 // values of each enumerator. However, value-based approach would not
4328 // work as well with C++ templates where enumerators declared within a
Douglas Gregord328d572009-09-21 18:10:23 +00004329 // template are type- and value-dependent.
4330 EnumeratorsSeen.insert(Enumerator);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004331
Douglas Gregorf2510672009-09-21 19:57:38 +00004332 // If this is a qualified-id, keep track of the nested-name-specifier
4333 // so that we can reproduce it as part of code completion, e.g.,
Douglas Gregord328d572009-09-21 18:10:23 +00004334 //
4335 // switch (TagD.getKind()) {
4336 // case TagDecl::TK_enum:
4337 // break;
4338 // case XXX
4339 //
Douglas Gregorf2510672009-09-21 19:57:38 +00004340 // At the XXX, our completions are TagDecl::TK_union,
Douglas Gregord328d572009-09-21 18:10:23 +00004341 // TagDecl::TK_struct, and TagDecl::TK_class, rather than TK_union,
4342 // TK_struct, and TK_class.
Douglas Gregor4bd90e52009-10-23 18:54:35 +00004343 Qualifier = DRE->getQualifier();
Douglas Gregord328d572009-09-21 18:10:23 +00004344 }
4345 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004346
David Blaikiebbafb8a2012-03-11 07:00:24 +00004347 if (getLangOpts().CPlusPlus && !Qualifier && EnumeratorsSeen.empty()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004348 // If there are no prior enumerators in C++, check whether we have to
Douglas Gregorf2510672009-09-21 19:57:38 +00004349 // qualify the names of the enumerators that we suggest, because they
4350 // may not be visible in this scope.
Douglas Gregord3cebdb2012-02-01 05:02:47 +00004351 Qualifier = getRequiredQualification(Context, CurContext, Enum);
Douglas Gregorf2510672009-09-21 19:57:38 +00004352 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004353
Douglas Gregord328d572009-09-21 18:10:23 +00004354 // Add any enumerators that have not yet been mentioned.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004355 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004356 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004357 CodeCompletionContext::CCC_Expression);
Douglas Gregord328d572009-09-21 18:10:23 +00004358 Results.EnterNewScope();
Aaron Ballman23a6dcb2014-03-08 18:45:14 +00004359 for (auto *E : Enum->enumerators()) {
4360 if (EnumeratorsSeen.count(E))
Douglas Gregord328d572009-09-21 18:10:23 +00004361 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004362
Aaron Ballman23a6dcb2014-03-08 18:45:14 +00004363 CodeCompletionResult R(E, CCP_EnumInCase, Qualifier);
Craig Topperc3ec1492014-05-26 06:22:03 +00004364 Results.AddResult(R, CurContext, nullptr, false);
Douglas Gregord328d572009-09-21 18:10:23 +00004365 }
4366 Results.ExitScope();
Douglas Gregor285560922010-04-06 20:02:15 +00004367
Douglas Gregor21325842011-07-07 16:03:39 +00004368 if (CodeCompleter->includeMacros()) {
Douglas Gregor8cb17462012-10-09 16:01:50 +00004369 AddMacroResults(PP, Results, false);
Douglas Gregor21325842011-07-07 16:03:39 +00004370 }
Eric Liuf5ba09f2018-07-04 10:01:18 +00004371 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4372 Results.data(), Results.size());
Douglas Gregord328d572009-09-21 18:10:23 +00004373}
4374
Robert Wilhelm16e94b92013-08-09 18:02:13 +00004375static bool anyNullArguments(ArrayRef<Expr *> Args) {
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00004376 if (Args.size() && !Args.data())
Douglas Gregor6ed3eb82010-05-30 06:10:08 +00004377 return true;
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00004378
4379 for (unsigned I = 0; I != Args.size(); ++I)
Douglas Gregor6ed3eb82010-05-30 06:10:08 +00004380 if (!Args[I])
4381 return true;
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00004382
Douglas Gregor6ed3eb82010-05-30 06:10:08 +00004383 return false;
4384}
4385
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004386typedef CodeCompleteConsumer::OverloadCandidate ResultCandidate;
4387
Francisco Lopes da Silva8cafefa2015-01-29 05:54:59 +00004388static void mergeCandidatesWithResults(Sema &SemaRef,
4389 SmallVectorImpl<ResultCandidate> &Results,
4390 OverloadCandidateSet &CandidateSet,
4391 SourceLocation Loc) {
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004392 if (!CandidateSet.empty()) {
4393 // Sort the overload candidate set by placing the best overloads first.
4394 std::stable_sort(
4395 CandidateSet.begin(), CandidateSet.end(),
4396 [&](const OverloadCandidate &X, const OverloadCandidate &Y) {
Richard Smith67ef14f2017-09-26 18:37:55 +00004397 return isBetterOverloadCandidate(SemaRef, X, Y, Loc,
4398 CandidateSet.getKind());
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004399 });
4400
4401 // Add the remaining viable overload candidates as code-completion results.
Erik Verbruggen7ec91072017-09-08 10:23:08 +00004402 for (auto &Candidate : CandidateSet) {
4403 if (Candidate.Function && Candidate.Function->isDeleted())
4404 continue;
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004405 if (Candidate.Viable)
4406 Results.push_back(ResultCandidate(Candidate.Function));
Erik Verbruggen7ec91072017-09-08 10:23:08 +00004407 }
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004408 }
4409}
4410
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00004411/// Get the type of the Nth parameter from a given set of overload
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004412/// candidates.
Francisco Lopes da Silva8cafefa2015-01-29 05:54:59 +00004413static QualType getParamType(Sema &SemaRef,
4414 ArrayRef<ResultCandidate> Candidates,
4415 unsigned N) {
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004416
4417 // Given the overloads 'Candidates' for a function call matching all arguments
4418 // up to N, return the type of the Nth parameter if it is the same for all
4419 // overload candidates.
4420 QualType ParamType;
4421 for (auto &Candidate : Candidates) {
4422 if (auto FType = Candidate.getFunctionType())
4423 if (auto Proto = dyn_cast<FunctionProtoType>(FType))
4424 if (N < Proto->getNumParams()) {
4425 if (ParamType.isNull())
4426 ParamType = Proto->getParamType(N);
4427 else if (!SemaRef.Context.hasSameUnqualifiedType(
4428 ParamType.getNonReferenceType(),
4429 Proto->getParamType(N).getNonReferenceType()))
4430 // Otherwise return a default-constructed QualType.
4431 return QualType();
4432 }
4433 }
4434
4435 return ParamType;
4436}
4437
Francisco Lopes da Silva8cafefa2015-01-29 05:54:59 +00004438static void CodeCompleteOverloadResults(Sema &SemaRef, Scope *S,
4439 MutableArrayRef<ResultCandidate> Candidates,
4440 unsigned CurrentArg,
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004441 bool CompleteExpressionWithCurrentArg = true) {
4442 QualType ParamType;
4443 if (CompleteExpressionWithCurrentArg)
4444 ParamType = getParamType(SemaRef, Candidates, CurrentArg);
4445
4446 if (ParamType.isNull())
4447 SemaRef.CodeCompleteOrdinaryName(S, Sema::PCC_Expression);
4448 else
4449 SemaRef.CodeCompleteExpression(S, ParamType);
4450
4451 if (!Candidates.empty())
4452 SemaRef.CodeCompleter->ProcessOverloadCandidates(SemaRef, CurrentArg,
4453 Candidates.data(),
4454 Candidates.size());
4455}
4456
4457void Sema::CodeCompleteCall(Scope *S, Expr *Fn, ArrayRef<Expr *> Args) {
Douglas Gregorcabea402009-09-22 15:41:20 +00004458 if (!CodeCompleter)
4459 return;
Douglas Gregor3ef59522009-12-11 19:06:04 +00004460
4461 // When we're code-completing for a call, we fall back to ordinary
4462 // name code-completion whenever we can't produce specific
4463 // results. We may want to revisit this strategy in the future,
4464 // e.g., by merging the two kinds of results.
4465
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004466 // FIXME: Provide support for variadic template functions.
Douglas Gregor3ef59522009-12-11 19:06:04 +00004467
Douglas Gregorcabea402009-09-22 15:41:20 +00004468 // Ignore type-dependent call expressions entirely.
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00004469 if (!Fn || Fn->isTypeDependent() || anyNullArguments(Args) ||
4470 Expr::hasAnyTypeDependentArguments(Args)) {
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004471 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregorcabea402009-09-22 15:41:20 +00004472 return;
Douglas Gregor3ef59522009-12-11 19:06:04 +00004473 }
Douglas Gregorcabea402009-09-22 15:41:20 +00004474
John McCall57500772009-12-16 12:17:52 +00004475 // Build an overload candidate set based on the functions we find.
John McCallbc077cf2010-02-08 23:07:23 +00004476 SourceLocation Loc = Fn->getExprLoc();
Richard Smith100b24a2014-04-17 01:52:14 +00004477 OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal);
John McCall57500772009-12-16 12:17:52 +00004478
Chris Lattner0e62c1c2011-07-23 10:55:15 +00004479 SmallVector<ResultCandidate, 8> Results;
Douglas Gregorff59f672010-01-21 15:46:19 +00004480
John McCall57500772009-12-16 12:17:52 +00004481 Expr *NakedFn = Fn->IgnoreParenCasts();
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004482 if (auto ULE = dyn_cast<UnresolvedLookupExpr>(NakedFn))
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00004483 AddOverloadedCallCandidates(ULE, Args, CandidateSet,
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004484 /*PartialOverloading=*/true);
4485 else if (auto UME = dyn_cast<UnresolvedMemberExpr>(NakedFn)) {
4486 TemplateArgumentListInfo TemplateArgsBuffer, *TemplateArgs = nullptr;
4487 if (UME->hasExplicitTemplateArgs()) {
4488 UME->copyTemplateArgumentsInto(TemplateArgsBuffer);
4489 TemplateArgs = &TemplateArgsBuffer;
Douglas Gregorff59f672010-01-21 15:46:19 +00004490 }
Erik Verbruggenf1898cf2017-03-28 07:22:21 +00004491
4492 // Add the base as first argument (use a nullptr if the base is implicit).
4493 SmallVector<Expr *, 12> ArgExprs(
4494 1, UME->isImplicitAccess() ? nullptr : UME->getBase());
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004495 ArgExprs.append(Args.begin(), Args.end());
4496 UnresolvedSet<8> Decls;
4497 Decls.append(UME->decls_begin(), UME->decls_end());
Benjamin Kramere3962ae2017-10-26 08:41:28 +00004498 const bool FirstArgumentIsBase = !UME->isImplicitAccess() && UME->getBase();
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004499 AddFunctionCandidates(Decls, ArgExprs, CandidateSet, TemplateArgs,
4500 /*SuppressUsedConversions=*/false,
Benjamin Kramere3962ae2017-10-26 08:41:28 +00004501 /*PartialOverloading=*/true,
4502 FirstArgumentIsBase);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004503 } else {
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004504 FunctionDecl *FD = nullptr;
4505 if (auto MCE = dyn_cast<MemberExpr>(NakedFn))
4506 FD = dyn_cast<FunctionDecl>(MCE->getMemberDecl());
4507 else if (auto DRE = dyn_cast<DeclRefExpr>(NakedFn))
4508 FD = dyn_cast<FunctionDecl>(DRE->getDecl());
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00004509 if (FD) { // We check whether it's a resolved function declaration.
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00004510 if (!getLangOpts().CPlusPlus ||
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004511 !FD->getType()->getAs<FunctionProtoType>())
4512 Results.push_back(ResultCandidate(FD));
4513 else
4514 AddOverloadCandidate(FD, DeclAccessPair::make(FD, FD->getAccess()),
4515 Args, CandidateSet,
4516 /*SuppressUsedConversions=*/false,
4517 /*PartialOverloading=*/true);
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00004518
4519 } else if (auto DC = NakedFn->getType()->getAsCXXRecordDecl()) {
4520 // If expression's type is CXXRecordDecl, it may overload the function
4521 // call operator, so we check if it does and add them as candidates.
Francisco Lopes da Silvaa349a8a2015-01-25 08:47:59 +00004522 // A complete type is needed to lookup for member function call operators.
Richard Smithdb0ac552015-12-18 22:40:25 +00004523 if (isCompleteType(Loc, NakedFn->getType())) {
Francisco Lopes da Silvaa349a8a2015-01-25 08:47:59 +00004524 DeclarationName OpName = Context.DeclarationNames
4525 .getCXXOperatorName(OO_Call);
4526 LookupResult R(*this, OpName, Loc, LookupOrdinaryName);
4527 LookupQualifiedName(R, DC);
4528 R.suppressDiagnostics();
4529 SmallVector<Expr *, 12> ArgExprs(1, NakedFn);
4530 ArgExprs.append(Args.begin(), Args.end());
4531 AddFunctionCandidates(R.asUnresolvedSet(), ArgExprs, CandidateSet,
4532 /*ExplicitArgs=*/nullptr,
4533 /*SuppressUsedConversions=*/false,
4534 /*PartialOverloading=*/true);
4535 }
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00004536 } else {
4537 // Lastly we check whether expression's type is function pointer or
4538 // function.
4539 QualType T = NakedFn->getType();
4540 if (!T->getPointeeType().isNull())
4541 T = T->getPointeeType();
4542
4543 if (auto FP = T->getAs<FunctionProtoType>()) {
4544 if (!TooManyArguments(FP->getNumParams(), Args.size(),
Francisco Lopes da Silva62a9a4f2015-01-23 13:17:51 +00004545 /*PartialOverloading=*/true) ||
4546 FP->isVariadic())
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00004547 Results.push_back(ResultCandidate(FP));
4548 } else if (auto FT = T->getAs<FunctionType>())
Francisco Lopes da Silva62a9a4f2015-01-23 13:17:51 +00004549 // No prototype and declaration, it may be a K & R style function.
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00004550 Results.push_back(ResultCandidate(FT));
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004551 }
Douglas Gregorcabea402009-09-22 15:41:20 +00004552 }
Douglas Gregor3ef59522009-12-11 19:06:04 +00004553
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004554 mergeCandidatesWithResults(*this, Results, CandidateSet, Loc);
4555 CodeCompleteOverloadResults(*this, S, Results, Args.size(),
4556 !CandidateSet.empty());
4557}
4558
4559void Sema::CodeCompleteConstructor(Scope *S, QualType Type, SourceLocation Loc,
4560 ArrayRef<Expr *> Args) {
4561 if (!CodeCompleter)
4562 return;
4563
4564 // A complete type is needed to lookup for constructors.
Ilya Biryukovfb9dde72018-05-14 13:50:36 +00004565 CXXRecordDecl *RD =
4566 isCompleteType(Loc, Type) ? Type->getAsCXXRecordDecl() : nullptr;
Argyrios Kyrtzidisee1d76f2015-03-13 07:39:30 +00004567 if (!RD) {
4568 CodeCompleteExpression(S, Type);
4569 return;
4570 }
4571
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004572 // FIXME: Provide support for member initializers.
4573 // FIXME: Provide support for variadic template constructors.
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004574
4575 OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal);
4576
Argyrios Kyrtzidisee1d76f2015-03-13 07:39:30 +00004577 for (auto C : LookupConstructors(RD)) {
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004578 if (auto FD = dyn_cast<FunctionDecl>(C)) {
4579 AddOverloadCandidate(FD, DeclAccessPair::make(FD, C->getAccess()),
4580 Args, CandidateSet,
4581 /*SuppressUsedConversions=*/false,
4582 /*PartialOverloading=*/true);
4583 } else if (auto FTD = dyn_cast<FunctionTemplateDecl>(C)) {
4584 AddTemplateOverloadCandidate(FTD,
4585 DeclAccessPair::make(FTD, C->getAccess()),
4586 /*ExplicitTemplateArgs=*/nullptr,
4587 Args, CandidateSet,
4588 /*SuppressUsedConversions=*/false,
4589 /*PartialOverloading=*/true);
4590 }
4591 }
4592
4593 SmallVector<ResultCandidate, 8> Results;
4594 mergeCandidatesWithResults(*this, Results, CandidateSet, Loc);
4595 CodeCompleteOverloadResults(*this, S, Results, Args.size());
Douglas Gregorcabea402009-09-22 15:41:20 +00004596}
4597
John McCall48871652010-08-21 09:40:31 +00004598void Sema::CodeCompleteInitializer(Scope *S, Decl *D) {
4599 ValueDecl *VD = dyn_cast_or_null<ValueDecl>(D);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004600 if (!VD) {
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004601 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004602 return;
4603 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004604
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004605 CodeCompleteExpression(S, VD->getType());
4606}
4607
4608void Sema::CodeCompleteReturn(Scope *S) {
4609 QualType ResultType;
4610 if (isa<BlockDecl>(CurContext)) {
4611 if (BlockScopeInfo *BSI = getCurBlock())
4612 ResultType = BSI->ReturnType;
4613 } else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(CurContext))
Alp Toker314cc812014-01-25 16:55:45 +00004614 ResultType = Function->getReturnType();
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004615 else if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(CurContext))
Alp Toker314cc812014-01-25 16:55:45 +00004616 ResultType = Method->getReturnType();
4617
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004618 if (ResultType.isNull())
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004619 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004620 else
4621 CodeCompleteExpression(S, ResultType);
4622}
4623
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004624void Sema::CodeCompleteAfterIf(Scope *S) {
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004625 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004626 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004627 mapCodeCompletionContext(*this, PCC_Statement));
4628 Results.setFilter(&ResultBuilder::IsOrdinaryName);
4629 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004630
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004631 CodeCompletionDeclConsumer Consumer(Results, CurContext);
4632 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00004633 CodeCompleter->includeGlobals(),
4634 CodeCompleter->loadExternal());
4635
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004636 AddOrdinaryNameResults(PCC_Statement, S, *this, Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004637
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004638 // "else" block
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004639 CodeCompletionBuilder Builder(Results.getAllocator(),
4640 Results.getCodeCompletionTUInfo());
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004641 Builder.AddTypedTextChunk("else");
Douglas Gregor3a5d6c22012-02-16 17:49:04 +00004642 if (Results.includeCodePatterns()) {
4643 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4644 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4645 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
4646 Builder.AddPlaceholderChunk("statements");
4647 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
4648 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4649 }
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004650 Results.AddResult(Builder.TakeString());
4651
4652 // "else if" block
4653 Builder.AddTypedTextChunk("else");
4654 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4655 Builder.AddTextChunk("if");
4656 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4657 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00004658 if (getLangOpts().CPlusPlus)
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004659 Builder.AddPlaceholderChunk("condition");
4660 else
4661 Builder.AddPlaceholderChunk("expression");
4662 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor3a5d6c22012-02-16 17:49:04 +00004663 if (Results.includeCodePatterns()) {
4664 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4665 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4666 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
4667 Builder.AddPlaceholderChunk("statements");
4668 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
4669 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4670 }
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004671 Results.AddResult(Builder.TakeString());
4672
4673 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004674
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004675 if (S->getFnParent())
Craig Topper12126262015-11-15 17:27:57 +00004676 AddPrettyFunctionResults(getLangOpts(), Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004677
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004678 if (CodeCompleter->includeMacros())
Douglas Gregor8cb17462012-10-09 16:01:50 +00004679 AddMacroResults(PP, Results, false);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004680
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004681 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4682 Results.data(),Results.size());
4683}
4684
Richard Trieu2bd04012011-09-09 02:00:50 +00004685void Sema::CodeCompleteAssignmentRHS(Scope *S, Expr *LHS) {
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004686 if (LHS)
4687 CodeCompleteExpression(S, static_cast<Expr *>(LHS)->getType());
4688 else
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004689 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004690}
4691
Jeffrey Yasskinc76498d2010-04-08 16:38:48 +00004692void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS,
Douglas Gregor2436e712009-09-17 21:32:03 +00004693 bool EnteringContext) {
Eric Liu06d34022017-12-12 11:35:46 +00004694 if (SS.isEmpty() || !CodeCompleter)
Douglas Gregor2436e712009-09-17 21:32:03 +00004695 return;
Alex Lorenz8a7a4cf2017-06-15 21:40:54 +00004696
Eric Liu06d34022017-12-12 11:35:46 +00004697 // We want to keep the scope specifier even if it's invalid (e.g. the scope
4698 // "a::b::" is not corresponding to any context/namespace in the AST), since
4699 // it can be useful for global code completion which have information about
4700 // contexts/symbols that are not in the AST.
4701 if (SS.isInvalid()) {
4702 CodeCompletionContext CC(CodeCompletionContext::CCC_Name);
4703 CC.setCXXScopeSpecifier(SS);
4704 HandleCodeCompleteResults(this, CodeCompleter, CC, nullptr, 0);
4705 return;
4706 }
Alex Lorenz8a7a4cf2017-06-15 21:40:54 +00004707 // Always pretend to enter a context to ensure that a dependent type
4708 // resolves to a dependent record.
4709 DeclContext *Ctx = computeDeclContext(SS, /*EnteringContext=*/true);
Douglas Gregor3545ff42009-09-21 16:56:56 +00004710 if (!Ctx)
4711 return;
Douglas Gregor800f2f02009-12-11 18:28:39 +00004712
4713 // Try to instantiate any non-dependent declaration contexts before
4714 // we look in them.
John McCall0b66eb32010-05-01 00:40:08 +00004715 if (!isDependentScopeSpecifier(SS) && RequireCompleteDeclContext(SS, Ctx))
Douglas Gregor800f2f02009-12-11 18:28:39 +00004716 return;
4717
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004718 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004719 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004720 CodeCompletionContext::CCC_Name);
Douglas Gregorac322ec2010-08-27 21:18:54 +00004721 Results.EnterNewScope();
Eric Liu06d34022017-12-12 11:35:46 +00004722
Douglas Gregor3545ff42009-09-21 16:56:56 +00004723 // The "template" keyword can follow "::" in the grammar, but only
4724 // put it into the grammar if the nested-name-specifier is dependent.
Aaron Ballman4a979672014-01-03 13:56:08 +00004725 NestedNameSpecifier *NNS = SS.getScopeRep();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004726 if (!Results.empty() && NNS->isDependent())
Douglas Gregor78a21012010-01-14 16:01:26 +00004727 Results.AddResult("template");
Douglas Gregorac322ec2010-08-27 21:18:54 +00004728
4729 // Add calls to overridden virtual functions, if there are any.
4730 //
4731 // FIXME: This isn't wonderful, because we don't know whether we're actually
4732 // in a context that permits expressions. This is a general issue with
4733 // qualified-id completions.
4734 if (!EnteringContext)
4735 MaybeAddOverrideCalls(*this, Ctx, Results);
Eric Liu06d34022017-12-12 11:35:46 +00004736 Results.ExitScope();
4737
Eric Liufead6ae2017-12-13 10:26:49 +00004738 if (CodeCompleter->includeNamespaceLevelDecls() ||
4739 (!Ctx->isNamespace() && !Ctx->isTranslationUnit())) {
4740 CodeCompletionDeclConsumer Consumer(Results, CurContext);
4741 LookupVisibleDecls(Ctx, LookupOrdinaryName, Consumer,
4742 /*IncludeGlobalScope=*/true,
Sam McCallbb2cf632018-01-12 14:51:47 +00004743 /*IncludeDependentBases=*/true,
4744 CodeCompleter->loadExternal());
Eric Liufead6ae2017-12-13 10:26:49 +00004745 }
Douglas Gregorac322ec2010-08-27 21:18:54 +00004746
Eric Liu06d34022017-12-12 11:35:46 +00004747 auto CC = Results.getCompletionContext();
4748 CC.setCXXScopeSpecifier(SS);
4749
4750 HandleCodeCompleteResults(this, CodeCompleter, CC, Results.data(),
4751 Results.size());
Douglas Gregor2436e712009-09-17 21:32:03 +00004752}
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00004753
4754void Sema::CodeCompleteUsing(Scope *S) {
4755 if (!CodeCompleter)
4756 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004757
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004758 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004759 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00004760 CodeCompletionContext::CCC_PotentiallyQualifiedName,
4761 &ResultBuilder::IsNestedNameSpecifier);
Douglas Gregor64b12b52009-09-22 23:31:26 +00004762 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004763
Douglas Gregor3545ff42009-09-21 16:56:56 +00004764 // If we aren't in class scope, we could see the "namespace" keyword.
4765 if (!S->isClassScope())
John McCall276321a2010-08-25 06:19:51 +00004766 Results.AddResult(CodeCompletionResult("namespace"));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004767
4768 // After "using", we can see anything that would start a
Douglas Gregor3545ff42009-09-21 16:56:56 +00004769 // nested-name-specifier.
Douglas Gregora6e2edc2010-01-14 03:27:13 +00004770 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00004771 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00004772 CodeCompleter->includeGlobals(),
4773 CodeCompleter->loadExternal());
Douglas Gregor64b12b52009-09-22 23:31:26 +00004774 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00004775
4776 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4777 Results.data(), Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00004778}
4779
4780void Sema::CodeCompleteUsingDirective(Scope *S) {
4781 if (!CodeCompleter)
4782 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004783
Douglas Gregor3545ff42009-09-21 16:56:56 +00004784 // After "using namespace", we expect to see a namespace name or namespace
4785 // alias.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004786 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004787 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004788 CodeCompletionContext::CCC_Namespace,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004789 &ResultBuilder::IsNamespaceOrAlias);
Douglas Gregor64b12b52009-09-22 23:31:26 +00004790 Results.EnterNewScope();
Douglas Gregora6e2edc2010-01-14 03:27:13 +00004791 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00004792 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00004793 CodeCompleter->includeGlobals(),
4794 CodeCompleter->loadExternal());
Douglas Gregor64b12b52009-09-22 23:31:26 +00004795 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00004796 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4797 Results.data(), Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00004798}
4799
4800void Sema::CodeCompleteNamespaceDecl(Scope *S) {
4801 if (!CodeCompleter)
4802 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004803
Ted Kremenekc37877d2013-10-08 17:08:03 +00004804 DeclContext *Ctx = S->getEntity();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004805 if (!S->getParent())
4806 Ctx = Context.getTranslationUnitDecl();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004807
Douglas Gregor0ac41382010-09-23 23:01:17 +00004808 bool SuppressedGlobalResults
4809 = Ctx && !CodeCompleter->includeGlobals() && isa<TranslationUnitDecl>(Ctx);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004810
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004811 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004812 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00004813 SuppressedGlobalResults
4814 ? CodeCompletionContext::CCC_Namespace
4815 : CodeCompletionContext::CCC_Other,
4816 &ResultBuilder::IsNamespace);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004817
Douglas Gregor0ac41382010-09-23 23:01:17 +00004818 if (Ctx && Ctx->isFileContext() && !SuppressedGlobalResults) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00004819 // We only want to see those namespaces that have already been defined
4820 // within this scope, because its likely that the user is creating an
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004821 // extended namespace declaration. Keep track of the most recent
Douglas Gregor3545ff42009-09-21 16:56:56 +00004822 // definition of each namespace.
4823 std::map<NamespaceDecl *, NamespaceDecl *> OrigToLatest;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004824 for (DeclContext::specific_decl_iterator<NamespaceDecl>
Douglas Gregor3545ff42009-09-21 16:56:56 +00004825 NS(Ctx->decls_begin()), NSEnd(Ctx->decls_end());
4826 NS != NSEnd; ++NS)
David Blaikie40ed2972012-06-06 20:45:41 +00004827 OrigToLatest[NS->getOriginalNamespace()] = *NS;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004828
4829 // Add the most recent definition (or extended definition) of each
Douglas Gregor3545ff42009-09-21 16:56:56 +00004830 // namespace to the list of results.
Douglas Gregor64b12b52009-09-22 23:31:26 +00004831 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004832 for (std::map<NamespaceDecl *, NamespaceDecl *>::iterator
Douglas Gregor78254c82012-03-27 23:34:16 +00004833 NS = OrigToLatest.begin(),
4834 NSEnd = OrigToLatest.end();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004835 NS != NSEnd; ++NS)
Douglas Gregor0a0e2b32013-01-31 04:52:16 +00004836 Results.AddResult(CodeCompletionResult(
Craig Topperc3ec1492014-05-26 06:22:03 +00004837 NS->second, Results.getBasePriority(NS->second),
4838 nullptr),
4839 CurContext, nullptr, false);
Douglas Gregor64b12b52009-09-22 23:31:26 +00004840 Results.ExitScope();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004841 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004842
4843 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004844 Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004845 Results.data(),Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00004846}
4847
4848void Sema::CodeCompleteNamespaceAliasDecl(Scope *S) {
4849 if (!CodeCompleter)
4850 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004851
Douglas Gregor3545ff42009-09-21 16:56:56 +00004852 // After "namespace", we expect to see a namespace or alias.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004853 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004854 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004855 CodeCompletionContext::CCC_Namespace,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004856 &ResultBuilder::IsNamespaceOrAlias);
Douglas Gregora6e2edc2010-01-14 03:27:13 +00004857 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00004858 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00004859 CodeCompleter->includeGlobals(),
4860 CodeCompleter->loadExternal());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004861 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004862 Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004863 Results.data(),Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00004864}
4865
Douglas Gregorc811ede2009-09-18 20:05:18 +00004866void Sema::CodeCompleteOperatorName(Scope *S) {
4867 if (!CodeCompleter)
4868 return;
Douglas Gregor3545ff42009-09-21 16:56:56 +00004869
John McCall276321a2010-08-25 06:19:51 +00004870 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004871 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004872 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004873 CodeCompletionContext::CCC_Type,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004874 &ResultBuilder::IsType);
Douglas Gregor64b12b52009-09-22 23:31:26 +00004875 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004876
Douglas Gregor3545ff42009-09-21 16:56:56 +00004877 // Add the names of overloadable operators.
4878#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
4879 if (std::strcmp(Spelling, "?")) \
Douglas Gregor78a21012010-01-14 16:01:26 +00004880 Results.AddResult(Result(Spelling));
Douglas Gregor3545ff42009-09-21 16:56:56 +00004881#include "clang/Basic/OperatorKinds.def"
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004882
Douglas Gregor3545ff42009-09-21 16:56:56 +00004883 // Add any type names visible from the current scope
Douglas Gregor6ae4c522010-01-14 03:21:49 +00004884 Results.allowNestedNameSpecifiers();
Douglas Gregora6e2edc2010-01-14 03:27:13 +00004885 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00004886 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00004887 CodeCompleter->includeGlobals(),
4888 CodeCompleter->loadExternal());
4889
Douglas Gregor3545ff42009-09-21 16:56:56 +00004890 // Add any type specifiers
David Blaikiebbafb8a2012-03-11 07:00:24 +00004891 AddTypeSpecifierResults(getLangOpts(), Results);
Douglas Gregor64b12b52009-09-22 23:31:26 +00004892 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00004893
4894 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4895 Results.data(), Results.size());
Douglas Gregorc811ede2009-09-18 20:05:18 +00004896}
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00004897
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00004898void Sema::CodeCompleteConstructorInitializer(
4899 Decl *ConstructorD,
4900 ArrayRef <CXXCtorInitializer *> Initializers) {
Benjamin Kramera4f8df02015-07-09 15:31:10 +00004901 if (!ConstructorD)
4902 return;
4903
4904 AdjustDeclIfTemplate(ConstructorD);
4905
4906 CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(ConstructorD);
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004907 if (!Constructor)
4908 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004909
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004910 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004911 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00004912 CodeCompletionContext::CCC_PotentiallyQualifiedName);
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004913 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004914
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004915 // Fill in any already-initialized fields or base classes.
4916 llvm::SmallPtrSet<FieldDecl *, 4> InitializedFields;
4917 llvm::SmallPtrSet<CanQualType, 4> InitializedBases;
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00004918 for (unsigned I = 0, E = Initializers.size(); I != E; ++I) {
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004919 if (Initializers[I]->isBaseInitializer())
4920 InitializedBases.insert(
4921 Context.getCanonicalType(QualType(Initializers[I]->getBaseClass(), 0)));
4922 else
Francois Pichetd583da02010-12-04 09:14:42 +00004923 InitializedFields.insert(cast<FieldDecl>(
4924 Initializers[I]->getAnyMember()));
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004925 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004926
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004927 // Add completions for base classes.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004928 CodeCompletionBuilder Builder(Results.getAllocator(),
4929 Results.getCodeCompletionTUInfo());
Benjamin Kramera4f8df02015-07-09 15:31:10 +00004930 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00004931 bool SawLastInitializer = Initializers.empty();
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004932 CXXRecordDecl *ClassDecl = Constructor->getParent();
Aaron Ballman574705e2014-03-13 15:41:46 +00004933 for (const auto &Base : ClassDecl->bases()) {
David Blaikie82e95a32014-11-19 07:49:47 +00004934 if (!InitializedBases.insert(Context.getCanonicalType(Base.getType()))
4935 .second) {
Douglas Gregor99129ef2010-08-29 19:27:27 +00004936 SawLastInitializer
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004937 = !Initializers.empty() &&
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00004938 Initializers.back()->isBaseInitializer() &&
Aaron Ballman574705e2014-03-13 15:41:46 +00004939 Context.hasSameUnqualifiedType(Base.getType(),
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00004940 QualType(Initializers.back()->getBaseClass(), 0));
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004941 continue;
Douglas Gregor99129ef2010-08-29 19:27:27 +00004942 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004943
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004944 Builder.AddTypedTextChunk(
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00004945 Results.getAllocator().CopyString(
Aaron Ballman574705e2014-03-13 15:41:46 +00004946 Base.getType().getAsString(Policy)));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004947 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4948 Builder.AddPlaceholderChunk("args");
4949 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004950 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor99129ef2010-08-29 19:27:27 +00004951 SawLastInitializer? CCP_NextInitializer
4952 : CCP_MemberDeclaration));
4953 SawLastInitializer = false;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004954 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004955
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004956 // Add completions for virtual base classes.
Aaron Ballman445a9392014-03-13 16:15:17 +00004957 for (const auto &Base : ClassDecl->vbases()) {
David Blaikie82e95a32014-11-19 07:49:47 +00004958 if (!InitializedBases.insert(Context.getCanonicalType(Base.getType()))
4959 .second) {
Douglas Gregor99129ef2010-08-29 19:27:27 +00004960 SawLastInitializer
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004961 = !Initializers.empty() &&
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00004962 Initializers.back()->isBaseInitializer() &&
Aaron Ballman445a9392014-03-13 16:15:17 +00004963 Context.hasSameUnqualifiedType(Base.getType(),
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00004964 QualType(Initializers.back()->getBaseClass(), 0));
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004965 continue;
Douglas Gregor99129ef2010-08-29 19:27:27 +00004966 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004967
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004968 Builder.AddTypedTextChunk(
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00004969 Builder.getAllocator().CopyString(
Aaron Ballman445a9392014-03-13 16:15:17 +00004970 Base.getType().getAsString(Policy)));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004971 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4972 Builder.AddPlaceholderChunk("args");
4973 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004974 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor99129ef2010-08-29 19:27:27 +00004975 SawLastInitializer? CCP_NextInitializer
4976 : CCP_MemberDeclaration));
4977 SawLastInitializer = false;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004978 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004979
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004980 // Add completions for members.
Aaron Ballmane8a8bae2014-03-08 20:12:42 +00004981 for (auto *Field : ClassDecl->fields()) {
David Blaikie82e95a32014-11-19 07:49:47 +00004982 if (!InitializedFields.insert(cast<FieldDecl>(Field->getCanonicalDecl()))
4983 .second) {
Douglas Gregor99129ef2010-08-29 19:27:27 +00004984 SawLastInitializer
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004985 = !Initializers.empty() &&
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00004986 Initializers.back()->isAnyMemberInitializer() &&
Aaron Ballmane8a8bae2014-03-08 20:12:42 +00004987 Initializers.back()->getAnyMember() == Field;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004988 continue;
Douglas Gregor99129ef2010-08-29 19:27:27 +00004989 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004990
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004991 if (!Field->getDeclName())
4992 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004993
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00004994 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004995 Field->getIdentifier()->getName()));
4996 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4997 Builder.AddPlaceholderChunk("args");
4998 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004999 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor99129ef2010-08-29 19:27:27 +00005000 SawLastInitializer? CCP_NextInitializer
Douglas Gregorf3af3112010-09-09 21:42:20 +00005001 : CCP_MemberDeclaration,
Douglas Gregor78254c82012-03-27 23:34:16 +00005002 CXCursor_MemberRef,
5003 CXAvailability_Available,
Aaron Ballmane8a8bae2014-03-08 20:12:42 +00005004 Field));
Douglas Gregor99129ef2010-08-29 19:27:27 +00005005 SawLastInitializer = false;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005006 }
5007 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005008
Douglas Gregor0ac41382010-09-23 23:01:17 +00005009 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005010 Results.data(), Results.size());
5011}
5012
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00005013/// Determine whether this scope denotes a namespace.
Douglas Gregord8c61782012-02-15 15:34:24 +00005014static bool isNamespaceScope(Scope *S) {
Ted Kremenekc37877d2013-10-08 17:08:03 +00005015 DeclContext *DC = S->getEntity();
Douglas Gregord8c61782012-02-15 15:34:24 +00005016 if (!DC)
5017 return false;
5018
5019 return DC->isFileContext();
5020}
5021
5022void Sema::CodeCompleteLambdaIntroducer(Scope *S, LambdaIntroducer &Intro,
5023 bool AfterAmpersand) {
5024 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005025 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregord8c61782012-02-15 15:34:24 +00005026 CodeCompletionContext::CCC_Other);
5027 Results.EnterNewScope();
5028
5029 // Note what has already been captured.
5030 llvm::SmallPtrSet<IdentifierInfo *, 4> Known;
5031 bool IncludedThis = false;
Benjamin Kramerf3ca26982014-05-10 16:31:55 +00005032 for (const auto &C : Intro.Captures) {
5033 if (C.Kind == LCK_This) {
Douglas Gregord8c61782012-02-15 15:34:24 +00005034 IncludedThis = true;
5035 continue;
5036 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005037
Benjamin Kramerf3ca26982014-05-10 16:31:55 +00005038 Known.insert(C.Id);
Douglas Gregord8c61782012-02-15 15:34:24 +00005039 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005040
Douglas Gregord8c61782012-02-15 15:34:24 +00005041 // Look for other capturable variables.
5042 for (; S && !isNamespaceScope(S); S = S->getParent()) {
Aaron Ballman35c54952014-03-17 16:55:25 +00005043 for (const auto *D : S->decls()) {
5044 const auto *Var = dyn_cast<VarDecl>(D);
Douglas Gregord8c61782012-02-15 15:34:24 +00005045 if (!Var ||
5046 !Var->hasLocalStorage() ||
5047 Var->hasAttr<BlocksAttr>())
5048 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005049
David Blaikie82e95a32014-11-19 07:49:47 +00005050 if (Known.insert(Var->getIdentifier()).second)
Douglas Gregor0a0e2b32013-01-31 04:52:16 +00005051 Results.AddResult(CodeCompletionResult(Var, CCP_LocalDeclaration),
Craig Topperc3ec1492014-05-26 06:22:03 +00005052 CurContext, nullptr, false);
Douglas Gregord8c61782012-02-15 15:34:24 +00005053 }
5054 }
5055
5056 // Add 'this', if it would be valid.
5057 if (!IncludedThis && !AfterAmpersand && Intro.Default != LCD_ByCopy)
5058 addThisCompletion(*this, Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005059
Douglas Gregord8c61782012-02-15 15:34:24 +00005060 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005061
Douglas Gregord8c61782012-02-15 15:34:24 +00005062 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5063 Results.data(), Results.size());
5064}
5065
James Dennett596e4752012-06-14 03:11:41 +00005066/// Macro that optionally prepends an "@" to the string literal passed in via
5067/// Keyword, depending on whether NeedAt is true or false.
5068#define OBJC_AT_KEYWORD_NAME(NeedAt,Keyword) ((NeedAt)? "@" Keyword : Keyword)
5069
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005070static void AddObjCImplementationResults(const LangOptions &LangOpts,
Douglas Gregorf1934162010-01-13 21:24:21 +00005071 ResultBuilder &Results,
5072 bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005073 typedef CodeCompletionResult Result;
Douglas Gregorf1934162010-01-13 21:24:21 +00005074 // Since we have an implementation, we can end it.
James Dennett596e4752012-06-14 03:11:41 +00005075 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"end")));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005076
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005077 CodeCompletionBuilder Builder(Results.getAllocator(),
5078 Results.getCodeCompletionTUInfo());
Douglas Gregorf1934162010-01-13 21:24:21 +00005079 if (LangOpts.ObjC2) {
5080 // @dynamic
James Dennett596e4752012-06-14 03:11:41 +00005081 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"dynamic"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005082 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5083 Builder.AddPlaceholderChunk("property");
5084 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005085
Douglas Gregorf1934162010-01-13 21:24:21 +00005086 // @synthesize
James Dennett596e4752012-06-14 03:11:41 +00005087 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"synthesize"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005088 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5089 Builder.AddPlaceholderChunk("property");
5090 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005091 }
Douglas Gregorf1934162010-01-13 21:24:21 +00005092}
5093
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005094static void AddObjCInterfaceResults(const LangOptions &LangOpts,
Douglas Gregorf1934162010-01-13 21:24:21 +00005095 ResultBuilder &Results,
5096 bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005097 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005098
Douglas Gregorf1934162010-01-13 21:24:21 +00005099 // Since we have an interface or protocol, we can end it.
James Dennett596e4752012-06-14 03:11:41 +00005100 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"end")));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005101
Douglas Gregorf1934162010-01-13 21:24:21 +00005102 if (LangOpts.ObjC2) {
5103 // @property
James Dennett596e4752012-06-14 03:11:41 +00005104 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"property")));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005105
Douglas Gregorf1934162010-01-13 21:24:21 +00005106 // @required
James Dennett596e4752012-06-14 03:11:41 +00005107 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"required")));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005108
Douglas Gregorf1934162010-01-13 21:24:21 +00005109 // @optional
James Dennett596e4752012-06-14 03:11:41 +00005110 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"optional")));
Douglas Gregorf1934162010-01-13 21:24:21 +00005111 }
5112}
5113
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005114static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005115 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005116 CodeCompletionBuilder Builder(Results.getAllocator(),
5117 Results.getCodeCompletionTUInfo());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005118
Douglas Gregorf1934162010-01-13 21:24:21 +00005119 // @class name ;
James Dennett596e4752012-06-14 03:11:41 +00005120 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"class"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005121 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5122 Builder.AddPlaceholderChunk("name");
5123 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005124
Douglas Gregorf4c33342010-05-28 00:22:41 +00005125 if (Results.includeCodePatterns()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005126 // @interface name
5127 // FIXME: Could introduce the whole pattern, including superclasses and
Douglas Gregorf4c33342010-05-28 00:22:41 +00005128 // such.
James Dennett596e4752012-06-14 03:11:41 +00005129 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"interface"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005130 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5131 Builder.AddPlaceholderChunk("class");
5132 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005133
Douglas Gregorf4c33342010-05-28 00:22:41 +00005134 // @protocol name
James Dennett596e4752012-06-14 03:11:41 +00005135 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"protocol"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005136 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5137 Builder.AddPlaceholderChunk("protocol");
5138 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005139
Douglas Gregorf4c33342010-05-28 00:22:41 +00005140 // @implementation name
James Dennett596e4752012-06-14 03:11:41 +00005141 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"implementation"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005142 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5143 Builder.AddPlaceholderChunk("class");
5144 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00005145 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005146
Douglas Gregorf1934162010-01-13 21:24:21 +00005147 // @compatibility_alias name
James Dennett596e4752012-06-14 03:11:41 +00005148 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"compatibility_alias"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005149 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5150 Builder.AddPlaceholderChunk("alias");
5151 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5152 Builder.AddPlaceholderChunk("class");
5153 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor61e36812013-03-07 23:26:24 +00005154
5155 if (Results.getSema().getLangOpts().Modules) {
5156 // @import name
5157 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "import"));
5158 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5159 Builder.AddPlaceholderChunk("module");
5160 Results.AddResult(Result(Builder.TakeString()));
5161 }
Douglas Gregorf1934162010-01-13 21:24:21 +00005162}
5163
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005164void Sema::CodeCompleteObjCAtDirective(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005165 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005166 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005167 CodeCompletionContext::CCC_Other);
Douglas Gregorf48706c2009-12-07 09:27:33 +00005168 Results.EnterNewScope();
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005169 if (isa<ObjCImplDecl>(CurContext))
David Blaikiebbafb8a2012-03-11 07:00:24 +00005170 AddObjCImplementationResults(getLangOpts(), Results, false);
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005171 else if (CurContext->isObjCContainer())
David Blaikiebbafb8a2012-03-11 07:00:24 +00005172 AddObjCInterfaceResults(getLangOpts(), Results, false);
Douglas Gregorf1934162010-01-13 21:24:21 +00005173 else
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005174 AddObjCTopLevelResults(Results, false);
Douglas Gregorf48706c2009-12-07 09:27:33 +00005175 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005176 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5177 Results.data(), Results.size());
Douglas Gregorf48706c2009-12-07 09:27:33 +00005178}
5179
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005180static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005181 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005182 CodeCompletionBuilder Builder(Results.getAllocator(),
5183 Results.getCodeCompletionTUInfo());
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005184
5185 // @encode ( type-name )
Douglas Gregore5c79d52011-10-18 21:20:17 +00005186 const char *EncodeType = "char[]";
David Blaikiebbafb8a2012-03-11 07:00:24 +00005187 if (Results.getSema().getLangOpts().CPlusPlus ||
5188 Results.getSema().getLangOpts().ConstStrings)
Jordan Rose9da05852012-06-15 18:19:56 +00005189 EncodeType = "const char[]";
Douglas Gregore5c79d52011-10-18 21:20:17 +00005190 Builder.AddResultTypeChunk(EncodeType);
James Dennett596e4752012-06-14 03:11:41 +00005191 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"encode"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005192 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5193 Builder.AddPlaceholderChunk("type-name");
5194 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5195 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005196
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005197 // @protocol ( protocol-name )
Douglas Gregore5c79d52011-10-18 21:20:17 +00005198 Builder.AddResultTypeChunk("Protocol *");
James Dennett596e4752012-06-14 03:11:41 +00005199 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"protocol"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005200 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5201 Builder.AddPlaceholderChunk("protocol-name");
5202 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5203 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005204
5205 // @selector ( selector )
Douglas Gregore5c79d52011-10-18 21:20:17 +00005206 Builder.AddResultTypeChunk("SEL");
James Dennett596e4752012-06-14 03:11:41 +00005207 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"selector"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005208 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5209 Builder.AddPlaceholderChunk("selector");
5210 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5211 Results.AddResult(Result(Builder.TakeString()));
Jordan Rose9da05852012-06-15 18:19:56 +00005212
5213 // @"string"
5214 Builder.AddResultTypeChunk("NSString *");
5215 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"\""));
5216 Builder.AddPlaceholderChunk("string");
5217 Builder.AddTextChunk("\"");
5218 Results.AddResult(Result(Builder.TakeString()));
5219
Douglas Gregor951de302012-07-17 23:24:47 +00005220 // @[objects, ...]
Jordan Rose9da05852012-06-15 18:19:56 +00005221 Builder.AddResultTypeChunk("NSArray *");
James Dennett596e4752012-06-14 03:11:41 +00005222 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"["));
Ted Kremeneke65b0862012-03-06 20:05:56 +00005223 Builder.AddPlaceholderChunk("objects, ...");
Ted Kremeneke65b0862012-03-06 20:05:56 +00005224 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
5225 Results.AddResult(Result(Builder.TakeString()));
5226
Douglas Gregor951de302012-07-17 23:24:47 +00005227 // @{key : object, ...}
Jordan Rose9da05852012-06-15 18:19:56 +00005228 Builder.AddResultTypeChunk("NSDictionary *");
James Dennett596e4752012-06-14 03:11:41 +00005229 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"{"));
Ted Kremeneke65b0862012-03-06 20:05:56 +00005230 Builder.AddPlaceholderChunk("key");
Ted Kremeneke65b0862012-03-06 20:05:56 +00005231 Builder.AddChunk(CodeCompletionString::CK_Colon);
5232 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5233 Builder.AddPlaceholderChunk("object, ...");
Ted Kremeneke65b0862012-03-06 20:05:56 +00005234 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5235 Results.AddResult(Result(Builder.TakeString()));
Jordan Rose9da05852012-06-15 18:19:56 +00005236
Douglas Gregor951de302012-07-17 23:24:47 +00005237 // @(expression)
Jordan Rose9da05852012-06-15 18:19:56 +00005238 Builder.AddResultTypeChunk("id");
5239 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "("));
Jordan Rose9da05852012-06-15 18:19:56 +00005240 Builder.AddPlaceholderChunk("expression");
Jordan Rose9da05852012-06-15 18:19:56 +00005241 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5242 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005243}
5244
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005245static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005246 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005247 CodeCompletionBuilder Builder(Results.getAllocator(),
5248 Results.getCodeCompletionTUInfo());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005249
Douglas Gregorf4c33342010-05-28 00:22:41 +00005250 if (Results.includeCodePatterns()) {
5251 // @try { statements } @catch ( declaration ) { statements } @finally
5252 // { statements }
James Dennett596e4752012-06-14 03:11:41 +00005253 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"try"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005254 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5255 Builder.AddPlaceholderChunk("statements");
5256 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5257 Builder.AddTextChunk("@catch");
5258 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5259 Builder.AddPlaceholderChunk("parameter");
5260 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5261 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5262 Builder.AddPlaceholderChunk("statements");
5263 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5264 Builder.AddTextChunk("@finally");
5265 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5266 Builder.AddPlaceholderChunk("statements");
5267 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5268 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00005269 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005270
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005271 // @throw
James Dennett596e4752012-06-14 03:11:41 +00005272 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"throw"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005273 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5274 Builder.AddPlaceholderChunk("expression");
5275 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005276
Douglas Gregorf4c33342010-05-28 00:22:41 +00005277 if (Results.includeCodePatterns()) {
5278 // @synchronized ( expression ) { statements }
James Dennett596e4752012-06-14 03:11:41 +00005279 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"synchronized"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005280 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5281 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5282 Builder.AddPlaceholderChunk("expression");
5283 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5284 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5285 Builder.AddPlaceholderChunk("statements");
5286 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5287 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00005288 }
Douglas Gregorf1934162010-01-13 21:24:21 +00005289}
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005290
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005291static void AddObjCVisibilityResults(const LangOptions &LangOpts,
Douglas Gregor48d46252010-01-13 21:54:15 +00005292 ResultBuilder &Results,
5293 bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005294 typedef CodeCompletionResult Result;
James Dennett596e4752012-06-14 03:11:41 +00005295 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"private")));
5296 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"protected")));
5297 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"public")));
Douglas Gregor48d46252010-01-13 21:54:15 +00005298 if (LangOpts.ObjC2)
James Dennett596e4752012-06-14 03:11:41 +00005299 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"package")));
Douglas Gregor48d46252010-01-13 21:54:15 +00005300}
5301
5302void Sema::CodeCompleteObjCAtVisibility(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005303 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005304 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005305 CodeCompletionContext::CCC_Other);
Douglas Gregor48d46252010-01-13 21:54:15 +00005306 Results.EnterNewScope();
David Blaikiebbafb8a2012-03-11 07:00:24 +00005307 AddObjCVisibilityResults(getLangOpts(), Results, false);
Douglas Gregor48d46252010-01-13 21:54:15 +00005308 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005309 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5310 Results.data(), Results.size());
Douglas Gregor48d46252010-01-13 21:54:15 +00005311}
5312
5313void Sema::CodeCompleteObjCAtStatement(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005314 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005315 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005316 CodeCompletionContext::CCC_Other);
Douglas Gregorf1934162010-01-13 21:24:21 +00005317 Results.EnterNewScope();
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005318 AddObjCStatementResults(Results, false);
5319 AddObjCExpressionResults(Results, false);
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005320 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005321 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5322 Results.data(), Results.size());
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005323}
5324
5325void Sema::CodeCompleteObjCAtExpression(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005326 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005327 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005328 CodeCompletionContext::CCC_Other);
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005329 Results.EnterNewScope();
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005330 AddObjCExpressionResults(Results, false);
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005331 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005332 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5333 Results.data(), Results.size());
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005334}
5335
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00005336/// Determine whether the addition of the given flag to an Objective-C
Douglas Gregore6078da2009-11-19 00:14:45 +00005337/// property's attributes will cause a conflict.
Bill Wendling44426052012-12-20 19:22:21 +00005338static bool ObjCPropertyFlagConflicts(unsigned Attributes, unsigned NewFlag) {
Douglas Gregore6078da2009-11-19 00:14:45 +00005339 // Check if we've already added this flag.
Bill Wendling44426052012-12-20 19:22:21 +00005340 if (Attributes & NewFlag)
Douglas Gregore6078da2009-11-19 00:14:45 +00005341 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005342
Bill Wendling44426052012-12-20 19:22:21 +00005343 Attributes |= NewFlag;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005344
Douglas Gregore6078da2009-11-19 00:14:45 +00005345 // Check for collisions with "readonly".
Bill Wendling44426052012-12-20 19:22:21 +00005346 if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) &&
5347 (Attributes & ObjCDeclSpec::DQ_PR_readwrite))
Douglas Gregore6078da2009-11-19 00:14:45 +00005348 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005349
Jordan Rose53cb2f32012-08-20 20:01:13 +00005350 // Check for more than one of { assign, copy, retain, strong, weak }.
Bill Wendling44426052012-12-20 19:22:21 +00005351 unsigned AssignCopyRetMask = Attributes & (ObjCDeclSpec::DQ_PR_assign |
John McCall31168b02011-06-15 23:02:42 +00005352 ObjCDeclSpec::DQ_PR_unsafe_unretained |
Douglas Gregore6078da2009-11-19 00:14:45 +00005353 ObjCDeclSpec::DQ_PR_copy |
Jordan Rose53cb2f32012-08-20 20:01:13 +00005354 ObjCDeclSpec::DQ_PR_retain |
5355 ObjCDeclSpec::DQ_PR_strong |
5356 ObjCDeclSpec::DQ_PR_weak);
Douglas Gregore6078da2009-11-19 00:14:45 +00005357 if (AssignCopyRetMask &&
5358 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_assign &&
John McCall31168b02011-06-15 23:02:42 +00005359 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_unsafe_unretained &&
Douglas Gregore6078da2009-11-19 00:14:45 +00005360 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_copy &&
John McCall31168b02011-06-15 23:02:42 +00005361 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_retain &&
Jordan Rose53cb2f32012-08-20 20:01:13 +00005362 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_strong &&
5363 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_weak)
Douglas Gregore6078da2009-11-19 00:14:45 +00005364 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005365
Douglas Gregore6078da2009-11-19 00:14:45 +00005366 return false;
5367}
5368
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005369void Sema::CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS) {
Steve Naroff936354c2009-10-08 21:55:05 +00005370 if (!CodeCompleter)
5371 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005372
Bill Wendling44426052012-12-20 19:22:21 +00005373 unsigned Attributes = ODS.getPropertyAttributes();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005374
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005375 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005376 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005377 CodeCompletionContext::CCC_Other);
Steve Naroff936354c2009-10-08 21:55:05 +00005378 Results.EnterNewScope();
Bill Wendling44426052012-12-20 19:22:21 +00005379 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readonly))
John McCall276321a2010-08-25 06:19:51 +00005380 Results.AddResult(CodeCompletionResult("readonly"));
Bill Wendling44426052012-12-20 19:22:21 +00005381 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_assign))
John McCall276321a2010-08-25 06:19:51 +00005382 Results.AddResult(CodeCompletionResult("assign"));
Bill Wendling44426052012-12-20 19:22:21 +00005383 if (!ObjCPropertyFlagConflicts(Attributes,
John McCall31168b02011-06-15 23:02:42 +00005384 ObjCDeclSpec::DQ_PR_unsafe_unretained))
5385 Results.AddResult(CodeCompletionResult("unsafe_unretained"));
Bill Wendling44426052012-12-20 19:22:21 +00005386 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readwrite))
John McCall276321a2010-08-25 06:19:51 +00005387 Results.AddResult(CodeCompletionResult("readwrite"));
Bill Wendling44426052012-12-20 19:22:21 +00005388 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_retain))
John McCall276321a2010-08-25 06:19:51 +00005389 Results.AddResult(CodeCompletionResult("retain"));
Bill Wendling44426052012-12-20 19:22:21 +00005390 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_strong))
John McCall31168b02011-06-15 23:02:42 +00005391 Results.AddResult(CodeCompletionResult("strong"));
Bill Wendling44426052012-12-20 19:22:21 +00005392 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_copy))
John McCall276321a2010-08-25 06:19:51 +00005393 Results.AddResult(CodeCompletionResult("copy"));
Bill Wendling44426052012-12-20 19:22:21 +00005394 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_nonatomic))
John McCall276321a2010-08-25 06:19:51 +00005395 Results.AddResult(CodeCompletionResult("nonatomic"));
Bill Wendling44426052012-12-20 19:22:21 +00005396 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_atomic))
Fariborz Jahanian1c2d29e2011-06-11 17:14:27 +00005397 Results.AddResult(CodeCompletionResult("atomic"));
Jordan Rose53cb2f32012-08-20 20:01:13 +00005398
5399 // Only suggest "weak" if we're compiling for ARC-with-weak-references or GC.
John McCall460ce582015-10-22 18:38:17 +00005400 if (getLangOpts().ObjCWeak || getLangOpts().getGC() != LangOptions::NonGC)
Bill Wendling44426052012-12-20 19:22:21 +00005401 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_weak))
Jordan Rose53cb2f32012-08-20 20:01:13 +00005402 Results.AddResult(CodeCompletionResult("weak"));
5403
Bill Wendling44426052012-12-20 19:22:21 +00005404 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_setter)) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005405 CodeCompletionBuilder Setter(Results.getAllocator(),
5406 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005407 Setter.AddTypedTextChunk("setter");
Argyrios Kyrtzidis7bbb8812014-02-20 07:55:15 +00005408 Setter.AddTextChunk("=");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005409 Setter.AddPlaceholderChunk("method");
5410 Results.AddResult(CodeCompletionResult(Setter.TakeString()));
Douglas Gregor45f83ee2009-11-19 00:01:57 +00005411 }
Bill Wendling44426052012-12-20 19:22:21 +00005412 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_getter)) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005413 CodeCompletionBuilder Getter(Results.getAllocator(),
5414 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005415 Getter.AddTypedTextChunk("getter");
Argyrios Kyrtzidis7bbb8812014-02-20 07:55:15 +00005416 Getter.AddTextChunk("=");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005417 Getter.AddPlaceholderChunk("method");
5418 Results.AddResult(CodeCompletionResult(Getter.TakeString()));
Douglas Gregor45f83ee2009-11-19 00:01:57 +00005419 }
Douglas Gregor86b42682015-06-19 18:27:52 +00005420 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_nullability)) {
5421 Results.AddResult(CodeCompletionResult("nonnull"));
5422 Results.AddResult(CodeCompletionResult("nullable"));
5423 Results.AddResult(CodeCompletionResult("null_unspecified"));
5424 Results.AddResult(CodeCompletionResult("null_resettable"));
5425 }
Steve Naroff936354c2009-10-08 21:55:05 +00005426 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005427 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5428 Results.data(), Results.size());
Steve Naroff936354c2009-10-08 21:55:05 +00005429}
Steve Naroffeae65032009-11-07 02:08:14 +00005430
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00005431/// Describes the kind of Objective-C method that we want to find
Douglas Gregorc8537c52009-11-19 07:41:15 +00005432/// via code completion.
5433enum ObjCMethodKind {
Dmitri Gribenko4280e5c2012-06-08 23:13:42 +00005434 MK_Any, ///< Any kind of method, provided it means other specified criteria.
5435 MK_ZeroArgSelector, ///< Zero-argument (unary) selector.
5436 MK_OneArgSelector ///< One-argument selector.
Douglas Gregorc8537c52009-11-19 07:41:15 +00005437};
5438
Douglas Gregor67c692c2010-08-26 15:07:07 +00005439static bool isAcceptableObjCSelector(Selector Sel,
5440 ObjCMethodKind WantKind,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005441 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005442 bool AllowSameLength = true) {
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005443 unsigned NumSelIdents = SelIdents.size();
Douglas Gregor67c692c2010-08-26 15:07:07 +00005444 if (NumSelIdents > Sel.getNumArgs())
5445 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005446
Douglas Gregor67c692c2010-08-26 15:07:07 +00005447 switch (WantKind) {
5448 case MK_Any: break;
5449 case MK_ZeroArgSelector: return Sel.isUnarySelector();
5450 case MK_OneArgSelector: return Sel.getNumArgs() == 1;
5451 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005452
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005453 if (!AllowSameLength && NumSelIdents && NumSelIdents == Sel.getNumArgs())
5454 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005455
Douglas Gregor67c692c2010-08-26 15:07:07 +00005456 for (unsigned I = 0; I != NumSelIdents; ++I)
5457 if (SelIdents[I] != Sel.getIdentifierInfoForSlot(I))
5458 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005459
Douglas Gregor67c692c2010-08-26 15:07:07 +00005460 return true;
5461}
5462
Douglas Gregorc8537c52009-11-19 07:41:15 +00005463static bool isAcceptableObjCMethod(ObjCMethodDecl *Method,
5464 ObjCMethodKind WantKind,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005465 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005466 bool AllowSameLength = true) {
Douglas Gregor67c692c2010-08-26 15:07:07 +00005467 return isAcceptableObjCSelector(Method->getSelector(), WantKind, SelIdents,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005468 AllowSameLength);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005469}
Douglas Gregor1154e272010-09-16 16:06:31 +00005470
5471namespace {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005472 /// A set of selectors, which is used to avoid introducing multiple
Douglas Gregor1154e272010-09-16 16:06:31 +00005473 /// completions with the same selector into the result set.
5474 typedef llvm::SmallPtrSet<Selector, 16> VisitedSelectorSet;
5475}
5476
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005477/// Add all of the Objective-C methods in the given Objective-C
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005478/// container to the set of results.
5479///
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005480/// The container will be a class, protocol, category, or implementation of
5481/// any of the above. This mether will recurse to include methods from
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005482/// the superclasses of classes along with their categories, protocols, and
5483/// implementations.
5484///
5485/// \param Container the container in which we'll look to find methods.
5486///
James Dennett596e4752012-06-14 03:11:41 +00005487/// \param WantInstanceMethods Whether to add instance methods (only); if
5488/// false, this routine will add factory methods (only).
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005489///
5490/// \param CurContext the context in which we're performing the lookup that
5491/// finds methods.
5492///
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005493/// \param AllowSameLength Whether we allow a method to be added to the list
5494/// when it has the same number of parameters as we have selector identifiers.
5495///
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005496/// \param Results the structure into which we'll add results.
Alex Lorenz638dbc32017-01-24 14:15:08 +00005497static void AddObjCMethods(ObjCContainerDecl *Container,
5498 bool WantInstanceMethods, ObjCMethodKind WantKind,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005499 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005500 DeclContext *CurContext,
Alex Lorenz638dbc32017-01-24 14:15:08 +00005501 VisitedSelectorSet &Selectors, bool AllowSameLength,
5502 ResultBuilder &Results, bool InOriginalClass = true,
5503 bool IsRootClass = false) {
John McCall276321a2010-08-25 06:19:51 +00005504 typedef CodeCompletionResult Result;
Douglas Gregor9b4f3702012-06-12 13:44:08 +00005505 Container = getContainerDef(Container);
Douglas Gregor41778c32013-01-30 06:58:39 +00005506 ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container);
Alex Lorenz638dbc32017-01-24 14:15:08 +00005507 IsRootClass = IsRootClass || (IFace && !IFace->getSuperClass());
Aaron Ballmanaff18c02014-03-13 19:03:34 +00005508 for (auto *M : Container->methods()) {
Douglas Gregor41778c32013-01-30 06:58:39 +00005509 // The instance methods on the root class can be messaged via the
5510 // metaclass.
5511 if (M->isInstanceMethod() == WantInstanceMethods ||
Alex Lorenz638dbc32017-01-24 14:15:08 +00005512 (IsRootClass && !WantInstanceMethods)) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005513 // Check whether the selector identifiers we've been given are a
Douglas Gregor1b605f72009-11-19 01:08:35 +00005514 // subset of the identifiers for this particular method.
Aaron Ballmanaff18c02014-03-13 19:03:34 +00005515 if (!isAcceptableObjCMethod(M, WantKind, SelIdents, AllowSameLength))
Douglas Gregor1b605f72009-11-19 01:08:35 +00005516 continue;
Douglas Gregorc8537c52009-11-19 07:41:15 +00005517
David Blaikie82e95a32014-11-19 07:49:47 +00005518 if (!Selectors.insert(M->getSelector()).second)
Douglas Gregor1154e272010-09-16 16:06:31 +00005519 continue;
Craig Topperc3ec1492014-05-26 06:22:03 +00005520
5521 Result R = Result(M, Results.getBasePriority(M), nullptr);
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005522 R.StartParameter = SelIdents.size();
Douglas Gregorc8537c52009-11-19 07:41:15 +00005523 R.AllParametersAreInformative = (WantKind != MK_Any);
Douglas Gregor416b5752010-08-25 01:08:01 +00005524 if (!InOriginalClass)
5525 R.Priority += CCD_InBaseClass;
Douglas Gregor1b605f72009-11-19 01:08:35 +00005526 Results.MaybeAddResult(R, CurContext);
5527 }
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005528 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005529
Douglas Gregorf37c9492010-09-16 15:34:59 +00005530 // Visit the protocols of protocols.
5531 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Douglas Gregore6e48b12012-01-01 19:29:29 +00005532 if (Protocol->hasDefinition()) {
5533 const ObjCList<ObjCProtocolDecl> &Protocols
5534 = Protocol->getReferencedProtocols();
5535 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005536 E = Protocols.end();
Douglas Gregore6e48b12012-01-01 19:29:29 +00005537 I != E; ++I)
Alex Lorenz638dbc32017-01-24 14:15:08 +00005538 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, CurContext,
5539 Selectors, AllowSameLength, Results, false, IsRootClass);
Douglas Gregore6e48b12012-01-01 19:29:29 +00005540 }
Douglas Gregorf37c9492010-09-16 15:34:59 +00005541 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005542
Douglas Gregorc0ac7d62011-12-15 05:27:12 +00005543 if (!IFace || !IFace->hasDefinition())
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005544 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005545
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005546 // Add methods in protocols.
Aaron Ballmana49c5062014-03-13 20:29:09 +00005547 for (auto *I : IFace->protocols())
Alex Lorenz638dbc32017-01-24 14:15:08 +00005548 AddObjCMethods(I, WantInstanceMethods, WantKind, SelIdents, CurContext,
5549 Selectors, AllowSameLength, Results, false, IsRootClass);
5550
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005551 // Add methods in categories.
Aaron Ballman15063e12014-03-13 21:35:02 +00005552 for (auto *CatDecl : IFace->known_categories()) {
Douglas Gregor048fbfa2013-01-16 23:00:23 +00005553 AddObjCMethods(CatDecl, WantInstanceMethods, WantKind, SelIdents,
Alex Lorenz638dbc32017-01-24 14:15:08 +00005554 CurContext, Selectors, AllowSameLength, Results,
5555 InOriginalClass, IsRootClass);
5556
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005557 // Add a categories protocol methods.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005558 const ObjCList<ObjCProtocolDecl> &Protocols
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005559 = CatDecl->getReferencedProtocols();
5560 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
5561 E = Protocols.end();
5562 I != E; ++I)
Alex Lorenz638dbc32017-01-24 14:15:08 +00005563 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, CurContext,
5564 Selectors, AllowSameLength, Results, false, IsRootClass);
5565
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005566 // Add methods in category implementations.
5567 if (ObjCCategoryImplDecl *Impl = CatDecl->getImplementation())
Alex Lorenz638dbc32017-01-24 14:15:08 +00005568 AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents, CurContext,
5569 Selectors, AllowSameLength, Results, InOriginalClass,
5570 IsRootClass);
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005571 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005572
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005573 // Add methods in superclass.
Alex Lorenz638dbc32017-01-24 14:15:08 +00005574 // Avoid passing in IsRootClass since root classes won't have super classes.
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005575 if (IFace->getSuperClass())
Alex Lorenz638dbc32017-01-24 14:15:08 +00005576 AddObjCMethods(IFace->getSuperClass(), WantInstanceMethods, WantKind,
5577 SelIdents, CurContext, Selectors, AllowSameLength, Results,
5578 /*IsRootClass=*/false);
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005579
5580 // Add methods in our implementation, if any.
5581 if (ObjCImplementationDecl *Impl = IFace->getImplementation())
Alex Lorenz638dbc32017-01-24 14:15:08 +00005582 AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents, CurContext,
5583 Selectors, AllowSameLength, Results, InOriginalClass,
5584 IsRootClass);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005585}
5586
5587
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005588void Sema::CodeCompleteObjCPropertyGetter(Scope *S) {
Douglas Gregorc8537c52009-11-19 07:41:15 +00005589 // Try to find the interface where getters might live.
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005590 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005591 if (!Class) {
5592 if (ObjCCategoryDecl *Category
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005593 = dyn_cast_or_null<ObjCCategoryDecl>(CurContext))
Douglas Gregorc8537c52009-11-19 07:41:15 +00005594 Class = Category->getClassInterface();
5595
5596 if (!Class)
5597 return;
5598 }
5599
5600 // Find all of the potential getters.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005601 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005602 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005603 CodeCompletionContext::CCC_Other);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005604 Results.EnterNewScope();
5605
Douglas Gregor1154e272010-09-16 16:06:31 +00005606 VisitedSelectorSet Selectors;
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005607 AddObjCMethods(Class, true, MK_ZeroArgSelector, None, CurContext, Selectors,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005608 /*AllowSameLength=*/true, Results);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005609 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005610 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5611 Results.data(), Results.size());
Douglas Gregorc8537c52009-11-19 07:41:15 +00005612}
5613
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005614void Sema::CodeCompleteObjCPropertySetter(Scope *S) {
Douglas Gregorc8537c52009-11-19 07:41:15 +00005615 // Try to find the interface where setters might live.
5616 ObjCInterfaceDecl *Class
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005617 = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005618 if (!Class) {
5619 if (ObjCCategoryDecl *Category
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005620 = dyn_cast_or_null<ObjCCategoryDecl>(CurContext))
Douglas Gregorc8537c52009-11-19 07:41:15 +00005621 Class = Category->getClassInterface();
5622
5623 if (!Class)
5624 return;
5625 }
5626
5627 // Find all of the potential getters.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005628 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005629 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005630 CodeCompletionContext::CCC_Other);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005631 Results.EnterNewScope();
5632
Douglas Gregor1154e272010-09-16 16:06:31 +00005633 VisitedSelectorSet Selectors;
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005634 AddObjCMethods(Class, true, MK_OneArgSelector, None, CurContext,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005635 Selectors, /*AllowSameLength=*/true, Results);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005636
5637 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005638 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5639 Results.data(), Results.size());
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005640}
5641
Douglas Gregorf34a6f02011-02-15 22:19:42 +00005642void Sema::CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS,
5643 bool IsParameter) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005644 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005645 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005646 CodeCompletionContext::CCC_Type);
Douglas Gregor99fa2642010-08-24 01:06:58 +00005647 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005648
Douglas Gregor99fa2642010-08-24 01:06:58 +00005649 // Add context-sensitive, Objective-C parameter-passing keywords.
5650 bool AddedInOut = false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005651 if ((DS.getObjCDeclQualifier() &
Douglas Gregor99fa2642010-08-24 01:06:58 +00005652 (ObjCDeclSpec::DQ_In | ObjCDeclSpec::DQ_Inout)) == 0) {
5653 Results.AddResult("in");
5654 Results.AddResult("inout");
5655 AddedInOut = true;
5656 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005657 if ((DS.getObjCDeclQualifier() &
Douglas Gregor99fa2642010-08-24 01:06:58 +00005658 (ObjCDeclSpec::DQ_Out | ObjCDeclSpec::DQ_Inout)) == 0) {
5659 Results.AddResult("out");
5660 if (!AddedInOut)
5661 Results.AddResult("inout");
5662 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005663 if ((DS.getObjCDeclQualifier() &
Douglas Gregor99fa2642010-08-24 01:06:58 +00005664 (ObjCDeclSpec::DQ_Bycopy | ObjCDeclSpec::DQ_Byref |
5665 ObjCDeclSpec::DQ_Oneway)) == 0) {
5666 Results.AddResult("bycopy");
5667 Results.AddResult("byref");
5668 Results.AddResult("oneway");
5669 }
Douglas Gregor86b42682015-06-19 18:27:52 +00005670 if ((DS.getObjCDeclQualifier() & ObjCDeclSpec::DQ_CSNullability) == 0) {
5671 Results.AddResult("nonnull");
5672 Results.AddResult("nullable");
5673 Results.AddResult("null_unspecified");
5674 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005675
5676 // If we're completing the return type of an Objective-C method and the
Douglas Gregorf34a6f02011-02-15 22:19:42 +00005677 // identifier IBAction refers to a macro, provide a completion item for
5678 // an action, e.g.,
5679 // IBAction)<#selector#>:(id)sender
5680 if (DS.getObjCDeclQualifier() == 0 && !IsParameter &&
Richard Smith20e883e2015-04-29 23:20:19 +00005681 PP.isMacroDefined("IBAction")) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005682 CodeCompletionBuilder Builder(Results.getAllocator(),
5683 Results.getCodeCompletionTUInfo(),
5684 CCP_CodePattern, CXAvailability_Available);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00005685 Builder.AddTypedTextChunk("IBAction");
Benjamin Kramerdb534a42012-03-26 16:57:36 +00005686 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00005687 Builder.AddPlaceholderChunk("selector");
Benjamin Kramerdb534a42012-03-26 16:57:36 +00005688 Builder.AddChunk(CodeCompletionString::CK_Colon);
5689 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00005690 Builder.AddTextChunk("id");
Benjamin Kramerdb534a42012-03-26 16:57:36 +00005691 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00005692 Builder.AddTextChunk("sender");
5693 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
5694 }
Douglas Gregored1f5972013-01-30 07:11:43 +00005695
5696 // If we're completing the return type, provide 'instancetype'.
5697 if (!IsParameter) {
5698 Results.AddResult(CodeCompletionResult("instancetype"));
5699 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005700
Douglas Gregor99fa2642010-08-24 01:06:58 +00005701 // Add various builtin type names and specifiers.
5702 AddOrdinaryNameResults(PCC_Type, S, *this, Results);
5703 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005704
Douglas Gregor99fa2642010-08-24 01:06:58 +00005705 // Add the various type names
5706 Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
5707 CodeCompletionDeclConsumer Consumer(Results, CurContext);
5708 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00005709 CodeCompleter->includeGlobals(),
5710 CodeCompleter->loadExternal());
5711
Douglas Gregor99fa2642010-08-24 01:06:58 +00005712 if (CodeCompleter->includeMacros())
Douglas Gregor8cb17462012-10-09 16:01:50 +00005713 AddMacroResults(PP, Results, false);
Douglas Gregor99fa2642010-08-24 01:06:58 +00005714
Eric Liuf5ba09f2018-07-04 10:01:18 +00005715 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor99fa2642010-08-24 01:06:58 +00005716 Results.data(), Results.size());
5717}
5718
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00005719/// When we have an expression with type "id", we may assume
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005720/// that it has some more-specific class type based on knowledge of
5721/// common uses of Objective-C. This routine returns that class type,
5722/// or NULL if no better result could be determined.
5723static ObjCInterfaceDecl *GetAssumedMessageSendExprType(Expr *E) {
Douglas Gregored0b69d2010-09-15 16:23:04 +00005724 ObjCMessageExpr *Msg = dyn_cast_or_null<ObjCMessageExpr>(E);
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005725 if (!Msg)
Craig Topperc3ec1492014-05-26 06:22:03 +00005726 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005727
5728 Selector Sel = Msg->getSelector();
5729 if (Sel.isNull())
Craig Topperc3ec1492014-05-26 06:22:03 +00005730 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005731
5732 IdentifierInfo *Id = Sel.getIdentifierInfoForSlot(0);
5733 if (!Id)
Craig Topperc3ec1492014-05-26 06:22:03 +00005734 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005735
5736 ObjCMethodDecl *Method = Msg->getMethodDecl();
5737 if (!Method)
Craig Topperc3ec1492014-05-26 06:22:03 +00005738 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005739
5740 // Determine the class that we're sending the message to.
Craig Topperc3ec1492014-05-26 06:22:03 +00005741 ObjCInterfaceDecl *IFace = nullptr;
Douglas Gregor9a129192010-04-21 00:45:42 +00005742 switch (Msg->getReceiverKind()) {
5743 case ObjCMessageExpr::Class:
John McCall8b07ec22010-05-15 11:32:37 +00005744 if (const ObjCObjectType *ObjType
5745 = Msg->getClassReceiver()->getAs<ObjCObjectType>())
5746 IFace = ObjType->getInterface();
Douglas Gregor9a129192010-04-21 00:45:42 +00005747 break;
5748
5749 case ObjCMessageExpr::Instance: {
5750 QualType T = Msg->getInstanceReceiver()->getType();
5751 if (const ObjCObjectPointerType *Ptr = T->getAs<ObjCObjectPointerType>())
5752 IFace = Ptr->getInterfaceDecl();
5753 break;
5754 }
5755
5756 case ObjCMessageExpr::SuperInstance:
5757 case ObjCMessageExpr::SuperClass:
5758 break;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005759 }
5760
5761 if (!IFace)
Craig Topperc3ec1492014-05-26 06:22:03 +00005762 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005763
5764 ObjCInterfaceDecl *Super = IFace->getSuperClass();
5765 if (Method->isInstanceMethod())
5766 return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
5767 .Case("retain", IFace)
John McCall31168b02011-06-15 23:02:42 +00005768 .Case("strong", IFace)
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005769 .Case("autorelease", IFace)
5770 .Case("copy", IFace)
5771 .Case("copyWithZone", IFace)
5772 .Case("mutableCopy", IFace)
5773 .Case("mutableCopyWithZone", IFace)
5774 .Case("awakeFromCoder", IFace)
5775 .Case("replacementObjectFromCoder", IFace)
5776 .Case("class", IFace)
5777 .Case("classForCoder", IFace)
5778 .Case("superclass", Super)
Craig Topperc3ec1492014-05-26 06:22:03 +00005779 .Default(nullptr);
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005780
5781 return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
5782 .Case("new", IFace)
5783 .Case("alloc", IFace)
5784 .Case("allocWithZone", IFace)
5785 .Case("class", IFace)
5786 .Case("superclass", Super)
Craig Topperc3ec1492014-05-26 06:22:03 +00005787 .Default(nullptr);
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005788}
5789
Douglas Gregor6fc04132010-08-27 15:10:57 +00005790// Add a special completion for a message send to "super", which fills in the
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005791// most likely case of forwarding all of our arguments to the superclass
Douglas Gregor6fc04132010-08-27 15:10:57 +00005792// function.
5793///
5794/// \param S The semantic analysis object.
5795///
Dmitri Gribenkoadba9be2012-08-23 17:58:28 +00005796/// \param NeedSuperKeyword Whether we need to prefix this completion with
Douglas Gregor6fc04132010-08-27 15:10:57 +00005797/// the "super" keyword. Otherwise, we just need to provide the arguments.
5798///
5799/// \param SelIdents The identifiers in the selector that have already been
5800/// provided as arguments for a send to "super".
5801///
Douglas Gregor6fc04132010-08-27 15:10:57 +00005802/// \param Results The set of results to augment.
5803///
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005804/// \returns the Objective-C method declaration that would be invoked by
Douglas Gregor6fc04132010-08-27 15:10:57 +00005805/// this "super" completion. If NULL, no completion was added.
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005806static ObjCMethodDecl *AddSuperSendCompletion(
5807 Sema &S, bool NeedSuperKeyword,
5808 ArrayRef<IdentifierInfo *> SelIdents,
5809 ResultBuilder &Results) {
Douglas Gregor6fc04132010-08-27 15:10:57 +00005810 ObjCMethodDecl *CurMethod = S.getCurMethodDecl();
5811 if (!CurMethod)
Craig Topperc3ec1492014-05-26 06:22:03 +00005812 return nullptr;
5813
Douglas Gregor6fc04132010-08-27 15:10:57 +00005814 ObjCInterfaceDecl *Class = CurMethod->getClassInterface();
5815 if (!Class)
Craig Topperc3ec1492014-05-26 06:22:03 +00005816 return nullptr;
5817
Douglas Gregor6fc04132010-08-27 15:10:57 +00005818 // Try to find a superclass method with the same selector.
Craig Topperc3ec1492014-05-26 06:22:03 +00005819 ObjCMethodDecl *SuperMethod = nullptr;
Douglas Gregorb5f1e462011-02-16 00:51:18 +00005820 while ((Class = Class->getSuperClass()) && !SuperMethod) {
5821 // Check in the class
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005822 SuperMethod = Class->getMethod(CurMethod->getSelector(),
Douglas Gregor6fc04132010-08-27 15:10:57 +00005823 CurMethod->isInstanceMethod());
5824
Douglas Gregorb5f1e462011-02-16 00:51:18 +00005825 // Check in categories or class extensions.
5826 if (!SuperMethod) {
Aaron Ballman15063e12014-03-13 21:35:02 +00005827 for (const auto *Cat : Class->known_categories()) {
Douglas Gregor048fbfa2013-01-16 23:00:23 +00005828 if ((SuperMethod = Cat->getMethod(CurMethod->getSelector(),
Douglas Gregorb5f1e462011-02-16 00:51:18 +00005829 CurMethod->isInstanceMethod())))
5830 break;
Douglas Gregor048fbfa2013-01-16 23:00:23 +00005831 }
Douglas Gregorb5f1e462011-02-16 00:51:18 +00005832 }
5833 }
5834
Douglas Gregor6fc04132010-08-27 15:10:57 +00005835 if (!SuperMethod)
Craig Topperc3ec1492014-05-26 06:22:03 +00005836 return nullptr;
5837
Douglas Gregor6fc04132010-08-27 15:10:57 +00005838 // Check whether the superclass method has the same signature.
5839 if (CurMethod->param_size() != SuperMethod->param_size() ||
5840 CurMethod->isVariadic() != SuperMethod->isVariadic())
Craig Topperc3ec1492014-05-26 06:22:03 +00005841 return nullptr;
5842
Douglas Gregor6fc04132010-08-27 15:10:57 +00005843 for (ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin(),
5844 CurPEnd = CurMethod->param_end(),
5845 SuperP = SuperMethod->param_begin();
5846 CurP != CurPEnd; ++CurP, ++SuperP) {
5847 // Make sure the parameter types are compatible.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005848 if (!S.Context.hasSameUnqualifiedType((*CurP)->getType(),
Douglas Gregor6fc04132010-08-27 15:10:57 +00005849 (*SuperP)->getType()))
Craig Topperc3ec1492014-05-26 06:22:03 +00005850 return nullptr;
5851
Douglas Gregor6fc04132010-08-27 15:10:57 +00005852 // Make sure we have a parameter name to forward!
5853 if (!(*CurP)->getIdentifier())
Craig Topperc3ec1492014-05-26 06:22:03 +00005854 return nullptr;
Douglas Gregor6fc04132010-08-27 15:10:57 +00005855 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005856
Douglas Gregor6fc04132010-08-27 15:10:57 +00005857 // We have a superclass method. Now, form the send-to-super completion.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005858 CodeCompletionBuilder Builder(Results.getAllocator(),
5859 Results.getCodeCompletionTUInfo());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005860
Douglas Gregor6fc04132010-08-27 15:10:57 +00005861 // Give this completion a return type.
Douglas Gregorc3425b12015-07-07 06:20:19 +00005862 AddResultTypeChunk(S.Context, getCompletionPrintingPolicy(S), SuperMethod,
5863 Results.getCompletionContext().getBaseType(),
Douglas Gregor75acd922011-09-27 23:30:47 +00005864 Builder);
Douglas Gregor6fc04132010-08-27 15:10:57 +00005865
5866 // If we need the "super" keyword, add it (plus some spacing).
5867 if (NeedSuperKeyword) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005868 Builder.AddTypedTextChunk("super");
5869 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregor6fc04132010-08-27 15:10:57 +00005870 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005871
Douglas Gregor6fc04132010-08-27 15:10:57 +00005872 Selector Sel = CurMethod->getSelector();
5873 if (Sel.isUnarySelector()) {
5874 if (NeedSuperKeyword)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005875 Builder.AddTextChunk(Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00005876 Sel.getNameForSlot(0)));
Douglas Gregor6fc04132010-08-27 15:10:57 +00005877 else
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005878 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00005879 Sel.getNameForSlot(0)));
Douglas Gregor6fc04132010-08-27 15:10:57 +00005880 } else {
5881 ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin();
5882 for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I, ++CurP) {
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005883 if (I > SelIdents.size())
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005884 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005885
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005886 if (I < SelIdents.size())
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005887 Builder.AddInformativeChunk(
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005888 Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00005889 Sel.getNameForSlot(I) + ":"));
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005890 else if (NeedSuperKeyword || I > SelIdents.size()) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005891 Builder.AddTextChunk(
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005892 Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00005893 Sel.getNameForSlot(I) + ":"));
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005894 Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005895 (*CurP)->getIdentifier()->getName()));
Douglas Gregor6fc04132010-08-27 15:10:57 +00005896 } else {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005897 Builder.AddTypedTextChunk(
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005898 Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00005899 Sel.getNameForSlot(I) + ":"));
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005900 Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005901 (*CurP)->getIdentifier()->getName()));
Douglas Gregor6fc04132010-08-27 15:10:57 +00005902 }
5903 }
5904 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005905
Douglas Gregor78254c82012-03-27 23:34:16 +00005906 Results.AddResult(CodeCompletionResult(Builder.TakeString(), SuperMethod,
5907 CCP_SuperCompletion));
Douglas Gregor6fc04132010-08-27 15:10:57 +00005908 return SuperMethod;
5909}
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005910
Douglas Gregora817a192010-05-27 23:06:34 +00005911void Sema::CodeCompleteObjCMessageReceiver(Scope *S) {
John McCall276321a2010-08-25 06:19:51 +00005912 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005913 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005914 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005915 CodeCompletionContext::CCC_ObjCMessageReceiver,
Richard Smith2bf7fdb2013-01-02 11:42:31 +00005916 getLangOpts().CPlusPlus11
Douglas Gregord8c61782012-02-15 15:34:24 +00005917 ? &ResultBuilder::IsObjCMessageReceiverOrLambdaCapture
5918 : &ResultBuilder::IsObjCMessageReceiver);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005919
Douglas Gregora817a192010-05-27 23:06:34 +00005920 CodeCompletionDeclConsumer Consumer(Results, CurContext);
5921 Results.EnterNewScope();
Douglas Gregor39982192010-08-15 06:18:01 +00005922 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00005923 CodeCompleter->includeGlobals(),
5924 CodeCompleter->loadExternal());
5925
Douglas Gregora817a192010-05-27 23:06:34 +00005926 // If we are in an Objective-C method inside a class that has a superclass,
5927 // add "super" as an option.
5928 if (ObjCMethodDecl *Method = getCurMethodDecl())
5929 if (ObjCInterfaceDecl *Iface = Method->getClassInterface())
Douglas Gregor6fc04132010-08-27 15:10:57 +00005930 if (Iface->getSuperClass()) {
Douglas Gregora817a192010-05-27 23:06:34 +00005931 Results.AddResult(Result("super"));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005932
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005933 AddSuperSendCompletion(*this, /*NeedSuperKeyword=*/true, None, Results);
Douglas Gregor6fc04132010-08-27 15:10:57 +00005934 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005935
Richard Smith2bf7fdb2013-01-02 11:42:31 +00005936 if (getLangOpts().CPlusPlus11)
Douglas Gregord8c61782012-02-15 15:34:24 +00005937 addThisCompletion(*this, Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005938
Douglas Gregora817a192010-05-27 23:06:34 +00005939 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005940
Douglas Gregora817a192010-05-27 23:06:34 +00005941 if (CodeCompleter->includeMacros())
Douglas Gregor8cb17462012-10-09 16:01:50 +00005942 AddMacroResults(PP, Results, false);
Douglas Gregor50832e02010-09-20 22:39:41 +00005943 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005944 Results.data(), Results.size());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005945
Douglas Gregora817a192010-05-27 23:06:34 +00005946}
5947
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005948void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005949 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00005950 bool AtArgumentExpression) {
Craig Topperc3ec1492014-05-26 06:22:03 +00005951 ObjCInterfaceDecl *CDecl = nullptr;
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005952 if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
5953 // Figure out which interface we're in.
5954 CDecl = CurMethod->getClassInterface();
5955 if (!CDecl)
5956 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005957
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005958 // Find the superclass of this class.
5959 CDecl = CDecl->getSuperClass();
5960 if (!CDecl)
5961 return;
5962
5963 if (CurMethod->isInstanceMethod()) {
5964 // We are inside an instance method, which means that the message
5965 // send [super ...] is actually calling an instance method on the
Douglas Gregor392a84b2010-10-13 21:24:53 +00005966 // current object.
Craig Topperc3ec1492014-05-26 06:22:03 +00005967 return CodeCompleteObjCInstanceMessage(S, nullptr, SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00005968 AtArgumentExpression,
Douglas Gregor392a84b2010-10-13 21:24:53 +00005969 CDecl);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005970 }
5971
5972 // Fall through to send to the superclass in CDecl.
5973 } else {
5974 // "super" may be the name of a type or variable. Figure out which
5975 // it is.
Argyrios Kyrtzidis3e56dd42013-03-14 22:56:43 +00005976 IdentifierInfo *Super = getSuperIdentifier();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005977 NamedDecl *ND = LookupSingleName(S, Super, SuperLoc,
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005978 LookupOrdinaryName);
5979 if ((CDecl = dyn_cast_or_null<ObjCInterfaceDecl>(ND))) {
5980 // "super" names an interface. Use it.
5981 } else if (TypeDecl *TD = dyn_cast_or_null<TypeDecl>(ND)) {
John McCall8b07ec22010-05-15 11:32:37 +00005982 if (const ObjCObjectType *Iface
5983 = Context.getTypeDeclType(TD)->getAs<ObjCObjectType>())
5984 CDecl = Iface->getInterface();
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005985 } else if (ND && isa<UnresolvedUsingTypenameDecl>(ND)) {
5986 // "super" names an unresolved type; we can't be more specific.
5987 } else {
5988 // Assume that "super" names some kind of value and parse that way.
5989 CXXScopeSpec SS;
Abramo Bagnara7945c982012-01-27 09:46:47 +00005990 SourceLocation TemplateKWLoc;
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005991 UnqualifiedId id;
5992 id.setIdentifier(Super, SuperLoc);
Abramo Bagnara7945c982012-01-27 09:46:47 +00005993 ExprResult SuperExpr = ActOnIdExpression(S, SS, TemplateKWLoc, id,
5994 false, false);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005995 return CodeCompleteObjCInstanceMessage(S, (Expr *)SuperExpr.get(),
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005996 SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00005997 AtArgumentExpression);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005998 }
5999
6000 // Fall through
6001 }
6002
John McCallba7bf592010-08-24 05:47:05 +00006003 ParsedType Receiver;
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006004 if (CDecl)
John McCallba7bf592010-08-24 05:47:05 +00006005 Receiver = ParsedType::make(Context.getObjCInterfaceType(CDecl));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006006 return CodeCompleteObjCClassMessage(S, Receiver, SelIdents,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006007 AtArgumentExpression,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006008 /*IsSuper=*/true);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006009}
6010
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006011/// Given a set of code-completion results for the argument of a message
Douglas Gregor74661272010-09-21 00:03:25 +00006012/// send, determine the preferred type (if any) for that argument expression.
6013static QualType getPreferredArgumentTypeForMessageSend(ResultBuilder &Results,
6014 unsigned NumSelIdents) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006015 typedef CodeCompletionResult Result;
Douglas Gregor74661272010-09-21 00:03:25 +00006016 ASTContext &Context = Results.getSema().Context;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006017
Douglas Gregor74661272010-09-21 00:03:25 +00006018 QualType PreferredType;
6019 unsigned BestPriority = CCP_Unlikely * 2;
6020 Result *ResultsData = Results.data();
6021 for (unsigned I = 0, N = Results.size(); I != N; ++I) {
6022 Result &R = ResultsData[I];
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006023 if (R.Kind == Result::RK_Declaration &&
Douglas Gregor74661272010-09-21 00:03:25 +00006024 isa<ObjCMethodDecl>(R.Declaration)) {
6025 if (R.Priority <= BestPriority) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00006026 const ObjCMethodDecl *Method = cast<ObjCMethodDecl>(R.Declaration);
Douglas Gregor74661272010-09-21 00:03:25 +00006027 if (NumSelIdents <= Method->param_size()) {
Alp Toker03376dc2014-07-07 09:02:20 +00006028 QualType MyPreferredType = Method->parameters()[NumSelIdents - 1]
Douglas Gregor74661272010-09-21 00:03:25 +00006029 ->getType();
6030 if (R.Priority < BestPriority || PreferredType.isNull()) {
6031 BestPriority = R.Priority;
6032 PreferredType = MyPreferredType;
6033 } else if (!Context.hasSameUnqualifiedType(PreferredType,
6034 MyPreferredType)) {
6035 PreferredType = QualType();
6036 }
6037 }
6038 }
6039 }
6040 }
6041
6042 return PreferredType;
6043}
6044
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006045static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006046 ParsedType Receiver,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006047 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006048 bool AtArgumentExpression,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006049 bool IsSuper,
6050 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00006051 typedef CodeCompletionResult Result;
Craig Topperc3ec1492014-05-26 06:22:03 +00006052 ObjCInterfaceDecl *CDecl = nullptr;
6053
Douglas Gregor8ce33212009-11-17 17:59:40 +00006054 // If the given name refers to an interface type, retrieve the
6055 // corresponding declaration.
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006056 if (Receiver) {
Craig Topperc3ec1492014-05-26 06:22:03 +00006057 QualType T = SemaRef.GetTypeFromParser(Receiver, nullptr);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006058 if (!T.isNull())
John McCall8b07ec22010-05-15 11:32:37 +00006059 if (const ObjCObjectType *Interface = T->getAs<ObjCObjectType>())
6060 CDecl = Interface->getInterface();
Douglas Gregor8ce33212009-11-17 17:59:40 +00006061 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006062
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006063 // Add all of the factory methods in this Objective-C class, its protocols,
6064 // superclasses, categories, implementation, etc.
Steve Naroffeae65032009-11-07 02:08:14 +00006065 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006066
6067 // If this is a send-to-super, try to add the special "super" send
Douglas Gregor6fc04132010-08-27 15:10:57 +00006068 // completion.
6069 if (IsSuper) {
6070 if (ObjCMethodDecl *SuperMethod
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006071 = AddSuperSendCompletion(SemaRef, false, SelIdents, Results))
Douglas Gregor6fc04132010-08-27 15:10:57 +00006072 Results.Ignore(SuperMethod);
6073 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006074
Douglas Gregorc2cb2e22010-08-27 15:29:55 +00006075 // If we're inside an Objective-C method definition, prefer its selector to
6076 // others.
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006077 if (ObjCMethodDecl *CurMethod = SemaRef.getCurMethodDecl())
Douglas Gregorc2cb2e22010-08-27 15:29:55 +00006078 Results.setPreferredSelector(CurMethod->getSelector());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006079
Douglas Gregor1154e272010-09-16 16:06:31 +00006080 VisitedSelectorSet Selectors;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006081 if (CDecl)
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006082 AddObjCMethods(CDecl, false, MK_Any, SelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00006083 SemaRef.CurContext, Selectors, AtArgumentExpression,
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006084 Results);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006085 else {
Douglas Gregor6285f752010-04-06 16:40:00 +00006086 // We're messaging "id" as a type; provide all class/factory methods.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006087
Douglas Gregord720daf2010-04-06 17:30:22 +00006088 // If we have an external source, load the entire class method
Sebastian Redld44cd6a2010-08-18 23:57:06 +00006089 // pool from the AST file.
Axel Naumanndd433f02012-10-18 19:05:02 +00006090 if (SemaRef.getExternalSource()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006091 for (uint32_t I = 0,
Axel Naumanndd433f02012-10-18 19:05:02 +00006092 N = SemaRef.getExternalSource()->GetNumExternalSelectors();
John McCall75b960e2010-06-01 09:23:16 +00006093 I != N; ++I) {
Axel Naumanndd433f02012-10-18 19:05:02 +00006094 Selector Sel = SemaRef.getExternalSource()->GetExternalSelector(I);
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006095 if (Sel.isNull() || SemaRef.MethodPool.count(Sel))
Douglas Gregord720daf2010-04-06 17:30:22 +00006096 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006097
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006098 SemaRef.ReadMethodPool(Sel);
Douglas Gregord720daf2010-04-06 17:30:22 +00006099 }
6100 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006101
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006102 for (Sema::GlobalMethodPool::iterator M = SemaRef.MethodPool.begin(),
6103 MEnd = SemaRef.MethodPool.end();
Sebastian Redl75d8a322010-08-02 23:18:59 +00006104 M != MEnd; ++M) {
6105 for (ObjCMethodList *MethList = &M->second.second;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006106 MethList && MethList->getMethod();
Argyrios Kyrtzidisd3da6e02013-04-17 00:08:58 +00006107 MethList = MethList->getNext()) {
Nico Weber2e0c8f72014-12-27 03:58:08 +00006108 if (!isAcceptableObjCMethod(MethList->getMethod(), MK_Any, SelIdents))
Douglas Gregor6285f752010-04-06 16:40:00 +00006109 continue;
Craig Topperc3ec1492014-05-26 06:22:03 +00006110
Nico Weber2e0c8f72014-12-27 03:58:08 +00006111 Result R(MethList->getMethod(),
6112 Results.getBasePriority(MethList->getMethod()), nullptr);
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006113 R.StartParameter = SelIdents.size();
Douglas Gregor6285f752010-04-06 16:40:00 +00006114 R.AllParametersAreInformative = false;
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006115 Results.MaybeAddResult(R, SemaRef.CurContext);
Douglas Gregor6285f752010-04-06 16:40:00 +00006116 }
6117 }
6118 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006119
6120 Results.ExitScope();
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006121}
Douglas Gregor6285f752010-04-06 16:40:00 +00006122
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006123void Sema::CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006124 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006125 bool AtArgumentExpression,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006126 bool IsSuper) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006127
Douglas Gregor63745d52011-07-21 01:05:26 +00006128 QualType T = this->GetTypeFromParser(Receiver);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006129
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006130 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006131 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor63745d52011-07-21 01:05:26 +00006132 CodeCompletionContext(CodeCompletionContext::CCC_ObjCClassMessage,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006133 T, SelIdents));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006134
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006135 AddClassMessageCompletions(*this, S, Receiver, SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006136 AtArgumentExpression, IsSuper, Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006137
6138 // If we're actually at the argument expression (rather than prior to the
Douglas Gregor74661272010-09-21 00:03:25 +00006139 // selector), we're actually performing code completion for an expression.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006140 // Determine whether we have a single, best method. If so, we can
Douglas Gregor74661272010-09-21 00:03:25 +00006141 // code-complete the expression using the corresponding parameter type as
6142 // our preferred type, improving completion results.
6143 if (AtArgumentExpression) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006144 QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006145 SelIdents.size());
Douglas Gregor74661272010-09-21 00:03:25 +00006146 if (PreferredType.isNull())
6147 CodeCompleteOrdinaryName(S, PCC_Expression);
6148 else
6149 CodeCompleteExpression(S, PreferredType);
6150 return;
6151 }
6152
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006153 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor63745d52011-07-21 01:05:26 +00006154 Results.getCompletionContext(),
Douglas Gregor6fc04132010-08-27 15:10:57 +00006155 Results.data(), Results.size());
Steve Naroffeae65032009-11-07 02:08:14 +00006156}
6157
Richard Trieu2bd04012011-09-09 02:00:50 +00006158void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006159 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006160 bool AtArgumentExpression,
Douglas Gregor392a84b2010-10-13 21:24:53 +00006161 ObjCInterfaceDecl *Super) {
John McCall276321a2010-08-25 06:19:51 +00006162 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006163
Steve Naroffeae65032009-11-07 02:08:14 +00006164 Expr *RecExpr = static_cast<Expr *>(Receiver);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006165
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006166 // If necessary, apply function/array conversion to the receiver.
6167 // C99 6.7.5.3p[7,8].
John Wiegley01296292011-04-08 18:41:53 +00006168 if (RecExpr) {
6169 ExprResult Conv = DefaultFunctionArrayLvalueConversion(RecExpr);
6170 if (Conv.isInvalid()) // conversion failed. bail.
6171 return;
Nikola Smiljanic01a75982014-05-29 10:55:11 +00006172 RecExpr = Conv.get();
John Wiegley01296292011-04-08 18:41:53 +00006173 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006174 QualType ReceiverType = RecExpr? RecExpr->getType()
Douglas Gregor392a84b2010-10-13 21:24:53 +00006175 : Super? Context.getObjCObjectPointerType(
6176 Context.getObjCInterfaceType(Super))
6177 : Context.getObjCIdType();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006178
Douglas Gregordc520b02010-11-08 21:12:30 +00006179 // If we're messaging an expression with type "id" or "Class", check
6180 // whether we know something special about the receiver that allows
6181 // us to assume a more-specific receiver type.
Anders Carlsson382ba412014-02-28 19:07:22 +00006182 if (ReceiverType->isObjCIdType() || ReceiverType->isObjCClassType()) {
Douglas Gregordc520b02010-11-08 21:12:30 +00006183 if (ObjCInterfaceDecl *IFace = GetAssumedMessageSendExprType(RecExpr)) {
6184 if (ReceiverType->isObjCClassType())
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006185 return CodeCompleteObjCClassMessage(S,
Douglas Gregordc520b02010-11-08 21:12:30 +00006186 ParsedType::make(Context.getObjCInterfaceType(IFace)),
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006187 SelIdents,
Douglas Gregordc520b02010-11-08 21:12:30 +00006188 AtArgumentExpression, Super);
6189
6190 ReceiverType = Context.getObjCObjectPointerType(
6191 Context.getObjCInterfaceType(IFace));
6192 }
Anders Carlsson382ba412014-02-28 19:07:22 +00006193 } else if (RecExpr && getLangOpts().CPlusPlus) {
6194 ExprResult Conv = PerformContextuallyConvertToObjCPointer(RecExpr);
6195 if (Conv.isUsable()) {
Nikola Smiljanic01a75982014-05-29 10:55:11 +00006196 RecExpr = Conv.get();
Anders Carlsson382ba412014-02-28 19:07:22 +00006197 ReceiverType = RecExpr->getType();
6198 }
6199 }
Douglas Gregordc520b02010-11-08 21:12:30 +00006200
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006201 // Build the set of methods we can see.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006202 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006203 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor63745d52011-07-21 01:05:26 +00006204 CodeCompletionContext(CodeCompletionContext::CCC_ObjCInstanceMessage,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006205 ReceiverType, SelIdents));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006206
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006207 Results.EnterNewScope();
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006208
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006209 // If this is a send-to-super, try to add the special "super" send
Douglas Gregor6fc04132010-08-27 15:10:57 +00006210 // completion.
Douglas Gregor392a84b2010-10-13 21:24:53 +00006211 if (Super) {
Douglas Gregor6fc04132010-08-27 15:10:57 +00006212 if (ObjCMethodDecl *SuperMethod
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006213 = AddSuperSendCompletion(*this, false, SelIdents, Results))
Douglas Gregor6fc04132010-08-27 15:10:57 +00006214 Results.Ignore(SuperMethod);
6215 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006216
Douglas Gregorc2cb2e22010-08-27 15:29:55 +00006217 // If we're inside an Objective-C method definition, prefer its selector to
6218 // others.
6219 if (ObjCMethodDecl *CurMethod = getCurMethodDecl())
6220 Results.setPreferredSelector(CurMethod->getSelector());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006221
Douglas Gregor1154e272010-09-16 16:06:31 +00006222 // Keep track of the selectors we've already added.
6223 VisitedSelectorSet Selectors;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006224
Douglas Gregora3329fa2009-11-18 00:06:18 +00006225 // Handle messages to Class. This really isn't a message to an instance
6226 // method, so we treat it the same way we would treat a message send to a
6227 // class method.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006228 if (ReceiverType->isObjCClassType() ||
Douglas Gregora3329fa2009-11-18 00:06:18 +00006229 ReceiverType->isObjCQualifiedClassType()) {
6230 if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
6231 if (ObjCInterfaceDecl *ClassDecl = CurMethod->getClassInterface())
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006232 AddObjCMethods(ClassDecl, false, MK_Any, SelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00006233 CurContext, Selectors, AtArgumentExpression, Results);
Douglas Gregora3329fa2009-11-18 00:06:18 +00006234 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006235 }
Douglas Gregora3329fa2009-11-18 00:06:18 +00006236 // Handle messages to a qualified ID ("id<foo>").
6237 else if (const ObjCObjectPointerType *QualID
6238 = ReceiverType->getAsObjCQualifiedIdType()) {
6239 // Search protocols for instance methods.
Aaron Ballman83731462014-03-17 16:14:00 +00006240 for (auto *I : QualID->quals())
6241 AddObjCMethods(I, true, MK_Any, SelIdents, CurContext,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00006242 Selectors, AtArgumentExpression, Results);
Douglas Gregora3329fa2009-11-18 00:06:18 +00006243 }
6244 // Handle messages to a pointer to interface type.
6245 else if (const ObjCObjectPointerType *IFacePtr
6246 = ReceiverType->getAsObjCInterfacePointerType()) {
6247 // Search the class, its superclasses, etc., for instance methods.
Douglas Gregorc8537c52009-11-19 07:41:15 +00006248 AddObjCMethods(IFacePtr->getInterfaceDecl(), true, MK_Any, SelIdents,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006249 CurContext, Selectors, AtArgumentExpression,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00006250 Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006251
Douglas Gregora3329fa2009-11-18 00:06:18 +00006252 // Search protocols for instance methods.
Aaron Ballman83731462014-03-17 16:14:00 +00006253 for (auto *I : IFacePtr->quals())
6254 AddObjCMethods(I, true, MK_Any, SelIdents, CurContext,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00006255 Selectors, AtArgumentExpression, Results);
Douglas Gregora3329fa2009-11-18 00:06:18 +00006256 }
Douglas Gregor6285f752010-04-06 16:40:00 +00006257 // Handle messages to "id".
6258 else if (ReceiverType->isObjCIdType()) {
Douglas Gregord720daf2010-04-06 17:30:22 +00006259 // We're messaging "id", so provide all instance methods we know
6260 // about as code-completion results.
6261
6262 // If we have an external source, load the entire class method
Sebastian Redld44cd6a2010-08-18 23:57:06 +00006263 // pool from the AST file.
Douglas Gregord720daf2010-04-06 17:30:22 +00006264 if (ExternalSource) {
John McCall75b960e2010-06-01 09:23:16 +00006265 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
6266 I != N; ++I) {
6267 Selector Sel = ExternalSource->GetExternalSelector(I);
Sebastian Redl75d8a322010-08-02 23:18:59 +00006268 if (Sel.isNull() || MethodPool.count(Sel))
Douglas Gregord720daf2010-04-06 17:30:22 +00006269 continue;
6270
Sebastian Redl75d8a322010-08-02 23:18:59 +00006271 ReadMethodPool(Sel);
Douglas Gregord720daf2010-04-06 17:30:22 +00006272 }
6273 }
6274
Sebastian Redl75d8a322010-08-02 23:18:59 +00006275 for (GlobalMethodPool::iterator M = MethodPool.begin(),
6276 MEnd = MethodPool.end();
6277 M != MEnd; ++M) {
6278 for (ObjCMethodList *MethList = &M->second.first;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006279 MethList && MethList->getMethod();
Argyrios Kyrtzidisd3da6e02013-04-17 00:08:58 +00006280 MethList = MethList->getNext()) {
Nico Weber2e0c8f72014-12-27 03:58:08 +00006281 if (!isAcceptableObjCMethod(MethList->getMethod(), MK_Any, SelIdents))
Douglas Gregor6285f752010-04-06 16:40:00 +00006282 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006283
Nico Weber2e0c8f72014-12-27 03:58:08 +00006284 if (!Selectors.insert(MethList->getMethod()->getSelector()).second)
Douglas Gregor1154e272010-09-16 16:06:31 +00006285 continue;
Craig Topperc3ec1492014-05-26 06:22:03 +00006286
Nico Weber2e0c8f72014-12-27 03:58:08 +00006287 Result R(MethList->getMethod(),
6288 Results.getBasePriority(MethList->getMethod()), nullptr);
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006289 R.StartParameter = SelIdents.size();
Douglas Gregor6285f752010-04-06 16:40:00 +00006290 R.AllParametersAreInformative = false;
6291 Results.MaybeAddResult(R, CurContext);
6292 }
6293 }
6294 }
Steve Naroffeae65032009-11-07 02:08:14 +00006295 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006296
6297
6298 // If we're actually at the argument expression (rather than prior to the
Douglas Gregor74661272010-09-21 00:03:25 +00006299 // selector), we're actually performing code completion for an expression.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006300 // Determine whether we have a single, best method. If so, we can
Douglas Gregor74661272010-09-21 00:03:25 +00006301 // code-complete the expression using the corresponding parameter type as
6302 // our preferred type, improving completion results.
6303 if (AtArgumentExpression) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006304 QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006305 SelIdents.size());
Douglas Gregor74661272010-09-21 00:03:25 +00006306 if (PreferredType.isNull())
6307 CodeCompleteOrdinaryName(S, PCC_Expression);
6308 else
6309 CodeCompleteExpression(S, PreferredType);
6310 return;
6311 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006312
6313 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor63745d52011-07-21 01:05:26 +00006314 Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006315 Results.data(),Results.size());
Steve Naroffeae65032009-11-07 02:08:14 +00006316}
Douglas Gregorbaf69612009-11-18 04:19:12 +00006317
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006318void Sema::CodeCompleteObjCForCollection(Scope *S,
Douglas Gregor68762e72010-08-23 21:17:50 +00006319 DeclGroupPtrTy IterationVar) {
6320 CodeCompleteExpressionData Data;
6321 Data.ObjCCollection = true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006322
Douglas Gregor68762e72010-08-23 21:17:50 +00006323 if (IterationVar.getAsOpaquePtr()) {
Serge Pavlov9ddb76e2013-08-27 13:15:56 +00006324 DeclGroupRef DG = IterationVar.get();
Douglas Gregor68762e72010-08-23 21:17:50 +00006325 for (DeclGroupRef::iterator I = DG.begin(), End = DG.end(); I != End; ++I) {
6326 if (*I)
6327 Data.IgnoreDecls.push_back(*I);
6328 }
6329 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006330
Douglas Gregor68762e72010-08-23 21:17:50 +00006331 CodeCompleteExpression(S, Data);
6332}
6333
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006334void Sema::CodeCompleteObjCSelector(Scope *S,
6335 ArrayRef<IdentifierInfo *> SelIdents) {
Douglas Gregor67c692c2010-08-26 15:07:07 +00006336 // If we have an external source, load the entire class method
6337 // pool from the AST file.
6338 if (ExternalSource) {
6339 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
6340 I != N; ++I) {
6341 Selector Sel = ExternalSource->GetExternalSelector(I);
6342 if (Sel.isNull() || MethodPool.count(Sel))
6343 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006344
Douglas Gregor67c692c2010-08-26 15:07:07 +00006345 ReadMethodPool(Sel);
6346 }
6347 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006348
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006349 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006350 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006351 CodeCompletionContext::CCC_SelectorName);
Douglas Gregor67c692c2010-08-26 15:07:07 +00006352 Results.EnterNewScope();
6353 for (GlobalMethodPool::iterator M = MethodPool.begin(),
6354 MEnd = MethodPool.end();
6355 M != MEnd; ++M) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006356
Douglas Gregor67c692c2010-08-26 15:07:07 +00006357 Selector Sel = M->first;
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006358 if (!isAcceptableObjCSelector(Sel, MK_Any, SelIdents))
Douglas Gregor67c692c2010-08-26 15:07:07 +00006359 continue;
6360
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006361 CodeCompletionBuilder Builder(Results.getAllocator(),
6362 Results.getCodeCompletionTUInfo());
Douglas Gregor67c692c2010-08-26 15:07:07 +00006363 if (Sel.isUnarySelector()) {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00006364 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00006365 Sel.getNameForSlot(0)));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006366 Results.AddResult(Builder.TakeString());
Douglas Gregor67c692c2010-08-26 15:07:07 +00006367 continue;
6368 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006369
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00006370 std::string Accumulator;
Douglas Gregor67c692c2010-08-26 15:07:07 +00006371 for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I) {
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006372 if (I == SelIdents.size()) {
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00006373 if (!Accumulator.empty()) {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00006374 Builder.AddInformativeChunk(Builder.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006375 Accumulator));
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00006376 Accumulator.clear();
6377 }
6378 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006379
Benjamin Kramer632500c2011-07-26 16:59:25 +00006380 Accumulator += Sel.getNameForSlot(I);
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00006381 Accumulator += ':';
Douglas Gregor67c692c2010-08-26 15:07:07 +00006382 }
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00006383 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString( Accumulator));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006384 Results.AddResult(Builder.TakeString());
Douglas Gregor67c692c2010-08-26 15:07:07 +00006385 }
6386 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00006387
6388 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor67c692c2010-08-26 15:07:07 +00006389 Results.data(), Results.size());
6390}
6391
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006392/// Add all of the protocol declarations that we find in the given
Douglas Gregorbaf69612009-11-18 04:19:12 +00006393/// (translation unit) context.
6394static void AddProtocolResults(DeclContext *Ctx, DeclContext *CurContext,
Douglas Gregor5b4671c2009-11-18 04:49:41 +00006395 bool OnlyForwardDeclarations,
Douglas Gregorbaf69612009-11-18 04:19:12 +00006396 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00006397 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006398
Aaron Ballman629afae2014-03-07 19:56:05 +00006399 for (const auto *D : Ctx->decls()) {
Douglas Gregorbaf69612009-11-18 04:19:12 +00006400 // Record any protocols we find.
Aaron Ballman629afae2014-03-07 19:56:05 +00006401 if (const auto *Proto = dyn_cast<ObjCProtocolDecl>(D))
Douglas Gregore6e48b12012-01-01 19:29:29 +00006402 if (!OnlyForwardDeclarations || !Proto->hasDefinition())
Craig Topperc3ec1492014-05-26 06:22:03 +00006403 Results.AddResult(Result(Proto, Results.getBasePriority(Proto),nullptr),
6404 CurContext, nullptr, false);
Douglas Gregorbaf69612009-11-18 04:19:12 +00006405 }
6406}
6407
Craig Topper883dd332015-12-24 23:58:11 +00006408void Sema::CodeCompleteObjCProtocolReferences(
6409 ArrayRef<IdentifierLocPair> Protocols) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006410 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006411 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006412 CodeCompletionContext::CCC_ObjCProtocolName);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006413
Chandler Carruthede11632016-11-04 06:06:50 +00006414 if (CodeCompleter->includeGlobals()) {
Douglas Gregora3b23b02010-12-09 21:44:02 +00006415 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006416
Douglas Gregora3b23b02010-12-09 21:44:02 +00006417 // Tell the result set to ignore all of the protocols we have
6418 // already seen.
6419 // FIXME: This doesn't work when caching code-completion results.
Craig Topper883dd332015-12-24 23:58:11 +00006420 for (const IdentifierLocPair &Pair : Protocols)
6421 if (ObjCProtocolDecl *Protocol = LookupProtocol(Pair.first,
6422 Pair.second))
Douglas Gregora3b23b02010-12-09 21:44:02 +00006423 Results.Ignore(Protocol);
Douglas Gregorbaf69612009-11-18 04:19:12 +00006424
Douglas Gregora3b23b02010-12-09 21:44:02 +00006425 // Add all protocols.
6426 AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, false,
6427 Results);
Douglas Gregor5b4671c2009-11-18 04:49:41 +00006428
Douglas Gregora3b23b02010-12-09 21:44:02 +00006429 Results.ExitScope();
6430 }
Eric Liuf5ba09f2018-07-04 10:01:18 +00006431
6432 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6433 Results.data(), Results.size());
Douglas Gregor5b4671c2009-11-18 04:49:41 +00006434}
6435
6436void Sema::CodeCompleteObjCProtocolDecl(Scope *) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006437 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006438 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006439 CodeCompletionContext::CCC_ObjCProtocolName);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006440
Chandler Carruthede11632016-11-04 06:06:50 +00006441 if (CodeCompleter->includeGlobals()) {
Douglas Gregora3b23b02010-12-09 21:44:02 +00006442 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006443
Douglas Gregora3b23b02010-12-09 21:44:02 +00006444 // Add all protocols.
6445 AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, true,
6446 Results);
Douglas Gregorbaf69612009-11-18 04:19:12 +00006447
Douglas Gregora3b23b02010-12-09 21:44:02 +00006448 Results.ExitScope();
6449 }
Eric Liuf5ba09f2018-07-04 10:01:18 +00006450
6451 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6452 Results.data(), Results.size());
Douglas Gregorbaf69612009-11-18 04:19:12 +00006453}
Douglas Gregor49c22a72009-11-18 16:26:39 +00006454
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006455/// Add all of the Objective-C interface declarations that we find in
Douglas Gregor49c22a72009-11-18 16:26:39 +00006456/// the given (translation unit) context.
6457static void AddInterfaceResults(DeclContext *Ctx, DeclContext *CurContext,
6458 bool OnlyForwardDeclarations,
6459 bool OnlyUnimplemented,
6460 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00006461 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006462
Aaron Ballman629afae2014-03-07 19:56:05 +00006463 for (const auto *D : Ctx->decls()) {
Douglas Gregor1c283312010-08-11 12:19:30 +00006464 // Record any interfaces we find.
Aaron Ballman629afae2014-03-07 19:56:05 +00006465 if (const auto *Class = dyn_cast<ObjCInterfaceDecl>(D))
Douglas Gregordc9166c2011-12-15 20:29:51 +00006466 if ((!OnlyForwardDeclarations || !Class->hasDefinition()) &&
Douglas Gregor1c283312010-08-11 12:19:30 +00006467 (!OnlyUnimplemented || !Class->getImplementation()))
Craig Topperc3ec1492014-05-26 06:22:03 +00006468 Results.AddResult(Result(Class, Results.getBasePriority(Class),nullptr),
6469 CurContext, nullptr, false);
Douglas Gregor49c22a72009-11-18 16:26:39 +00006470 }
6471}
6472
Eric Liuf5ba09f2018-07-04 10:01:18 +00006473void Sema::CodeCompleteObjCInterfaceDecl(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006474 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006475 CodeCompleter->getCodeCompletionTUInfo(),
Eric Liuf5ba09f2018-07-04 10:01:18 +00006476 CodeCompletionContext::CCC_ObjCInterfaceName);
Douglas Gregor49c22a72009-11-18 16:26:39 +00006477 Results.EnterNewScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00006478
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006479 if (CodeCompleter->includeGlobals()) {
6480 // Add all classes.
6481 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
6482 false, Results);
6483 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006484
Douglas Gregor49c22a72009-11-18 16:26:39 +00006485 Results.ExitScope();
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006486
Eric Liuf5ba09f2018-07-04 10:01:18 +00006487 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6488 Results.data(), Results.size());
Douglas Gregor49c22a72009-11-18 16:26:39 +00006489}
6490
Douglas Gregorb2ccf012010-04-15 22:33:43 +00006491void Sema::CodeCompleteObjCSuperclass(Scope *S, IdentifierInfo *ClassName,
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006492 SourceLocation ClassNameLoc) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006493 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006494 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006495 CodeCompletionContext::CCC_ObjCInterfaceName);
Douglas Gregor49c22a72009-11-18 16:26:39 +00006496 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006497
Douglas Gregor49c22a72009-11-18 16:26:39 +00006498 // Make sure that we ignore the class we're currently defining.
6499 NamedDecl *CurClass
Douglas Gregorb2ccf012010-04-15 22:33:43 +00006500 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006501 if (CurClass && isa<ObjCInterfaceDecl>(CurClass))
Douglas Gregor49c22a72009-11-18 16:26:39 +00006502 Results.Ignore(CurClass);
6503
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006504 if (CodeCompleter->includeGlobals()) {
6505 // Add all classes.
6506 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
6507 false, Results);
6508 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006509
Douglas Gregor49c22a72009-11-18 16:26:39 +00006510 Results.ExitScope();
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006511
Eric Liuf5ba09f2018-07-04 10:01:18 +00006512 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6513 Results.data(), Results.size());
Douglas Gregor49c22a72009-11-18 16:26:39 +00006514}
6515
Eric Liuf5ba09f2018-07-04 10:01:18 +00006516void Sema::CodeCompleteObjCImplementationDecl(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006517 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006518 CodeCompleter->getCodeCompletionTUInfo(),
Eric Liuf5ba09f2018-07-04 10:01:18 +00006519 CodeCompletionContext::CCC_ObjCImplementation);
Douglas Gregor49c22a72009-11-18 16:26:39 +00006520 Results.EnterNewScope();
6521
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006522 if (CodeCompleter->includeGlobals()) {
6523 // Add all unimplemented classes.
6524 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
6525 true, Results);
6526 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006527
Douglas Gregor49c22a72009-11-18 16:26:39 +00006528 Results.ExitScope();
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006529
Eric Liuf5ba09f2018-07-04 10:01:18 +00006530 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6531 Results.data(), Results.size());
Douglas Gregor49c22a72009-11-18 16:26:39 +00006532}
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006533
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006534void Sema::CodeCompleteObjCInterfaceCategory(Scope *S,
Douglas Gregorb2ccf012010-04-15 22:33:43 +00006535 IdentifierInfo *ClassName,
6536 SourceLocation ClassNameLoc) {
John McCall276321a2010-08-25 06:19:51 +00006537 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006538
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006539 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006540 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor21325842011-07-07 16:03:39 +00006541 CodeCompletionContext::CCC_ObjCCategoryName);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006542
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006543 // Ignore any categories we find that have already been implemented by this
6544 // interface.
6545 llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
6546 NamedDecl *CurClass
Douglas Gregorb2ccf012010-04-15 22:33:43 +00006547 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006548 if (ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass)){
Aaron Ballman3fe486a2014-03-13 21:23:55 +00006549 for (const auto *Cat : Class->visible_categories())
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006550 CategoryNames.insert(Cat->getIdentifier());
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006551 }
6552
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006553 // Add all of the categories we know about.
6554 Results.EnterNewScope();
6555 TranslationUnitDecl *TU = Context.getTranslationUnitDecl();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006556 for (const auto *D : TU->decls())
Aaron Ballman629afae2014-03-07 19:56:05 +00006557 if (const auto *Category = dyn_cast<ObjCCategoryDecl>(D))
David Blaikie82e95a32014-11-19 07:49:47 +00006558 if (CategoryNames.insert(Category->getIdentifier()).second)
Craig Topperc3ec1492014-05-26 06:22:03 +00006559 Results.AddResult(Result(Category, Results.getBasePriority(Category),
6560 nullptr),
6561 CurContext, nullptr, false);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006562 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00006563
6564 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6565 Results.data(), Results.size());
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006566}
6567
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006568void Sema::CodeCompleteObjCImplementationCategory(Scope *S,
Douglas Gregorb2ccf012010-04-15 22:33:43 +00006569 IdentifierInfo *ClassName,
6570 SourceLocation ClassNameLoc) {
John McCall276321a2010-08-25 06:19:51 +00006571 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006572
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006573 // Find the corresponding interface. If we couldn't find the interface, the
6574 // program itself is ill-formed. However, we'll try to be helpful still by
6575 // providing the list of all of the categories we know about.
6576 NamedDecl *CurClass
Douglas Gregorb2ccf012010-04-15 22:33:43 +00006577 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006578 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass);
6579 if (!Class)
Douglas Gregorb2ccf012010-04-15 22:33:43 +00006580 return CodeCompleteObjCInterfaceCategory(S, ClassName, ClassNameLoc);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006581
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006582 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006583 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor21325842011-07-07 16:03:39 +00006584 CodeCompletionContext::CCC_ObjCCategoryName);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006585
6586 // Add all of the categories that have have corresponding interface
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006587 // declarations in this class and any of its superclasses, except for
6588 // already-implemented categories in the class itself.
6589 llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
6590 Results.EnterNewScope();
6591 bool IgnoreImplemented = true;
6592 while (Class) {
Aaron Ballman3fe486a2014-03-13 21:23:55 +00006593 for (const auto *Cat : Class->visible_categories()) {
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006594 if ((!IgnoreImplemented || !Cat->getImplementation()) &&
David Blaikie82e95a32014-11-19 07:49:47 +00006595 CategoryNames.insert(Cat->getIdentifier()).second)
Craig Topperc3ec1492014-05-26 06:22:03 +00006596 Results.AddResult(Result(Cat, Results.getBasePriority(Cat), nullptr),
6597 CurContext, nullptr, false);
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006598 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006599
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006600 Class = Class->getSuperClass();
6601 IgnoreImplemented = false;
6602 }
6603 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00006604
6605 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6606 Results.data(), Results.size());
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006607}
Douglas Gregor5d649882009-11-18 22:32:06 +00006608
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00006609void Sema::CodeCompleteObjCPropertyDefinition(Scope *S) {
Douglas Gregorc3425b12015-07-07 06:20:19 +00006610 CodeCompletionContext CCContext(CodeCompletionContext::CCC_Other);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006611 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006612 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorc3425b12015-07-07 06:20:19 +00006613 CCContext);
Douglas Gregor5d649882009-11-18 22:32:06 +00006614
6615 // Figure out where this @synthesize lives.
6616 ObjCContainerDecl *Container
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00006617 = dyn_cast_or_null<ObjCContainerDecl>(CurContext);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006618 if (!Container ||
6619 (!isa<ObjCImplementationDecl>(Container) &&
Douglas Gregor5d649882009-11-18 22:32:06 +00006620 !isa<ObjCCategoryImplDecl>(Container)))
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006621 return;
Douglas Gregor5d649882009-11-18 22:32:06 +00006622
6623 // Ignore any properties that have already been implemented.
Douglas Gregor9b4f3702012-06-12 13:44:08 +00006624 Container = getContainerDef(Container);
Aaron Ballman629afae2014-03-07 19:56:05 +00006625 for (const auto *D : Container->decls())
6626 if (const auto *PropertyImpl = dyn_cast<ObjCPropertyImplDecl>(D))
Douglas Gregor5d649882009-11-18 22:32:06 +00006627 Results.Ignore(PropertyImpl->getPropertyDecl());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006628
Douglas Gregor5d649882009-11-18 22:32:06 +00006629 // Add any properties that we find.
Douglas Gregorb888acf2010-12-09 23:01:55 +00006630 AddedPropertiesSet AddedProperties;
Douglas Gregor5d649882009-11-18 22:32:06 +00006631 Results.EnterNewScope();
6632 if (ObjCImplementationDecl *ClassImpl
6633 = dyn_cast<ObjCImplementationDecl>(Container))
Douglas Gregorc3425b12015-07-07 06:20:19 +00006634 AddObjCProperties(CCContext, ClassImpl->getClassInterface(), false,
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006635 /*AllowNullaryMethods=*/false, CurContext,
Douglas Gregorb888acf2010-12-09 23:01:55 +00006636 AddedProperties, Results);
Douglas Gregor5d649882009-11-18 22:32:06 +00006637 else
Douglas Gregorc3425b12015-07-07 06:20:19 +00006638 AddObjCProperties(CCContext,
6639 cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl(),
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006640 false, /*AllowNullaryMethods=*/false, CurContext,
Douglas Gregor95147142011-05-05 15:50:42 +00006641 AddedProperties, Results);
Douglas Gregor5d649882009-11-18 22:32:06 +00006642 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00006643
6644 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6645 Results.data(), Results.size());
Douglas Gregor5d649882009-11-18 22:32:06 +00006646}
6647
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006648void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S,
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00006649 IdentifierInfo *PropertyName) {
John McCall276321a2010-08-25 06:19:51 +00006650 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006651 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006652 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006653 CodeCompletionContext::CCC_Other);
Douglas Gregor5d649882009-11-18 22:32:06 +00006654
6655 // Figure out where this @synthesize lives.
6656 ObjCContainerDecl *Container
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00006657 = dyn_cast_or_null<ObjCContainerDecl>(CurContext);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006658 if (!Container ||
6659 (!isa<ObjCImplementationDecl>(Container) &&
Douglas Gregor5d649882009-11-18 22:32:06 +00006660 !isa<ObjCCategoryImplDecl>(Container)))
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006661 return;
6662
Douglas Gregor5d649882009-11-18 22:32:06 +00006663 // Figure out which interface we're looking into.
Craig Topperc3ec1492014-05-26 06:22:03 +00006664 ObjCInterfaceDecl *Class = nullptr;
Douglas Gregor5d649882009-11-18 22:32:06 +00006665 if (ObjCImplementationDecl *ClassImpl
Manman Ren5b786402016-01-28 18:49:28 +00006666 = dyn_cast<ObjCImplementationDecl>(Container))
Douglas Gregor5d649882009-11-18 22:32:06 +00006667 Class = ClassImpl->getClassInterface();
6668 else
6669 Class = cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl()
6670 ->getClassInterface();
6671
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006672 // Determine the type of the property we're synthesizing.
6673 QualType PropertyType = Context.getObjCIdType();
6674 if (Class) {
Manman Ren5b786402016-01-28 18:49:28 +00006675 if (ObjCPropertyDecl *Property = Class->FindPropertyDeclaration(
6676 PropertyName, ObjCPropertyQueryKind::OBJC_PR_query_instance)) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006677 PropertyType
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006678 = Property->getType().getNonReferenceType().getUnqualifiedType();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006679
6680 // Give preference to ivars
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006681 Results.setPreferredType(PropertyType);
6682 }
6683 }
6684
Douglas Gregor5d649882009-11-18 22:32:06 +00006685 // Add all of the instance variables in this class and its superclasses.
6686 Results.EnterNewScope();
Douglas Gregor331faa02011-04-18 14:13:53 +00006687 bool SawSimilarlyNamedIvar = false;
6688 std::string NameWithPrefix;
6689 NameWithPrefix += '_';
Benjamin Kramer632500c2011-07-26 16:59:25 +00006690 NameWithPrefix += PropertyName->getName();
Douglas Gregor331faa02011-04-18 14:13:53 +00006691 std::string NameWithSuffix = PropertyName->getName().str();
6692 NameWithSuffix += '_';
Douglas Gregor5d649882009-11-18 22:32:06 +00006693 for(; Class; Class = Class->getSuperClass()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006694 for (ObjCIvarDecl *Ivar = Class->all_declared_ivar_begin(); Ivar;
Douglas Gregor331faa02011-04-18 14:13:53 +00006695 Ivar = Ivar->getNextIvar()) {
Craig Topperc3ec1492014-05-26 06:22:03 +00006696 Results.AddResult(Result(Ivar, Results.getBasePriority(Ivar), nullptr),
6697 CurContext, nullptr, false);
6698
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006699 // Determine whether we've seen an ivar with a name similar to the
Douglas Gregor331faa02011-04-18 14:13:53 +00006700 // property.
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006701 if ((PropertyName == Ivar->getIdentifier() ||
Douglas Gregor331faa02011-04-18 14:13:53 +00006702 NameWithPrefix == Ivar->getName() ||
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006703 NameWithSuffix == Ivar->getName())) {
Douglas Gregor331faa02011-04-18 14:13:53 +00006704 SawSimilarlyNamedIvar = true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006705
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006706 // Reduce the priority of this result by one, to give it a slight
6707 // advantage over other results whose names don't match so closely.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006708 if (Results.size() &&
6709 Results.data()[Results.size() - 1].Kind
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006710 == CodeCompletionResult::RK_Declaration &&
6711 Results.data()[Results.size() - 1].Declaration == Ivar)
6712 Results.data()[Results.size() - 1].Priority--;
6713 }
Douglas Gregor331faa02011-04-18 14:13:53 +00006714 }
Douglas Gregor5d649882009-11-18 22:32:06 +00006715 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006716
Douglas Gregor331faa02011-04-18 14:13:53 +00006717 if (!SawSimilarlyNamedIvar) {
6718 // Create ivar result _propName, that the user can use to synthesize
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006719 // an ivar of the appropriate type.
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006720 unsigned Priority = CCP_MemberDeclaration + 1;
Douglas Gregor331faa02011-04-18 14:13:53 +00006721 typedef CodeCompletionResult Result;
6722 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006723 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo(),
6724 Priority,CXAvailability_Available);
Douglas Gregor331faa02011-04-18 14:13:53 +00006725
Douglas Gregor75acd922011-09-27 23:30:47 +00006726 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006727 Builder.AddResultTypeChunk(GetCompletionTypeString(PropertyType, Context,
Douglas Gregor75acd922011-09-27 23:30:47 +00006728 Policy, Allocator));
Douglas Gregor331faa02011-04-18 14:13:53 +00006729 Builder.AddTypedTextChunk(Allocator.CopyString(NameWithPrefix));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006730 Results.AddResult(Result(Builder.TakeString(), Priority,
Douglas Gregor331faa02011-04-18 14:13:53 +00006731 CXCursor_ObjCIvarDecl));
6732 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006733
Douglas Gregor5d649882009-11-18 22:32:06 +00006734 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00006735
6736 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6737 Results.data(), Results.size());
Douglas Gregor5d649882009-11-18 22:32:06 +00006738}
Douglas Gregor636a61e2010-04-07 00:21:17 +00006739
Douglas Gregor416b5752010-08-25 01:08:01 +00006740// Mapping from selectors to the methods that implement that selector, along
6741// with the "in original class" flag.
Benjamin Kramereb8c4462013-06-29 17:52:13 +00006742typedef llvm::DenseMap<
6743 Selector, llvm::PointerIntPair<ObjCMethodDecl *, 1, bool> > KnownMethodsMap;
Douglas Gregor636a61e2010-04-07 00:21:17 +00006744
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006745/// Find all of the methods that reside in the given container
Douglas Gregor636a61e2010-04-07 00:21:17 +00006746/// (and its superclasses, protocols, etc.) that meet the given
6747/// criteria. Insert those methods into the map of known methods,
6748/// indexed by selector so they can be easily found.
6749static void FindImplementableMethods(ASTContext &Context,
6750 ObjCContainerDecl *Container,
Alex Lorenzb8740422017-10-24 16:39:37 +00006751 Optional<bool> WantInstanceMethods,
Douglas Gregor636a61e2010-04-07 00:21:17 +00006752 QualType ReturnType,
Douglas Gregor416b5752010-08-25 01:08:01 +00006753 KnownMethodsMap &KnownMethods,
6754 bool InOriginalClass = true) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00006755 if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)) {
Douglas Gregor9b4f3702012-06-12 13:44:08 +00006756 // Make sure we have a definition; that's what we'll walk.
Douglas Gregorc0ac7d62011-12-15 05:27:12 +00006757 if (!IFace->hasDefinition())
6758 return;
Douglas Gregor9b4f3702012-06-12 13:44:08 +00006759
6760 IFace = IFace->getDefinition();
6761 Container = IFace;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006762
Douglas Gregor636a61e2010-04-07 00:21:17 +00006763 const ObjCList<ObjCProtocolDecl> &Protocols
6764 = IFace->getReferencedProtocols();
6765 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006766 E = Protocols.end();
Douglas Gregor636a61e2010-04-07 00:21:17 +00006767 I != E; ++I)
6768 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006769 KnownMethods, InOriginalClass);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006770
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006771 // Add methods from any class extensions and categories.
Aaron Ballman3fe486a2014-03-13 21:23:55 +00006772 for (auto *Cat : IFace->visible_categories()) {
6773 FindImplementableMethods(Context, Cat, WantInstanceMethods, ReturnType,
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006774 KnownMethods, false);
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006775 }
6776
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006777 // Visit the superclass.
6778 if (IFace->getSuperClass())
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006779 FindImplementableMethods(Context, IFace->getSuperClass(),
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006780 WantInstanceMethods, ReturnType,
6781 KnownMethods, false);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006782 }
6783
6784 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(Container)) {
6785 // Recurse into protocols.
6786 const ObjCList<ObjCProtocolDecl> &Protocols
6787 = Category->getReferencedProtocols();
6788 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006789 E = Protocols.end();
Douglas Gregor636a61e2010-04-07 00:21:17 +00006790 I != E; ++I)
6791 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006792 KnownMethods, InOriginalClass);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006793
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006794 // If this category is the original class, jump to the interface.
6795 if (InOriginalClass && Category->getClassInterface())
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006796 FindImplementableMethods(Context, Category->getClassInterface(),
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006797 WantInstanceMethods, ReturnType, KnownMethods,
6798 false);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006799 }
6800
6801 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Douglas Gregor9b4f3702012-06-12 13:44:08 +00006802 // Make sure we have a definition; that's what we'll walk.
6803 if (!Protocol->hasDefinition())
6804 return;
6805 Protocol = Protocol->getDefinition();
6806 Container = Protocol;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006807
Douglas Gregor9b4f3702012-06-12 13:44:08 +00006808 // Recurse into protocols.
6809 const ObjCList<ObjCProtocolDecl> &Protocols
6810 = Protocol->getReferencedProtocols();
6811 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006812 E = Protocols.end();
Douglas Gregor9b4f3702012-06-12 13:44:08 +00006813 I != E; ++I)
6814 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
6815 KnownMethods, false);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006816 }
6817
6818 // Add methods in this container. This operation occurs last because
6819 // we want the methods from this container to override any methods
6820 // we've previously seen with the same selector.
Aaron Ballmanaff18c02014-03-13 19:03:34 +00006821 for (auto *M : Container->methods()) {
Alex Lorenzb8740422017-10-24 16:39:37 +00006822 if (!WantInstanceMethods || M->isInstanceMethod() == *WantInstanceMethods) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00006823 if (!ReturnType.isNull() &&
Alp Toker314cc812014-01-25 16:55:45 +00006824 !Context.hasSameUnqualifiedType(ReturnType, M->getReturnType()))
Douglas Gregor636a61e2010-04-07 00:21:17 +00006825 continue;
6826
Benjamin Kramereb8c4462013-06-29 17:52:13 +00006827 KnownMethods[M->getSelector()] =
Aaron Ballmanaff18c02014-03-13 19:03:34 +00006828 KnownMethodsMap::mapped_type(M, InOriginalClass);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006829 }
6830 }
6831}
6832
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006833/// Add the parenthesized return or parameter type chunk to a code
Douglas Gregor669a25a2011-02-17 00:22:45 +00006834/// completion string.
6835static void AddObjCPassingTypeChunk(QualType Type,
Douglas Gregor29979142012-04-10 18:35:07 +00006836 unsigned ObjCDeclQuals,
Douglas Gregor669a25a2011-02-17 00:22:45 +00006837 ASTContext &Context,
Douglas Gregor75acd922011-09-27 23:30:47 +00006838 const PrintingPolicy &Policy,
Douglas Gregor669a25a2011-02-17 00:22:45 +00006839 CodeCompletionBuilder &Builder) {
6840 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregor86b42682015-06-19 18:27:52 +00006841 std::string Quals = formatObjCParamQualifiers(ObjCDeclQuals, Type);
Douglas Gregor29979142012-04-10 18:35:07 +00006842 if (!Quals.empty())
6843 Builder.AddTextChunk(Builder.getAllocator().CopyString(Quals));
Douglas Gregor75acd922011-09-27 23:30:47 +00006844 Builder.AddTextChunk(GetCompletionTypeString(Type, Context, Policy,
Douglas Gregor669a25a2011-02-17 00:22:45 +00006845 Builder.getAllocator()));
6846 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6847}
6848
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006849/// Determine whether the given class is or inherits from a class by
Douglas Gregor669a25a2011-02-17 00:22:45 +00006850/// the given name.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006851static bool InheritsFromClassNamed(ObjCInterfaceDecl *Class,
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006852 StringRef Name) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006853 if (!Class)
6854 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006855
Douglas Gregor669a25a2011-02-17 00:22:45 +00006856 if (Class->getIdentifier() && Class->getIdentifier()->getName() == Name)
6857 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006858
Douglas Gregor669a25a2011-02-17 00:22:45 +00006859 return InheritsFromClassNamed(Class->getSuperClass(), Name);
6860}
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006861
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006862/// Add code completions for Objective-C Key-Value Coding (KVC) and
Douglas Gregor669a25a2011-02-17 00:22:45 +00006863/// Key-Value Observing (KVO).
6864static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
6865 bool IsInstanceMethod,
6866 QualType ReturnType,
6867 ASTContext &Context,
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006868 VisitedSelectorSet &KnownSelectors,
Douglas Gregor669a25a2011-02-17 00:22:45 +00006869 ResultBuilder &Results) {
6870 IdentifierInfo *PropName = Property->getIdentifier();
6871 if (!PropName || PropName->getLength() == 0)
6872 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006873
Douglas Gregor75acd922011-09-27 23:30:47 +00006874 PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema());
6875
Douglas Gregor669a25a2011-02-17 00:22:45 +00006876 // Builder that will create each code completion.
6877 typedef CodeCompletionResult Result;
6878 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006879 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006880
Douglas Gregor669a25a2011-02-17 00:22:45 +00006881 // The selector table.
6882 SelectorTable &Selectors = Context.Selectors;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006883
Douglas Gregor669a25a2011-02-17 00:22:45 +00006884 // The property name, copied into the code completion allocation region
6885 // on demand.
6886 struct KeyHolder {
6887 CodeCompletionAllocator &Allocator;
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006888 StringRef Key;
Douglas Gregor669a25a2011-02-17 00:22:45 +00006889 const char *CopiedKey;
Craig Topperc3ec1492014-05-26 06:22:03 +00006890
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006891 KeyHolder(CodeCompletionAllocator &Allocator, StringRef Key)
Craig Topperc3ec1492014-05-26 06:22:03 +00006892 : Allocator(Allocator), Key(Key), CopiedKey(nullptr) {}
6893
Douglas Gregor669a25a2011-02-17 00:22:45 +00006894 operator const char *() {
6895 if (CopiedKey)
6896 return CopiedKey;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006897
Douglas Gregor669a25a2011-02-17 00:22:45 +00006898 return CopiedKey = Allocator.CopyString(Key);
6899 }
6900 } Key(Allocator, PropName->getName());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006901
Douglas Gregor669a25a2011-02-17 00:22:45 +00006902 // The uppercased name of the property name.
6903 std::string UpperKey = PropName->getName();
6904 if (!UpperKey.empty())
Jordan Rose4938f272013-02-09 10:09:43 +00006905 UpperKey[0] = toUppercase(UpperKey[0]);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006906
Douglas Gregor669a25a2011-02-17 00:22:45 +00006907 bool ReturnTypeMatchesProperty = ReturnType.isNull() ||
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006908 Context.hasSameUnqualifiedType(ReturnType.getNonReferenceType(),
Douglas Gregor669a25a2011-02-17 00:22:45 +00006909 Property->getType());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006910 bool ReturnTypeMatchesVoid
Douglas Gregor669a25a2011-02-17 00:22:45 +00006911 = ReturnType.isNull() || ReturnType->isVoidType();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006912
Douglas Gregor669a25a2011-02-17 00:22:45 +00006913 // Add the normal accessor -(type)key.
6914 if (IsInstanceMethod &&
David Blaikie82e95a32014-11-19 07:49:47 +00006915 KnownSelectors.insert(Selectors.getNullarySelector(PropName)).second &&
Douglas Gregor669a25a2011-02-17 00:22:45 +00006916 ReturnTypeMatchesProperty && !Property->getGetterMethodDecl()) {
6917 if (ReturnType.isNull())
Douglas Gregor29979142012-04-10 18:35:07 +00006918 AddObjCPassingTypeChunk(Property->getType(), /*Quals=*/0,
6919 Context, Policy, Builder);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006920
Douglas Gregor669a25a2011-02-17 00:22:45 +00006921 Builder.AddTypedTextChunk(Key);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006922 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Douglas Gregor669a25a2011-02-17 00:22:45 +00006923 CXCursor_ObjCInstanceMethodDecl));
6924 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006925
Douglas Gregor669a25a2011-02-17 00:22:45 +00006926 // If we have an integral or boolean property (or the user has provided
6927 // an integral or boolean return type), add the accessor -(type)isKey.
6928 if (IsInstanceMethod &&
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006929 ((!ReturnType.isNull() &&
Douglas Gregor669a25a2011-02-17 00:22:45 +00006930 (ReturnType->isIntegerType() || ReturnType->isBooleanType())) ||
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006931 (ReturnType.isNull() &&
6932 (Property->getType()->isIntegerType() ||
Douglas Gregor669a25a2011-02-17 00:22:45 +00006933 Property->getType()->isBooleanType())))) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006934 std::string SelectorName = (Twine("is") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006935 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00006936 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
6937 .second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006938 if (ReturnType.isNull()) {
6939 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6940 Builder.AddTextChunk("BOOL");
6941 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6942 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006943
Douglas Gregor669a25a2011-02-17 00:22:45 +00006944 Builder.AddTypedTextChunk(
6945 Allocator.CopyString(SelectorId->getName()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006946 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Douglas Gregor669a25a2011-02-17 00:22:45 +00006947 CXCursor_ObjCInstanceMethodDecl));
6948 }
6949 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006950
Douglas Gregor669a25a2011-02-17 00:22:45 +00006951 // Add the normal mutator.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006952 if (IsInstanceMethod && ReturnTypeMatchesVoid &&
Douglas Gregor669a25a2011-02-17 00:22:45 +00006953 !Property->getSetterMethodDecl()) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006954 std::string SelectorName = (Twine("set") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006955 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00006956 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006957 if (ReturnType.isNull()) {
6958 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6959 Builder.AddTextChunk("void");
6960 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6961 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006962
Douglas Gregor669a25a2011-02-17 00:22:45 +00006963 Builder.AddTypedTextChunk(
6964 Allocator.CopyString(SelectorId->getName()));
6965 Builder.AddTypedTextChunk(":");
Douglas Gregor29979142012-04-10 18:35:07 +00006966 AddObjCPassingTypeChunk(Property->getType(), /*Quals=*/0,
6967 Context, Policy, Builder);
Douglas Gregor669a25a2011-02-17 00:22:45 +00006968 Builder.AddTextChunk(Key);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006969 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Douglas Gregor669a25a2011-02-17 00:22:45 +00006970 CXCursor_ObjCInstanceMethodDecl));
6971 }
6972 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006973
Douglas Gregor669a25a2011-02-17 00:22:45 +00006974 // Indexed and unordered accessors
6975 unsigned IndexedGetterPriority = CCP_CodePattern;
6976 unsigned IndexedSetterPriority = CCP_CodePattern;
6977 unsigned UnorderedGetterPriority = CCP_CodePattern;
6978 unsigned UnorderedSetterPriority = CCP_CodePattern;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006979 if (const ObjCObjectPointerType *ObjCPointer
Douglas Gregor669a25a2011-02-17 00:22:45 +00006980 = Property->getType()->getAs<ObjCObjectPointerType>()) {
6981 if (ObjCInterfaceDecl *IFace = ObjCPointer->getInterfaceDecl()) {
6982 // If this interface type is not provably derived from a known
6983 // collection, penalize the corresponding completions.
6984 if (!InheritsFromClassNamed(IFace, "NSMutableArray")) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006985 IndexedSetterPriority += CCD_ProbablyNotObjCCollection;
Douglas Gregor669a25a2011-02-17 00:22:45 +00006986 if (!InheritsFromClassNamed(IFace, "NSArray"))
6987 IndexedGetterPriority += CCD_ProbablyNotObjCCollection;
6988 }
6989
6990 if (!InheritsFromClassNamed(IFace, "NSMutableSet")) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006991 UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;
Douglas Gregor669a25a2011-02-17 00:22:45 +00006992 if (!InheritsFromClassNamed(IFace, "NSSet"))
6993 UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;
6994 }
6995 }
6996 } else {
6997 IndexedGetterPriority += CCD_ProbablyNotObjCCollection;
6998 IndexedSetterPriority += CCD_ProbablyNotObjCCollection;
6999 UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;
7000 UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;
7001 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007002
Douglas Gregor669a25a2011-02-17 00:22:45 +00007003 // Add -(NSUInteger)countOf<key>
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007004 if (IsInstanceMethod &&
Douglas Gregor669a25a2011-02-17 00:22:45 +00007005 (ReturnType.isNull() || ReturnType->isIntegerType())) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007006 std::string SelectorName = (Twine("countOf") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007007 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007008 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
7009 .second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007010 if (ReturnType.isNull()) {
7011 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7012 Builder.AddTextChunk("NSUInteger");
7013 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7014 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007015
Douglas Gregor669a25a2011-02-17 00:22:45 +00007016 Builder.AddTypedTextChunk(
7017 Allocator.CopyString(SelectorId->getName()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007018 Results.AddResult(Result(Builder.TakeString(),
7019 std::min(IndexedGetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007020 UnorderedGetterPriority),
7021 CXCursor_ObjCInstanceMethodDecl));
7022 }
7023 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007024
Douglas Gregor669a25a2011-02-17 00:22:45 +00007025 // Indexed getters
7026 // Add -(id)objectInKeyAtIndex:(NSUInteger)index
7027 if (IsInstanceMethod &&
7028 (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007029 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007030 = (Twine("objectIn") + UpperKey + "AtIndex").str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007031 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007032 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007033 if (ReturnType.isNull()) {
7034 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7035 Builder.AddTextChunk("id");
7036 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7037 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007038
Douglas Gregor669a25a2011-02-17 00:22:45 +00007039 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7040 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7041 Builder.AddTextChunk("NSUInteger");
7042 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7043 Builder.AddTextChunk("index");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007044 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007045 CXCursor_ObjCInstanceMethodDecl));
7046 }
7047 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007048
Douglas Gregor669a25a2011-02-17 00:22:45 +00007049 // Add -(NSArray *)keyAtIndexes:(NSIndexSet *)indexes
7050 if (IsInstanceMethod &&
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007051 (ReturnType.isNull() ||
Douglas Gregor669a25a2011-02-17 00:22:45 +00007052 (ReturnType->isObjCObjectPointerType() &&
7053 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
7054 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
7055 ->getName() == "NSArray"))) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007056 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007057 = (Twine(Property->getName()) + "AtIndexes").str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007058 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007059 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007060 if (ReturnType.isNull()) {
7061 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7062 Builder.AddTextChunk("NSArray *");
7063 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7064 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007065
Douglas Gregor669a25a2011-02-17 00:22:45 +00007066 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7067 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7068 Builder.AddTextChunk("NSIndexSet *");
7069 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7070 Builder.AddTextChunk("indexes");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007071 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007072 CXCursor_ObjCInstanceMethodDecl));
7073 }
7074 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007075
Douglas Gregor669a25a2011-02-17 00:22:45 +00007076 // Add -(void)getKey:(type **)buffer range:(NSRange)inRange
7077 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007078 std::string SelectorName = (Twine("get") + UpperKey).str();
Douglas Gregor669a25a2011-02-17 00:22:45 +00007079 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007080 &Context.Idents.get(SelectorName),
Douglas Gregor669a25a2011-02-17 00:22:45 +00007081 &Context.Idents.get("range")
7082 };
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007083
David Blaikie82e95a32014-11-19 07:49:47 +00007084 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007085 if (ReturnType.isNull()) {
7086 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7087 Builder.AddTextChunk("void");
7088 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7089 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007090
Douglas Gregor669a25a2011-02-17 00:22:45 +00007091 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7092 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7093 Builder.AddPlaceholderChunk("object-type");
7094 Builder.AddTextChunk(" **");
7095 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7096 Builder.AddTextChunk("buffer");
7097 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7098 Builder.AddTypedTextChunk("range:");
7099 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7100 Builder.AddTextChunk("NSRange");
7101 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7102 Builder.AddTextChunk("inRange");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007103 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007104 CXCursor_ObjCInstanceMethodDecl));
7105 }
7106 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007107
Douglas Gregor669a25a2011-02-17 00:22:45 +00007108 // Mutable indexed accessors
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007109
Douglas Gregor669a25a2011-02-17 00:22:45 +00007110 // - (void)insertObject:(type *)object inKeyAtIndex:(NSUInteger)index
7111 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007112 std::string SelectorName = (Twine("in") + UpperKey + "AtIndex").str();
Douglas Gregor669a25a2011-02-17 00:22:45 +00007113 IdentifierInfo *SelectorIds[2] = {
7114 &Context.Idents.get("insertObject"),
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007115 &Context.Idents.get(SelectorName)
Douglas Gregor669a25a2011-02-17 00:22:45 +00007116 };
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007117
David Blaikie82e95a32014-11-19 07:49:47 +00007118 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007119 if (ReturnType.isNull()) {
7120 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7121 Builder.AddTextChunk("void");
7122 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7123 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007124
Douglas Gregor669a25a2011-02-17 00:22:45 +00007125 Builder.AddTypedTextChunk("insertObject:");
7126 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7127 Builder.AddPlaceholderChunk("object-type");
7128 Builder.AddTextChunk(" *");
7129 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7130 Builder.AddTextChunk("object");
7131 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7132 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7133 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7134 Builder.AddPlaceholderChunk("NSUInteger");
7135 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7136 Builder.AddTextChunk("index");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007137 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007138 CXCursor_ObjCInstanceMethodDecl));
7139 }
7140 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007141
Douglas Gregor669a25a2011-02-17 00:22:45 +00007142 // - (void)insertKey:(NSArray *)array atIndexes:(NSIndexSet *)indexes
7143 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007144 std::string SelectorName = (Twine("insert") + UpperKey).str();
Douglas Gregor669a25a2011-02-17 00:22:45 +00007145 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007146 &Context.Idents.get(SelectorName),
Douglas Gregor669a25a2011-02-17 00:22:45 +00007147 &Context.Idents.get("atIndexes")
7148 };
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007149
David Blaikie82e95a32014-11-19 07:49:47 +00007150 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007151 if (ReturnType.isNull()) {
7152 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7153 Builder.AddTextChunk("void");
7154 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7155 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007156
Douglas Gregor669a25a2011-02-17 00:22:45 +00007157 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7158 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7159 Builder.AddTextChunk("NSArray *");
7160 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7161 Builder.AddTextChunk("array");
7162 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7163 Builder.AddTypedTextChunk("atIndexes:");
7164 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7165 Builder.AddPlaceholderChunk("NSIndexSet *");
7166 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7167 Builder.AddTextChunk("indexes");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007168 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007169 CXCursor_ObjCInstanceMethodDecl));
7170 }
7171 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007172
Douglas Gregor669a25a2011-02-17 00:22:45 +00007173 // -(void)removeObjectFromKeyAtIndex:(NSUInteger)index
7174 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007175 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007176 = (Twine("removeObjectFrom") + UpperKey + "AtIndex").str();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007177 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007178 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007179 if (ReturnType.isNull()) {
7180 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7181 Builder.AddTextChunk("void");
7182 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7183 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007184
Douglas Gregor669a25a2011-02-17 00:22:45 +00007185 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7186 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7187 Builder.AddTextChunk("NSUInteger");
7188 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7189 Builder.AddTextChunk("index");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007190 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007191 CXCursor_ObjCInstanceMethodDecl));
7192 }
7193 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007194
Douglas Gregor669a25a2011-02-17 00:22:45 +00007195 // -(void)removeKeyAtIndexes:(NSIndexSet *)indexes
7196 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007197 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007198 = (Twine("remove") + UpperKey + "AtIndexes").str();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007199 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007200 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007201 if (ReturnType.isNull()) {
7202 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7203 Builder.AddTextChunk("void");
7204 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7205 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007206
Douglas Gregor669a25a2011-02-17 00:22:45 +00007207 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7208 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7209 Builder.AddTextChunk("NSIndexSet *");
7210 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7211 Builder.AddTextChunk("indexes");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007212 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007213 CXCursor_ObjCInstanceMethodDecl));
7214 }
7215 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007216
Douglas Gregor669a25a2011-02-17 00:22:45 +00007217 // - (void)replaceObjectInKeyAtIndex:(NSUInteger)index withObject:(id)object
7218 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007219 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007220 = (Twine("replaceObjectIn") + UpperKey + "AtIndex").str();
Douglas Gregor669a25a2011-02-17 00:22:45 +00007221 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007222 &Context.Idents.get(SelectorName),
Douglas Gregor669a25a2011-02-17 00:22:45 +00007223 &Context.Idents.get("withObject")
7224 };
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007225
David Blaikie82e95a32014-11-19 07:49:47 +00007226 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007227 if (ReturnType.isNull()) {
7228 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7229 Builder.AddTextChunk("void");
7230 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7231 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007232
Douglas Gregor669a25a2011-02-17 00:22:45 +00007233 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7234 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7235 Builder.AddPlaceholderChunk("NSUInteger");
7236 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7237 Builder.AddTextChunk("index");
7238 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7239 Builder.AddTypedTextChunk("withObject:");
7240 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7241 Builder.AddTextChunk("id");
7242 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7243 Builder.AddTextChunk("object");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007244 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007245 CXCursor_ObjCInstanceMethodDecl));
7246 }
7247 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007248
Douglas Gregor669a25a2011-02-17 00:22:45 +00007249 // - (void)replaceKeyAtIndexes:(NSIndexSet *)indexes withKey:(NSArray *)array
7250 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007251 std::string SelectorName1
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007252 = (Twine("replace") + UpperKey + "AtIndexes").str();
7253 std::string SelectorName2 = (Twine("with") + UpperKey).str();
Douglas Gregor669a25a2011-02-17 00:22:45 +00007254 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007255 &Context.Idents.get(SelectorName1),
7256 &Context.Idents.get(SelectorName2)
Douglas Gregor669a25a2011-02-17 00:22:45 +00007257 };
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007258
David Blaikie82e95a32014-11-19 07:49:47 +00007259 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007260 if (ReturnType.isNull()) {
7261 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7262 Builder.AddTextChunk("void");
7263 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7264 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007265
Douglas Gregor669a25a2011-02-17 00:22:45 +00007266 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName1 + ":"));
7267 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7268 Builder.AddPlaceholderChunk("NSIndexSet *");
7269 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7270 Builder.AddTextChunk("indexes");
7271 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7272 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName2 + ":"));
7273 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7274 Builder.AddTextChunk("NSArray *");
7275 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7276 Builder.AddTextChunk("array");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007277 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007278 CXCursor_ObjCInstanceMethodDecl));
7279 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007280 }
7281
Douglas Gregor669a25a2011-02-17 00:22:45 +00007282 // Unordered getters
7283 // - (NSEnumerator *)enumeratorOfKey
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007284 if (IsInstanceMethod &&
7285 (ReturnType.isNull() ||
Douglas Gregor669a25a2011-02-17 00:22:45 +00007286 (ReturnType->isObjCObjectPointerType() &&
7287 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
7288 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
7289 ->getName() == "NSEnumerator"))) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007290 std::string SelectorName = (Twine("enumeratorOf") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007291 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007292 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
7293 .second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007294 if (ReturnType.isNull()) {
7295 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7296 Builder.AddTextChunk("NSEnumerator *");
7297 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7298 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007299
Douglas Gregor669a25a2011-02-17 00:22:45 +00007300 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007301 Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007302 CXCursor_ObjCInstanceMethodDecl));
7303 }
7304 }
7305
7306 // - (type *)memberOfKey:(type *)object
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007307 if (IsInstanceMethod &&
Douglas Gregor669a25a2011-02-17 00:22:45 +00007308 (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007309 std::string SelectorName = (Twine("memberOf") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007310 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007311 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007312 if (ReturnType.isNull()) {
7313 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7314 Builder.AddPlaceholderChunk("object-type");
7315 Builder.AddTextChunk(" *");
7316 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7317 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007318
Douglas Gregor669a25a2011-02-17 00:22:45 +00007319 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7320 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7321 if (ReturnType.isNull()) {
7322 Builder.AddPlaceholderChunk("object-type");
7323 Builder.AddTextChunk(" *");
7324 } else {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007325 Builder.AddTextChunk(GetCompletionTypeString(ReturnType, Context,
Douglas Gregor75acd922011-09-27 23:30:47 +00007326 Policy,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007327 Builder.getAllocator()));
7328 }
7329 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7330 Builder.AddTextChunk("object");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007331 Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007332 CXCursor_ObjCInstanceMethodDecl));
7333 }
7334 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007335
Douglas Gregor669a25a2011-02-17 00:22:45 +00007336 // Mutable unordered accessors
7337 // - (void)addKeyObject:(type *)object
7338 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007339 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007340 = (Twine("add") + UpperKey + Twine("Object")).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007341 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007342 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007343 if (ReturnType.isNull()) {
7344 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7345 Builder.AddTextChunk("void");
7346 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7347 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007348
Douglas Gregor669a25a2011-02-17 00:22:45 +00007349 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7350 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7351 Builder.AddPlaceholderChunk("object-type");
7352 Builder.AddTextChunk(" *");
7353 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7354 Builder.AddTextChunk("object");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007355 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007356 CXCursor_ObjCInstanceMethodDecl));
7357 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007358 }
Douglas Gregor669a25a2011-02-17 00:22:45 +00007359
7360 // - (void)addKey:(NSSet *)objects
7361 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007362 std::string SelectorName = (Twine("add") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007363 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007364 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007365 if (ReturnType.isNull()) {
7366 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7367 Builder.AddTextChunk("void");
7368 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7369 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007370
Douglas Gregor669a25a2011-02-17 00:22:45 +00007371 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7372 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7373 Builder.AddTextChunk("NSSet *");
7374 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7375 Builder.AddTextChunk("objects");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007376 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007377 CXCursor_ObjCInstanceMethodDecl));
7378 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007379 }
7380
Douglas Gregor669a25a2011-02-17 00:22:45 +00007381 // - (void)removeKeyObject:(type *)object
7382 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007383 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007384 = (Twine("remove") + UpperKey + Twine("Object")).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007385 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007386 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007387 if (ReturnType.isNull()) {
7388 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7389 Builder.AddTextChunk("void");
7390 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7391 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007392
Douglas Gregor669a25a2011-02-17 00:22:45 +00007393 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7394 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7395 Builder.AddPlaceholderChunk("object-type");
7396 Builder.AddTextChunk(" *");
7397 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7398 Builder.AddTextChunk("object");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007399 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007400 CXCursor_ObjCInstanceMethodDecl));
7401 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007402 }
7403
Douglas Gregor669a25a2011-02-17 00:22:45 +00007404 // - (void)removeKey:(NSSet *)objects
7405 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007406 std::string SelectorName = (Twine("remove") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007407 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007408 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007409 if (ReturnType.isNull()) {
7410 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7411 Builder.AddTextChunk("void");
7412 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7413 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007414
Douglas Gregor669a25a2011-02-17 00:22:45 +00007415 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7416 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7417 Builder.AddTextChunk("NSSet *");
7418 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7419 Builder.AddTextChunk("objects");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007420 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007421 CXCursor_ObjCInstanceMethodDecl));
7422 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007423 }
Douglas Gregor669a25a2011-02-17 00:22:45 +00007424
7425 // - (void)intersectKey:(NSSet *)objects
7426 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007427 std::string SelectorName = (Twine("intersect") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007428 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007429 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007430 if (ReturnType.isNull()) {
7431 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7432 Builder.AddTextChunk("void");
7433 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7434 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007435
Douglas Gregor669a25a2011-02-17 00:22:45 +00007436 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7437 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7438 Builder.AddTextChunk("NSSet *");
7439 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7440 Builder.AddTextChunk("objects");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007441 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007442 CXCursor_ObjCInstanceMethodDecl));
7443 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007444 }
7445
Douglas Gregor669a25a2011-02-17 00:22:45 +00007446 // Key-Value Observing
7447 // + (NSSet *)keyPathsForValuesAffectingKey
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007448 if (!IsInstanceMethod &&
7449 (ReturnType.isNull() ||
Douglas Gregor669a25a2011-02-17 00:22:45 +00007450 (ReturnType->isObjCObjectPointerType() &&
7451 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
7452 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
7453 ->getName() == "NSSet"))) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007454 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007455 = (Twine("keyPathsForValuesAffecting") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007456 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007457 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
7458 .second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007459 if (ReturnType.isNull()) {
7460 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Alex Lorenz71ecb072016-12-08 16:49:05 +00007461 Builder.AddTextChunk("NSSet<NSString *> *");
Douglas Gregor669a25a2011-02-17 00:22:45 +00007462 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7463 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007464
Douglas Gregor669a25a2011-02-17 00:22:45 +00007465 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007466 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Douglas Gregor857bcda2011-06-02 04:02:27 +00007467 CXCursor_ObjCClassMethodDecl));
7468 }
7469 }
7470
7471 // + (BOOL)automaticallyNotifiesObserversForKey
7472 if (!IsInstanceMethod &&
7473 (ReturnType.isNull() ||
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007474 ReturnType->isIntegerType() ||
Douglas Gregor857bcda2011-06-02 04:02:27 +00007475 ReturnType->isBooleanType())) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007476 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007477 = (Twine("automaticallyNotifiesObserversOf") + UpperKey).str();
Douglas Gregor857bcda2011-06-02 04:02:27 +00007478 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007479 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
7480 .second) {
Douglas Gregor857bcda2011-06-02 04:02:27 +00007481 if (ReturnType.isNull()) {
7482 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7483 Builder.AddTextChunk("BOOL");
7484 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7485 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007486
Douglas Gregor857bcda2011-06-02 04:02:27 +00007487 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007488 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Douglas Gregor857bcda2011-06-02 04:02:27 +00007489 CXCursor_ObjCClassMethodDecl));
Douglas Gregor669a25a2011-02-17 00:22:45 +00007490 }
7491 }
7492}
7493
Alex Lorenzb8740422017-10-24 16:39:37 +00007494void Sema::CodeCompleteObjCMethodDecl(Scope *S, Optional<bool> IsInstanceMethod,
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00007495 ParsedType ReturnTy) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00007496 // Determine the return type of the method we're declaring, if
7497 // provided.
7498 QualType ReturnType = GetTypeFromParser(ReturnTy);
Craig Topperc3ec1492014-05-26 06:22:03 +00007499 Decl *IDecl = nullptr;
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00007500 if (CurContext->isObjCContainer()) {
7501 ObjCContainerDecl *OCD = dyn_cast<ObjCContainerDecl>(CurContext);
George Burgess IV00f70bd2018-03-01 05:43:23 +00007502 IDecl = OCD;
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00007503 }
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007504 // Determine where we should start searching for methods.
Craig Topperc3ec1492014-05-26 06:22:03 +00007505 ObjCContainerDecl *SearchDecl = nullptr;
Douglas Gregor636a61e2010-04-07 00:21:17 +00007506 bool IsInImplementation = false;
John McCall48871652010-08-21 09:40:31 +00007507 if (Decl *D = IDecl) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00007508 if (ObjCImplementationDecl *Impl = dyn_cast<ObjCImplementationDecl>(D)) {
7509 SearchDecl = Impl->getClassInterface();
Douglas Gregor636a61e2010-04-07 00:21:17 +00007510 IsInImplementation = true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007511 } else if (ObjCCategoryImplDecl *CatImpl
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007512 = dyn_cast<ObjCCategoryImplDecl>(D)) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00007513 SearchDecl = CatImpl->getCategoryDecl();
Douglas Gregor636a61e2010-04-07 00:21:17 +00007514 IsInImplementation = true;
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007515 } else
Douglas Gregor636a61e2010-04-07 00:21:17 +00007516 SearchDecl = dyn_cast<ObjCContainerDecl>(D);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007517 }
7518
7519 if (!SearchDecl && S) {
Ted Kremenekc37877d2013-10-08 17:08:03 +00007520 if (DeclContext *DC = S->getEntity())
Douglas Gregor636a61e2010-04-07 00:21:17 +00007521 SearchDecl = dyn_cast<ObjCContainerDecl>(DC);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007522 }
7523
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007524 if (!SearchDecl) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007525 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00007526 CodeCompletionContext::CCC_Other,
Craig Topperc3ec1492014-05-26 06:22:03 +00007527 nullptr, 0);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007528 return;
7529 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007530
Douglas Gregor636a61e2010-04-07 00:21:17 +00007531 // Find all of the methods that we could declare/implement here.
7532 KnownMethodsMap KnownMethods;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007533 FindImplementableMethods(Context, SearchDecl, IsInstanceMethod,
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007534 ReturnType, KnownMethods);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007535
Douglas Gregor636a61e2010-04-07 00:21:17 +00007536 // Add declarations or definitions for each of the known methods.
John McCall276321a2010-08-25 06:19:51 +00007537 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007538 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007539 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007540 CodeCompletionContext::CCC_Other);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007541 Results.EnterNewScope();
Douglas Gregor75acd922011-09-27 23:30:47 +00007542 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007543 for (KnownMethodsMap::iterator M = KnownMethods.begin(),
Douglas Gregor636a61e2010-04-07 00:21:17 +00007544 MEnd = KnownMethods.end();
7545 M != MEnd; ++M) {
Benjamin Kramereb8c4462013-06-29 17:52:13 +00007546 ObjCMethodDecl *Method = M->second.getPointer();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007547 CodeCompletionBuilder Builder(Results.getAllocator(),
7548 Results.getCodeCompletionTUInfo());
Alex Lorenzb8740422017-10-24 16:39:37 +00007549
7550 // Add the '-'/'+' prefix if it wasn't provided yet.
7551 if (!IsInstanceMethod) {
7552 Builder.AddTextChunk(Method->isInstanceMethod() ? "-" : "+");
7553 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7554 }
7555
Douglas Gregor636a61e2010-04-07 00:21:17 +00007556 // If the result type was not already provided, add it to the
7557 // pattern as (type).
Argyrios Kyrtzidisf0917ab2015-07-24 17:00:19 +00007558 if (ReturnType.isNull()) {
7559 QualType ResTy = Method->getSendResultType().stripObjCKindOfType(Context);
7560 AttributedType::stripOuterNullability(ResTy);
7561 AddObjCPassingTypeChunk(ResTy,
Alp Toker314cc812014-01-25 16:55:45 +00007562 Method->getObjCDeclQualifier(), Context, Policy,
7563 Builder);
Argyrios Kyrtzidisf0917ab2015-07-24 17:00:19 +00007564 }
Douglas Gregor636a61e2010-04-07 00:21:17 +00007565
7566 Selector Sel = Method->getSelector();
7567
7568 // Add the first part of the selector to the pattern.
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00007569 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00007570 Sel.getNameForSlot(0)));
Douglas Gregor636a61e2010-04-07 00:21:17 +00007571
7572 // Add parameters to the pattern.
7573 unsigned I = 0;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007574 for (ObjCMethodDecl::param_iterator P = Method->param_begin(),
Douglas Gregor636a61e2010-04-07 00:21:17 +00007575 PEnd = Method->param_end();
7576 P != PEnd; (void)++P, ++I) {
7577 // Add the part of the selector name.
7578 if (I == 0)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007579 Builder.AddTypedTextChunk(":");
Douglas Gregor636a61e2010-04-07 00:21:17 +00007580 else if (I < Sel.getNumArgs()) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007581 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7582 Builder.AddTypedTextChunk(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00007583 Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":"));
Douglas Gregor636a61e2010-04-07 00:21:17 +00007584 } else
7585 break;
7586
7587 // Add the parameter type.
Douglas Gregor86b42682015-06-19 18:27:52 +00007588 QualType ParamType;
7589 if ((*P)->getObjCDeclQualifier() & Decl::OBJC_TQ_CSNullability)
7590 ParamType = (*P)->getType();
7591 else
7592 ParamType = (*P)->getOriginalType();
Douglas Gregor9b7b3e92015-07-07 06:20:27 +00007593 ParamType = ParamType.substObjCTypeArgs(Context, {},
7594 ObjCSubstitutionContext::Parameter);
Argyrios Kyrtzidisf0917ab2015-07-24 17:00:19 +00007595 AttributedType::stripOuterNullability(ParamType);
Douglas Gregor86b42682015-06-19 18:27:52 +00007596 AddObjCPassingTypeChunk(ParamType,
Douglas Gregor29979142012-04-10 18:35:07 +00007597 (*P)->getObjCDeclQualifier(),
7598 Context, Policy,
Douglas Gregor75acd922011-09-27 23:30:47 +00007599 Builder);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007600
Douglas Gregor636a61e2010-04-07 00:21:17 +00007601 if (IdentifierInfo *Id = (*P)->getIdentifier())
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007602 Builder.AddTextChunk(Builder.getAllocator().CopyString( Id->getName()));
Douglas Gregor636a61e2010-04-07 00:21:17 +00007603 }
7604
7605 if (Method->isVariadic()) {
7606 if (Method->param_size() > 0)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007607 Builder.AddChunk(CodeCompletionString::CK_Comma);
7608 Builder.AddTextChunk("...");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007609 }
Douglas Gregor636a61e2010-04-07 00:21:17 +00007610
Douglas Gregord37c59d2010-05-28 00:57:46 +00007611 if (IsInImplementation && Results.includeCodePatterns()) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00007612 // We will be defining the method here, so add a compound statement.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007613 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7614 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
7615 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
Alp Toker314cc812014-01-25 16:55:45 +00007616 if (!Method->getReturnType()->isVoidType()) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00007617 // If the result type is not void, add a return clause.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007618 Builder.AddTextChunk("return");
7619 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7620 Builder.AddPlaceholderChunk("expression");
7621 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007622 } else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007623 Builder.AddPlaceholderChunk("statements");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007624
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007625 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
7626 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007627 }
7628
Douglas Gregor416b5752010-08-25 01:08:01 +00007629 unsigned Priority = CCP_CodePattern;
Benjamin Kramereb8c4462013-06-29 17:52:13 +00007630 if (!M->second.getInt())
Douglas Gregor416b5752010-08-25 01:08:01 +00007631 Priority += CCD_InBaseClass;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007632
Douglas Gregor78254c82012-03-27 23:34:16 +00007633 Results.AddResult(Result(Builder.TakeString(), Method, Priority));
Douglas Gregor636a61e2010-04-07 00:21:17 +00007634 }
7635
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007636 // Add Key-Value-Coding and Key-Value-Observing accessor methods for all of
Douglas Gregor669a25a2011-02-17 00:22:45 +00007637 // the properties in this class and its categories.
David Blaikiebbafb8a2012-03-11 07:00:24 +00007638 if (Context.getLangOpts().ObjC2) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007639 SmallVector<ObjCContainerDecl *, 4> Containers;
Douglas Gregor669a25a2011-02-17 00:22:45 +00007640 Containers.push_back(SearchDecl);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007641
Douglas Gregord4a8ced2011-05-04 23:50:46 +00007642 VisitedSelectorSet KnownSelectors;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007643 for (KnownMethodsMap::iterator M = KnownMethods.begin(),
Douglas Gregord4a8ced2011-05-04 23:50:46 +00007644 MEnd = KnownMethods.end();
7645 M != MEnd; ++M)
7646 KnownSelectors.insert(M->first);
7647
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007648
Douglas Gregor669a25a2011-02-17 00:22:45 +00007649 ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(SearchDecl);
7650 if (!IFace)
7651 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(SearchDecl))
7652 IFace = Category->getClassInterface();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007653
Aaron Ballman3fe486a2014-03-13 21:23:55 +00007654 if (IFace)
7655 for (auto *Cat : IFace->visible_categories())
7656 Containers.push_back(Cat);
Alex Lorenzb8740422017-10-24 16:39:37 +00007657
7658 if (IsInstanceMethod) {
7659 for (unsigned I = 0, N = Containers.size(); I != N; ++I)
7660 for (auto *P : Containers[I]->instance_properties())
7661 AddObjCKeyValueCompletions(P, *IsInstanceMethod, ReturnType, Context,
7662 KnownSelectors, Results);
7663 }
Douglas Gregor669a25a2011-02-17 00:22:45 +00007664 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007665
Douglas Gregor636a61e2010-04-07 00:21:17 +00007666 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00007667
7668 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
7669 Results.data(), Results.size());
Douglas Gregor636a61e2010-04-07 00:21:17 +00007670}
Douglas Gregor95887f92010-07-08 23:20:03 +00007671
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007672void Sema::CodeCompleteObjCMethodDeclSelector(Scope *S,
Douglas Gregor95887f92010-07-08 23:20:03 +00007673 bool IsInstanceMethod,
Douglas Gregor45879692010-07-08 23:37:41 +00007674 bool AtParameterName,
John McCallba7bf592010-08-24 05:47:05 +00007675 ParsedType ReturnTy,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00007676 ArrayRef<IdentifierInfo *> SelIdents) {
Douglas Gregor95887f92010-07-08 23:20:03 +00007677 // If we have an external source, load the entire class method
Sebastian Redld44cd6a2010-08-18 23:57:06 +00007678 // pool from the AST file.
Douglas Gregor95887f92010-07-08 23:20:03 +00007679 if (ExternalSource) {
7680 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
7681 I != N; ++I) {
7682 Selector Sel = ExternalSource->GetExternalSelector(I);
Sebastian Redl75d8a322010-08-02 23:18:59 +00007683 if (Sel.isNull() || MethodPool.count(Sel))
Douglas Gregor95887f92010-07-08 23:20:03 +00007684 continue;
Sebastian Redl75d8a322010-08-02 23:18:59 +00007685
7686 ReadMethodPool(Sel);
Douglas Gregor95887f92010-07-08 23:20:03 +00007687 }
7688 }
7689
7690 // Build the set of methods we can see.
John McCall276321a2010-08-25 06:19:51 +00007691 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007692 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007693 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007694 CodeCompletionContext::CCC_Other);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007695
Douglas Gregor95887f92010-07-08 23:20:03 +00007696 if (ReturnTy)
7697 Results.setPreferredType(GetTypeFromParser(ReturnTy).getNonReferenceType());
Sebastian Redl75d8a322010-08-02 23:18:59 +00007698
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007699 Results.EnterNewScope();
Sebastian Redl75d8a322010-08-02 23:18:59 +00007700 for (GlobalMethodPool::iterator M = MethodPool.begin(),
7701 MEnd = MethodPool.end();
7702 M != MEnd; ++M) {
7703 for (ObjCMethodList *MethList = IsInstanceMethod ? &M->second.first :
7704 &M->second.second;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007705 MethList && MethList->getMethod();
Argyrios Kyrtzidisd3da6e02013-04-17 00:08:58 +00007706 MethList = MethList->getNext()) {
Nico Weber2e0c8f72014-12-27 03:58:08 +00007707 if (!isAcceptableObjCMethod(MethList->getMethod(), MK_Any, SelIdents))
Douglas Gregor95887f92010-07-08 23:20:03 +00007708 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007709
Douglas Gregor45879692010-07-08 23:37:41 +00007710 if (AtParameterName) {
7711 // Suggest parameter names we've seen before.
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00007712 unsigned NumSelIdents = SelIdents.size();
Nico Weber2e0c8f72014-12-27 03:58:08 +00007713 if (NumSelIdents &&
7714 NumSelIdents <= MethList->getMethod()->param_size()) {
7715 ParmVarDecl *Param =
7716 MethList->getMethod()->parameters()[NumSelIdents - 1];
Douglas Gregor45879692010-07-08 23:37:41 +00007717 if (Param->getIdentifier()) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007718 CodeCompletionBuilder Builder(Results.getAllocator(),
7719 Results.getCodeCompletionTUInfo());
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00007720 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007721 Param->getIdentifier()->getName()));
7722 Results.AddResult(Builder.TakeString());
Douglas Gregor45879692010-07-08 23:37:41 +00007723 }
7724 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007725
Douglas Gregor45879692010-07-08 23:37:41 +00007726 continue;
7727 }
Craig Topperc3ec1492014-05-26 06:22:03 +00007728
Nico Weber2e0c8f72014-12-27 03:58:08 +00007729 Result R(MethList->getMethod(),
7730 Results.getBasePriority(MethList->getMethod()), nullptr);
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00007731 R.StartParameter = SelIdents.size();
Douglas Gregor95887f92010-07-08 23:20:03 +00007732 R.AllParametersAreInformative = false;
7733 R.DeclaringEntity = true;
7734 Results.MaybeAddResult(R, CurContext);
7735 }
7736 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007737
Douglas Gregor95887f92010-07-08 23:20:03 +00007738 Results.ExitScope();
Alex Lorenz847fda12017-01-03 11:56:40 +00007739
7740 if (!AtParameterName && !SelIdents.empty() &&
7741 SelIdents.front()->getName().startswith("init")) {
7742 for (const auto &M : PP.macros()) {
7743 if (M.first->getName() != "NS_DESIGNATED_INITIALIZER")
7744 continue;
7745 Results.EnterNewScope();
7746 CodeCompletionBuilder Builder(Results.getAllocator(),
7747 Results.getCodeCompletionTUInfo());
7748 Builder.AddTypedTextChunk(
7749 Builder.getAllocator().CopyString(M.first->getName()));
7750 Results.AddResult(CodeCompletionResult(Builder.TakeString(), CCP_Macro,
7751 CXCursor_MacroDefinition));
7752 Results.ExitScope();
7753 }
7754 }
7755
Eric Liuf5ba09f2018-07-04 10:01:18 +00007756 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
7757 Results.data(), Results.size());
Douglas Gregor95887f92010-07-08 23:20:03 +00007758}
Douglas Gregorb14904c2010-08-13 22:48:40 +00007759
Douglas Gregorec00a262010-08-24 22:20:20 +00007760void Sema::CodeCompletePreprocessorDirective(bool InConditional) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007761 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007762 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00007763 CodeCompletionContext::CCC_PreprocessorDirective);
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007764 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007765
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007766 // #if <condition>
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007767 CodeCompletionBuilder Builder(Results.getAllocator(),
7768 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007769 Builder.AddTypedTextChunk("if");
7770 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7771 Builder.AddPlaceholderChunk("condition");
7772 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007773
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007774 // #ifdef <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007775 Builder.AddTypedTextChunk("ifdef");
7776 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7777 Builder.AddPlaceholderChunk("macro");
7778 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007779
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007780 // #ifndef <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007781 Builder.AddTypedTextChunk("ifndef");
7782 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7783 Builder.AddPlaceholderChunk("macro");
7784 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007785
7786 if (InConditional) {
7787 // #elif <condition>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007788 Builder.AddTypedTextChunk("elif");
7789 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7790 Builder.AddPlaceholderChunk("condition");
7791 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007792
7793 // #else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007794 Builder.AddTypedTextChunk("else");
7795 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007796
7797 // #endif
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007798 Builder.AddTypedTextChunk("endif");
7799 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007800 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007801
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007802 // #include "header"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007803 Builder.AddTypedTextChunk("include");
7804 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7805 Builder.AddTextChunk("\"");
7806 Builder.AddPlaceholderChunk("header");
7807 Builder.AddTextChunk("\"");
7808 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007809
7810 // #include <header>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007811 Builder.AddTypedTextChunk("include");
7812 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7813 Builder.AddTextChunk("<");
7814 Builder.AddPlaceholderChunk("header");
7815 Builder.AddTextChunk(">");
7816 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007817
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007818 // #define <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007819 Builder.AddTypedTextChunk("define");
7820 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7821 Builder.AddPlaceholderChunk("macro");
7822 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007823
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007824 // #define <macro>(<args>)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007825 Builder.AddTypedTextChunk("define");
7826 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7827 Builder.AddPlaceholderChunk("macro");
7828 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7829 Builder.AddPlaceholderChunk("args");
7830 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7831 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007832
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007833 // #undef <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007834 Builder.AddTypedTextChunk("undef");
7835 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7836 Builder.AddPlaceholderChunk("macro");
7837 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007838
7839 // #line <number>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007840 Builder.AddTypedTextChunk("line");
7841 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7842 Builder.AddPlaceholderChunk("number");
7843 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007844
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007845 // #line <number> "filename"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007846 Builder.AddTypedTextChunk("line");
7847 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7848 Builder.AddPlaceholderChunk("number");
7849 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7850 Builder.AddTextChunk("\"");
7851 Builder.AddPlaceholderChunk("filename");
7852 Builder.AddTextChunk("\"");
7853 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007854
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007855 // #error <message>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007856 Builder.AddTypedTextChunk("error");
7857 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7858 Builder.AddPlaceholderChunk("message");
7859 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007860
7861 // #pragma <arguments>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007862 Builder.AddTypedTextChunk("pragma");
7863 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7864 Builder.AddPlaceholderChunk("arguments");
7865 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007866
David Blaikiebbafb8a2012-03-11 07:00:24 +00007867 if (getLangOpts().ObjC1) {
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007868 // #import "header"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007869 Builder.AddTypedTextChunk("import");
7870 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7871 Builder.AddTextChunk("\"");
7872 Builder.AddPlaceholderChunk("header");
7873 Builder.AddTextChunk("\"");
7874 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007875
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007876 // #import <header>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007877 Builder.AddTypedTextChunk("import");
7878 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7879 Builder.AddTextChunk("<");
7880 Builder.AddPlaceholderChunk("header");
7881 Builder.AddTextChunk(">");
7882 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007883 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007884
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007885 // #include_next "header"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007886 Builder.AddTypedTextChunk("include_next");
7887 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7888 Builder.AddTextChunk("\"");
7889 Builder.AddPlaceholderChunk("header");
7890 Builder.AddTextChunk("\"");
7891 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007892
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007893 // #include_next <header>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007894 Builder.AddTypedTextChunk("include_next");
7895 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7896 Builder.AddTextChunk("<");
7897 Builder.AddPlaceholderChunk("header");
7898 Builder.AddTextChunk(">");
7899 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007900
7901 // #warning <message>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007902 Builder.AddTypedTextChunk("warning");
7903 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7904 Builder.AddPlaceholderChunk("message");
7905 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007906
7907 // Note: #ident and #sccs are such crazy anachronisms that we don't provide
7908 // completions for them. And __include_macros is a Clang-internal extension
7909 // that we don't want to encourage anyone to use.
7910
7911 // FIXME: we don't support #assert or #unassert, so don't suggest them.
7912 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00007913
7914 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007915 Results.data(), Results.size());
7916}
7917
7918void Sema::CodeCompleteInPreprocessorConditionalExclusion(Scope *S) {
Douglas Gregorec00a262010-08-24 22:20:20 +00007919 CodeCompleteOrdinaryName(S,
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007920 S->getFnParent()? Sema::PCC_RecoveryInFunction
John McCallfaf5fb42010-08-26 23:41:50 +00007921 : Sema::PCC_Namespace);
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007922}
7923
Douglas Gregorec00a262010-08-24 22:20:20 +00007924void Sema::CodeCompletePreprocessorMacroName(bool IsDefinition) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007925 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007926 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00007927 IsDefinition? CodeCompletionContext::CCC_MacroName
7928 : CodeCompletionContext::CCC_MacroNameUse);
Douglas Gregor12785102010-08-24 20:21:13 +00007929 if (!IsDefinition && (!CodeCompleter || CodeCompleter->includeMacros())) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007930 // Add just the names of macros, not their arguments.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007931 CodeCompletionBuilder Builder(Results.getAllocator(),
7932 Results.getCodeCompletionTUInfo());
Douglas Gregor12785102010-08-24 20:21:13 +00007933 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007934 for (Preprocessor::macro_iterator M = PP.macro_begin(),
Douglas Gregor12785102010-08-24 20:21:13 +00007935 MEnd = PP.macro_end();
7936 M != MEnd; ++M) {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00007937 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007938 M->first->getName()));
Argyrios Kyrtzidis5c8b1cd2012-09-27 00:24:09 +00007939 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
7940 CCP_CodePattern,
7941 CXCursor_MacroDefinition));
Douglas Gregor12785102010-08-24 20:21:13 +00007942 }
7943 Results.ExitScope();
7944 } else if (IsDefinition) {
7945 // FIXME: Can we detect when the user just wrote an include guard above?
7946 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007947
Douglas Gregor0ac41382010-09-23 23:01:17 +00007948 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007949 Results.data(), Results.size());
Douglas Gregor12785102010-08-24 20:21:13 +00007950}
7951
Douglas Gregorec00a262010-08-24 22:20:20 +00007952void Sema::CodeCompletePreprocessorExpression() {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007953 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007954 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00007955 CodeCompletionContext::CCC_PreprocessorExpression);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007956
Douglas Gregorec00a262010-08-24 22:20:20 +00007957 if (!CodeCompleter || CodeCompleter->includeMacros())
Douglas Gregor8cb17462012-10-09 16:01:50 +00007958 AddMacroResults(PP, Results, true);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007959
Douglas Gregorec00a262010-08-24 22:20:20 +00007960 // defined (<macro>)
7961 Results.EnterNewScope();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007962 CodeCompletionBuilder Builder(Results.getAllocator(),
7963 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007964 Builder.AddTypedTextChunk("defined");
7965 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7966 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7967 Builder.AddPlaceholderChunk("macro");
7968 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7969 Results.AddResult(Builder.TakeString());
Douglas Gregorec00a262010-08-24 22:20:20 +00007970 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00007971
7972 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
7973 Results.data(), Results.size());
Douglas Gregorec00a262010-08-24 22:20:20 +00007974}
7975
7976void Sema::CodeCompletePreprocessorMacroArgument(Scope *S,
7977 IdentifierInfo *Macro,
7978 MacroInfo *MacroInfo,
7979 unsigned Argument) {
7980 // FIXME: In the future, we could provide "overload" results, much like we
7981 // do for function calls.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007982
Argyrios Kyrtzidis75f6cd22011-08-18 19:41:28 +00007983 // Now just ignore this. There will be another code-completion callback
7984 // for the expanded tokens.
Douglas Gregorec00a262010-08-24 22:20:20 +00007985}
7986
Douglas Gregor11583702010-08-25 17:04:25 +00007987void Sema::CodeCompleteNaturalLanguage() {
Douglas Gregor11583702010-08-25 17:04:25 +00007988 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregorea736372010-08-25 17:10:00 +00007989 CodeCompletionContext::CCC_NaturalLanguage,
Craig Topperc3ec1492014-05-26 06:22:03 +00007990 nullptr, 0);
Douglas Gregor11583702010-08-25 17:04:25 +00007991}
7992
Alex Lorenzf7f6f822017-05-09 16:05:04 +00007993void Sema::CodeCompleteAvailabilityPlatformName() {
7994 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
7995 CodeCompleter->getCodeCompletionTUInfo(),
7996 CodeCompletionContext::CCC_Other);
7997 Results.EnterNewScope();
7998 static const char *Platforms[] = {"macOS", "iOS", "watchOS", "tvOS"};
7999 for (const char *Platform : llvm::makeArrayRef(Platforms)) {
8000 Results.AddResult(CodeCompletionResult(Platform));
8001 Results.AddResult(CodeCompletionResult(Results.getAllocator().CopyString(
8002 Twine(Platform) + "ApplicationExtension")));
8003 }
8004 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00008005 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
8006 Results.data(), Results.size());
Alex Lorenzf7f6f822017-05-09 16:05:04 +00008007}
8008
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00008009void Sema::GatherGlobalCodeCompletions(CodeCompletionAllocator &Allocator,
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008010 CodeCompletionTUInfo &CCTUInfo,
Chris Lattner0e62c1c2011-07-23 10:55:15 +00008011 SmallVectorImpl<CodeCompletionResult> &Results) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008012 ResultBuilder Builder(*this, Allocator, CCTUInfo,
8013 CodeCompletionContext::CCC_Recovery);
Douglas Gregor39982192010-08-15 06:18:01 +00008014 if (!CodeCompleter || CodeCompleter->includeGlobals()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008015 CodeCompletionDeclConsumer Consumer(Builder,
Douglas Gregor39982192010-08-15 06:18:01 +00008016 Context.getTranslationUnitDecl());
Sam McCallbb2cf632018-01-12 14:51:47 +00008017 LookupVisibleDecls(Context.getTranslationUnitDecl(), LookupAnyName,
8018 Consumer,
8019 !CodeCompleter || CodeCompleter->loadExternal());
Douglas Gregor39982192010-08-15 06:18:01 +00008020 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008021
Douglas Gregorb14904c2010-08-13 22:48:40 +00008022 if (!CodeCompleter || CodeCompleter->includeMacros())
Douglas Gregor8cb17462012-10-09 16:01:50 +00008023 AddMacroResults(PP, Builder, true);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008024
Douglas Gregorb14904c2010-08-13 22:48:40 +00008025 Results.clear();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008026 Results.insert(Results.end(),
Douglas Gregorb14904c2010-08-13 22:48:40 +00008027 Builder.data(), Builder.data() + Builder.size());
8028}