File: | clang/lib/Sema/SemaCodeComplete.cpp |
Warning: | line 4786, column 22 Called C++ object pointer is null |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | //===---------------- SemaCodeComplete.cpp - Code Completion ----*- C++ -*-===// | ||||
2 | // | ||||
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||||
4 | // See https://llvm.org/LICENSE.txt for license information. | ||||
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||||
6 | // | ||||
7 | //===----------------------------------------------------------------------===// | ||||
8 | // | ||||
9 | // This file defines the code-completion semantic actions. | ||||
10 | // | ||||
11 | //===----------------------------------------------------------------------===// | ||||
12 | #include "clang/AST/Decl.h" | ||||
13 | #include "clang/AST/DeclBase.h" | ||||
14 | #include "clang/AST/DeclCXX.h" | ||||
15 | #include "clang/AST/DeclObjC.h" | ||||
16 | #include "clang/AST/ExprCXX.h" | ||||
17 | #include "clang/AST/ExprObjC.h" | ||||
18 | #include "clang/AST/QualTypeNames.h" | ||||
19 | #include "clang/AST/Type.h" | ||||
20 | #include "clang/Basic/CharInfo.h" | ||||
21 | #include "clang/Basic/Specifiers.h" | ||||
22 | #include "clang/Lex/HeaderSearch.h" | ||||
23 | #include "clang/Lex/MacroInfo.h" | ||||
24 | #include "clang/Lex/Preprocessor.h" | ||||
25 | #include "clang/Sema/CodeCompleteConsumer.h" | ||||
26 | #include "clang/Sema/Lookup.h" | ||||
27 | #include "clang/Sema/Overload.h" | ||||
28 | #include "clang/Sema/Scope.h" | ||||
29 | #include "clang/Sema/ScopeInfo.h" | ||||
30 | #include "clang/Sema/SemaInternal.h" | ||||
31 | #include "llvm/ADT/DenseSet.h" | ||||
32 | #include "llvm/ADT/SmallBitVector.h" | ||||
33 | #include "llvm/ADT/SmallPtrSet.h" | ||||
34 | #include "llvm/ADT/SmallString.h" | ||||
35 | #include "llvm/ADT/StringExtras.h" | ||||
36 | #include "llvm/ADT/StringSwitch.h" | ||||
37 | #include "llvm/ADT/Twine.h" | ||||
38 | #include "llvm/ADT/iterator_range.h" | ||||
39 | #include "llvm/Support/Path.h" | ||||
40 | #include <list> | ||||
41 | #include <map> | ||||
42 | #include <string> | ||||
43 | #include <vector> | ||||
44 | |||||
45 | using namespace clang; | ||||
46 | using namespace sema; | ||||
47 | |||||
48 | namespace { | ||||
49 | /// A container of code-completion results. | ||||
50 | class ResultBuilder { | ||||
51 | public: | ||||
52 | /// The type of a name-lookup filter, which can be provided to the | ||||
53 | /// name-lookup routines to specify which declarations should be included in | ||||
54 | /// the result set (when it returns true) and which declarations should be | ||||
55 | /// filtered out (returns false). | ||||
56 | typedef bool (ResultBuilder::*LookupFilter)(const NamedDecl *) const; | ||||
57 | |||||
58 | typedef CodeCompletionResult Result; | ||||
59 | |||||
60 | private: | ||||
61 | /// The actual results we have found. | ||||
62 | std::vector<Result> Results; | ||||
63 | |||||
64 | /// A record of all of the declarations we have found and placed | ||||
65 | /// into the result set, used to ensure that no declaration ever gets into | ||||
66 | /// the result set twice. | ||||
67 | llvm::SmallPtrSet<const Decl *, 16> AllDeclsFound; | ||||
68 | |||||
69 | typedef std::pair<const NamedDecl *, unsigned> DeclIndexPair; | ||||
70 | |||||
71 | /// An entry in the shadow map, which is optimized to store | ||||
72 | /// a single (declaration, index) mapping (the common case) but | ||||
73 | /// can also store a list of (declaration, index) mappings. | ||||
74 | class ShadowMapEntry { | ||||
75 | typedef SmallVector<DeclIndexPair, 4> DeclIndexPairVector; | ||||
76 | |||||
77 | /// Contains either the solitary NamedDecl * or a vector | ||||
78 | /// of (declaration, index) pairs. | ||||
79 | llvm::PointerUnion<const NamedDecl *, DeclIndexPairVector *> DeclOrVector; | ||||
80 | |||||
81 | /// When the entry contains a single declaration, this is | ||||
82 | /// the index associated with that entry. | ||||
83 | unsigned SingleDeclIndex; | ||||
84 | |||||
85 | public: | ||||
86 | ShadowMapEntry() : DeclOrVector(), SingleDeclIndex(0) {} | ||||
87 | ShadowMapEntry(const ShadowMapEntry &) = delete; | ||||
88 | ShadowMapEntry(ShadowMapEntry &&Move) { *this = std::move(Move); } | ||||
89 | ShadowMapEntry &operator=(const ShadowMapEntry &) = delete; | ||||
90 | ShadowMapEntry &operator=(ShadowMapEntry &&Move) { | ||||
91 | SingleDeclIndex = Move.SingleDeclIndex; | ||||
92 | DeclOrVector = Move.DeclOrVector; | ||||
93 | Move.DeclOrVector = nullptr; | ||||
94 | return *this; | ||||
95 | } | ||||
96 | |||||
97 | void Add(const NamedDecl *ND, unsigned Index) { | ||||
98 | if (DeclOrVector.isNull()) { | ||||
99 | // 0 - > 1 elements: just set the single element information. | ||||
100 | DeclOrVector = ND; | ||||
101 | SingleDeclIndex = Index; | ||||
102 | return; | ||||
103 | } | ||||
104 | |||||
105 | if (const NamedDecl *PrevND = | ||||
106 | DeclOrVector.dyn_cast<const NamedDecl *>()) { | ||||
107 | // 1 -> 2 elements: create the vector of results and push in the | ||||
108 | // existing declaration. | ||||
109 | DeclIndexPairVector *Vec = new DeclIndexPairVector; | ||||
110 | Vec->push_back(DeclIndexPair(PrevND, SingleDeclIndex)); | ||||
111 | DeclOrVector = Vec; | ||||
112 | } | ||||
113 | |||||
114 | // Add the new element to the end of the vector. | ||||
115 | DeclOrVector.get<DeclIndexPairVector *>()->push_back( | ||||
116 | DeclIndexPair(ND, Index)); | ||||
117 | } | ||||
118 | |||||
119 | ~ShadowMapEntry() { | ||||
120 | if (DeclIndexPairVector *Vec = | ||||
121 | DeclOrVector.dyn_cast<DeclIndexPairVector *>()) { | ||||
122 | delete Vec; | ||||
123 | DeclOrVector = ((NamedDecl *)nullptr); | ||||
124 | } | ||||
125 | } | ||||
126 | |||||
127 | // Iteration. | ||||
128 | class iterator; | ||||
129 | iterator begin() const; | ||||
130 | iterator end() const; | ||||
131 | }; | ||||
132 | |||||
133 | /// A mapping from declaration names to the declarations that have | ||||
134 | /// this name within a particular scope and their index within the list of | ||||
135 | /// results. | ||||
136 | typedef llvm::DenseMap<DeclarationName, ShadowMapEntry> ShadowMap; | ||||
137 | |||||
138 | /// The semantic analysis object for which results are being | ||||
139 | /// produced. | ||||
140 | Sema &SemaRef; | ||||
141 | |||||
142 | /// The allocator used to allocate new code-completion strings. | ||||
143 | CodeCompletionAllocator &Allocator; | ||||
144 | |||||
145 | CodeCompletionTUInfo &CCTUInfo; | ||||
146 | |||||
147 | /// If non-NULL, a filter function used to remove any code-completion | ||||
148 | /// results that are not desirable. | ||||
149 | LookupFilter Filter; | ||||
150 | |||||
151 | /// Whether we should allow declarations as | ||||
152 | /// nested-name-specifiers that would otherwise be filtered out. | ||||
153 | bool AllowNestedNameSpecifiers; | ||||
154 | |||||
155 | /// If set, the type that we would prefer our resulting value | ||||
156 | /// declarations to have. | ||||
157 | /// | ||||
158 | /// Closely matching the preferred type gives a boost to a result's | ||||
159 | /// priority. | ||||
160 | CanQualType PreferredType; | ||||
161 | |||||
162 | /// A list of shadow maps, which is used to model name hiding at | ||||
163 | /// different levels of, e.g., the inheritance hierarchy. | ||||
164 | std::list<ShadowMap> ShadowMaps; | ||||
165 | |||||
166 | /// Overloaded C++ member functions found by SemaLookup. | ||||
167 | /// Used to determine when one overload is dominated by another. | ||||
168 | llvm::DenseMap<std::pair<DeclContext *, /*Name*/uintptr_t>, ShadowMapEntry> | ||||
169 | OverloadMap; | ||||
170 | |||||
171 | /// If we're potentially referring to a C++ member function, the set | ||||
172 | /// of qualifiers applied to the object type. | ||||
173 | Qualifiers ObjectTypeQualifiers; | ||||
174 | /// The kind of the object expression, for rvalue/lvalue overloads. | ||||
175 | ExprValueKind ObjectKind; | ||||
176 | |||||
177 | /// Whether the \p ObjectTypeQualifiers field is active. | ||||
178 | bool HasObjectTypeQualifiers; | ||||
179 | |||||
180 | /// The selector that we prefer. | ||||
181 | Selector PreferredSelector; | ||||
182 | |||||
183 | /// The completion context in which we are gathering results. | ||||
184 | CodeCompletionContext CompletionContext; | ||||
185 | |||||
186 | /// If we are in an instance method definition, the \@implementation | ||||
187 | /// object. | ||||
188 | ObjCImplementationDecl *ObjCImplementation; | ||||
189 | |||||
190 | void AdjustResultPriorityForDecl(Result &R); | ||||
191 | |||||
192 | void MaybeAddConstructorResults(Result R); | ||||
193 | |||||
194 | public: | ||||
195 | explicit ResultBuilder(Sema &SemaRef, CodeCompletionAllocator &Allocator, | ||||
196 | CodeCompletionTUInfo &CCTUInfo, | ||||
197 | const CodeCompletionContext &CompletionContext, | ||||
198 | LookupFilter Filter = nullptr) | ||||
199 | : SemaRef(SemaRef), Allocator(Allocator), CCTUInfo(CCTUInfo), | ||||
200 | Filter(Filter), AllowNestedNameSpecifiers(false), | ||||
201 | HasObjectTypeQualifiers(false), CompletionContext(CompletionContext), | ||||
202 | ObjCImplementation(nullptr) { | ||||
203 | // If this is an Objective-C instance method definition, dig out the | ||||
204 | // corresponding implementation. | ||||
205 | switch (CompletionContext.getKind()) { | ||||
206 | case CodeCompletionContext::CCC_Expression: | ||||
207 | case CodeCompletionContext::CCC_ObjCMessageReceiver: | ||||
208 | case CodeCompletionContext::CCC_ParenthesizedExpression: | ||||
209 | case CodeCompletionContext::CCC_Statement: | ||||
210 | case CodeCompletionContext::CCC_Recovery: | ||||
211 | if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl()) | ||||
212 | if (Method->isInstanceMethod()) | ||||
213 | if (ObjCInterfaceDecl *Interface = Method->getClassInterface()) | ||||
214 | ObjCImplementation = Interface->getImplementation(); | ||||
215 | break; | ||||
216 | |||||
217 | default: | ||||
218 | break; | ||||
219 | } | ||||
220 | } | ||||
221 | |||||
222 | /// Determine the priority for a reference to the given declaration. | ||||
223 | unsigned getBasePriority(const NamedDecl *D); | ||||
224 | |||||
225 | /// Whether we should include code patterns in the completion | ||||
226 | /// results. | ||||
227 | bool includeCodePatterns() const { | ||||
228 | return SemaRef.CodeCompleter && | ||||
229 | SemaRef.CodeCompleter->includeCodePatterns(); | ||||
230 | } | ||||
231 | |||||
232 | /// Set the filter used for code-completion results. | ||||
233 | void setFilter(LookupFilter Filter) { this->Filter = Filter; } | ||||
234 | |||||
235 | Result *data() { return Results.empty() ? nullptr : &Results.front(); } | ||||
236 | unsigned size() const { return Results.size(); } | ||||
237 | bool empty() const { return Results.empty(); } | ||||
238 | |||||
239 | /// Specify the preferred type. | ||||
240 | void setPreferredType(QualType T) { | ||||
241 | PreferredType = SemaRef.Context.getCanonicalType(T); | ||||
242 | } | ||||
243 | |||||
244 | /// Set the cv-qualifiers on the object type, for us in filtering | ||||
245 | /// calls to member functions. | ||||
246 | /// | ||||
247 | /// When there are qualifiers in this set, they will be used to filter | ||||
248 | /// out member functions that aren't available (because there will be a | ||||
249 | /// cv-qualifier mismatch) or prefer functions with an exact qualifier | ||||
250 | /// match. | ||||
251 | void setObjectTypeQualifiers(Qualifiers Quals, ExprValueKind Kind) { | ||||
252 | ObjectTypeQualifiers = Quals; | ||||
253 | ObjectKind = Kind; | ||||
254 | HasObjectTypeQualifiers = true; | ||||
255 | } | ||||
256 | |||||
257 | /// Set the preferred selector. | ||||
258 | /// | ||||
259 | /// When an Objective-C method declaration result is added, and that | ||||
260 | /// method's selector matches this preferred selector, we give that method | ||||
261 | /// a slight priority boost. | ||||
262 | void setPreferredSelector(Selector Sel) { PreferredSelector = Sel; } | ||||
263 | |||||
264 | /// Retrieve the code-completion context for which results are | ||||
265 | /// being collected. | ||||
266 | const CodeCompletionContext &getCompletionContext() const { | ||||
267 | return CompletionContext; | ||||
268 | } | ||||
269 | |||||
270 | /// Specify whether nested-name-specifiers are allowed. | ||||
271 | void allowNestedNameSpecifiers(bool Allow = true) { | ||||
272 | AllowNestedNameSpecifiers = Allow; | ||||
273 | } | ||||
274 | |||||
275 | /// Return the semantic analysis object for which we are collecting | ||||
276 | /// code completion results. | ||||
277 | Sema &getSema() const { return SemaRef; } | ||||
278 | |||||
279 | /// Retrieve the allocator used to allocate code completion strings. | ||||
280 | CodeCompletionAllocator &getAllocator() const { return Allocator; } | ||||
281 | |||||
282 | CodeCompletionTUInfo &getCodeCompletionTUInfo() const { return CCTUInfo; } | ||||
283 | |||||
284 | /// Determine whether the given declaration is at all interesting | ||||
285 | /// as a code-completion result. | ||||
286 | /// | ||||
287 | /// \param ND the declaration that we are inspecting. | ||||
288 | /// | ||||
289 | /// \param AsNestedNameSpecifier will be set true if this declaration is | ||||
290 | /// only interesting when it is a nested-name-specifier. | ||||
291 | bool isInterestingDecl(const NamedDecl *ND, | ||||
292 | bool &AsNestedNameSpecifier) const; | ||||
293 | |||||
294 | /// Check whether the result is hidden by the Hiding declaration. | ||||
295 | /// | ||||
296 | /// \returns true if the result is hidden and cannot be found, false if | ||||
297 | /// the hidden result could still be found. When false, \p R may be | ||||
298 | /// modified to describe how the result can be found (e.g., via extra | ||||
299 | /// qualification). | ||||
300 | bool CheckHiddenResult(Result &R, DeclContext *CurContext, | ||||
301 | const NamedDecl *Hiding); | ||||
302 | |||||
303 | /// Add a new result to this result set (if it isn't already in one | ||||
304 | /// of the shadow maps), or replace an existing result (for, e.g., a | ||||
305 | /// redeclaration). | ||||
306 | /// | ||||
307 | /// \param R the result to add (if it is unique). | ||||
308 | /// | ||||
309 | /// \param CurContext the context in which this result will be named. | ||||
310 | void MaybeAddResult(Result R, DeclContext *CurContext = nullptr); | ||||
311 | |||||
312 | /// Add a new result to this result set, where we already know | ||||
313 | /// the hiding declaration (if any). | ||||
314 | /// | ||||
315 | /// \param R the result to add (if it is unique). | ||||
316 | /// | ||||
317 | /// \param CurContext the context in which this result will be named. | ||||
318 | /// | ||||
319 | /// \param Hiding the declaration that hides the result. | ||||
320 | /// | ||||
321 | /// \param InBaseClass whether the result was found in a base | ||||
322 | /// class of the searched context. | ||||
323 | void AddResult(Result R, DeclContext *CurContext, NamedDecl *Hiding, | ||||
324 | bool InBaseClass); | ||||
325 | |||||
326 | /// Add a new non-declaration result to this result set. | ||||
327 | void AddResult(Result R); | ||||
328 | |||||
329 | /// Enter into a new scope. | ||||
330 | void EnterNewScope(); | ||||
331 | |||||
332 | /// Exit from the current scope. | ||||
333 | void ExitScope(); | ||||
334 | |||||
335 | /// Ignore this declaration, if it is seen again. | ||||
336 | void Ignore(const Decl *D) { AllDeclsFound.insert(D->getCanonicalDecl()); } | ||||
337 | |||||
338 | /// Add a visited context. | ||||
339 | void addVisitedContext(DeclContext *Ctx) { | ||||
340 | CompletionContext.addVisitedContext(Ctx); | ||||
341 | } | ||||
342 | |||||
343 | /// \name Name lookup predicates | ||||
344 | /// | ||||
345 | /// These predicates can be passed to the name lookup functions to filter the | ||||
346 | /// results of name lookup. All of the predicates have the same type, so that | ||||
347 | /// | ||||
348 | //@{ | ||||
349 | bool IsOrdinaryName(const NamedDecl *ND) const; | ||||
350 | bool IsOrdinaryNonTypeName(const NamedDecl *ND) const; | ||||
351 | bool IsIntegralConstantValue(const NamedDecl *ND) const; | ||||
352 | bool IsOrdinaryNonValueName(const NamedDecl *ND) const; | ||||
353 | bool IsNestedNameSpecifier(const NamedDecl *ND) const; | ||||
354 | bool IsEnum(const NamedDecl *ND) const; | ||||
355 | bool IsClassOrStruct(const NamedDecl *ND) const; | ||||
356 | bool IsUnion(const NamedDecl *ND) const; | ||||
357 | bool IsNamespace(const NamedDecl *ND) const; | ||||
358 | bool IsNamespaceOrAlias(const NamedDecl *ND) const; | ||||
359 | bool IsType(const NamedDecl *ND) const; | ||||
360 | bool IsMember(const NamedDecl *ND) const; | ||||
361 | bool IsObjCIvar(const NamedDecl *ND) const; | ||||
362 | bool IsObjCMessageReceiver(const NamedDecl *ND) const; | ||||
363 | bool IsObjCMessageReceiverOrLambdaCapture(const NamedDecl *ND) const; | ||||
364 | bool IsObjCCollection(const NamedDecl *ND) const; | ||||
365 | bool IsImpossibleToSatisfy(const NamedDecl *ND) const; | ||||
366 | //@} | ||||
367 | }; | ||||
368 | } // namespace | ||||
369 | |||||
370 | void PreferredTypeBuilder::enterReturn(Sema &S, SourceLocation Tok) { | ||||
371 | if (isa<BlockDecl>(S.CurContext)) { | ||||
372 | if (sema::BlockScopeInfo *BSI = S.getCurBlock()) { | ||||
373 | ComputeType = nullptr; | ||||
374 | Type = BSI->ReturnType; | ||||
375 | ExpectedLoc = Tok; | ||||
376 | } | ||||
377 | } else if (const auto *Function = dyn_cast<FunctionDecl>(S.CurContext)) { | ||||
378 | ComputeType = nullptr; | ||||
379 | Type = Function->getReturnType(); | ||||
380 | ExpectedLoc = Tok; | ||||
381 | } else if (const auto *Method = dyn_cast<ObjCMethodDecl>(S.CurContext)) { | ||||
382 | ComputeType = nullptr; | ||||
383 | Type = Method->getReturnType(); | ||||
384 | ExpectedLoc = Tok; | ||||
385 | } | ||||
386 | } | ||||
387 | |||||
388 | void PreferredTypeBuilder::enterVariableInit(SourceLocation Tok, Decl *D) { | ||||
389 | auto *VD = llvm::dyn_cast_or_null<ValueDecl>(D); | ||||
390 | ComputeType = nullptr; | ||||
391 | Type = VD ? VD->getType() : QualType(); | ||||
392 | ExpectedLoc = Tok; | ||||
393 | } | ||||
394 | |||||
395 | void PreferredTypeBuilder::enterFunctionArgument( | ||||
396 | SourceLocation Tok, llvm::function_ref<QualType()> ComputeType) { | ||||
397 | this->ComputeType = ComputeType; | ||||
398 | Type = QualType(); | ||||
399 | ExpectedLoc = Tok; | ||||
400 | } | ||||
401 | |||||
402 | void PreferredTypeBuilder::enterParenExpr(SourceLocation Tok, | ||||
403 | SourceLocation LParLoc) { | ||||
404 | // expected type for parenthesized expression does not change. | ||||
405 | if (ExpectedLoc == LParLoc) | ||||
406 | ExpectedLoc = Tok; | ||||
407 | } | ||||
408 | |||||
409 | static QualType getPreferredTypeOfBinaryRHS(Sema &S, Expr *LHS, | ||||
410 | tok::TokenKind Op) { | ||||
411 | if (!LHS) | ||||
412 | return QualType(); | ||||
413 | |||||
414 | QualType LHSType = LHS->getType(); | ||||
415 | if (LHSType->isPointerType()) { | ||||
416 | if (Op == tok::plus || Op == tok::plusequal || Op == tok::minusequal) | ||||
417 | return S.getASTContext().getPointerDiffType(); | ||||
418 | // Pointer difference is more common than subtracting an int from a pointer. | ||||
419 | if (Op == tok::minus) | ||||
420 | return LHSType; | ||||
421 | } | ||||
422 | |||||
423 | switch (Op) { | ||||
424 | // No way to infer the type of RHS from LHS. | ||||
425 | case tok::comma: | ||||
426 | return QualType(); | ||||
427 | // Prefer the type of the left operand for all of these. | ||||
428 | // Arithmetic operations. | ||||
429 | case tok::plus: | ||||
430 | case tok::plusequal: | ||||
431 | case tok::minus: | ||||
432 | case tok::minusequal: | ||||
433 | case tok::percent: | ||||
434 | case tok::percentequal: | ||||
435 | case tok::slash: | ||||
436 | case tok::slashequal: | ||||
437 | case tok::star: | ||||
438 | case tok::starequal: | ||||
439 | // Assignment. | ||||
440 | case tok::equal: | ||||
441 | // Comparison operators. | ||||
442 | case tok::equalequal: | ||||
443 | case tok::exclaimequal: | ||||
444 | case tok::less: | ||||
445 | case tok::lessequal: | ||||
446 | case tok::greater: | ||||
447 | case tok::greaterequal: | ||||
448 | case tok::spaceship: | ||||
449 | return LHS->getType(); | ||||
450 | // Binary shifts are often overloaded, so don't try to guess those. | ||||
451 | case tok::greatergreater: | ||||
452 | case tok::greatergreaterequal: | ||||
453 | case tok::lessless: | ||||
454 | case tok::lesslessequal: | ||||
455 | if (LHSType->isIntegralOrEnumerationType()) | ||||
456 | return S.getASTContext().IntTy; | ||||
457 | return QualType(); | ||||
458 | // Logical operators, assume we want bool. | ||||
459 | case tok::ampamp: | ||||
460 | case tok::pipepipe: | ||||
461 | case tok::caretcaret: | ||||
462 | return S.getASTContext().BoolTy; | ||||
463 | // Operators often used for bit manipulation are typically used with the type | ||||
464 | // of the left argument. | ||||
465 | case tok::pipe: | ||||
466 | case tok::pipeequal: | ||||
467 | case tok::caret: | ||||
468 | case tok::caretequal: | ||||
469 | case tok::amp: | ||||
470 | case tok::ampequal: | ||||
471 | if (LHSType->isIntegralOrEnumerationType()) | ||||
472 | return LHSType; | ||||
473 | return QualType(); | ||||
474 | // RHS should be a pointer to a member of the 'LHS' type, but we can't give | ||||
475 | // any particular type here. | ||||
476 | case tok::periodstar: | ||||
477 | case tok::arrowstar: | ||||
478 | return QualType(); | ||||
479 | default: | ||||
480 | // FIXME(ibiryukov): handle the missing op, re-add the assertion. | ||||
481 | // assert(false && "unhandled binary op"); | ||||
482 | return QualType(); | ||||
483 | } | ||||
484 | } | ||||
485 | |||||
486 | /// Get preferred type for an argument of an unary expression. \p ContextType is | ||||
487 | /// preferred type of the whole unary expression. | ||||
488 | static QualType getPreferredTypeOfUnaryArg(Sema &S, QualType ContextType, | ||||
489 | tok::TokenKind Op) { | ||||
490 | switch (Op) { | ||||
491 | case tok::exclaim: | ||||
492 | return S.getASTContext().BoolTy; | ||||
493 | case tok::amp: | ||||
494 | if (!ContextType.isNull() && ContextType->isPointerType()) | ||||
495 | return ContextType->getPointeeType(); | ||||
496 | return QualType(); | ||||
497 | case tok::star: | ||||
498 | if (ContextType.isNull()) | ||||
499 | return QualType(); | ||||
500 | return S.getASTContext().getPointerType(ContextType.getNonReferenceType()); | ||||
501 | case tok::plus: | ||||
502 | case tok::minus: | ||||
503 | case tok::tilde: | ||||
504 | case tok::minusminus: | ||||
505 | case tok::plusplus: | ||||
506 | if (ContextType.isNull()) | ||||
507 | return S.getASTContext().IntTy; | ||||
508 | // leave as is, these operators typically return the same type. | ||||
509 | return ContextType; | ||||
510 | case tok::kw___real: | ||||
511 | case tok::kw___imag: | ||||
512 | return QualType(); | ||||
513 | default: | ||||
514 | assert(false && "unhandled unary op")((false && "unhandled unary op") ? static_cast<void > (0) : __assert_fail ("false && \"unhandled unary op\"" , "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/clang/lib/Sema/SemaCodeComplete.cpp" , 514, __PRETTY_FUNCTION__)); | ||||
515 | return QualType(); | ||||
516 | } | ||||
517 | } | ||||
518 | |||||
519 | void PreferredTypeBuilder::enterBinary(Sema &S, SourceLocation Tok, Expr *LHS, | ||||
520 | tok::TokenKind Op) { | ||||
521 | ComputeType = nullptr; | ||||
522 | Type = getPreferredTypeOfBinaryRHS(S, LHS, Op); | ||||
523 | ExpectedLoc = Tok; | ||||
524 | } | ||||
525 | |||||
526 | void PreferredTypeBuilder::enterMemAccess(Sema &S, SourceLocation Tok, | ||||
527 | Expr *Base) { | ||||
528 | if (!Base) | ||||
529 | return; | ||||
530 | // Do we have expected type for Base? | ||||
531 | if (ExpectedLoc != Base->getBeginLoc()) | ||||
532 | return; | ||||
533 | // Keep the expected type, only update the location. | ||||
534 | ExpectedLoc = Tok; | ||||
535 | return; | ||||
536 | } | ||||
537 | |||||
538 | void PreferredTypeBuilder::enterUnary(Sema &S, SourceLocation Tok, | ||||
539 | tok::TokenKind OpKind, | ||||
540 | SourceLocation OpLoc) { | ||||
541 | ComputeType = nullptr; | ||||
542 | Type = getPreferredTypeOfUnaryArg(S, this->get(OpLoc), OpKind); | ||||
543 | ExpectedLoc = Tok; | ||||
544 | } | ||||
545 | |||||
546 | void PreferredTypeBuilder::enterSubscript(Sema &S, SourceLocation Tok, | ||||
547 | Expr *LHS) { | ||||
548 | ComputeType = nullptr; | ||||
549 | Type = S.getASTContext().IntTy; | ||||
550 | ExpectedLoc = Tok; | ||||
551 | } | ||||
552 | |||||
553 | void PreferredTypeBuilder::enterTypeCast(SourceLocation Tok, | ||||
554 | QualType CastType) { | ||||
555 | ComputeType = nullptr; | ||||
556 | Type = !CastType.isNull() ? CastType.getCanonicalType() : QualType(); | ||||
557 | ExpectedLoc = Tok; | ||||
558 | } | ||||
559 | |||||
560 | void PreferredTypeBuilder::enterCondition(Sema &S, SourceLocation Tok) { | ||||
561 | ComputeType = nullptr; | ||||
562 | Type = S.getASTContext().BoolTy; | ||||
563 | ExpectedLoc = Tok; | ||||
564 | } | ||||
565 | |||||
566 | class ResultBuilder::ShadowMapEntry::iterator { | ||||
567 | llvm::PointerUnion<const NamedDecl *, const DeclIndexPair *> DeclOrIterator; | ||||
568 | unsigned SingleDeclIndex; | ||||
569 | |||||
570 | public: | ||||
571 | typedef DeclIndexPair value_type; | ||||
572 | typedef value_type reference; | ||||
573 | typedef std::ptrdiff_t difference_type; | ||||
574 | typedef std::input_iterator_tag iterator_category; | ||||
575 | |||||
576 | class pointer { | ||||
577 | DeclIndexPair Value; | ||||
578 | |||||
579 | public: | ||||
580 | pointer(const DeclIndexPair &Value) : Value(Value) {} | ||||
581 | |||||
582 | const DeclIndexPair *operator->() const { return &Value; } | ||||
583 | }; | ||||
584 | |||||
585 | iterator() : DeclOrIterator((NamedDecl *)nullptr), SingleDeclIndex(0) {} | ||||
586 | |||||
587 | iterator(const NamedDecl *SingleDecl, unsigned Index) | ||||
588 | : DeclOrIterator(SingleDecl), SingleDeclIndex(Index) {} | ||||
589 | |||||
590 | iterator(const DeclIndexPair *Iterator) | ||||
591 | : DeclOrIterator(Iterator), SingleDeclIndex(0) {} | ||||
592 | |||||
593 | iterator &operator++() { | ||||
594 | if (DeclOrIterator.is<const NamedDecl *>()) { | ||||
595 | DeclOrIterator = (NamedDecl *)nullptr; | ||||
596 | SingleDeclIndex = 0; | ||||
597 | return *this; | ||||
598 | } | ||||
599 | |||||
600 | const DeclIndexPair *I = DeclOrIterator.get<const DeclIndexPair *>(); | ||||
601 | ++I; | ||||
602 | DeclOrIterator = I; | ||||
603 | return *this; | ||||
604 | } | ||||
605 | |||||
606 | /*iterator operator++(int) { | ||||
607 | iterator tmp(*this); | ||||
608 | ++(*this); | ||||
609 | return tmp; | ||||
610 | }*/ | ||||
611 | |||||
612 | reference operator*() const { | ||||
613 | if (const NamedDecl *ND = DeclOrIterator.dyn_cast<const NamedDecl *>()) | ||||
614 | return reference(ND, SingleDeclIndex); | ||||
615 | |||||
616 | return *DeclOrIterator.get<const DeclIndexPair *>(); | ||||
617 | } | ||||
618 | |||||
619 | pointer operator->() const { return pointer(**this); } | ||||
620 | |||||
621 | friend bool operator==(const iterator &X, const iterator &Y) { | ||||
622 | return X.DeclOrIterator.getOpaqueValue() == | ||||
623 | Y.DeclOrIterator.getOpaqueValue() && | ||||
624 | X.SingleDeclIndex == Y.SingleDeclIndex; | ||||
625 | } | ||||
626 | |||||
627 | friend bool operator!=(const iterator &X, const iterator &Y) { | ||||
628 | return !(X == Y); | ||||
629 | } | ||||
630 | }; | ||||
631 | |||||
632 | ResultBuilder::ShadowMapEntry::iterator | ||||
633 | ResultBuilder::ShadowMapEntry::begin() const { | ||||
634 | if (DeclOrVector.isNull()) | ||||
635 | return iterator(); | ||||
636 | |||||
637 | if (const NamedDecl *ND = DeclOrVector.dyn_cast<const NamedDecl *>()) | ||||
638 | return iterator(ND, SingleDeclIndex); | ||||
639 | |||||
640 | return iterator(DeclOrVector.get<DeclIndexPairVector *>()->begin()); | ||||
641 | } | ||||
642 | |||||
643 | ResultBuilder::ShadowMapEntry::iterator | ||||
644 | ResultBuilder::ShadowMapEntry::end() const { | ||||
645 | if (DeclOrVector.is<const NamedDecl *>() || DeclOrVector.isNull()) | ||||
646 | return iterator(); | ||||
647 | |||||
648 | return iterator(DeclOrVector.get<DeclIndexPairVector *>()->end()); | ||||
649 | } | ||||
650 | |||||
651 | /// Compute the qualification required to get from the current context | ||||
652 | /// (\p CurContext) to the target context (\p TargetContext). | ||||
653 | /// | ||||
654 | /// \param Context the AST context in which the qualification will be used. | ||||
655 | /// | ||||
656 | /// \param CurContext the context where an entity is being named, which is | ||||
657 | /// typically based on the current scope. | ||||
658 | /// | ||||
659 | /// \param TargetContext the context in which the named entity actually | ||||
660 | /// resides. | ||||
661 | /// | ||||
662 | /// \returns a nested name specifier that refers into the target context, or | ||||
663 | /// NULL if no qualification is needed. | ||||
664 | static NestedNameSpecifier * | ||||
665 | getRequiredQualification(ASTContext &Context, const DeclContext *CurContext, | ||||
666 | const DeclContext *TargetContext) { | ||||
667 | SmallVector<const DeclContext *, 4> TargetParents; | ||||
668 | |||||
669 | for (const DeclContext *CommonAncestor = TargetContext; | ||||
670 | CommonAncestor && !CommonAncestor->Encloses(CurContext); | ||||
671 | CommonAncestor = CommonAncestor->getLookupParent()) { | ||||
672 | if (CommonAncestor->isTransparentContext() || | ||||
673 | CommonAncestor->isFunctionOrMethod()) | ||||
674 | continue; | ||||
675 | |||||
676 | TargetParents.push_back(CommonAncestor); | ||||
677 | } | ||||
678 | |||||
679 | NestedNameSpecifier *Result = nullptr; | ||||
680 | while (!TargetParents.empty()) { | ||||
681 | const DeclContext *Parent = TargetParents.pop_back_val(); | ||||
682 | |||||
683 | if (const auto *Namespace = dyn_cast<NamespaceDecl>(Parent)) { | ||||
684 | if (!Namespace->getIdentifier()) | ||||
685 | continue; | ||||
686 | |||||
687 | Result = NestedNameSpecifier::Create(Context, Result, Namespace); | ||||
688 | } else if (const auto *TD = dyn_cast<TagDecl>(Parent)) | ||||
689 | Result = NestedNameSpecifier::Create( | ||||
690 | Context, Result, false, Context.getTypeDeclType(TD).getTypePtr()); | ||||
691 | } | ||||
692 | return Result; | ||||
693 | } | ||||
694 | |||||
695 | /// Determine whether \p Id is a name reserved for the implementation (C99 | ||||
696 | /// 7.1.3, C++ [lib.global.names]). | ||||
697 | static bool isReservedName(const IdentifierInfo *Id, | ||||
698 | bool doubleUnderscoreOnly = false) { | ||||
699 | if (Id->getLength() < 2) | ||||
700 | return false; | ||||
701 | const char *Name = Id->getNameStart(); | ||||
702 | return Name[0] == '_' && | ||||
703 | (Name[1] == '_' || | ||||
704 | (Name[1] >= 'A' && Name[1] <= 'Z' && !doubleUnderscoreOnly)); | ||||
705 | } | ||||
706 | |||||
707 | // Some declarations have reserved names that we don't want to ever show. | ||||
708 | // Filter out names reserved for the implementation if they come from a | ||||
709 | // system header. | ||||
710 | static bool shouldIgnoreDueToReservedName(const NamedDecl *ND, Sema &SemaRef) { | ||||
711 | const IdentifierInfo *Id = ND->getIdentifier(); | ||||
712 | if (!Id) | ||||
713 | return false; | ||||
714 | |||||
715 | // Ignore reserved names for compiler provided decls. | ||||
716 | if (isReservedName(Id) && ND->getLocation().isInvalid()) | ||||
717 | return true; | ||||
718 | |||||
719 | // For system headers ignore only double-underscore names. | ||||
720 | // This allows for system headers providing private symbols with a single | ||||
721 | // underscore. | ||||
722 | if (isReservedName(Id, /*doubleUnderscoreOnly=*/true) && | ||||
723 | SemaRef.SourceMgr.isInSystemHeader( | ||||
724 | SemaRef.SourceMgr.getSpellingLoc(ND->getLocation()))) | ||||
725 | return true; | ||||
726 | |||||
727 | return false; | ||||
728 | } | ||||
729 | |||||
730 | bool ResultBuilder::isInterestingDecl(const NamedDecl *ND, | ||||
731 | bool &AsNestedNameSpecifier) const { | ||||
732 | AsNestedNameSpecifier = false; | ||||
733 | |||||
734 | auto *Named = ND; | ||||
735 | ND = ND->getUnderlyingDecl(); | ||||
736 | |||||
737 | // Skip unnamed entities. | ||||
738 | if (!ND->getDeclName()) | ||||
739 | return false; | ||||
740 | |||||
741 | // Friend declarations and declarations introduced due to friends are never | ||||
742 | // added as results. | ||||
743 | if (ND->getFriendObjectKind() == Decl::FOK_Undeclared) | ||||
744 | return false; | ||||
745 | |||||
746 | // Class template (partial) specializations are never added as results. | ||||
747 | if (isa<ClassTemplateSpecializationDecl>(ND) || | ||||
748 | isa<ClassTemplatePartialSpecializationDecl>(ND)) | ||||
749 | return false; | ||||
750 | |||||
751 | // Using declarations themselves are never added as results. | ||||
752 | if (isa<UsingDecl>(ND)) | ||||
753 | return false; | ||||
754 | |||||
755 | if (shouldIgnoreDueToReservedName(ND, SemaRef)) | ||||
756 | return false; | ||||
757 | |||||
758 | if (Filter == &ResultBuilder::IsNestedNameSpecifier || | ||||
759 | (isa<NamespaceDecl>(ND) && Filter != &ResultBuilder::IsNamespace && | ||||
760 | Filter != &ResultBuilder::IsNamespaceOrAlias && Filter != nullptr)) | ||||
761 | AsNestedNameSpecifier = true; | ||||
762 | |||||
763 | // Filter out any unwanted results. | ||||
764 | if (Filter && !(this->*Filter)(Named)) { | ||||
765 | // Check whether it is interesting as a nested-name-specifier. | ||||
766 | if (AllowNestedNameSpecifiers && SemaRef.getLangOpts().CPlusPlus && | ||||
767 | IsNestedNameSpecifier(ND) && | ||||
768 | (Filter != &ResultBuilder::IsMember || | ||||
769 | (isa<CXXRecordDecl>(ND) && | ||||
770 | cast<CXXRecordDecl>(ND)->isInjectedClassName()))) { | ||||
771 | AsNestedNameSpecifier = true; | ||||
772 | return true; | ||||
773 | } | ||||
774 | |||||
775 | return false; | ||||
776 | } | ||||
777 | // ... then it must be interesting! | ||||
778 | return true; | ||||
779 | } | ||||
780 | |||||
781 | bool ResultBuilder::CheckHiddenResult(Result &R, DeclContext *CurContext, | ||||
782 | const NamedDecl *Hiding) { | ||||
783 | // In C, there is no way to refer to a hidden name. | ||||
784 | // FIXME: This isn't true; we can find a tag name hidden by an ordinary | ||||
785 | // name if we introduce the tag type. | ||||
786 | if (!SemaRef.getLangOpts().CPlusPlus) | ||||
787 | return true; | ||||
788 | |||||
789 | const DeclContext *HiddenCtx = | ||||
790 | R.Declaration->getDeclContext()->getRedeclContext(); | ||||
791 | |||||
792 | // There is no way to qualify a name declared in a function or method. | ||||
793 | if (HiddenCtx->isFunctionOrMethod()) | ||||
794 | return true; | ||||
795 | |||||
796 | if (HiddenCtx == Hiding->getDeclContext()->getRedeclContext()) | ||||
797 | return true; | ||||
798 | |||||
799 | // We can refer to the result with the appropriate qualification. Do it. | ||||
800 | R.Hidden = true; | ||||
801 | R.QualifierIsInformative = false; | ||||
802 | |||||
803 | if (!R.Qualifier) | ||||
804 | R.Qualifier = getRequiredQualification(SemaRef.Context, CurContext, | ||||
805 | R.Declaration->getDeclContext()); | ||||
806 | return false; | ||||
807 | } | ||||
808 | |||||
809 | /// A simplified classification of types used to determine whether two | ||||
810 | /// types are "similar enough" when adjusting priorities. | ||||
811 | SimplifiedTypeClass clang::getSimplifiedTypeClass(CanQualType T) { | ||||
812 | switch (T->getTypeClass()) { | ||||
813 | case Type::Builtin: | ||||
814 | switch (cast<BuiltinType>(T)->getKind()) { | ||||
815 | case BuiltinType::Void: | ||||
816 | return STC_Void; | ||||
817 | |||||
818 | case BuiltinType::NullPtr: | ||||
819 | return STC_Pointer; | ||||
820 | |||||
821 | case BuiltinType::Overload: | ||||
822 | case BuiltinType::Dependent: | ||||
823 | return STC_Other; | ||||
824 | |||||
825 | case BuiltinType::ObjCId: | ||||
826 | case BuiltinType::ObjCClass: | ||||
827 | case BuiltinType::ObjCSel: | ||||
828 | return STC_ObjectiveC; | ||||
829 | |||||
830 | default: | ||||
831 | return STC_Arithmetic; | ||||
832 | } | ||||
833 | |||||
834 | case Type::Complex: | ||||
835 | return STC_Arithmetic; | ||||
836 | |||||
837 | case Type::Pointer: | ||||
838 | return STC_Pointer; | ||||
839 | |||||
840 | case Type::BlockPointer: | ||||
841 | return STC_Block; | ||||
842 | |||||
843 | case Type::LValueReference: | ||||
844 | case Type::RValueReference: | ||||
845 | return getSimplifiedTypeClass(T->getAs<ReferenceType>()->getPointeeType()); | ||||
846 | |||||
847 | case Type::ConstantArray: | ||||
848 | case Type::IncompleteArray: | ||||
849 | case Type::VariableArray: | ||||
850 | case Type::DependentSizedArray: | ||||
851 | return STC_Array; | ||||
852 | |||||
853 | case Type::DependentSizedExtVector: | ||||
854 | case Type::Vector: | ||||
855 | case Type::ExtVector: | ||||
856 | return STC_Arithmetic; | ||||
857 | |||||
858 | case Type::FunctionProto: | ||||
859 | case Type::FunctionNoProto: | ||||
860 | return STC_Function; | ||||
861 | |||||
862 | case Type::Record: | ||||
863 | return STC_Record; | ||||
864 | |||||
865 | case Type::Enum: | ||||
866 | return STC_Arithmetic; | ||||
867 | |||||
868 | case Type::ObjCObject: | ||||
869 | case Type::ObjCInterface: | ||||
870 | case Type::ObjCObjectPointer: | ||||
871 | return STC_ObjectiveC; | ||||
872 | |||||
873 | default: | ||||
874 | return STC_Other; | ||||
875 | } | ||||
876 | } | ||||
877 | |||||
878 | /// Get the type that a given expression will have if this declaration | ||||
879 | /// is used as an expression in its "typical" code-completion form. | ||||
880 | QualType clang::getDeclUsageType(ASTContext &C, const NamedDecl *ND) { | ||||
881 | ND = ND->getUnderlyingDecl(); | ||||
882 | |||||
883 | if (const auto *Type = dyn_cast<TypeDecl>(ND)) | ||||
884 | return C.getTypeDeclType(Type); | ||||
885 | if (const auto *Iface = dyn_cast<ObjCInterfaceDecl>(ND)) | ||||
886 | return C.getObjCInterfaceType(Iface); | ||||
887 | |||||
888 | QualType T; | ||||
889 | if (const FunctionDecl *Function = ND->getAsFunction()) | ||||
890 | T = Function->getCallResultType(); | ||||
891 | else if (const auto *Method = dyn_cast<ObjCMethodDecl>(ND)) | ||||
892 | T = Method->getSendResultType(); | ||||
893 | else if (const auto *Enumerator = dyn_cast<EnumConstantDecl>(ND)) | ||||
894 | T = C.getTypeDeclType(cast<EnumDecl>(Enumerator->getDeclContext())); | ||||
895 | else if (const auto *Property = dyn_cast<ObjCPropertyDecl>(ND)) | ||||
896 | T = Property->getType(); | ||||
897 | else if (const auto *Value = dyn_cast<ValueDecl>(ND)) | ||||
898 | T = Value->getType(); | ||||
899 | |||||
900 | if (T.isNull()) | ||||
901 | return QualType(); | ||||
902 | |||||
903 | // Dig through references, function pointers, and block pointers to | ||||
904 | // get down to the likely type of an expression when the entity is | ||||
905 | // used. | ||||
906 | do { | ||||
907 | if (const auto *Ref = T->getAs<ReferenceType>()) { | ||||
908 | T = Ref->getPointeeType(); | ||||
909 | continue; | ||||
910 | } | ||||
911 | |||||
912 | if (const auto *Pointer = T->getAs<PointerType>()) { | ||||
913 | if (Pointer->getPointeeType()->isFunctionType()) { | ||||
914 | T = Pointer->getPointeeType(); | ||||
915 | continue; | ||||
916 | } | ||||
917 | |||||
918 | break; | ||||
919 | } | ||||
920 | |||||
921 | if (const auto *Block = T->getAs<BlockPointerType>()) { | ||||
922 | T = Block->getPointeeType(); | ||||
923 | continue; | ||||
924 | } | ||||
925 | |||||
926 | if (const auto *Function = T->getAs<FunctionType>()) { | ||||
927 | T = Function->getReturnType(); | ||||
928 | continue; | ||||
929 | } | ||||
930 | |||||
931 | break; | ||||
932 | } while (true); | ||||
933 | |||||
934 | return T; | ||||
935 | } | ||||
936 | |||||
937 | unsigned ResultBuilder::getBasePriority(const NamedDecl *ND) { | ||||
938 | if (!ND) | ||||
939 | return CCP_Unlikely; | ||||
940 | |||||
941 | // Context-based decisions. | ||||
942 | const DeclContext *LexicalDC = ND->getLexicalDeclContext(); | ||||
943 | if (LexicalDC->isFunctionOrMethod()) { | ||||
944 | // _cmd is relatively rare | ||||
945 | if (const auto *ImplicitParam = dyn_cast<ImplicitParamDecl>(ND)) | ||||
946 | if (ImplicitParam->getIdentifier() && | ||||
947 | ImplicitParam->getIdentifier()->isStr("_cmd")) | ||||
948 | return CCP_ObjC_cmd; | ||||
949 | |||||
950 | return CCP_LocalDeclaration; | ||||
951 | } | ||||
952 | |||||
953 | const DeclContext *DC = ND->getDeclContext()->getRedeclContext(); | ||||
954 | if (DC->isRecord() || isa<ObjCContainerDecl>(DC)) { | ||||
955 | // Explicit destructor calls are very rare. | ||||
956 | if (isa<CXXDestructorDecl>(ND)) | ||||
957 | return CCP_Unlikely; | ||||
958 | // Explicit operator and conversion function calls are also very rare. | ||||
959 | auto DeclNameKind = ND->getDeclName().getNameKind(); | ||||
960 | if (DeclNameKind == DeclarationName::CXXOperatorName || | ||||
961 | DeclNameKind == DeclarationName::CXXLiteralOperatorName || | ||||
962 | DeclNameKind == DeclarationName::CXXConversionFunctionName) | ||||
963 | return CCP_Unlikely; | ||||
964 | return CCP_MemberDeclaration; | ||||
965 | } | ||||
966 | |||||
967 | // Content-based decisions. | ||||
968 | if (isa<EnumConstantDecl>(ND)) | ||||
969 | return CCP_Constant; | ||||
970 | |||||
971 | // Use CCP_Type for type declarations unless we're in a statement, Objective-C | ||||
972 | // message receiver, or parenthesized expression context. There, it's as | ||||
973 | // likely that the user will want to write a type as other declarations. | ||||
974 | if ((isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND)) && | ||||
975 | !(CompletionContext.getKind() == CodeCompletionContext::CCC_Statement || | ||||
976 | CompletionContext.getKind() == | ||||
977 | CodeCompletionContext::CCC_ObjCMessageReceiver || | ||||
978 | CompletionContext.getKind() == | ||||
979 | CodeCompletionContext::CCC_ParenthesizedExpression)) | ||||
980 | return CCP_Type; | ||||
981 | |||||
982 | return CCP_Declaration; | ||||
983 | } | ||||
984 | |||||
985 | void ResultBuilder::AdjustResultPriorityForDecl(Result &R) { | ||||
986 | // If this is an Objective-C method declaration whose selector matches our | ||||
987 | // preferred selector, give it a priority boost. | ||||
988 | if (!PreferredSelector.isNull()) | ||||
989 | if (const auto *Method = dyn_cast<ObjCMethodDecl>(R.Declaration)) | ||||
990 | if (PreferredSelector == Method->getSelector()) | ||||
991 | R.Priority += CCD_SelectorMatch; | ||||
992 | |||||
993 | // If we have a preferred type, adjust the priority for results with exactly- | ||||
994 | // matching or nearly-matching types. | ||||
995 | if (!PreferredType.isNull()) { | ||||
996 | QualType T = getDeclUsageType(SemaRef.Context, R.Declaration); | ||||
997 | if (!T.isNull()) { | ||||
998 | CanQualType TC = SemaRef.Context.getCanonicalType(T); | ||||
999 | // Check for exactly-matching types (modulo qualifiers). | ||||
1000 | if (SemaRef.Context.hasSameUnqualifiedType(PreferredType, TC)) | ||||
1001 | R.Priority /= CCF_ExactTypeMatch; | ||||
1002 | // Check for nearly-matching types, based on classification of each. | ||||
1003 | else if ((getSimplifiedTypeClass(PreferredType) == | ||||
1004 | getSimplifiedTypeClass(TC)) && | ||||
1005 | !(PreferredType->isEnumeralType() && TC->isEnumeralType())) | ||||
1006 | R.Priority /= CCF_SimilarTypeMatch; | ||||
1007 | } | ||||
1008 | } | ||||
1009 | } | ||||
1010 | |||||
1011 | static DeclContext::lookup_result getConstructors(ASTContext &Context, | ||||
1012 | const CXXRecordDecl *Record) { | ||||
1013 | QualType RecordTy = Context.getTypeDeclType(Record); | ||||
1014 | DeclarationName ConstructorName = | ||||
1015 | Context.DeclarationNames.getCXXConstructorName( | ||||
1016 | Context.getCanonicalType(RecordTy)); | ||||
1017 | return Record->lookup(ConstructorName); | ||||
1018 | } | ||||
1019 | |||||
1020 | void ResultBuilder::MaybeAddConstructorResults(Result R) { | ||||
1021 | if (!SemaRef.getLangOpts().CPlusPlus || !R.Declaration || | ||||
1022 | !CompletionContext.wantConstructorResults()) | ||||
1023 | return; | ||||
1024 | |||||
1025 | const NamedDecl *D = R.Declaration; | ||||
1026 | const CXXRecordDecl *Record = nullptr; | ||||
1027 | if (const ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(D)) | ||||
1028 | Record = ClassTemplate->getTemplatedDecl(); | ||||
1029 | else if ((Record = dyn_cast<CXXRecordDecl>(D))) { | ||||
1030 | // Skip specializations and partial specializations. | ||||
1031 | if (isa<ClassTemplateSpecializationDecl>(Record)) | ||||
1032 | return; | ||||
1033 | } else { | ||||
1034 | // There are no constructors here. | ||||
1035 | return; | ||||
1036 | } | ||||
1037 | |||||
1038 | Record = Record->getDefinition(); | ||||
1039 | if (!Record) | ||||
1040 | return; | ||||
1041 | |||||
1042 | for (NamedDecl *Ctor : getConstructors(SemaRef.Context, Record)) { | ||||
1043 | R.Declaration = Ctor; | ||||
1044 | R.CursorKind = getCursorKindForDecl(R.Declaration); | ||||
1045 | Results.push_back(R); | ||||
1046 | } | ||||
1047 | } | ||||
1048 | |||||
1049 | static bool isConstructor(const Decl *ND) { | ||||
1050 | if (const auto *Tmpl = dyn_cast<FunctionTemplateDecl>(ND)) | ||||
1051 | ND = Tmpl->getTemplatedDecl(); | ||||
1052 | return isa<CXXConstructorDecl>(ND); | ||||
1053 | } | ||||
1054 | |||||
1055 | void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) { | ||||
1056 | assert(!ShadowMaps.empty() && "Must enter into a results scope")((!ShadowMaps.empty() && "Must enter into a results scope" ) ? static_cast<void> (0) : __assert_fail ("!ShadowMaps.empty() && \"Must enter into a results scope\"" , "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/clang/lib/Sema/SemaCodeComplete.cpp" , 1056, __PRETTY_FUNCTION__)); | ||||
1057 | |||||
1058 | if (R.Kind != Result::RK_Declaration) { | ||||
1059 | // For non-declaration results, just add the result. | ||||
1060 | Results.push_back(R); | ||||
1061 | return; | ||||
1062 | } | ||||
1063 | |||||
1064 | // Look through using declarations. | ||||
1065 | if (const UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(R.Declaration)) { | ||||
1066 | CodeCompletionResult Result(Using->getTargetDecl(), | ||||
1067 | getBasePriority(Using->getTargetDecl()), | ||||
1068 | R.Qualifier); | ||||
1069 | Result.ShadowDecl = Using; | ||||
1070 | MaybeAddResult(Result, CurContext); | ||||
1071 | return; | ||||
1072 | } | ||||
1073 | |||||
1074 | const Decl *CanonDecl = R.Declaration->getCanonicalDecl(); | ||||
1075 | unsigned IDNS = CanonDecl->getIdentifierNamespace(); | ||||
1076 | |||||
1077 | bool AsNestedNameSpecifier = false; | ||||
1078 | if (!isInterestingDecl(R.Declaration, AsNestedNameSpecifier)) | ||||
1079 | return; | ||||
1080 | |||||
1081 | // C++ constructors are never found by name lookup. | ||||
1082 | if (isConstructor(R.Declaration)) | ||||
1083 | return; | ||||
1084 | |||||
1085 | ShadowMap &SMap = ShadowMaps.back(); | ||||
1086 | ShadowMapEntry::iterator I, IEnd; | ||||
1087 | ShadowMap::iterator NamePos = SMap.find(R.Declaration->getDeclName()); | ||||
1088 | if (NamePos != SMap.end()) { | ||||
1089 | I = NamePos->second.begin(); | ||||
1090 | IEnd = NamePos->second.end(); | ||||
1091 | } | ||||
1092 | |||||
1093 | for (; I != IEnd; ++I) { | ||||
1094 | const NamedDecl *ND = I->first; | ||||
1095 | unsigned Index = I->second; | ||||
1096 | if (ND->getCanonicalDecl() == CanonDecl) { | ||||
1097 | // This is a redeclaration. Always pick the newer declaration. | ||||
1098 | Results[Index].Declaration = R.Declaration; | ||||
1099 | |||||
1100 | // We're done. | ||||
1101 | return; | ||||
1102 | } | ||||
1103 | } | ||||
1104 | |||||
1105 | // This is a new declaration in this scope. However, check whether this | ||||
1106 | // declaration name is hidden by a similarly-named declaration in an outer | ||||
1107 | // scope. | ||||
1108 | std::list<ShadowMap>::iterator SM, SMEnd = ShadowMaps.end(); | ||||
1109 | --SMEnd; | ||||
1110 | for (SM = ShadowMaps.begin(); SM != SMEnd; ++SM) { | ||||
1111 | ShadowMapEntry::iterator I, IEnd; | ||||
1112 | ShadowMap::iterator NamePos = SM->find(R.Declaration->getDeclName()); | ||||
1113 | if (NamePos != SM->end()) { | ||||
1114 | I = NamePos->second.begin(); | ||||
1115 | IEnd = NamePos->second.end(); | ||||
1116 | } | ||||
1117 | for (; I != IEnd; ++I) { | ||||
1118 | // A tag declaration does not hide a non-tag declaration. | ||||
1119 | if (I->first->hasTagIdentifierNamespace() && | ||||
1120 | (IDNS & (Decl::IDNS_Member | Decl::IDNS_Ordinary | | ||||
1121 | Decl::IDNS_LocalExtern | Decl::IDNS_ObjCProtocol))) | ||||
1122 | continue; | ||||
1123 | |||||
1124 | // Protocols are in distinct namespaces from everything else. | ||||
1125 | if (((I->first->getIdentifierNamespace() & Decl::IDNS_ObjCProtocol) || | ||||
1126 | (IDNS & Decl::IDNS_ObjCProtocol)) && | ||||
1127 | I->first->getIdentifierNamespace() != IDNS) | ||||
1128 | continue; | ||||
1129 | |||||
1130 | // The newly-added result is hidden by an entry in the shadow map. | ||||
1131 | if (CheckHiddenResult(R, CurContext, I->first)) | ||||
1132 | return; | ||||
1133 | |||||
1134 | break; | ||||
1135 | } | ||||
1136 | } | ||||
1137 | |||||
1138 | // Make sure that any given declaration only shows up in the result set once. | ||||
1139 | if (!AllDeclsFound.insert(CanonDecl).second) | ||||
1140 | return; | ||||
1141 | |||||
1142 | // If the filter is for nested-name-specifiers, then this result starts a | ||||
1143 | // nested-name-specifier. | ||||
1144 | if (AsNestedNameSpecifier) { | ||||
1145 | R.StartsNestedNameSpecifier = true; | ||||
1146 | R.Priority = CCP_NestedNameSpecifier; | ||||
1147 | } else | ||||
1148 | AdjustResultPriorityForDecl(R); | ||||
1149 | |||||
1150 | // If this result is supposed to have an informative qualifier, add one. | ||||
1151 | if (R.QualifierIsInformative && !R.Qualifier && | ||||
1152 | !R.StartsNestedNameSpecifier) { | ||||
1153 | const DeclContext *Ctx = R.Declaration->getDeclContext(); | ||||
1154 | if (const NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Ctx)) | ||||
1155 | R.Qualifier = | ||||
1156 | NestedNameSpecifier::Create(SemaRef.Context, nullptr, Namespace); | ||||
1157 | else if (const TagDecl *Tag = dyn_cast<TagDecl>(Ctx)) | ||||
1158 | R.Qualifier = NestedNameSpecifier::Create( | ||||
1159 | SemaRef.Context, nullptr, false, | ||||
1160 | SemaRef.Context.getTypeDeclType(Tag).getTypePtr()); | ||||
1161 | else | ||||
1162 | R.QualifierIsInformative = false; | ||||
1163 | } | ||||
1164 | |||||
1165 | // Insert this result into the set of results and into the current shadow | ||||
1166 | // map. | ||||
1167 | SMap[R.Declaration->getDeclName()].Add(R.Declaration, Results.size()); | ||||
1168 | Results.push_back(R); | ||||
1169 | |||||
1170 | if (!AsNestedNameSpecifier) | ||||
1171 | MaybeAddConstructorResults(R); | ||||
1172 | } | ||||
1173 | |||||
1174 | static void setInBaseClass(ResultBuilder::Result &R) { | ||||
1175 | R.Priority += CCD_InBaseClass; | ||||
1176 | R.InBaseClass = true; | ||||
1177 | } | ||||
1178 | |||||
1179 | enum class OverloadCompare { BothViable, Dominates, Dominated }; | ||||
1180 | // Will Candidate ever be called on the object, when overloaded with Incumbent? | ||||
1181 | // Returns Dominates if Candidate is always called, Dominated if Incumbent is | ||||
1182 | // always called, BothViable if either may be called dependending on arguments. | ||||
1183 | // Precondition: must actually be overloads! | ||||
1184 | static OverloadCompare compareOverloads(const CXXMethodDecl &Candidate, | ||||
1185 | const CXXMethodDecl &Incumbent, | ||||
1186 | const Qualifiers &ObjectQuals, | ||||
1187 | ExprValueKind ObjectKind) { | ||||
1188 | // Base/derived shadowing is handled elsewhere. | ||||
1189 | if (Candidate.getDeclContext() != Incumbent.getDeclContext()) | ||||
1190 | return OverloadCompare::BothViable; | ||||
1191 | if (Candidate.isVariadic() != Incumbent.isVariadic() || | ||||
1192 | Candidate.getNumParams() != Incumbent.getNumParams() || | ||||
1193 | Candidate.getMinRequiredArguments() != | ||||
1194 | Incumbent.getMinRequiredArguments()) | ||||
1195 | return OverloadCompare::BothViable; | ||||
1196 | for (unsigned I = 0, E = Candidate.getNumParams(); I != E; ++I) | ||||
1197 | if (Candidate.parameters()[I]->getType().getCanonicalType() != | ||||
1198 | Incumbent.parameters()[I]->getType().getCanonicalType()) | ||||
1199 | return OverloadCompare::BothViable; | ||||
1200 | if (!llvm::empty(Candidate.specific_attrs<EnableIfAttr>()) || | ||||
1201 | !llvm::empty(Incumbent.specific_attrs<EnableIfAttr>())) | ||||
1202 | return OverloadCompare::BothViable; | ||||
1203 | // At this point, we know calls can't pick one or the other based on | ||||
1204 | // arguments, so one of the two must win. (Or both fail, handled elsewhere). | ||||
1205 | RefQualifierKind CandidateRef = Candidate.getRefQualifier(); | ||||
1206 | RefQualifierKind IncumbentRef = Incumbent.getRefQualifier(); | ||||
1207 | if (CandidateRef != IncumbentRef) { | ||||
1208 | // If the object kind is LValue/RValue, there's one acceptable ref-qualifier | ||||
1209 | // and it can't be mixed with ref-unqualified overloads (in valid code). | ||||
1210 | |||||
1211 | // For xvalue objects, we prefer the rvalue overload even if we have to | ||||
1212 | // add qualifiers (which is rare, because const&& is rare). | ||||
1213 | if (ObjectKind == clang::VK_XValue) | ||||
1214 | return CandidateRef == RQ_RValue ? OverloadCompare::Dominates | ||||
1215 | : OverloadCompare::Dominated; | ||||
1216 | } | ||||
1217 | // Now the ref qualifiers are the same (or we're in some invalid state). | ||||
1218 | // So make some decision based on the qualifiers. | ||||
1219 | Qualifiers CandidateQual = Candidate.getMethodQualifiers(); | ||||
1220 | Qualifiers IncumbentQual = Incumbent.getMethodQualifiers(); | ||||
1221 | bool CandidateSuperset = CandidateQual.compatiblyIncludes(IncumbentQual); | ||||
1222 | bool IncumbentSuperset = IncumbentQual.compatiblyIncludes(CandidateQual); | ||||
1223 | if (CandidateSuperset == IncumbentSuperset) | ||||
1224 | return OverloadCompare::BothViable; | ||||
1225 | return IncumbentSuperset ? OverloadCompare::Dominates | ||||
1226 | : OverloadCompare::Dominated; | ||||
1227 | } | ||||
1228 | |||||
1229 | void ResultBuilder::AddResult(Result R, DeclContext *CurContext, | ||||
1230 | NamedDecl *Hiding, bool InBaseClass = false) { | ||||
1231 | if (R.Kind != Result::RK_Declaration) { | ||||
1232 | // For non-declaration results, just add the result. | ||||
1233 | Results.push_back(R); | ||||
1234 | return; | ||||
1235 | } | ||||
1236 | |||||
1237 | // Look through using declarations. | ||||
1238 | if (const auto *Using = dyn_cast<UsingShadowDecl>(R.Declaration)) { | ||||
1239 | CodeCompletionResult Result(Using->getTargetDecl(), | ||||
1240 | getBasePriority(Using->getTargetDecl()), | ||||
1241 | R.Qualifier); | ||||
1242 | Result.ShadowDecl = Using; | ||||
1243 | AddResult(Result, CurContext, Hiding); | ||||
1244 | return; | ||||
1245 | } | ||||
1246 | |||||
1247 | bool AsNestedNameSpecifier = false; | ||||
1248 | if (!isInterestingDecl(R.Declaration, AsNestedNameSpecifier)) | ||||
1249 | return; | ||||
1250 | |||||
1251 | // C++ constructors are never found by name lookup. | ||||
1252 | if (isConstructor(R.Declaration)) | ||||
1253 | return; | ||||
1254 | |||||
1255 | if (Hiding && CheckHiddenResult(R, CurContext, Hiding)) | ||||
1256 | return; | ||||
1257 | |||||
1258 | // Make sure that any given declaration only shows up in the result set once. | ||||
1259 | if (!AllDeclsFound.insert(R.Declaration->getCanonicalDecl()).second) | ||||
1260 | return; | ||||
1261 | |||||
1262 | // If the filter is for nested-name-specifiers, then this result starts a | ||||
1263 | // nested-name-specifier. | ||||
1264 | if (AsNestedNameSpecifier) { | ||||
1265 | R.StartsNestedNameSpecifier = true; | ||||
1266 | R.Priority = CCP_NestedNameSpecifier; | ||||
1267 | } else if (Filter == &ResultBuilder::IsMember && !R.Qualifier && | ||||
1268 | InBaseClass && | ||||
1269 | isa<CXXRecordDecl>( | ||||
1270 | R.Declaration->getDeclContext()->getRedeclContext())) | ||||
1271 | R.QualifierIsInformative = true; | ||||
1272 | |||||
1273 | // If this result is supposed to have an informative qualifier, add one. | ||||
1274 | if (R.QualifierIsInformative && !R.Qualifier && | ||||
1275 | !R.StartsNestedNameSpecifier) { | ||||
1276 | const DeclContext *Ctx = R.Declaration->getDeclContext(); | ||||
1277 | if (const auto *Namespace = dyn_cast<NamespaceDecl>(Ctx)) | ||||
1278 | R.Qualifier = | ||||
1279 | NestedNameSpecifier::Create(SemaRef.Context, nullptr, Namespace); | ||||
1280 | else if (const auto *Tag = dyn_cast<TagDecl>(Ctx)) | ||||
1281 | R.Qualifier = NestedNameSpecifier::Create( | ||||
1282 | SemaRef.Context, nullptr, false, | ||||
1283 | SemaRef.Context.getTypeDeclType(Tag).getTypePtr()); | ||||
1284 | else | ||||
1285 | R.QualifierIsInformative = false; | ||||
1286 | } | ||||
1287 | |||||
1288 | // Adjust the priority if this result comes from a base class. | ||||
1289 | if (InBaseClass) | ||||
1290 | setInBaseClass(R); | ||||
1291 | |||||
1292 | AdjustResultPriorityForDecl(R); | ||||
1293 | |||||
1294 | if (HasObjectTypeQualifiers) | ||||
1295 | if (const auto *Method = dyn_cast<CXXMethodDecl>(R.Declaration)) | ||||
1296 | if (Method->isInstance()) { | ||||
1297 | Qualifiers MethodQuals = Method->getMethodQualifiers(); | ||||
1298 | if (ObjectTypeQualifiers == MethodQuals) | ||||
1299 | R.Priority += CCD_ObjectQualifierMatch; | ||||
1300 | else if (ObjectTypeQualifiers - MethodQuals) { | ||||
1301 | // The method cannot be invoked, because doing so would drop | ||||
1302 | // qualifiers. | ||||
1303 | return; | ||||
1304 | } | ||||
1305 | // Detect cases where a ref-qualified method cannot be invoked. | ||||
1306 | switch (Method->getRefQualifier()) { | ||||
1307 | case RQ_LValue: | ||||
1308 | if (ObjectKind != VK_LValue && !MethodQuals.hasConst()) | ||||
1309 | return; | ||||
1310 | break; | ||||
1311 | case RQ_RValue: | ||||
1312 | if (ObjectKind == VK_LValue) | ||||
1313 | return; | ||||
1314 | break; | ||||
1315 | case RQ_None: | ||||
1316 | break; | ||||
1317 | } | ||||
1318 | |||||
1319 | /// Check whether this dominates another overloaded method, which should | ||||
1320 | /// be suppressed (or vice versa). | ||||
1321 | /// Motivating case is const_iterator begin() const vs iterator begin(). | ||||
1322 | auto &OverloadSet = OverloadMap[std::make_pair( | ||||
1323 | CurContext, Method->getDeclName().getAsOpaqueInteger())]; | ||||
1324 | for (const DeclIndexPair& Entry : OverloadSet) { | ||||
1325 | Result &Incumbent = Results[Entry.second]; | ||||
1326 | switch (compareOverloads(*Method, | ||||
1327 | *cast<CXXMethodDecl>(Incumbent.Declaration), | ||||
1328 | ObjectTypeQualifiers, ObjectKind)) { | ||||
1329 | case OverloadCompare::Dominates: | ||||
1330 | // Replace the dominated overload with this one. | ||||
1331 | // FIXME: if the overload dominates multiple incumbents then we | ||||
1332 | // should remove all. But two overloads is by far the common case. | ||||
1333 | Incumbent = std::move(R); | ||||
1334 | return; | ||||
1335 | case OverloadCompare::Dominated: | ||||
1336 | // This overload can't be called, drop it. | ||||
1337 | return; | ||||
1338 | case OverloadCompare::BothViable: | ||||
1339 | break; | ||||
1340 | } | ||||
1341 | } | ||||
1342 | OverloadSet.Add(Method, Results.size()); | ||||
1343 | } | ||||
1344 | |||||
1345 | // Insert this result into the set of results. | ||||
1346 | Results.push_back(R); | ||||
1347 | |||||
1348 | if (!AsNestedNameSpecifier) | ||||
1349 | MaybeAddConstructorResults(R); | ||||
1350 | } | ||||
1351 | |||||
1352 | void ResultBuilder::AddResult(Result R) { | ||||
1353 | assert(R.Kind != Result::RK_Declaration &&((R.Kind != Result::RK_Declaration && "Declaration results need more context" ) ? static_cast<void> (0) : __assert_fail ("R.Kind != Result::RK_Declaration && \"Declaration results need more context\"" , "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/clang/lib/Sema/SemaCodeComplete.cpp" , 1354, __PRETTY_FUNCTION__)) | ||||
1354 | "Declaration results need more context")((R.Kind != Result::RK_Declaration && "Declaration results need more context" ) ? static_cast<void> (0) : __assert_fail ("R.Kind != Result::RK_Declaration && \"Declaration results need more context\"" , "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/clang/lib/Sema/SemaCodeComplete.cpp" , 1354, __PRETTY_FUNCTION__)); | ||||
1355 | Results.push_back(R); | ||||
1356 | } | ||||
1357 | |||||
1358 | /// Enter into a new scope. | ||||
1359 | void ResultBuilder::EnterNewScope() { ShadowMaps.emplace_back(); } | ||||
1360 | |||||
1361 | /// Exit from the current scope. | ||||
1362 | void ResultBuilder::ExitScope() { | ||||
1363 | ShadowMaps.pop_back(); | ||||
1364 | } | ||||
1365 | |||||
1366 | /// Determines whether this given declaration will be found by | ||||
1367 | /// ordinary name lookup. | ||||
1368 | bool ResultBuilder::IsOrdinaryName(const NamedDecl *ND) const { | ||||
1369 | ND = ND->getUnderlyingDecl(); | ||||
1370 | |||||
1371 | // If name lookup finds a local extern declaration, then we are in a | ||||
1372 | // context where it behaves like an ordinary name. | ||||
1373 | unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_LocalExtern; | ||||
1374 | if (SemaRef.getLangOpts().CPlusPlus) | ||||
1375 | IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member; | ||||
1376 | else if (SemaRef.getLangOpts().ObjC) { | ||||
1377 | if (isa<ObjCIvarDecl>(ND)) | ||||
1378 | return true; | ||||
1379 | } | ||||
1380 | |||||
1381 | return ND->getIdentifierNamespace() & IDNS; | ||||
1382 | } | ||||
1383 | |||||
1384 | /// Determines whether this given declaration will be found by | ||||
1385 | /// ordinary name lookup but is not a type name. | ||||
1386 | bool ResultBuilder::IsOrdinaryNonTypeName(const NamedDecl *ND) const { | ||||
1387 | ND = ND->getUnderlyingDecl(); | ||||
1388 | if (isa<TypeDecl>(ND)) | ||||
1389 | return false; | ||||
1390 | // Objective-C interfaces names are not filtered by this method because they | ||||
1391 | // can be used in a class property expression. We can still filter out | ||||
1392 | // @class declarations though. | ||||
1393 | if (const auto *ID = dyn_cast<ObjCInterfaceDecl>(ND)) { | ||||
1394 | if (!ID->getDefinition()) | ||||
1395 | return false; | ||||
1396 | } | ||||
1397 | |||||
1398 | unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_LocalExtern; | ||||
1399 | if (SemaRef.getLangOpts().CPlusPlus) | ||||
1400 | IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member; | ||||
1401 | else if (SemaRef.getLangOpts().ObjC) { | ||||
1402 | if (isa<ObjCIvarDecl>(ND)) | ||||
1403 | return true; | ||||
1404 | } | ||||
1405 | |||||
1406 | return ND->getIdentifierNamespace() & IDNS; | ||||
1407 | } | ||||
1408 | |||||
1409 | bool ResultBuilder::IsIntegralConstantValue(const NamedDecl *ND) const { | ||||
1410 | if (!IsOrdinaryNonTypeName(ND)) | ||||
1411 | return 0; | ||||
1412 | |||||
1413 | if (const auto *VD = dyn_cast<ValueDecl>(ND->getUnderlyingDecl())) | ||||
1414 | if (VD->getType()->isIntegralOrEnumerationType()) | ||||
1415 | return true; | ||||
1416 | |||||
1417 | return false; | ||||
1418 | } | ||||
1419 | |||||
1420 | /// Determines whether this given declaration will be found by | ||||
1421 | /// ordinary name lookup. | ||||
1422 | bool ResultBuilder::IsOrdinaryNonValueName(const NamedDecl *ND) const { | ||||
1423 | ND = ND->getUnderlyingDecl(); | ||||
1424 | |||||
1425 | unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_LocalExtern; | ||||
1426 | if (SemaRef.getLangOpts().CPlusPlus) | ||||
1427 | IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace; | ||||
1428 | |||||
1429 | return (ND->getIdentifierNamespace() & IDNS) && !isa<ValueDecl>(ND) && | ||||
1430 | !isa<FunctionTemplateDecl>(ND) && !isa<ObjCPropertyDecl>(ND); | ||||
1431 | } | ||||
1432 | |||||
1433 | /// Determines whether the given declaration is suitable as the | ||||
1434 | /// start of a C++ nested-name-specifier, e.g., a class or namespace. | ||||
1435 | bool ResultBuilder::IsNestedNameSpecifier(const NamedDecl *ND) const { | ||||
1436 | // Allow us to find class templates, too. | ||||
1437 | if (const auto *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND)) | ||||
1438 | ND = ClassTemplate->getTemplatedDecl(); | ||||
1439 | |||||
1440 | return SemaRef.isAcceptableNestedNameSpecifier(ND); | ||||
1441 | } | ||||
1442 | |||||
1443 | /// Determines whether the given declaration is an enumeration. | ||||
1444 | bool ResultBuilder::IsEnum(const NamedDecl *ND) const { | ||||
1445 | return isa<EnumDecl>(ND); | ||||
1446 | } | ||||
1447 | |||||
1448 | /// Determines whether the given declaration is a class or struct. | ||||
1449 | bool ResultBuilder::IsClassOrStruct(const NamedDecl *ND) const { | ||||
1450 | // Allow us to find class templates, too. | ||||
1451 | if (const auto *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND)) | ||||
1452 | ND = ClassTemplate->getTemplatedDecl(); | ||||
1453 | |||||
1454 | // For purposes of this check, interfaces match too. | ||||
1455 | if (const auto *RD = dyn_cast<RecordDecl>(ND)) | ||||
1456 | return RD->getTagKind() == TTK_Class || RD->getTagKind() == TTK_Struct || | ||||
1457 | RD->getTagKind() == TTK_Interface; | ||||
1458 | |||||
1459 | return false; | ||||
1460 | } | ||||
1461 | |||||
1462 | /// Determines whether the given declaration is a union. | ||||
1463 | bool ResultBuilder::IsUnion(const NamedDecl *ND) const { | ||||
1464 | // Allow us to find class templates, too. | ||||
1465 | if (const auto *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND)) | ||||
1466 | ND = ClassTemplate->getTemplatedDecl(); | ||||
1467 | |||||
1468 | if (const auto *RD = dyn_cast<RecordDecl>(ND)) | ||||
1469 | return RD->getTagKind() == TTK_Union; | ||||
1470 | |||||
1471 | return false; | ||||
1472 | } | ||||
1473 | |||||
1474 | /// Determines whether the given declaration is a namespace. | ||||
1475 | bool ResultBuilder::IsNamespace(const NamedDecl *ND) const { | ||||
1476 | return isa<NamespaceDecl>(ND); | ||||
1477 | } | ||||
1478 | |||||
1479 | /// Determines whether the given declaration is a namespace or | ||||
1480 | /// namespace alias. | ||||
1481 | bool ResultBuilder::IsNamespaceOrAlias(const NamedDecl *ND) const { | ||||
1482 | return isa<NamespaceDecl>(ND->getUnderlyingDecl()); | ||||
1483 | } | ||||
1484 | |||||
1485 | /// Determines whether the given declaration is a type. | ||||
1486 | bool ResultBuilder::IsType(const NamedDecl *ND) const { | ||||
1487 | ND = ND->getUnderlyingDecl(); | ||||
1488 | return isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND); | ||||
1489 | } | ||||
1490 | |||||
1491 | /// Determines which members of a class should be visible via | ||||
1492 | /// "." or "->". Only value declarations, nested name specifiers, and | ||||
1493 | /// using declarations thereof should show up. | ||||
1494 | bool ResultBuilder::IsMember(const NamedDecl *ND) const { | ||||
1495 | ND = ND->getUnderlyingDecl(); | ||||
1496 | return isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND) || | ||||
1497 | isa<ObjCPropertyDecl>(ND); | ||||
1498 | } | ||||
1499 | |||||
1500 | static bool isObjCReceiverType(ASTContext &C, QualType T) { | ||||
1501 | T = C.getCanonicalType(T); | ||||
1502 | switch (T->getTypeClass()) { | ||||
1503 | case Type::ObjCObject: | ||||
1504 | case Type::ObjCInterface: | ||||
1505 | case Type::ObjCObjectPointer: | ||||
1506 | return true; | ||||
1507 | |||||
1508 | case Type::Builtin: | ||||
1509 | switch (cast<BuiltinType>(T)->getKind()) { | ||||
1510 | case BuiltinType::ObjCId: | ||||
1511 | case BuiltinType::ObjCClass: | ||||
1512 | case BuiltinType::ObjCSel: | ||||
1513 | return true; | ||||
1514 | |||||
1515 | default: | ||||
1516 | break; | ||||
1517 | } | ||||
1518 | return false; | ||||
1519 | |||||
1520 | default: | ||||
1521 | break; | ||||
1522 | } | ||||
1523 | |||||
1524 | if (!C.getLangOpts().CPlusPlus) | ||||
1525 | return false; | ||||
1526 | |||||
1527 | // FIXME: We could perform more analysis here to determine whether a | ||||
1528 | // particular class type has any conversions to Objective-C types. For now, | ||||
1529 | // just accept all class types. | ||||
1530 | return T->isDependentType() || T->isRecordType(); | ||||
1531 | } | ||||
1532 | |||||
1533 | bool ResultBuilder::IsObjCMessageReceiver(const NamedDecl *ND) const { | ||||
1534 | QualType T = getDeclUsageType(SemaRef.Context, ND); | ||||
1535 | if (T.isNull()) | ||||
1536 | return false; | ||||
1537 | |||||
1538 | T = SemaRef.Context.getBaseElementType(T); | ||||
1539 | return isObjCReceiverType(SemaRef.Context, T); | ||||
1540 | } | ||||
1541 | |||||
1542 | bool ResultBuilder::IsObjCMessageReceiverOrLambdaCapture( | ||||
1543 | const NamedDecl *ND) const { | ||||
1544 | if (IsObjCMessageReceiver(ND)) | ||||
1545 | return true; | ||||
1546 | |||||
1547 | const auto *Var = dyn_cast<VarDecl>(ND); | ||||
1548 | if (!Var) | ||||
1549 | return false; | ||||
1550 | |||||
1551 | return Var->hasLocalStorage() && !Var->hasAttr<BlocksAttr>(); | ||||
1552 | } | ||||
1553 | |||||
1554 | bool ResultBuilder::IsObjCCollection(const NamedDecl *ND) const { | ||||
1555 | if ((SemaRef.getLangOpts().CPlusPlus && !IsOrdinaryName(ND)) || | ||||
1556 | (!SemaRef.getLangOpts().CPlusPlus && !IsOrdinaryNonTypeName(ND))) | ||||
1557 | return false; | ||||
1558 | |||||
1559 | QualType T = getDeclUsageType(SemaRef.Context, ND); | ||||
1560 | if (T.isNull()) | ||||
1561 | return false; | ||||
1562 | |||||
1563 | T = SemaRef.Context.getBaseElementType(T); | ||||
1564 | return T->isObjCObjectType() || T->isObjCObjectPointerType() || | ||||
1565 | T->isObjCIdType() || | ||||
1566 | (SemaRef.getLangOpts().CPlusPlus && T->isRecordType()); | ||||
1567 | } | ||||
1568 | |||||
1569 | bool ResultBuilder::IsImpossibleToSatisfy(const NamedDecl *ND) const { | ||||
1570 | return false; | ||||
1571 | } | ||||
1572 | |||||
1573 | /// Determines whether the given declaration is an Objective-C | ||||
1574 | /// instance variable. | ||||
1575 | bool ResultBuilder::IsObjCIvar(const NamedDecl *ND) const { | ||||
1576 | return isa<ObjCIvarDecl>(ND); | ||||
1577 | } | ||||
1578 | |||||
1579 | namespace { | ||||
1580 | |||||
1581 | /// Visible declaration consumer that adds a code-completion result | ||||
1582 | /// for each visible declaration. | ||||
1583 | class CodeCompletionDeclConsumer : public VisibleDeclConsumer { | ||||
1584 | ResultBuilder &Results; | ||||
1585 | DeclContext *InitialLookupCtx; | ||||
1586 | // NamingClass and BaseType are used for access-checking. See | ||||
1587 | // Sema::IsSimplyAccessible for details. | ||||
1588 | CXXRecordDecl *NamingClass; | ||||
1589 | QualType BaseType; | ||||
1590 | std::vector<FixItHint> FixIts; | ||||
1591 | |||||
1592 | public: | ||||
1593 | CodeCompletionDeclConsumer( | ||||
1594 | ResultBuilder &Results, DeclContext *InitialLookupCtx, | ||||
1595 | QualType BaseType = QualType(), | ||||
1596 | std::vector<FixItHint> FixIts = std::vector<FixItHint>()) | ||||
1597 | : Results(Results), InitialLookupCtx(InitialLookupCtx), | ||||
1598 | FixIts(std::move(FixIts)) { | ||||
1599 | NamingClass = llvm::dyn_cast<CXXRecordDecl>(InitialLookupCtx); | ||||
1600 | // If BaseType was not provided explicitly, emulate implicit 'this->'. | ||||
1601 | if (BaseType.isNull()) { | ||||
1602 | auto ThisType = Results.getSema().getCurrentThisType(); | ||||
1603 | if (!ThisType.isNull()) { | ||||
1604 | assert(ThisType->isPointerType())((ThisType->isPointerType()) ? static_cast<void> (0) : __assert_fail ("ThisType->isPointerType()", "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/clang/lib/Sema/SemaCodeComplete.cpp" , 1604, __PRETTY_FUNCTION__)); | ||||
1605 | BaseType = ThisType->getPointeeType(); | ||||
1606 | if (!NamingClass) | ||||
1607 | NamingClass = BaseType->getAsCXXRecordDecl(); | ||||
1608 | } | ||||
1609 | } | ||||
1610 | this->BaseType = BaseType; | ||||
1611 | } | ||||
1612 | |||||
1613 | void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx, | ||||
1614 | bool InBaseClass) override { | ||||
1615 | ResultBuilder::Result Result(ND, Results.getBasePriority(ND), nullptr, | ||||
1616 | false, IsAccessible(ND, Ctx), FixIts); | ||||
1617 | Results.AddResult(Result, InitialLookupCtx, Hiding, InBaseClass); | ||||
1618 | } | ||||
1619 | |||||
1620 | void EnteredContext(DeclContext *Ctx) override { | ||||
1621 | Results.addVisitedContext(Ctx); | ||||
1622 | } | ||||
1623 | |||||
1624 | private: | ||||
1625 | bool IsAccessible(NamedDecl *ND, DeclContext *Ctx) { | ||||
1626 | // Naming class to use for access check. In most cases it was provided | ||||
1627 | // explicitly (e.g. member access (lhs.foo) or qualified lookup (X::)), | ||||
1628 | // for unqualified lookup we fallback to the \p Ctx in which we found the | ||||
1629 | // member. | ||||
1630 | auto *NamingClass = this->NamingClass; | ||||
1631 | QualType BaseType = this->BaseType; | ||||
1632 | if (auto *Cls = llvm::dyn_cast_or_null<CXXRecordDecl>(Ctx)) { | ||||
1633 | if (!NamingClass) | ||||
1634 | NamingClass = Cls; | ||||
1635 | // When we emulate implicit 'this->' in an unqualified lookup, we might | ||||
1636 | // end up with an invalid naming class. In that case, we avoid emulating | ||||
1637 | // 'this->' qualifier to satisfy preconditions of the access checking. | ||||
1638 | if (NamingClass->getCanonicalDecl() != Cls->getCanonicalDecl() && | ||||
1639 | !NamingClass->isDerivedFrom(Cls)) { | ||||
1640 | NamingClass = Cls; | ||||
1641 | BaseType = QualType(); | ||||
1642 | } | ||||
1643 | } else { | ||||
1644 | // The decl was found outside the C++ class, so only ObjC access checks | ||||
1645 | // apply. Those do not rely on NamingClass and BaseType, so we clear them | ||||
1646 | // out. | ||||
1647 | NamingClass = nullptr; | ||||
1648 | BaseType = QualType(); | ||||
1649 | } | ||||
1650 | return Results.getSema().IsSimplyAccessible(ND, NamingClass, BaseType); | ||||
1651 | } | ||||
1652 | }; | ||||
1653 | } // namespace | ||||
1654 | |||||
1655 | /// Add type specifiers for the current language as keyword results. | ||||
1656 | static void AddTypeSpecifierResults(const LangOptions &LangOpts, | ||||
1657 | ResultBuilder &Results) { | ||||
1658 | typedef CodeCompletionResult Result; | ||||
1659 | Results.AddResult(Result("short", CCP_Type)); | ||||
1660 | Results.AddResult(Result("long", CCP_Type)); | ||||
1661 | Results.AddResult(Result("signed", CCP_Type)); | ||||
1662 | Results.AddResult(Result("unsigned", CCP_Type)); | ||||
1663 | Results.AddResult(Result("void", CCP_Type)); | ||||
1664 | Results.AddResult(Result("char", CCP_Type)); | ||||
1665 | Results.AddResult(Result("int", CCP_Type)); | ||||
1666 | Results.AddResult(Result("float", CCP_Type)); | ||||
1667 | Results.AddResult(Result("double", CCP_Type)); | ||||
1668 | Results.AddResult(Result("enum", CCP_Type)); | ||||
1669 | Results.AddResult(Result("struct", CCP_Type)); | ||||
1670 | Results.AddResult(Result("union", CCP_Type)); | ||||
1671 | Results.AddResult(Result("const", CCP_Type)); | ||||
1672 | Results.AddResult(Result("volatile", CCP_Type)); | ||||
1673 | |||||
1674 | if (LangOpts.C99) { | ||||
1675 | // C99-specific | ||||
1676 | Results.AddResult(Result("_Complex", CCP_Type)); | ||||
1677 | Results.AddResult(Result("_Imaginary", CCP_Type)); | ||||
1678 | Results.AddResult(Result("_Bool", CCP_Type)); | ||||
1679 | Results.AddResult(Result("restrict", CCP_Type)); | ||||
1680 | } | ||||
1681 | |||||
1682 | CodeCompletionBuilder Builder(Results.getAllocator(), | ||||
1683 | Results.getCodeCompletionTUInfo()); | ||||
1684 | if (LangOpts.CPlusPlus) { | ||||
1685 | // C++-specific | ||||
1686 | Results.AddResult( | ||||
1687 | Result("bool", CCP_Type + (LangOpts.ObjC ? CCD_bool_in_ObjC : 0))); | ||||
1688 | Results.AddResult(Result("class", CCP_Type)); | ||||
1689 | Results.AddResult(Result("wchar_t", CCP_Type)); | ||||
1690 | |||||
1691 | // typename qualified-id | ||||
1692 | Builder.AddTypedTextChunk("typename"); | ||||
1693 | Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | ||||
1694 | Builder.AddPlaceholderChunk("qualifier"); | ||||
1695 | Builder.AddTextChunk("::"); | ||||
1696 | Builder.AddPlaceholderChunk("name"); | ||||
1697 | Results.AddResult(Result(Builder.TakeString())); | ||||
1698 | |||||
1699 | if (LangOpts.CPlusPlus11) { | ||||
1700 | Results.AddResult(Result("auto", CCP_Type)); | ||||
1701 | Results.AddResult(Result("char16_t", CCP_Type)); | ||||
1702 | Results.AddResult(Result("char32_t", CCP_Type)); | ||||
1703 | |||||
1704 | Builder.AddTypedTextChunk("decltype"); | ||||
1705 | Builder.AddChunk(CodeCompletionString::CK_LeftParen); | ||||
1706 | Builder.AddPlaceholderChunk("expression"); | ||||
1707 | Builder.AddChunk(CodeCompletionString::CK_RightParen); | ||||
1708 | Results.AddResult(Result(Builder.TakeString())); | ||||
1709 | } | ||||
1710 | } else | ||||
1711 | Results.AddResult(Result("__auto_type", CCP_Type)); | ||||
1712 | |||||
1713 | // GNU keywords | ||||
1714 | if (LangOpts.GNUKeywords) { | ||||
1715 | // FIXME: Enable when we actually support decimal floating point. | ||||
1716 | // Results.AddResult(Result("_Decimal32")); | ||||
1717 | // Results.AddResult(Result("_Decimal64")); | ||||
1718 | // Results.AddResult(Result("_Decimal128")); | ||||
1719 | |||||
1720 | Builder.AddTypedTextChunk("typeof"); | ||||
1721 | Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | ||||
1722 | Builder.AddPlaceholderChunk("expression"); | ||||
1723 | Results.AddResult(Result(Builder.TakeString())); | ||||
1724 | |||||
1725 | Builder.AddTypedTextChunk("typeof"); | ||||
1726 | Builder.AddChunk(CodeCompletionString::CK_LeftParen); | ||||
1727 | Builder.AddPlaceholderChunk("type"); | ||||
1728 | Builder.AddChunk(CodeCompletionString::CK_RightParen); | ||||
1729 | Results.AddResult(Result(Builder.TakeString())); | ||||
1730 | } | ||||
1731 | |||||
1732 | // Nullability | ||||
1733 | Results.AddResult(Result("_Nonnull", CCP_Type)); | ||||
1734 | Results.AddResult(Result("_Null_unspecified", CCP_Type)); | ||||
1735 | Results.AddResult(Result("_Nullable", CCP_Type)); | ||||
1736 | } | ||||
1737 | |||||
1738 | static void AddStorageSpecifiers(Sema::ParserCompletionContext CCC, | ||||
1739 | const LangOptions &LangOpts, | ||||
1740 | ResultBuilder &Results) { | ||||
1741 | typedef CodeCompletionResult Result; | ||||
1742 | // Note: we don't suggest either "auto" or "register", because both | ||||
1743 | // are pointless as storage specifiers. Elsewhere, we suggest "auto" | ||||
1744 | // in C++0x as a type specifier. | ||||
1745 | Results.AddResult(Result("extern")); | ||||
1746 | Results.AddResult(Result("static")); | ||||
1747 | |||||
1748 | if (LangOpts.CPlusPlus11) { | ||||
1749 | CodeCompletionAllocator &Allocator = Results.getAllocator(); | ||||
1750 | CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo()); | ||||
1751 | |||||
1752 | // alignas | ||||
1753 | Builder.AddTypedTextChunk("alignas"); | ||||
1754 | Builder.AddChunk(CodeCompletionString::CK_LeftParen); | ||||
1755 | Builder.AddPlaceholderChunk("expression"); | ||||
1756 | Builder.AddChunk(CodeCompletionString::CK_RightParen); | ||||
1757 | Results.AddResult(Result(Builder.TakeString())); | ||||
1758 | |||||
1759 | Results.AddResult(Result("constexpr")); | ||||
1760 | Results.AddResult(Result("thread_local")); | ||||
1761 | } | ||||
1762 | } | ||||
1763 | |||||
1764 | static void AddFunctionSpecifiers(Sema::ParserCompletionContext CCC, | ||||
1765 | const LangOptions &LangOpts, | ||||
1766 | ResultBuilder &Results) { | ||||
1767 | typedef CodeCompletionResult Result; | ||||
1768 | switch (CCC) { | ||||
1769 | case Sema::PCC_Class: | ||||
1770 | case Sema::PCC_MemberTemplate: | ||||
1771 | if (LangOpts.CPlusPlus) { | ||||
1772 | Results.AddResult(Result("explicit")); | ||||
1773 | Results.AddResult(Result("friend")); | ||||
1774 | Results.AddResult(Result("mutable")); | ||||
1775 | Results.AddResult(Result("virtual")); | ||||
1776 | } | ||||
1777 | LLVM_FALLTHROUGH[[gnu::fallthrough]]; | ||||
1778 | |||||
1779 | case Sema::PCC_ObjCInterface: | ||||
1780 | case Sema::PCC_ObjCImplementation: | ||||
1781 | case Sema::PCC_Namespace: | ||||
1782 | case Sema::PCC_Template: | ||||
1783 | if (LangOpts.CPlusPlus || LangOpts.C99) | ||||
1784 | Results.AddResult(Result("inline")); | ||||
1785 | break; | ||||
1786 | |||||
1787 | case Sema::PCC_ObjCInstanceVariableList: | ||||
1788 | case Sema::PCC_Expression: | ||||
1789 | case Sema::PCC_Statement: | ||||
1790 | case Sema::PCC_ForInit: | ||||
1791 | case Sema::PCC_Condition: | ||||
1792 | case Sema::PCC_RecoveryInFunction: | ||||
1793 | case Sema::PCC_Type: | ||||
1794 | case Sema::PCC_ParenthesizedExpression: | ||||
1795 | case Sema::PCC_LocalDeclarationSpecifiers: | ||||
1796 | break; | ||||
1797 | } | ||||
1798 | } | ||||
1799 | |||||
1800 | static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt); | ||||
1801 | static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt); | ||||
1802 | static void AddObjCVisibilityResults(const LangOptions &LangOpts, | ||||
1803 | ResultBuilder &Results, bool NeedAt); | ||||
1804 | static void AddObjCImplementationResults(const LangOptions &LangOpts, | ||||
1805 | ResultBuilder &Results, bool NeedAt); | ||||
1806 | static void AddObjCInterfaceResults(const LangOptions &LangOpts, | ||||
1807 | ResultBuilder &Results, bool NeedAt); | ||||
1808 | static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt); | ||||
1809 | |||||
1810 | static void AddTypedefResult(ResultBuilder &Results) { | ||||
1811 | CodeCompletionBuilder Builder(Results.getAllocator(), | ||||
1812 | Results.getCodeCompletionTUInfo()); | ||||
1813 | Builder.AddTypedTextChunk("typedef"); | ||||
1814 | Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | ||||
1815 | Builder.AddPlaceholderChunk("type"); | ||||
1816 | Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | ||||
1817 | Builder.AddPlaceholderChunk("name"); | ||||
1818 | Builder.AddChunk(CodeCompletionString::CK_SemiColon); | ||||
1819 | Results.AddResult(CodeCompletionResult(Builder.TakeString())); | ||||
1820 | } | ||||
1821 | |||||
1822 | static bool WantTypesInContext(Sema::ParserCompletionContext CCC, | ||||
1823 | const LangOptions &LangOpts) { | ||||
1824 | switch (CCC) { | ||||
1825 | case Sema::PCC_Namespace: | ||||
1826 | case Sema::PCC_Class: | ||||
1827 | case Sema::PCC_ObjCInstanceVariableList: | ||||
1828 | case Sema::PCC_Template: | ||||
1829 | case Sema::PCC_MemberTemplate: | ||||
1830 | case Sema::PCC_Statement: | ||||
1831 | case Sema::PCC_RecoveryInFunction: | ||||
1832 | case Sema::PCC_Type: | ||||
1833 | case Sema::PCC_ParenthesizedExpression: | ||||
1834 | case Sema::PCC_LocalDeclarationSpecifiers: | ||||
1835 | return true; | ||||
1836 | |||||
1837 | case Sema::PCC_Expression: | ||||
1838 | case Sema::PCC_Condition: | ||||
1839 | return LangOpts.CPlusPlus; | ||||
1840 | |||||
1841 | case Sema::PCC_ObjCInterface: | ||||
1842 | case Sema::PCC_ObjCImplementation: | ||||
1843 | return false; | ||||
1844 | |||||
1845 | case Sema::PCC_ForInit: | ||||
1846 | return LangOpts.CPlusPlus || LangOpts.ObjC || LangOpts.C99; | ||||
1847 | } | ||||
1848 | |||||
1849 | llvm_unreachable("Invalid ParserCompletionContext!")::llvm::llvm_unreachable_internal("Invalid ParserCompletionContext!" , "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/clang/lib/Sema/SemaCodeComplete.cpp" , 1849); | ||||
1850 | } | ||||
1851 | |||||
1852 | static PrintingPolicy getCompletionPrintingPolicy(const ASTContext &Context, | ||||
1853 | const Preprocessor &PP) { | ||||
1854 | PrintingPolicy Policy = Sema::getPrintingPolicy(Context, PP); | ||||
1855 | Policy.AnonymousTagLocations = false; | ||||
1856 | Policy.SuppressStrongLifetime = true; | ||||
1857 | Policy.SuppressUnwrittenScope = true; | ||||
1858 | Policy.SuppressScope = true; | ||||
1859 | return Policy; | ||||
1860 | } | ||||
1861 | |||||
1862 | /// Retrieve a printing policy suitable for code completion. | ||||
1863 | static PrintingPolicy getCompletionPrintingPolicy(Sema &S) { | ||||
1864 | return getCompletionPrintingPolicy(S.Context, S.PP); | ||||
1865 | } | ||||
1866 | |||||
1867 | /// Retrieve the string representation of the given type as a string | ||||
1868 | /// that has the appropriate lifetime for code completion. | ||||
1869 | /// | ||||
1870 | /// This routine provides a fast path where we provide constant strings for | ||||
1871 | /// common type names. | ||||
1872 | static const char *GetCompletionTypeString(QualType T, ASTContext &Context, | ||||
1873 | const PrintingPolicy &Policy, | ||||
1874 | CodeCompletionAllocator &Allocator) { | ||||
1875 | if (!T.getLocalQualifiers()) { | ||||
1876 | // Built-in type names are constant strings. | ||||
1877 | if (const BuiltinType *BT = dyn_cast<BuiltinType>(T)) | ||||
1878 | return BT->getNameAsCString(Policy); | ||||
1879 | |||||
1880 | // Anonymous tag types are constant strings. | ||||
1881 | if (const TagType *TagT = dyn_cast<TagType>(T)) | ||||
1882 | if (TagDecl *Tag = TagT->getDecl()) | ||||
1883 | if (!Tag->hasNameForLinkage()) { | ||||
1884 | switch (Tag->getTagKind()) { | ||||
1885 | case TTK_Struct: | ||||
1886 | return "struct <anonymous>"; | ||||
1887 | case TTK_Interface: | ||||
1888 | return "__interface <anonymous>"; | ||||
1889 | case TTK_Class: | ||||
1890 | return "class <anonymous>"; | ||||
1891 | case TTK_Union: | ||||
1892 | return "union <anonymous>"; | ||||
1893 | case TTK_Enum: | ||||
1894 | return "enum <anonymous>"; | ||||
1895 | } | ||||
1896 | } | ||||
1897 | } | ||||
1898 | |||||
1899 | // Slow path: format the type as a string. | ||||
1900 | std::string Result; | ||||
1901 | T.getAsStringInternal(Result, Policy); | ||||
1902 | return Allocator.CopyString(Result); | ||||
1903 | } | ||||
1904 | |||||
1905 | /// Add a completion for "this", if we're in a member function. | ||||
1906 | static void addThisCompletion(Sema &S, ResultBuilder &Results) { | ||||
1907 | QualType ThisTy = S.getCurrentThisType(); | ||||
1908 | if (ThisTy.isNull()) | ||||
1909 | return; | ||||
1910 | |||||
1911 | CodeCompletionAllocator &Allocator = Results.getAllocator(); | ||||
1912 | CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo()); | ||||
1913 | PrintingPolicy Policy = getCompletionPrintingPolicy(S); | ||||
1914 | Builder.AddResultTypeChunk( | ||||
1915 | GetCompletionTypeString(ThisTy, S.Context, Policy, Allocator)); | ||||
1916 | Builder.AddTypedTextChunk("this"); | ||||
1917 | Results.AddResult(CodeCompletionResult(Builder.TakeString())); | ||||
1918 | } | ||||
1919 | |||||
1920 | static void AddStaticAssertResult(CodeCompletionBuilder &Builder, | ||||
1921 | ResultBuilder &Results, | ||||
1922 | const LangOptions &LangOpts) { | ||||
1923 | if (!LangOpts.CPlusPlus11) | ||||
1924 | return; | ||||
1925 | |||||
1926 | Builder.AddTypedTextChunk("static_assert"); | ||||
1927 | Builder.AddChunk(CodeCompletionString::CK_LeftParen); | ||||
1928 | Builder.AddPlaceholderChunk("expression"); | ||||
1929 | Builder.AddChunk(CodeCompletionString::CK_Comma); | ||||
1930 | Builder.AddPlaceholderChunk("message"); | ||||
1931 | Builder.AddChunk(CodeCompletionString::CK_RightParen); | ||||
1932 | Builder.AddChunk(CodeCompletionString::CK_SemiColon); | ||||
1933 | Results.AddResult(CodeCompletionResult(Builder.TakeString())); | ||||
1934 | } | ||||
1935 | |||||
1936 | static void AddOverrideResults(ResultBuilder &Results, | ||||
1937 | const CodeCompletionContext &CCContext, | ||||
1938 | CodeCompletionBuilder &Builder) { | ||||
1939 | Sema &S = Results.getSema(); | ||||
1940 | const auto *CR = llvm::dyn_cast<CXXRecordDecl>(S.CurContext); | ||||
1941 | // If not inside a class/struct/union return empty. | ||||
1942 | if (!CR) | ||||
1943 | return; | ||||
1944 | // First store overrides within current class. | ||||
1945 | // These are stored by name to make querying fast in the later step. | ||||
1946 | llvm::StringMap<std::vector<FunctionDecl *>> Overrides; | ||||
1947 | for (auto *Method : CR->methods()) { | ||||
1948 | if (!Method->isVirtual() || !Method->getIdentifier()) | ||||
1949 | continue; | ||||
1950 | Overrides[Method->getName()].push_back(Method); | ||||
1951 | } | ||||
1952 | |||||
1953 | for (const auto &Base : CR->bases()) { | ||||
1954 | const auto *BR = Base.getType().getTypePtr()->getAsCXXRecordDecl(); | ||||
1955 | if (!BR) | ||||
1956 | continue; | ||||
1957 | for (auto *Method : BR->methods()) { | ||||
1958 | if (!Method->isVirtual() || !Method->getIdentifier()) | ||||
1959 | continue; | ||||
1960 | const auto it = Overrides.find(Method->getName()); | ||||
1961 | bool IsOverriden = false; | ||||
1962 | if (it != Overrides.end()) { | ||||
1963 | for (auto *MD : it->second) { | ||||
1964 | // If the method in current body is not an overload of this virtual | ||||
1965 | // function, then it overrides this one. | ||||
1966 | if (!S.IsOverload(MD, Method, false)) { | ||||
1967 | IsOverriden = true; | ||||
1968 | break; | ||||
1969 | } | ||||
1970 | } | ||||
1971 | } | ||||
1972 | if (!IsOverriden) { | ||||
1973 | // Generates a new CodeCompletionResult by taking this function and | ||||
1974 | // converting it into an override declaration with only one chunk in the | ||||
1975 | // final CodeCompletionString as a TypedTextChunk. | ||||
1976 | std::string OverrideSignature; | ||||
1977 | llvm::raw_string_ostream OS(OverrideSignature); | ||||
1978 | CodeCompletionResult CCR(Method, 0); | ||||
1979 | PrintingPolicy Policy = | ||||
1980 | getCompletionPrintingPolicy(S.getASTContext(), S.getPreprocessor()); | ||||
1981 | auto *CCS = CCR.createCodeCompletionStringForOverride( | ||||
1982 | S.getPreprocessor(), S.getASTContext(), Builder, | ||||
1983 | /*IncludeBriefComments=*/false, CCContext, Policy); | ||||
1984 | Results.AddResult(CodeCompletionResult(CCS, Method, CCP_CodePattern)); | ||||
1985 | } | ||||
1986 | } | ||||
1987 | } | ||||
1988 | } | ||||
1989 | |||||
1990 | /// Add language constructs that show up for "ordinary" names. | ||||
1991 | static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, Scope *S, | ||||
1992 | Sema &SemaRef, ResultBuilder &Results) { | ||||
1993 | CodeCompletionAllocator &Allocator = Results.getAllocator(); | ||||
1994 | CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo()); | ||||
1995 | |||||
1996 | typedef CodeCompletionResult Result; | ||||
1997 | switch (CCC) { | ||||
1998 | case Sema::PCC_Namespace: | ||||
1999 | if (SemaRef.getLangOpts().CPlusPlus) { | ||||
2000 | if (Results.includeCodePatterns()) { | ||||
2001 | // namespace <identifier> { declarations } | ||||
2002 | Builder.AddTypedTextChunk("namespace"); | ||||
2003 | Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | ||||
2004 | Builder.AddPlaceholderChunk("identifier"); | ||||
2005 | Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | ||||
2006 | Builder.AddChunk(CodeCompletionString::CK_LeftBrace); | ||||
2007 | Builder.AddChunk(CodeCompletionString::CK_VerticalSpace); | ||||
2008 | Builder.AddPlaceholderChunk("declarations"); | ||||
2009 | Builder.AddChunk(CodeCompletionString::CK_VerticalSpace); | ||||
2010 | Builder.AddChunk(CodeCompletionString::CK_RightBrace); | ||||
2011 | Results.AddResult(Result(Builder.TakeString())); | ||||
2012 | } | ||||
2013 | |||||
2014 | // namespace identifier = identifier ; | ||||
2015 | Builder.AddTypedTextChunk("namespace"); | ||||
2016 | Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | ||||
2017 | Builder.AddPlaceholderChunk("name"); | ||||
2018 | Builder.AddChunk(CodeCompletionString::CK_Equal); | ||||
2019 | Builder.AddPlaceholderChunk("namespace"); | ||||
2020 | Builder.AddChunk(CodeCompletionString::CK_SemiColon); | ||||
2021 | Results.AddResult(Result(Builder.TakeString())); | ||||
2022 | |||||
2023 | // Using directives | ||||
2024 | Builder.AddTypedTextChunk("using namespace"); | ||||
2025 | Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | ||||
2026 | Builder.AddPlaceholderChunk("identifier"); | ||||
2027 | Builder.AddChunk(CodeCompletionString::CK_SemiColon); | ||||
2028 | Results.AddResult(Result(Builder.TakeString())); | ||||
2029 | |||||
2030 | // asm(string-literal) | ||||
2031 | Builder.AddTypedTextChunk("asm"); | ||||
2032 | Builder.AddChunk(CodeCompletionString::CK_LeftParen); | ||||
2033 | Builder.AddPlaceholderChunk("string-literal"); | ||||
2034 | Builder.AddChunk(CodeCompletionString::CK_RightParen); | ||||
2035 | Results.AddResult(Result(Builder.TakeString())); | ||||
2036 | |||||
2037 | if (Results.includeCodePatterns()) { | ||||
2038 | // Explicit template instantiation | ||||
2039 | Builder.AddTypedTextChunk("template"); | ||||
2040 | Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | ||||
2041 | Builder.AddPlaceholderChunk("declaration"); | ||||
2042 | Results.AddResult(Result(Builder.TakeString())); | ||||
2043 | } else { | ||||
2044 | Results.AddResult(Result("template", CodeCompletionResult::RK_Keyword)); | ||||
2045 | } | ||||
2046 | } | ||||
2047 | |||||
2048 | if (SemaRef.getLangOpts().ObjC) | ||||
2049 | AddObjCTopLevelResults(Results, true); | ||||
2050 | |||||
2051 | AddTypedefResult(Results); | ||||
2052 | LLVM_FALLTHROUGH[[gnu::fallthrough]]; | ||||
2053 | |||||
2054 | case Sema::PCC_Class: | ||||
2055 | if (SemaRef.getLangOpts().CPlusPlus) { | ||||
2056 | // Using declaration | ||||
2057 | Builder.AddTypedTextChunk("using"); | ||||
2058 | Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | ||||
2059 | Builder.AddPlaceholderChunk("qualifier"); | ||||
2060 | Builder.AddTextChunk("::"); | ||||
2061 | Builder.AddPlaceholderChunk("name"); | ||||
2062 | Builder.AddChunk(CodeCompletionString::CK_SemiColon); | ||||
2063 | Results.AddResult(Result(Builder.TakeString())); | ||||
2064 | |||||
2065 | // using typename qualifier::name (only in a dependent context) | ||||
2066 | if (SemaRef.CurContext->isDependentContext()) { | ||||
2067 | Builder.AddTypedTextChunk("using typename"); | ||||
2068 | Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | ||||
2069 | Builder.AddPlaceholderChunk("qualifier"); | ||||
2070 | Builder.AddTextChunk("::"); | ||||
2071 | Builder.AddPlaceholderChunk("name"); | ||||
2072 | Builder.AddChunk(CodeCompletionString::CK_SemiColon); | ||||
2073 | Results.AddResult(Result(Builder.TakeString())); | ||||
2074 | } | ||||
2075 | |||||
2076 | AddStaticAssertResult(Builder, Results, SemaRef.getLangOpts()); | ||||
2077 | |||||
2078 | if (CCC == Sema::PCC_Class) { | ||||
2079 | AddTypedefResult(Results); | ||||
2080 | |||||
2081 | bool IsNotInheritanceScope = | ||||
2082 | !(S->getFlags() & Scope::ClassInheritanceScope); | ||||
2083 | // public: | ||||
2084 | Builder.AddTypedTextChunk("public"); | ||||
2085 | if (IsNotInheritanceScope && Results.includeCodePatterns()) | ||||
2086 | Builder.AddChunk(CodeCompletionString::CK_Colon); | ||||
2087 | Results.AddResult(Result(Builder.TakeString())); | ||||
2088 | |||||
2089 | // protected: | ||||
2090 | Builder.AddTypedTextChunk("protected"); | ||||
2091 | if (IsNotInheritanceScope && Results.includeCodePatterns()) | ||||
2092 | Builder.AddChunk(CodeCompletionString::CK_Colon); | ||||
2093 | Results.AddResult(Result(Builder.TakeString())); | ||||
2094 | |||||
2095 | // private: | ||||
2096 | Builder.AddTypedTextChunk("private"); | ||||
2097 | if (IsNotInheritanceScope && Results.includeCodePatterns()) | ||||
2098 | Builder.AddChunk(CodeCompletionString::CK_Colon); | ||||
2099 | Results.AddResult(Result(Builder.TakeString())); | ||||
2100 | |||||
2101 | // FIXME: This adds override results only if we are at the first word of | ||||
2102 | // the declaration/definition. Also call this from other sides to have | ||||
2103 | // more use-cases. | ||||
2104 | AddOverrideResults(Results, CodeCompletionContext::CCC_ClassStructUnion, | ||||
2105 | Builder); | ||||
2106 | } | ||||
2107 | } | ||||
2108 | LLVM_FALLTHROUGH[[gnu::fallthrough]]; | ||||
2109 | |||||
2110 | case Sema::PCC_Template: | ||||
2111 | case Sema::PCC_MemberTemplate: | ||||
2112 | if (SemaRef.getLangOpts().CPlusPlus && Results.includeCodePatterns()) { | ||||
2113 | // template < parameters > | ||||
2114 | Builder.AddTypedTextChunk("template"); | ||||
2115 | Builder.AddChunk(CodeCompletionString::CK_LeftAngle); | ||||
2116 | Builder.AddPlaceholderChunk("parameters"); | ||||
2117 | Builder.AddChunk(CodeCompletionString::CK_RightAngle); | ||||
2118 | Results.AddResult(Result(Builder.TakeString())); | ||||
2119 | } else { | ||||
2120 | Results.AddResult(Result("template", CodeCompletionResult::RK_Keyword)); | ||||
2121 | } | ||||
2122 | |||||
2123 | AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results); | ||||
2124 | AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results); | ||||
2125 | break; | ||||
2126 | |||||
2127 | case Sema::PCC_ObjCInterface: | ||||
2128 | AddObjCInterfaceResults(SemaRef.getLangOpts(), Results, true); | ||||
2129 | AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results); | ||||
2130 | AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results); | ||||
2131 | break; | ||||
2132 | |||||
2133 | case Sema::PCC_ObjCImplementation: | ||||
2134 | AddObjCImplementationResults(SemaRef.getLangOpts(), Results, true); | ||||
2135 | AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results); | ||||
2136 | AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results); | ||||
2137 | break; | ||||
2138 | |||||
2139 | case Sema::PCC_ObjCInstanceVariableList: | ||||
2140 | AddObjCVisibilityResults(SemaRef.getLangOpts(), Results, true); | ||||
2141 | break; | ||||
2142 | |||||
2143 | case Sema::PCC_RecoveryInFunction: | ||||
2144 | case Sema::PCC_Statement: { | ||||
2145 | AddTypedefResult(Results); | ||||
2146 | |||||
2147 | if (SemaRef.getLangOpts().CPlusPlus && Results.includeCodePatterns() && | ||||
2148 | SemaRef.getLangOpts().CXXExceptions) { | ||||
2149 | Builder.AddTypedTextChunk("try"); | ||||
2150 | Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | ||||
2151 | Builder.AddChunk(CodeCompletionString::CK_LeftBrace); | ||||
2152 | Builder.AddChunk(CodeCompletionString::CK_VerticalSpace); | ||||
2153 | Builder.AddPlaceholderChunk("statements"); | ||||
2154 | Builder.AddChunk(CodeCompletionString::CK_VerticalSpace); | ||||
2155 | Builder.AddChunk(CodeCompletionString::CK_RightBrace); | ||||
2156 | Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | ||||
2157 | Builder.AddTextChunk("catch"); | ||||
2158 | Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | ||||
2159 | Builder.AddChunk(CodeCompletionString::CK_LeftParen); | ||||
2160 | Builder.AddPlaceholderChunk("declaration"); | ||||
2161 | Builder.AddChunk(CodeCompletionString::CK_RightParen); | ||||
2162 | Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | ||||
2163 | Builder.AddChunk(CodeCompletionString::CK_LeftBrace); | ||||
2164 | Builder.AddChunk(CodeCompletionString::CK_VerticalSpace); | ||||
2165 | Builder.AddPlaceholderChunk("statements"); | ||||
2166 | Builder.AddChunk(CodeCompletionString::CK_VerticalSpace); | ||||
2167 | Builder.AddChunk(CodeCompletionString::CK_RightBrace); | ||||
2168 | Results.AddResult(Result(Builder.TakeString())); | ||||
2169 | } | ||||
2170 | if (SemaRef.getLangOpts().ObjC) | ||||
2171 | AddObjCStatementResults(Results, true); | ||||
2172 | |||||
2173 | if (Results.includeCodePatterns()) { | ||||
2174 | // if (condition) { statements } | ||||
2175 | Builder.AddTypedTextChunk("if"); | ||||
2176 | Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | ||||
2177 | Builder.AddChunk(CodeCompletionString::CK_LeftParen); | ||||
2178 | if (SemaRef.getLangOpts().CPlusPlus) | ||||
2179 | Builder.AddPlaceholderChunk("condition"); | ||||
2180 | else | ||||
2181 | Builder.AddPlaceholderChunk("expression"); | ||||
2182 | Builder.AddChunk(CodeCompletionString::CK_RightParen); | ||||
2183 | Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | ||||
2184 | Builder.AddChunk(CodeCompletionString::CK_LeftBrace); | ||||
2185 | Builder.AddChunk(CodeCompletionString::CK_VerticalSpace); | ||||
2186 | Builder.AddPlaceholderChunk("statements"); | ||||
2187 | Builder.AddChunk(CodeCompletionString::CK_VerticalSpace); | ||||
2188 | Builder.AddChunk(CodeCompletionString::CK_RightBrace); | ||||
2189 | Results.AddResult(Result(Builder.TakeString())); | ||||
2190 | |||||
2191 | // switch (condition) { } | ||||
2192 | Builder.AddTypedTextChunk("switch"); | ||||
2193 | Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | ||||
2194 | Builder.AddChunk(CodeCompletionString::CK_LeftParen); | ||||
2195 | if (SemaRef.getLangOpts().CPlusPlus) | ||||
2196 | Builder.AddPlaceholderChunk("condition"); | ||||
2197 | else | ||||
2198 | Builder.AddPlaceholderChunk("expression"); | ||||
2199 | Builder.AddChunk(CodeCompletionString::CK_RightParen); | ||||
2200 | Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | ||||
2201 | Builder.AddChunk(CodeCompletionString::CK_LeftBrace); | ||||
2202 | Builder.AddChunk(CodeCompletionString::CK_VerticalSpace); | ||||
2203 | Builder.AddPlaceholderChunk("cases"); | ||||
2204 | Builder.AddChunk(CodeCompletionString::CK_VerticalSpace); | ||||
2205 | Builder.AddChunk(CodeCompletionString::CK_RightBrace); | ||||
2206 | Results.AddResult(Result(Builder.TakeString())); | ||||
2207 | } | ||||
2208 | |||||
2209 | // Switch-specific statements. | ||||
2210 | if (SemaRef.getCurFunction() && | ||||
2211 | !SemaRef.getCurFunction()->SwitchStack.empty()) { | ||||
2212 | // case expression: | ||||
2213 | Builder.AddTypedTextChunk("case"); | ||||
2214 | Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | ||||
2215 | Builder.AddPlaceholderChunk("expression"); | ||||
2216 | Builder.AddChunk(CodeCompletionString::CK_Colon); | ||||
2217 | Results.AddResult(Result(Builder.TakeString())); | ||||
2218 | |||||
2219 | // default: | ||||
2220 | Builder.AddTypedTextChunk("default"); | ||||
2221 | Builder.AddChunk(CodeCompletionString::CK_Colon); | ||||
2222 | Results.AddResult(Result(Builder.TakeString())); | ||||
2223 | } | ||||
2224 | |||||
2225 | if (Results.includeCodePatterns()) { | ||||
2226 | /// while (condition) { statements } | ||||
2227 | Builder.AddTypedTextChunk("while"); | ||||
2228 | Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | ||||
2229 | Builder.AddChunk(CodeCompletionString::CK_LeftParen); | ||||
2230 | if (SemaRef.getLangOpts().CPlusPlus) | ||||
2231 | Builder.AddPlaceholderChunk("condition"); | ||||
2232 | else | ||||
2233 | Builder.AddPlaceholderChunk("expression"); | ||||
2234 | Builder.AddChunk(CodeCompletionString::CK_RightParen); | ||||
2235 | Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | ||||
2236 | Builder.AddChunk(CodeCompletionString::CK_LeftBrace); | ||||
2237 | Builder.AddChunk(CodeCompletionString::CK_VerticalSpace); | ||||
2238 | Builder.AddPlaceholderChunk("statements"); | ||||
2239 | Builder.AddChunk(CodeCompletionString::CK_VerticalSpace); | ||||
2240 | Builder.AddChunk(CodeCompletionString::CK_RightBrace); | ||||
2241 | Results.AddResult(Result(Builder.TakeString())); | ||||
2242 | |||||
2243 | // do { statements } while ( expression ); | ||||
2244 | Builder.AddTypedTextChunk("do"); | ||||
2245 | Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | ||||
2246 | Builder.AddChunk(CodeCompletionString::CK_LeftBrace); | ||||
2247 | Builder.AddChunk(CodeCompletionString::CK_VerticalSpace); | ||||
2248 | Builder.AddPlaceholderChunk("statements"); | ||||
2249 | Builder.AddChunk(CodeCompletionString::CK_VerticalSpace); | ||||
2250 | Builder.AddChunk(CodeCompletionString::CK_RightBrace); | ||||
2251 | Builder.AddTextChunk("while"); | ||||
2252 | Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | ||||
2253 | Builder.AddChunk(CodeCompletionString::CK_LeftParen); | ||||
2254 | Builder.AddPlaceholderChunk("expression"); | ||||
2255 | Builder.AddChunk(CodeCompletionString::CK_RightParen); | ||||
2256 | Results.AddResult(Result(Builder.TakeString())); | ||||
2257 | |||||
2258 | // for ( for-init-statement ; condition ; expression ) { statements } | ||||
2259 | Builder.AddTypedTextChunk("for"); | ||||
2260 | Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | ||||
2261 | Builder.AddChunk(CodeCompletionString::CK_LeftParen); | ||||
2262 | if (SemaRef.getLangOpts().CPlusPlus || SemaRef.getLangOpts().C99) | ||||
2263 | Builder.AddPlaceholderChunk("init-statement"); | ||||
2264 | else | ||||
2265 | Builder.AddPlaceholderChunk("init-expression"); | ||||
2266 | Builder.AddChunk(CodeCompletionString::CK_SemiColon); | ||||
2267 | Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | ||||
2268 | Builder.AddPlaceholderChunk("condition"); | ||||
2269 | Builder.AddChunk(CodeCompletionString::CK_SemiColon); | ||||
2270 | Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | ||||
2271 | Builder.AddPlaceholderChunk("inc-expression"); | ||||
2272 | Builder.AddChunk(CodeCompletionString::CK_RightParen); | ||||
2273 | Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | ||||
2274 | Builder.AddChunk(CodeCompletionString::CK_LeftBrace); | ||||
2275 | Builder.AddChunk(CodeCompletionString::CK_VerticalSpace); | ||||
2276 | Builder.AddPlaceholderChunk("statements"); | ||||
2277 | Builder.AddChunk(CodeCompletionString::CK_VerticalSpace); | ||||
2278 | Builder.AddChunk(CodeCompletionString::CK_RightBrace); | ||||
2279 | Results.AddResult(Result(Builder.TakeString())); | ||||
2280 | } | ||||
2281 | |||||
2282 | if (S->getContinueParent()) { | ||||
2283 | // continue ; | ||||
2284 | Builder.AddTypedTextChunk("continue"); | ||||
2285 | Builder.AddChunk(CodeCompletionString::CK_SemiColon); | ||||
2286 | Results.AddResult(Result(Builder.TakeString())); | ||||
2287 | } | ||||
2288 | |||||
2289 | if (S->getBreakParent()) { | ||||
2290 | // break ; | ||||
2291 | Builder.AddTypedTextChunk("break"); | ||||
2292 | Builder.AddChunk(CodeCompletionString::CK_SemiColon); | ||||
2293 | Results.AddResult(Result(Builder.TakeString())); | ||||
2294 | } | ||||
2295 | |||||
2296 | // "return expression ;" or "return ;", depending on the return type. | ||||
2297 | QualType ReturnType; | ||||
2298 | if (const auto *Function = dyn_cast<FunctionDecl>(SemaRef.CurContext)) | ||||
2299 | ReturnType = Function->getReturnType(); | ||||
2300 | else if (const auto *Method = dyn_cast<ObjCMethodDecl>(SemaRef.CurContext)) | ||||
2301 | ReturnType = Method->getReturnType(); | ||||
2302 | else if (SemaRef.getCurBlock() && | ||||
2303 | !SemaRef.getCurBlock()->ReturnType.isNull()) | ||||
2304 | ReturnType = SemaRef.getCurBlock()->ReturnType;; | ||||
2305 | if (ReturnType.isNull() || ReturnType->isVoidType()) { | ||||
2306 | Builder.AddTypedTextChunk("return"); | ||||
2307 | Builder.AddChunk(CodeCompletionString::CK_SemiColon); | ||||
2308 | Results.AddResult(Result(Builder.TakeString())); | ||||
2309 | } else { | ||||
2310 | assert(!ReturnType.isNull())((!ReturnType.isNull()) ? static_cast<void> (0) : __assert_fail ("!ReturnType.isNull()", "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/clang/lib/Sema/SemaCodeComplete.cpp" , 2310, __PRETTY_FUNCTION__)); | ||||
2311 | // "return expression ;" | ||||
2312 | Builder.AddTypedTextChunk("return"); | ||||
2313 | Builder.AddChunk(clang::CodeCompletionString::CK_HorizontalSpace); | ||||
2314 | Builder.AddPlaceholderChunk("expression"); | ||||
2315 | Builder.AddChunk(CodeCompletionString::CK_SemiColon); | ||||
2316 | Results.AddResult(Result(Builder.TakeString())); | ||||
2317 | // When boolean, also add 'return true;' and 'return false;'. | ||||
2318 | if (ReturnType->isBooleanType()) { | ||||
2319 | Builder.AddTypedTextChunk("return true"); | ||||
2320 | Builder.AddChunk(CodeCompletionString::CK_SemiColon); | ||||
2321 | Results.AddResult(Result(Builder.TakeString())); | ||||
2322 | |||||
2323 | Builder.AddTypedTextChunk("return false"); | ||||
2324 | Builder.AddChunk(CodeCompletionString::CK_SemiColon); | ||||
2325 | Results.AddResult(Result(Builder.TakeString())); | ||||
2326 | } | ||||
2327 | } | ||||
2328 | |||||
2329 | // goto identifier ; | ||||
2330 | Builder.AddTypedTextChunk("goto"); | ||||
2331 | Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | ||||
2332 | Builder.AddPlaceholderChunk("label"); | ||||
2333 | Builder.AddChunk(CodeCompletionString::CK_SemiColon); | ||||
2334 | Results.AddResult(Result(Builder.TakeString())); | ||||
2335 | |||||
2336 | // Using directives | ||||
2337 | Builder.AddTypedTextChunk("using namespace"); | ||||
2338 | Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | ||||
2339 | Builder.AddPlaceholderChunk("identifier"); | ||||
2340 | Builder.AddChunk(CodeCompletionString::CK_SemiColon); | ||||
2341 | Results.AddResult(Result(Builder.TakeString())); | ||||
2342 | |||||
2343 | AddStaticAssertResult(Builder, Results, SemaRef.getLangOpts()); | ||||
2344 | } | ||||
2345 | LLVM_FALLTHROUGH[[gnu::fallthrough]]; | ||||
2346 | |||||
2347 | // Fall through (for statement expressions). | ||||
2348 | case Sema::PCC_ForInit: | ||||
2349 | case Sema::PCC_Condition: | ||||
2350 | AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results); | ||||
2351 | // Fall through: conditions and statements can have expressions. | ||||
2352 | LLVM_FALLTHROUGH[[gnu::fallthrough]]; | ||||
2353 | |||||
2354 | case Sema::PCC_ParenthesizedExpression: | ||||
2355 | if (SemaRef.getLangOpts().ObjCAutoRefCount && | ||||
2356 | CCC == Sema::PCC_ParenthesizedExpression) { | ||||
2357 | // (__bridge <type>)<expression> | ||||
2358 | Builder.AddTypedTextChunk("__bridge"); | ||||
2359 | Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | ||||
2360 | Builder.AddPlaceholderChunk("type"); | ||||
2361 | Builder.AddChunk(CodeCompletionString::CK_RightParen); | ||||
2362 | Builder.AddPlaceholderChunk("expression"); | ||||
2363 | Results.AddResult(Result(Builder.TakeString())); | ||||
2364 | |||||
2365 | // (__bridge_transfer <Objective-C type>)<expression> | ||||
2366 | Builder.AddTypedTextChunk("__bridge_transfer"); | ||||
2367 | Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | ||||
2368 | Builder.AddPlaceholderChunk("Objective-C type"); | ||||
2369 | Builder.AddChunk(CodeCompletionString::CK_RightParen); | ||||
2370 | Builder.AddPlaceholderChunk("expression"); | ||||
2371 | Results.AddResult(Result(Builder.TakeString())); | ||||
2372 | |||||
2373 | // (__bridge_retained <CF type>)<expression> | ||||
2374 | Builder.AddTypedTextChunk("__bridge_retained"); | ||||
2375 | Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | ||||
2376 | Builder.AddPlaceholderChunk("CF type"); | ||||
2377 | Builder.AddChunk(CodeCompletionString::CK_RightParen); | ||||
2378 | Builder.AddPlaceholderChunk("expression"); | ||||
2379 | Results.AddResult(Result(Builder.TakeString())); | ||||
2380 | } | ||||
2381 | // Fall through | ||||
2382 | LLVM_FALLTHROUGH[[gnu::fallthrough]]; | ||||
2383 | |||||
2384 | case Sema::PCC_Expression: { | ||||
2385 | if (SemaRef.getLangOpts().CPlusPlus) { | ||||
2386 | // 'this', if we're in a non-static member function. | ||||
2387 | addThisCompletion(SemaRef, Results); | ||||
2388 | |||||
2389 | // true | ||||
2390 | Builder.AddResultTypeChunk("bool"); | ||||
2391 | Builder.AddTypedTextChunk("true"); | ||||
2392 | Results.AddResult(Result(Builder.TakeString())); | ||||
2393 | |||||
2394 | // false | ||||
2395 | Builder.AddResultTypeChunk("bool"); | ||||
2396 | Builder.AddTypedTextChunk("false"); | ||||
2397 | Results.AddResult(Result(Builder.TakeString())); | ||||
2398 | |||||
2399 | if (SemaRef.getLangOpts().RTTI) { | ||||
2400 | // dynamic_cast < type-id > ( expression ) | ||||
2401 | Builder.AddTypedTextChunk("dynamic_cast"); | ||||
2402 | Builder.AddChunk(CodeCompletionString::CK_LeftAngle); | ||||
2403 | Builder.AddPlaceholderChunk("type"); | ||||
2404 | Builder.AddChunk(CodeCompletionString::CK_RightAngle); | ||||
2405 | Builder.AddChunk(CodeCompletionString::CK_LeftParen); | ||||
2406 | Builder.AddPlaceholderChunk("expression"); | ||||
2407 | Builder.AddChunk(CodeCompletionString::CK_RightParen); | ||||
2408 | Results.AddResult(Result(Builder.TakeString())); | ||||
2409 | } | ||||
2410 | |||||
2411 | // static_cast < type-id > ( expression ) | ||||
2412 | Builder.AddTypedTextChunk("static_cast"); | ||||
2413 | Builder.AddChunk(CodeCompletionString::CK_LeftAngle); | ||||
2414 | Builder.AddPlaceholderChunk("type"); | ||||
2415 | Builder.AddChunk(CodeCompletionString::CK_RightAngle); | ||||
2416 | Builder.AddChunk(CodeCompletionString::CK_LeftParen); | ||||
2417 | Builder.AddPlaceholderChunk("expression"); | ||||
2418 | Builder.AddChunk(CodeCompletionString::CK_RightParen); | ||||
2419 | Results.AddResult(Result(Builder.TakeString())); | ||||
2420 | |||||
2421 | // reinterpret_cast < type-id > ( expression ) | ||||
2422 | Builder.AddTypedTextChunk("reinterpret_cast"); | ||||
2423 | Builder.AddChunk(CodeCompletionString::CK_LeftAngle); | ||||
2424 | Builder.AddPlaceholderChunk("type"); | ||||
2425 | Builder.AddChunk(CodeCompletionString::CK_RightAngle); | ||||
2426 | Builder.AddChunk(CodeCompletionString::CK_LeftParen); | ||||
2427 | Builder.AddPlaceholderChunk("expression"); | ||||
2428 | Builder.AddChunk(CodeCompletionString::CK_RightParen); | ||||
2429 | Results.AddResult(Result(Builder.TakeString())); | ||||
2430 | |||||
2431 | // const_cast < type-id > ( expression ) | ||||
2432 | Builder.AddTypedTextChunk("const_cast"); | ||||
2433 | Builder.AddChunk(CodeCompletionString::CK_LeftAngle); | ||||
2434 | Builder.AddPlaceholderChunk("type"); | ||||
2435 | Builder.AddChunk(CodeCompletionString::CK_RightAngle); | ||||
2436 | Builder.AddChunk(CodeCompletionString::CK_LeftParen); | ||||
2437 | Builder.AddPlaceholderChunk("expression"); | ||||
2438 | Builder.AddChunk(CodeCompletionString::CK_RightParen); | ||||
2439 | Results.AddResult(Result(Builder.TakeString())); | ||||
2440 | |||||
2441 | if (SemaRef.getLangOpts().RTTI) { | ||||
2442 | // typeid ( expression-or-type ) | ||||
2443 | Builder.AddResultTypeChunk("std::type_info"); | ||||
2444 | Builder.AddTypedTextChunk("typeid"); | ||||
2445 | Builder.AddChunk(CodeCompletionString::CK_LeftParen); | ||||
2446 | Builder.AddPlaceholderChunk("expression-or-type"); | ||||
2447 | Builder.AddChunk(CodeCompletionString::CK_RightParen); | ||||
2448 | Results.AddResult(Result(Builder.TakeString())); | ||||
2449 | } | ||||
2450 | |||||
2451 | // new T ( ... ) | ||||
2452 | Builder.AddTypedTextChunk("new"); | ||||
2453 | Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | ||||
2454 | Builder.AddPlaceholderChunk("type"); | ||||
2455 | Builder.AddChunk(CodeCompletionString::CK_LeftParen); | ||||
2456 | Builder.AddPlaceholderChunk("expressions"); | ||||
2457 | Builder.AddChunk(CodeCompletionString::CK_RightParen); | ||||
2458 | Results.AddResult(Result(Builder.TakeString())); | ||||
2459 | |||||
2460 | // new T [ ] ( ... ) | ||||
2461 | Builder.AddTypedTextChunk("new"); | ||||
2462 | Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | ||||
2463 | Builder.AddPlaceholderChunk("type"); | ||||
2464 | Builder.AddChunk(CodeCompletionString::CK_LeftBracket); | ||||
2465 | Builder.AddPlaceholderChunk("size"); | ||||
2466 | Builder.AddChunk(CodeCompletionString::CK_RightBracket); | ||||
2467 | Builder.AddChunk(CodeCompletionString::CK_LeftParen); | ||||
2468 | Builder.AddPlaceholderChunk("expressions"); | ||||
2469 | Builder.AddChunk(CodeCompletionString::CK_RightParen); | ||||
2470 | Results.AddResult(Result(Builder.TakeString())); | ||||
2471 | |||||
2472 | // delete expression | ||||
2473 | Builder.AddResultTypeChunk("void"); | ||||
2474 | Builder.AddTypedTextChunk("delete"); | ||||
2475 | Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | ||||
2476 | Builder.AddPlaceholderChunk("expression"); | ||||
2477 | Results.AddResult(Result(Builder.TakeString())); | ||||
2478 | |||||
2479 | // delete [] expression | ||||
2480 | Builder.AddResultTypeChunk("void"); | ||||
2481 | Builder.AddTypedTextChunk("delete"); | ||||
2482 | Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | ||||
2483 | Builder.AddChunk(CodeCompletionString::CK_LeftBracket); | ||||
2484 | Builder.AddChunk(CodeCompletionString::CK_RightBracket); | ||||
2485 | Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | ||||
2486 | Builder.AddPlaceholderChunk("expression"); | ||||
2487 | Results.AddResult(Result(Builder.TakeString())); | ||||
2488 | |||||
2489 | if (SemaRef.getLangOpts().CXXExceptions) { | ||||
2490 | // throw expression | ||||
2491 | Builder.AddResultTypeChunk("void"); | ||||
2492 | Builder.AddTypedTextChunk("throw"); | ||||
2493 | Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | ||||
2494 | Builder.AddPlaceholderChunk("expression"); | ||||
2495 | Results.AddResult(Result(Builder.TakeString())); | ||||
2496 | } | ||||
2497 | |||||
2498 | // FIXME: Rethrow? | ||||
2499 | |||||
2500 | if (SemaRef.getLangOpts().CPlusPlus11) { | ||||
2501 | // nullptr | ||||
2502 | Builder.AddResultTypeChunk("std::nullptr_t"); | ||||
2503 | Builder.AddTypedTextChunk("nullptr"); | ||||
2504 | Results.AddResult(Result(Builder.TakeString())); | ||||
2505 | |||||
2506 | // alignof | ||||
2507 | Builder.AddResultTypeChunk("size_t"); | ||||
2508 | Builder.AddTypedTextChunk("alignof"); | ||||
2509 | Builder.AddChunk(CodeCompletionString::CK_LeftParen); | ||||
2510 | Builder.AddPlaceholderChunk("type"); | ||||
2511 | Builder.AddChunk(CodeCompletionString::CK_RightParen); | ||||
2512 | Results.AddResult(Result(Builder.TakeString())); | ||||
2513 | |||||
2514 | // noexcept | ||||
2515 | Builder.AddResultTypeChunk("bool"); | ||||
2516 | Builder.AddTypedTextChunk("noexcept"); | ||||
2517 | Builder.AddChunk(CodeCompletionString::CK_LeftParen); | ||||
2518 | Builder.AddPlaceholderChunk("expression"); | ||||
2519 | Builder.AddChunk(CodeCompletionString::CK_RightParen); | ||||
2520 | Results.AddResult(Result(Builder.TakeString())); | ||||
2521 | |||||
2522 | // sizeof... expression | ||||
2523 | Builder.AddResultTypeChunk("size_t"); | ||||
2524 | Builder.AddTypedTextChunk("sizeof..."); | ||||
2525 | Builder.AddChunk(CodeCompletionString::CK_LeftParen); | ||||
2526 | Builder.AddPlaceholderChunk("parameter-pack"); | ||||
2527 | Builder.AddChunk(CodeCompletionString::CK_RightParen); | ||||
2528 | Results.AddResult(Result(Builder.TakeString())); | ||||
2529 | } | ||||
2530 | } | ||||
2531 | |||||
2532 | if (SemaRef.getLangOpts().ObjC) { | ||||
2533 | // Add "super", if we're in an Objective-C class with a superclass. | ||||
2534 | if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl()) { | ||||
2535 | // The interface can be NULL. | ||||
2536 | if (ObjCInterfaceDecl *ID = Method->getClassInterface()) | ||||
2537 | if (ID->getSuperClass()) { | ||||
2538 | std::string SuperType; | ||||
2539 | SuperType = ID->getSuperClass()->getNameAsString(); | ||||
2540 | if (Method->isInstanceMethod()) | ||||
2541 | SuperType += " *"; | ||||
2542 | |||||
2543 | Builder.AddResultTypeChunk(Allocator.CopyString(SuperType)); | ||||
2544 | Builder.AddTypedTextChunk("super"); | ||||
2545 | Results.AddResult(Result(Builder.TakeString())); | ||||
2546 | } | ||||
2547 | } | ||||
2548 | |||||
2549 | AddObjCExpressionResults(Results, true); | ||||
2550 | } | ||||
2551 | |||||
2552 | if (SemaRef.getLangOpts().C11) { | ||||
2553 | // _Alignof | ||||
2554 | Builder.AddResultTypeChunk("size_t"); | ||||
2555 | if (SemaRef.PP.isMacroDefined("alignof")) | ||||
2556 | Builder.AddTypedTextChunk("alignof"); | ||||
2557 | else | ||||
2558 | Builder.AddTypedTextChunk("_Alignof"); | ||||
2559 | Builder.AddChunk(CodeCompletionString::CK_LeftParen); | ||||
2560 | Builder.AddPlaceholderChunk("type"); | ||||
2561 | Builder.AddChunk(CodeCompletionString::CK_RightParen); | ||||
2562 | Results.AddResult(Result(Builder.TakeString())); | ||||
2563 | } | ||||
2564 | |||||
2565 | // sizeof expression | ||||
2566 | Builder.AddResultTypeChunk("size_t"); | ||||
2567 | Builder.AddTypedTextChunk("sizeof"); | ||||
2568 | Builder.AddChunk(CodeCompletionString::CK_LeftParen); | ||||
2569 | Builder.AddPlaceholderChunk("expression-or-type"); | ||||
2570 | Builder.AddChunk(CodeCompletionString::CK_RightParen); | ||||
2571 | Results.AddResult(Result(Builder.TakeString())); | ||||
2572 | break; | ||||
2573 | } | ||||
2574 | |||||
2575 | case Sema::PCC_Type: | ||||
2576 | case Sema::PCC_LocalDeclarationSpecifiers: | ||||
2577 | break; | ||||
2578 | } | ||||
2579 | |||||
2580 | if (WantTypesInContext(CCC, SemaRef.getLangOpts())) | ||||
2581 | AddTypeSpecifierResults(SemaRef.getLangOpts(), Results); | ||||
2582 | |||||
2583 | if (SemaRef.getLangOpts().CPlusPlus && CCC != Sema::PCC_Type) | ||||
2584 | Results.AddResult(Result("operator")); | ||||
2585 | } | ||||
2586 | |||||
2587 | /// If the given declaration has an associated type, add it as a result | ||||
2588 | /// type chunk. | ||||
2589 | static void AddResultTypeChunk(ASTContext &Context, | ||||
2590 | const PrintingPolicy &Policy, | ||||
2591 | const NamedDecl *ND, QualType BaseType, | ||||
2592 | CodeCompletionBuilder &Result) { | ||||
2593 | if (!ND) | ||||
2594 | return; | ||||
2595 | |||||
2596 | // Skip constructors and conversion functions, which have their return types | ||||
2597 | // built into their names. | ||||
2598 | if (isConstructor(ND) || isa<CXXConversionDecl>(ND)) | ||||
2599 | return; | ||||
2600 | |||||
2601 | // Determine the type of the declaration (if it has a type). | ||||
2602 | QualType T; | ||||
2603 | if (const FunctionDecl *Function = ND->getAsFunction()) | ||||
2604 | T = Function->getReturnType(); | ||||
2605 | else if (const auto *Method = dyn_cast<ObjCMethodDecl>(ND)) { | ||||
2606 | if (!BaseType.isNull()) | ||||
2607 | T = Method->getSendResultType(BaseType); | ||||
2608 | else | ||||
2609 | T = Method->getReturnType(); | ||||
2610 | } else if (const auto *Enumerator = dyn_cast<EnumConstantDecl>(ND)) { | ||||
2611 | T = Context.getTypeDeclType(cast<TypeDecl>(Enumerator->getDeclContext())); | ||||
2612 | T = clang::TypeName::getFullyQualifiedType(T, Context); | ||||
2613 | } else if (isa<UnresolvedUsingValueDecl>(ND)) { | ||||
2614 | /* Do nothing: ignore unresolved using declarations*/ | ||||
2615 | } else if (const auto *Ivar = dyn_cast<ObjCIvarDecl>(ND)) { | ||||
2616 | if (!BaseType.isNull()) | ||||
2617 | T = Ivar->getUsageType(BaseType); | ||||
2618 | else | ||||
2619 | T = Ivar->getType(); | ||||
2620 | } else if (const auto *Value = dyn_cast<ValueDecl>(ND)) { | ||||
2621 | T = Value->getType(); | ||||
2622 | } else if (const auto *Property = dyn_cast<ObjCPropertyDecl>(ND)) { | ||||
2623 | if (!BaseType.isNull()) | ||||
2624 | T = Property->getUsageType(BaseType); | ||||
2625 | else | ||||
2626 | T = Property->getType(); | ||||
2627 | } | ||||
2628 | |||||
2629 | if (T.isNull() || Context.hasSameType(T, Context.DependentTy)) | ||||
2630 | return; | ||||
2631 | |||||
2632 | Result.AddResultTypeChunk( | ||||
2633 | GetCompletionTypeString(T, Context, Policy, Result.getAllocator())); | ||||
2634 | } | ||||
2635 | |||||
2636 | static void MaybeAddSentinel(Preprocessor &PP, | ||||
2637 | const NamedDecl *FunctionOrMethod, | ||||
2638 | CodeCompletionBuilder &Result) { | ||||
2639 | if (SentinelAttr *Sentinel = FunctionOrMethod->getAttr<SentinelAttr>()) | ||||
2640 | if (Sentinel->getSentinel() == 0) { | ||||
2641 | if (PP.getLangOpts().ObjC && PP.isMacroDefined("nil")) | ||||
2642 | Result.AddTextChunk(", nil"); | ||||
2643 | else if (PP.isMacroDefined("NULL")) | ||||
2644 | Result.AddTextChunk(", NULL"); | ||||
2645 | else | ||||
2646 | Result.AddTextChunk(", (void*)0"); | ||||
2647 | } | ||||
2648 | } | ||||
2649 | |||||
2650 | static std::string formatObjCParamQualifiers(unsigned ObjCQuals, | ||||
2651 | QualType &Type) { | ||||
2652 | std::string Result; | ||||
2653 | if (ObjCQuals & Decl::OBJC_TQ_In) | ||||
2654 | Result += "in "; | ||||
2655 | else if (ObjCQuals & Decl::OBJC_TQ_Inout) | ||||
2656 | Result += "inout "; | ||||
2657 | else if (ObjCQuals & Decl::OBJC_TQ_Out) | ||||
2658 | Result += "out "; | ||||
2659 | if (ObjCQuals & Decl::OBJC_TQ_Bycopy) | ||||
2660 | Result += "bycopy "; | ||||
2661 | else if (ObjCQuals & Decl::OBJC_TQ_Byref) | ||||
2662 | Result += "byref "; | ||||
2663 | if (ObjCQuals & Decl::OBJC_TQ_Oneway) | ||||
2664 | Result += "oneway "; | ||||
2665 | if (ObjCQuals & Decl::OBJC_TQ_CSNullability) { | ||||
2666 | if (auto nullability = AttributedType::stripOuterNullability(Type)) { | ||||
2667 | switch (*nullability) { | ||||
2668 | case NullabilityKind::NonNull: | ||||
2669 | Result += "nonnull "; | ||||
2670 | break; | ||||
2671 | |||||
2672 | case NullabilityKind::Nullable: | ||||
2673 | Result += "nullable "; | ||||
2674 | break; | ||||
2675 | |||||
2676 | case NullabilityKind::Unspecified: | ||||
2677 | Result += "null_unspecified "; | ||||
2678 | break; | ||||
2679 | } | ||||
2680 | } | ||||
2681 | } | ||||
2682 | return Result; | ||||
2683 | } | ||||
2684 | |||||
2685 | /// Tries to find the most appropriate type location for an Objective-C | ||||
2686 | /// block placeholder. | ||||
2687 | /// | ||||
2688 | /// This function ignores things like typedefs and qualifiers in order to | ||||
2689 | /// present the most relevant and accurate block placeholders in code completion | ||||
2690 | /// results. | ||||
2691 | static void findTypeLocationForBlockDecl(const TypeSourceInfo *TSInfo, | ||||
2692 | FunctionTypeLoc &Block, | ||||
2693 | FunctionProtoTypeLoc &BlockProto, | ||||
2694 | bool SuppressBlock = false) { | ||||
2695 | if (!TSInfo) | ||||
2696 | return; | ||||
2697 | TypeLoc TL = TSInfo->getTypeLoc().getUnqualifiedLoc(); | ||||
2698 | while (true) { | ||||
2699 | // Look through typedefs. | ||||
2700 | if (!SuppressBlock) { | ||||
2701 | if (TypedefTypeLoc TypedefTL = TL.getAs<TypedefTypeLoc>()) { | ||||
2702 | if (TypeSourceInfo *InnerTSInfo = | ||||
2703 | TypedefTL.getTypedefNameDecl()->getTypeSourceInfo()) { | ||||
2704 | TL = InnerTSInfo->getTypeLoc().getUnqualifiedLoc(); | ||||
2705 | continue; | ||||
2706 | } | ||||
2707 | } | ||||
2708 | |||||
2709 | // Look through qualified types | ||||
2710 | if (QualifiedTypeLoc QualifiedTL = TL.getAs<QualifiedTypeLoc>()) { | ||||
2711 | TL = QualifiedTL.getUnqualifiedLoc(); | ||||
2712 | continue; | ||||
2713 | } | ||||
2714 | |||||
2715 | if (AttributedTypeLoc AttrTL = TL.getAs<AttributedTypeLoc>()) { | ||||
2716 | TL = AttrTL.getModifiedLoc(); | ||||
2717 | continue; | ||||
2718 | } | ||||
2719 | } | ||||
2720 | |||||
2721 | // Try to get the function prototype behind the block pointer type, | ||||
2722 | // then we're done. | ||||
2723 | if (BlockPointerTypeLoc BlockPtr = TL.getAs<BlockPointerTypeLoc>()) { | ||||
2724 | TL = BlockPtr.getPointeeLoc().IgnoreParens(); | ||||
2725 | Block = TL.getAs<FunctionTypeLoc>(); | ||||
2726 | BlockProto = TL.getAs<FunctionProtoTypeLoc>(); | ||||
2727 | } | ||||
2728 | break; | ||||
2729 | } | ||||
2730 | } | ||||
2731 | |||||
2732 | static std::string | ||||
2733 | formatBlockPlaceholder(const PrintingPolicy &Policy, const NamedDecl *BlockDecl, | ||||
2734 | FunctionTypeLoc &Block, FunctionProtoTypeLoc &BlockProto, | ||||
2735 | bool SuppressBlockName = false, | ||||
2736 | bool SuppressBlock = false, | ||||
2737 | Optional<ArrayRef<QualType>> ObjCSubsts = None); | ||||
2738 | |||||
2739 | static std::string | ||||
2740 | FormatFunctionParameter(const PrintingPolicy &Policy, const ParmVarDecl *Param, | ||||
2741 | bool SuppressName = false, bool SuppressBlock = false, | ||||
2742 | Optional<ArrayRef<QualType>> ObjCSubsts = None) { | ||||
2743 | // Params are unavailable in FunctionTypeLoc if the FunctionType is invalid. | ||||
2744 | // It would be better to pass in the param Type, which is usually avaliable. | ||||
2745 | // But this case is rare, so just pretend we fell back to int as elsewhere. | ||||
2746 | if (!Param) | ||||
2747 | return "int"; | ||||
2748 | bool ObjCMethodParam = isa<ObjCMethodDecl>(Param->getDeclContext()); | ||||
2749 | if (Param->getType()->isDependentType() || | ||||
2750 | !Param->getType()->isBlockPointerType()) { | ||||
2751 | // The argument for a dependent or non-block parameter is a placeholder | ||||
2752 | // containing that parameter's type. | ||||
2753 | std::string Result; | ||||
2754 | |||||
2755 | if (Param->getIdentifier() && !ObjCMethodParam && !SuppressName) | ||||
2756 | Result = Param->getIdentifier()->getName(); | ||||
2757 | |||||
2758 | QualType Type = Param->getType(); | ||||
2759 | if (ObjCSubsts) | ||||
2760 | Type = Type.substObjCTypeArgs(Param->getASTContext(), *ObjCSubsts, | ||||
2761 | ObjCSubstitutionContext::Parameter); | ||||
2762 | if (ObjCMethodParam) { | ||||
2763 | Result = | ||||
2764 | "(" + formatObjCParamQualifiers(Param->getObjCDeclQualifier(), Type); | ||||
2765 | Result += Type.getAsString(Policy) + ")"; | ||||
2766 | if (Param->getIdentifier() && !SuppressName) | ||||
2767 | Result += Param->getIdentifier()->getName(); | ||||
2768 | } else { | ||||
2769 | Type.getAsStringInternal(Result, Policy); | ||||
2770 | } | ||||
2771 | return Result; | ||||
2772 | } | ||||
2773 | |||||
2774 | // The argument for a block pointer parameter is a block literal with | ||||
2775 | // the appropriate type. | ||||
2776 | FunctionTypeLoc Block; | ||||
2777 | FunctionProtoTypeLoc BlockProto; | ||||
2778 | findTypeLocationForBlockDecl(Param->getTypeSourceInfo(), Block, BlockProto, | ||||
2779 | SuppressBlock); | ||||
2780 | // Try to retrieve the block type information from the property if this is a | ||||
2781 | // parameter in a setter. | ||||
2782 | if (!Block && ObjCMethodParam && | ||||
2783 | cast<ObjCMethodDecl>(Param->getDeclContext())->isPropertyAccessor()) { | ||||
2784 | if (const auto *PD = cast<ObjCMethodDecl>(Param->getDeclContext()) | ||||
2785 | ->findPropertyDecl(/*CheckOverrides=*/false)) | ||||
2786 | findTypeLocationForBlockDecl(PD->getTypeSourceInfo(), Block, BlockProto, | ||||
2787 | SuppressBlock); | ||||
2788 | } | ||||
2789 | |||||
2790 | if (!Block) { | ||||
2791 | // We were unable to find a FunctionProtoTypeLoc with parameter names | ||||
2792 | // for the block; just use the parameter type as a placeholder. | ||||
2793 | std::string Result; | ||||
2794 | if (!ObjCMethodParam && Param->getIdentifier()) | ||||
2795 | Result = Param->getIdentifier()->getName(); | ||||
2796 | |||||
2797 | QualType Type = Param->getType().getUnqualifiedType(); | ||||
2798 | |||||
2799 | if (ObjCMethodParam) { | ||||
2800 | Result = Type.getAsString(Policy); | ||||
2801 | std::string Quals = | ||||
2802 | formatObjCParamQualifiers(Param->getObjCDeclQualifier(), Type); | ||||
2803 | if (!Quals.empty()) | ||||
2804 | Result = "(" + Quals + " " + Result + ")"; | ||||
2805 | if (Result.back() != ')') | ||||
2806 | Result += " "; | ||||
2807 | if (Param->getIdentifier()) | ||||
2808 | Result += Param->getIdentifier()->getName(); | ||||
2809 | } else { | ||||
2810 | Type.getAsStringInternal(Result, Policy); | ||||
2811 | } | ||||
2812 | |||||
2813 | return Result; | ||||
2814 | } | ||||
2815 | |||||
2816 | // We have the function prototype behind the block pointer type, as it was | ||||
2817 | // written in the source. | ||||
2818 | return formatBlockPlaceholder(Policy, Param, Block, BlockProto, | ||||
2819 | /*SuppressBlockName=*/false, SuppressBlock, | ||||
2820 | ObjCSubsts); | ||||
2821 | } | ||||
2822 | |||||
2823 | /// Returns a placeholder string that corresponds to an Objective-C block | ||||
2824 | /// declaration. | ||||
2825 | /// | ||||
2826 | /// \param BlockDecl A declaration with an Objective-C block type. | ||||
2827 | /// | ||||
2828 | /// \param Block The most relevant type location for that block type. | ||||
2829 | /// | ||||
2830 | /// \param SuppressBlockName Determines whether or not the name of the block | ||||
2831 | /// declaration is included in the resulting string. | ||||
2832 | static std::string | ||||
2833 | formatBlockPlaceholder(const PrintingPolicy &Policy, const NamedDecl *BlockDecl, | ||||
2834 | FunctionTypeLoc &Block, FunctionProtoTypeLoc &BlockProto, | ||||
2835 | bool SuppressBlockName, bool SuppressBlock, | ||||
2836 | Optional<ArrayRef<QualType>> ObjCSubsts) { | ||||
2837 | std::string Result; | ||||
2838 | QualType ResultType = Block.getTypePtr()->getReturnType(); | ||||
2839 | if (ObjCSubsts) | ||||
2840 | ResultType = | ||||
2841 | ResultType.substObjCTypeArgs(BlockDecl->getASTContext(), *ObjCSubsts, | ||||
2842 | ObjCSubstitutionContext::Result); | ||||
2843 | if (!ResultType->isVoidType() || SuppressBlock) | ||||
2844 | ResultType.getAsStringInternal(Result, Policy); | ||||
2845 | |||||
2846 | // Format the parameter list. | ||||
2847 | std::string Params; | ||||
2848 | if (!BlockProto || Block.getNumParams() == 0) { | ||||
2849 | if (BlockProto && BlockProto.getTypePtr()->isVariadic()) | ||||
2850 | Params = "(...)"; | ||||
2851 | else | ||||
2852 | Params = "(void)"; | ||||
2853 | } else { | ||||
2854 | Params += "("; | ||||
2855 | for (unsigned I = 0, N = Block.getNumParams(); I != N; ++I) { | ||||
2856 | if (I) | ||||
2857 | Params += ", "; | ||||
2858 | Params += FormatFunctionParameter(Policy, Block.getParam(I), | ||||
2859 | /*SuppressName=*/false, | ||||
2860 | /*SuppressBlock=*/true, ObjCSubsts); | ||||
2861 | |||||
2862 | if (I == N - 1 && BlockProto.getTypePtr()->isVariadic()) | ||||
2863 | Params += ", ..."; | ||||
2864 | } | ||||
2865 | Params += ")"; | ||||
2866 | } | ||||
2867 | |||||
2868 | if (SuppressBlock) { | ||||
2869 | // Format as a parameter. | ||||
2870 | Result = Result + " (^"; | ||||
2871 | if (!SuppressBlockName && BlockDecl->getIdentifier()) | ||||
2872 | Result += BlockDecl->getIdentifier()->getName(); | ||||
2873 | Result += ")"; | ||||
2874 | Result += Params; | ||||
2875 | } else { | ||||
2876 | // Format as a block literal argument. | ||||
2877 | Result = '^' + Result; | ||||
2878 | Result += Params; | ||||
2879 | |||||
2880 | if (!SuppressBlockName && BlockDecl->getIdentifier()) | ||||
2881 | Result += BlockDecl->getIdentifier()->getName(); | ||||
2882 | } | ||||
2883 | |||||
2884 | return Result; | ||||
2885 | } | ||||
2886 | |||||
2887 | static std::string GetDefaultValueString(const ParmVarDecl *Param, | ||||
2888 | const SourceManager &SM, | ||||
2889 | const LangOptions &LangOpts) { | ||||
2890 | const SourceRange SrcRange = Param->getDefaultArgRange(); | ||||
2891 | CharSourceRange CharSrcRange = CharSourceRange::getTokenRange(SrcRange); | ||||
2892 | bool Invalid = CharSrcRange.isInvalid(); | ||||
2893 | if (Invalid) | ||||
2894 | return ""; | ||||
2895 | StringRef srcText = | ||||
2896 | Lexer::getSourceText(CharSrcRange, SM, LangOpts, &Invalid); | ||||
2897 | if (Invalid) | ||||
2898 | return ""; | ||||
2899 | |||||
2900 | if (srcText.empty() || srcText == "=") { | ||||
2901 | // Lexer can't determine the value. | ||||
2902 | // This happens if the code is incorrect (for example class is forward | ||||
2903 | // declared). | ||||
2904 | return ""; | ||||
2905 | } | ||||
2906 | std::string DefValue(srcText.str()); | ||||
2907 | // FIXME: remove this check if the Lexer::getSourceText value is fixed and | ||||
2908 | // this value always has (or always does not have) '=' in front of it | ||||
2909 | if (DefValue.at(0) != '=') { | ||||
2910 | // If we don't have '=' in front of value. | ||||
2911 | // Lexer returns built-in types values without '=' and user-defined types | ||||
2912 | // values with it. | ||||
2913 | return " = " + DefValue; | ||||
2914 | } | ||||
2915 | return " " + DefValue; | ||||
2916 | } | ||||
2917 | |||||
2918 | /// Add function parameter chunks to the given code completion string. | ||||
2919 | static void AddFunctionParameterChunks(Preprocessor &PP, | ||||
2920 | const PrintingPolicy &Policy, | ||||
2921 | const FunctionDecl *Function, | ||||
2922 | CodeCompletionBuilder &Result, | ||||
2923 | unsigned Start = 0, | ||||
2924 | bool InOptional = false) { | ||||
2925 | bool FirstParameter = true; | ||||
2926 | |||||
2927 | for (unsigned P = Start, N = Function->getNumParams(); P != N; ++P) { | ||||
2928 | const ParmVarDecl *Param = Function->getParamDecl(P); | ||||
2929 | |||||
2930 | if (Param->hasDefaultArg() && !InOptional) { | ||||
2931 | // When we see an optional default argument, put that argument and | ||||
2932 | // the remaining default arguments into a new, optional string. | ||||
2933 | CodeCompletionBuilder Opt(Result.getAllocator(), | ||||
2934 | Result.getCodeCompletionTUInfo()); | ||||
2935 | if (!FirstParameter) | ||||
2936 | Opt.AddChunk(CodeCompletionString::CK_Comma); | ||||
2937 | AddFunctionParameterChunks(PP, Policy, Function, Opt, P, true); | ||||
2938 | Result.AddOptionalChunk(Opt.TakeString()); | ||||
2939 | break; | ||||
2940 | } | ||||
2941 | |||||
2942 | if (FirstParameter) | ||||
2943 | FirstParameter = false; | ||||
2944 | else | ||||
2945 | Result.AddChunk(CodeCompletionString::CK_Comma); | ||||
2946 | |||||
2947 | InOptional = false; | ||||
2948 | |||||
2949 | // Format the placeholder string. | ||||
2950 | std::string PlaceholderStr = FormatFunctionParameter(Policy, Param); | ||||
2951 | if (Param->hasDefaultArg()) | ||||
2952 | PlaceholderStr += | ||||
2953 | GetDefaultValueString(Param, PP.getSourceManager(), PP.getLangOpts()); | ||||
2954 | |||||
2955 | if (Function->isVariadic() && P == N - 1) | ||||
2956 | PlaceholderStr += ", ..."; | ||||
2957 | |||||
2958 | // Add the placeholder string. | ||||
2959 | Result.AddPlaceholderChunk( | ||||
2960 | Result.getAllocator().CopyString(PlaceholderStr)); | ||||
2961 | } | ||||
2962 | |||||
2963 | if (const auto *Proto = Function->getType()->getAs<FunctionProtoType>()) | ||||
2964 | if (Proto->isVariadic()) { | ||||
2965 | if (Proto->getNumParams() == 0) | ||||
2966 | Result.AddPlaceholderChunk("..."); | ||||
2967 | |||||
2968 | MaybeAddSentinel(PP, Function, Result); | ||||
2969 | } | ||||
2970 | } | ||||
2971 | |||||
2972 | /// Add template parameter chunks to the given code completion string. | ||||
2973 | static void AddTemplateParameterChunks( | ||||
2974 | ASTContext &Context, const PrintingPolicy &Policy, | ||||
2975 | const TemplateDecl *Template, CodeCompletionBuilder &Result, | ||||
2976 | unsigned MaxParameters = 0, unsigned Start = 0, bool InDefaultArg = false) { | ||||
2977 | bool FirstParameter = true; | ||||
2978 | |||||
2979 | // Prefer to take the template parameter names from the first declaration of | ||||
2980 | // the template. | ||||
2981 | Template = cast<TemplateDecl>(Template->getCanonicalDecl()); | ||||
2982 | |||||
2983 | TemplateParameterList *Params = Template->getTemplateParameters(); | ||||
2984 | TemplateParameterList::iterator PEnd = Params->end(); | ||||
2985 | if (MaxParameters) | ||||
2986 | PEnd = Params->begin() + MaxParameters; | ||||
2987 | for (TemplateParameterList::iterator P = Params->begin() + Start; P != PEnd; | ||||
2988 | ++P) { | ||||
2989 | bool HasDefaultArg = false; | ||||
2990 | std::string PlaceholderStr; | ||||
2991 | if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*P)) { | ||||
2992 | if (TTP->wasDeclaredWithTypename()) | ||||
2993 | PlaceholderStr = "typename"; | ||||
2994 | else | ||||
2995 | PlaceholderStr = "class"; | ||||
2996 | |||||
2997 | if (TTP->getIdentifier()) { | ||||
2998 | PlaceholderStr += ' '; | ||||
2999 | PlaceholderStr += TTP->getIdentifier()->getName(); | ||||
3000 | } | ||||
3001 | |||||
3002 | HasDefaultArg = TTP->hasDefaultArgument(); | ||||
3003 | } else if (NonTypeTemplateParmDecl *NTTP = | ||||
3004 | dyn_cast<NonTypeTemplateParmDecl>(*P)) { | ||||
3005 | if (NTTP->getIdentifier()) | ||||
3006 | PlaceholderStr = NTTP->getIdentifier()->getName(); | ||||
3007 | NTTP->getType().getAsStringInternal(PlaceholderStr, Policy); | ||||
3008 | HasDefaultArg = NTTP->hasDefaultArgument(); | ||||
3009 | } else { | ||||
3010 | assert(isa<TemplateTemplateParmDecl>(*P))((isa<TemplateTemplateParmDecl>(*P)) ? static_cast<void > (0) : __assert_fail ("isa<TemplateTemplateParmDecl>(*P)" , "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/clang/lib/Sema/SemaCodeComplete.cpp" , 3010, __PRETTY_FUNCTION__)); | ||||
3011 | TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*P); | ||||
3012 | |||||
3013 | // Since putting the template argument list into the placeholder would | ||||
3014 | // be very, very long, we just use an abbreviation. | ||||
3015 | PlaceholderStr = "template<...> class"; | ||||
3016 | if (TTP->getIdentifier()) { | ||||
3017 | PlaceholderStr += ' '; | ||||
3018 | PlaceholderStr += TTP->getIdentifier()->getName(); | ||||
3019 | } | ||||
3020 | |||||
3021 | HasDefaultArg = TTP->hasDefaultArgument(); | ||||
3022 | } | ||||
3023 | |||||
3024 | if (HasDefaultArg && !InDefaultArg) { | ||||
3025 | // When we see an optional default argument, put that argument and | ||||
3026 | // the remaining default arguments into a new, optional string. | ||||
3027 | CodeCompletionBuilder Opt(Result.getAllocator(), | ||||
3028 | Result.getCodeCompletionTUInfo()); | ||||
3029 | if (!FirstParameter) | ||||
3030 | Opt.AddChunk(CodeCompletionString::CK_Comma); | ||||
3031 | AddTemplateParameterChunks(Context, Policy, Template, Opt, MaxParameters, | ||||
3032 | P - Params->begin(), true); | ||||
3033 | Result.AddOptionalChunk(Opt.TakeString()); | ||||
3034 | break; | ||||
3035 | } | ||||
3036 | |||||
3037 | InDefaultArg = false; | ||||
3038 | |||||
3039 | if (FirstParameter) | ||||
3040 | FirstParameter = false; | ||||
3041 | else | ||||
3042 | Result.AddChunk(CodeCompletionString::CK_Comma); | ||||
3043 | |||||
3044 | // Add the placeholder string. | ||||
3045 | Result.AddPlaceholderChunk( | ||||
3046 | Result.getAllocator().CopyString(PlaceholderStr)); | ||||
3047 | } | ||||
3048 | } | ||||
3049 | |||||
3050 | /// Add a qualifier to the given code-completion string, if the | ||||
3051 | /// provided nested-name-specifier is non-NULL. | ||||
3052 | static void AddQualifierToCompletionString(CodeCompletionBuilder &Result, | ||||
3053 | NestedNameSpecifier *Qualifier, | ||||
3054 | bool QualifierIsInformative, | ||||
3055 | ASTContext &Context, | ||||
3056 | const PrintingPolicy &Policy) { | ||||
3057 | if (!Qualifier) | ||||
3058 | return; | ||||
3059 | |||||
3060 | std::string PrintedNNS; | ||||
3061 | { | ||||
3062 | llvm::raw_string_ostream OS(PrintedNNS); | ||||
3063 | Qualifier->print(OS, Policy); | ||||
3064 | } | ||||
3065 | if (QualifierIsInformative) | ||||
3066 | Result.AddInformativeChunk(Result.getAllocator().CopyString(PrintedNNS)); | ||||
3067 | else | ||||
3068 | Result.AddTextChunk(Result.getAllocator().CopyString(PrintedNNS)); | ||||
3069 | } | ||||
3070 | |||||
3071 | static void | ||||
3072 | AddFunctionTypeQualsToCompletionString(CodeCompletionBuilder &Result, | ||||
3073 | const FunctionDecl *Function) { | ||||
3074 | const auto *Proto = Function->getType()->getAs<FunctionProtoType>(); | ||||
3075 | if (!Proto || !Proto->getMethodQuals()) | ||||
3076 | return; | ||||
3077 | |||||
3078 | // FIXME: Add ref-qualifier! | ||||
3079 | |||||
3080 | // Handle single qualifiers without copying | ||||
3081 | if (Proto->getMethodQuals().hasOnlyConst()) { | ||||
3082 | Result.AddInformativeChunk(" const"); | ||||
3083 | return; | ||||
3084 | } | ||||
3085 | |||||
3086 | if (Proto->getMethodQuals().hasOnlyVolatile()) { | ||||
3087 | Result.AddInformativeChunk(" volatile"); | ||||
3088 | return; | ||||
3089 | } | ||||
3090 | |||||
3091 | if (Proto->getMethodQuals().hasOnlyRestrict()) { | ||||
3092 | Result.AddInformativeChunk(" restrict"); | ||||
3093 | return; | ||||
3094 | } | ||||
3095 | |||||
3096 | // Handle multiple qualifiers. | ||||
3097 | std::string QualsStr; | ||||
3098 | if (Proto->isConst()) | ||||
3099 | QualsStr += " const"; | ||||
3100 | if (Proto->isVolatile()) | ||||
3101 | QualsStr += " volatile"; | ||||
3102 | if (Proto->isRestrict()) | ||||
3103 | QualsStr += " restrict"; | ||||
3104 | Result.AddInformativeChunk(Result.getAllocator().CopyString(QualsStr)); | ||||
3105 | } | ||||
3106 | |||||
3107 | /// Add the name of the given declaration | ||||
3108 | static void AddTypedNameChunk(ASTContext &Context, const PrintingPolicy &Policy, | ||||
3109 | const NamedDecl *ND, | ||||
3110 | CodeCompletionBuilder &Result) { | ||||
3111 | DeclarationName Name = ND->getDeclName(); | ||||
3112 | if (!Name) | ||||
3113 | return; | ||||
3114 | |||||
3115 | switch (Name.getNameKind()) { | ||||
3116 | case DeclarationName::CXXOperatorName: { | ||||
3117 | const char *OperatorName = nullptr; | ||||
3118 | switch (Name.getCXXOverloadedOperator()) { | ||||
3119 | case OO_None: | ||||
3120 | case OO_Conditional: | ||||
3121 | case NUM_OVERLOADED_OPERATORS: | ||||
3122 | OperatorName = "operator"; | ||||
3123 | break; | ||||
3124 | |||||
3125 | #define OVERLOADED_OPERATOR(Name, Spelling, Token, Unary, Binary, MemberOnly) \ | ||||
3126 | case OO_##Name: \ | ||||
3127 | OperatorName = "operator" Spelling; \ | ||||
3128 | break; | ||||
3129 | #define OVERLOADED_OPERATOR_MULTI(Name, Spelling, Unary, Binary, MemberOnly) | ||||
3130 | #include "clang/Basic/OperatorKinds.def" | ||||
3131 | |||||
3132 | case OO_New: | ||||
3133 | OperatorName = "operator new"; | ||||
3134 | break; | ||||
3135 | case OO_Delete: | ||||
3136 | OperatorName = "operator delete"; | ||||
3137 | break; | ||||
3138 | case OO_Array_New: | ||||
3139 | OperatorName = "operator new[]"; | ||||
3140 | break; | ||||
3141 | case OO_Array_Delete: | ||||
3142 | OperatorName = "operator delete[]"; | ||||
3143 | break; | ||||
3144 | case OO_Call: | ||||
3145 | OperatorName = "operator()"; | ||||
3146 | break; | ||||
3147 | case OO_Subscript: | ||||
3148 | OperatorName = "operator[]"; | ||||
3149 | break; | ||||
3150 | } | ||||
3151 | Result.AddTypedTextChunk(OperatorName); | ||||
3152 | break; | ||||
3153 | } | ||||
3154 | |||||
3155 | case DeclarationName::Identifier: | ||||
3156 | case DeclarationName::CXXConversionFunctionName: | ||||
3157 | case DeclarationName::CXXDestructorName: | ||||
3158 | case DeclarationName::CXXLiteralOperatorName: | ||||
3159 | Result.AddTypedTextChunk( | ||||
3160 | Result.getAllocator().CopyString(ND->getNameAsString())); | ||||
3161 | break; | ||||
3162 | |||||
3163 | case DeclarationName::CXXDeductionGuideName: | ||||
3164 | case DeclarationName::CXXUsingDirective: | ||||
3165 | case DeclarationName::ObjCZeroArgSelector: | ||||
3166 | case DeclarationName::ObjCOneArgSelector: | ||||
3167 | case DeclarationName::ObjCMultiArgSelector: | ||||
3168 | break; | ||||
3169 | |||||
3170 | case DeclarationName::CXXConstructorName: { | ||||
3171 | CXXRecordDecl *Record = nullptr; | ||||
3172 | QualType Ty = Name.getCXXNameType(); | ||||
3173 | if (const auto *RecordTy = Ty->getAs<RecordType>()) | ||||
3174 | Record = cast<CXXRecordDecl>(RecordTy->getDecl()); | ||||
3175 | else if (const auto *InjectedTy = Ty->getAs<InjectedClassNameType>()) | ||||
3176 | Record = InjectedTy->getDecl(); | ||||
3177 | else { | ||||
3178 | Result.AddTypedTextChunk( | ||||
3179 | Result.getAllocator().CopyString(ND->getNameAsString())); | ||||
3180 | break; | ||||
3181 | } | ||||
3182 | |||||
3183 | Result.AddTypedTextChunk( | ||||
3184 | Result.getAllocator().CopyString(Record->getNameAsString())); | ||||
3185 | if (ClassTemplateDecl *Template = Record->getDescribedClassTemplate()) { | ||||
3186 | Result.AddChunk(CodeCompletionString::CK_LeftAngle); | ||||
3187 | AddTemplateParameterChunks(Context, Policy, Template, Result); | ||||
3188 | Result.AddChunk(CodeCompletionString::CK_RightAngle); | ||||
3189 | } | ||||
3190 | break; | ||||
3191 | } | ||||
3192 | } | ||||
3193 | } | ||||
3194 | |||||
3195 | CodeCompletionString *CodeCompletionResult::CreateCodeCompletionString( | ||||
3196 | Sema &S, const CodeCompletionContext &CCContext, | ||||
3197 | CodeCompletionAllocator &Allocator, CodeCompletionTUInfo &CCTUInfo, | ||||
3198 | bool IncludeBriefComments) { | ||||
3199 | return CreateCodeCompletionString(S.Context, S.PP, CCContext, Allocator, | ||||
3200 | CCTUInfo, IncludeBriefComments); | ||||
3201 | } | ||||
3202 | |||||
3203 | CodeCompletionString *CodeCompletionResult::CreateCodeCompletionStringForMacro( | ||||
3204 | Preprocessor &PP, CodeCompletionAllocator &Allocator, | ||||
3205 | CodeCompletionTUInfo &CCTUInfo) { | ||||
3206 | assert(Kind == RK_Macro)((Kind == RK_Macro) ? static_cast<void> (0) : __assert_fail ("Kind == RK_Macro", "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/clang/lib/Sema/SemaCodeComplete.cpp" , 3206, __PRETTY_FUNCTION__)); | ||||
3207 | CodeCompletionBuilder Result(Allocator, CCTUInfo, Priority, Availability); | ||||
3208 | const MacroInfo *MI = PP.getMacroInfo(Macro); | ||||
3209 | Result.AddTypedTextChunk(Result.getAllocator().CopyString(Macro->getName())); | ||||
3210 | |||||
3211 | if (!MI || !MI->isFunctionLike()) | ||||
3212 | return Result.TakeString(); | ||||
3213 | |||||
3214 | // Format a function-like macro with placeholders for the arguments. | ||||
3215 | Result.AddChunk(CodeCompletionString::CK_LeftParen); | ||||
3216 | MacroInfo::param_iterator A = MI->param_begin(), AEnd = MI->param_end(); | ||||
3217 | |||||
3218 | // C99 variadic macros add __VA_ARGS__ at the end. Skip it. | ||||
3219 | if (MI->isC99Varargs()) { | ||||
3220 | --AEnd; | ||||
3221 | |||||
3222 | if (A == AEnd) { | ||||
3223 | Result.AddPlaceholderChunk("..."); | ||||
3224 | } | ||||
3225 | } | ||||
3226 | |||||
3227 | for (MacroInfo::param_iterator A = MI->param_begin(); A != AEnd; ++A) { | ||||
3228 | if (A != MI->param_begin()) | ||||
3229 | Result.AddChunk(CodeCompletionString::CK_Comma); | ||||
3230 | |||||
3231 | if (MI->isVariadic() && (A + 1) == AEnd) { | ||||
3232 | SmallString<32> Arg = (*A)->getName(); | ||||
3233 | if (MI->isC99Varargs()) | ||||
3234 | Arg += ", ..."; | ||||
3235 | else | ||||
3236 | Arg += "..."; | ||||
3237 | Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg)); | ||||
3238 | break; | ||||
3239 | } | ||||
3240 | |||||
3241 | // Non-variadic macros are simple. | ||||
3242 | Result.AddPlaceholderChunk( | ||||
3243 | Result.getAllocator().CopyString((*A)->getName())); | ||||
3244 | } | ||||
3245 | Result.AddChunk(CodeCompletionString::CK_RightParen); | ||||
3246 | return Result.TakeString(); | ||||
3247 | } | ||||
3248 | |||||
3249 | /// If possible, create a new code completion string for the given | ||||
3250 | /// result. | ||||
3251 | /// | ||||
3252 | /// \returns Either a new, heap-allocated code completion string describing | ||||
3253 | /// how to use this result, or NULL to indicate that the string or name of the | ||||
3254 | /// result is all that is needed. | ||||
3255 | CodeCompletionString *CodeCompletionResult::CreateCodeCompletionString( | ||||
3256 | ASTContext &Ctx, Preprocessor &PP, const CodeCompletionContext &CCContext, | ||||
3257 | CodeCompletionAllocator &Allocator, CodeCompletionTUInfo &CCTUInfo, | ||||
3258 | bool IncludeBriefComments) { | ||||
3259 | if (Kind == RK_Macro) | ||||
3260 | return CreateCodeCompletionStringForMacro(PP, Allocator, CCTUInfo); | ||||
3261 | |||||
3262 | CodeCompletionBuilder Result(Allocator, CCTUInfo, Priority, Availability); | ||||
3263 | |||||
3264 | PrintingPolicy Policy = getCompletionPrintingPolicy(Ctx, PP); | ||||
3265 | if (Kind == RK_Pattern) { | ||||
3266 | Pattern->Priority = Priority; | ||||
3267 | Pattern->Availability = Availability; | ||||
3268 | |||||
3269 | if (Declaration) { | ||||
3270 | Result.addParentContext(Declaration->getDeclContext()); | ||||
3271 | Pattern->ParentName = Result.getParentName(); | ||||
3272 | if (const RawComment *RC = | ||||
3273 | getPatternCompletionComment(Ctx, Declaration)) { | ||||
3274 | Result.addBriefComment(RC->getBriefText(Ctx)); | ||||
3275 | Pattern->BriefComment = Result.getBriefComment(); | ||||
3276 | } | ||||
3277 | } | ||||
3278 | |||||
3279 | return Pattern; | ||||
3280 | } | ||||
3281 | |||||
3282 | if (Kind == RK_Keyword) { | ||||
3283 | Result.AddTypedTextChunk(Keyword); | ||||
3284 | return Result.TakeString(); | ||||
3285 | } | ||||
3286 | assert(Kind == RK_Declaration && "Missed a result kind?")((Kind == RK_Declaration && "Missed a result kind?") ? static_cast<void> (0) : __assert_fail ("Kind == RK_Declaration && \"Missed a result kind?\"" , "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/clang/lib/Sema/SemaCodeComplete.cpp" , 3286, __PRETTY_FUNCTION__)); | ||||
3287 | return createCodeCompletionStringForDecl( | ||||
3288 | PP, Ctx, Result, IncludeBriefComments, CCContext, Policy); | ||||
3289 | } | ||||
3290 | |||||
3291 | static void printOverrideString(const CodeCompletionString &CCS, | ||||
3292 | std::string &BeforeName, | ||||
3293 | std::string &NameAndSignature) { | ||||
3294 | bool SeenTypedChunk = false; | ||||
3295 | for (auto &Chunk : CCS) { | ||||
3296 | if (Chunk.Kind == CodeCompletionString::CK_Optional) { | ||||
3297 | assert(SeenTypedChunk && "optional parameter before name")((SeenTypedChunk && "optional parameter before name") ? static_cast<void> (0) : __assert_fail ("SeenTypedChunk && \"optional parameter before name\"" , "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/clang/lib/Sema/SemaCodeComplete.cpp" , 3297, __PRETTY_FUNCTION__)); | ||||
3298 | // Note that we put all chunks inside into NameAndSignature. | ||||
3299 | printOverrideString(*Chunk.Optional, NameAndSignature, NameAndSignature); | ||||
3300 | continue; | ||||
3301 | } | ||||
3302 | SeenTypedChunk |= Chunk.Kind == CodeCompletionString::CK_TypedText; | ||||
3303 | if (SeenTypedChunk) | ||||
3304 | NameAndSignature += Chunk.Text; | ||||
3305 | else | ||||
3306 | BeforeName += Chunk.Text; | ||||
3307 | } | ||||
3308 | } | ||||
3309 | |||||
3310 | CodeCompletionString * | ||||
3311 | CodeCompletionResult::createCodeCompletionStringForOverride( | ||||
3312 | Preprocessor &PP, ASTContext &Ctx, CodeCompletionBuilder &Result, | ||||
3313 | bool IncludeBriefComments, const CodeCompletionContext &CCContext, | ||||
3314 | PrintingPolicy &Policy) { | ||||
3315 | auto *CCS = createCodeCompletionStringForDecl(PP, Ctx, Result, | ||||
3316 | /*IncludeBriefComments=*/false, | ||||
3317 | CCContext, Policy); | ||||
3318 | std::string BeforeName; | ||||
3319 | std::string NameAndSignature; | ||||
3320 | // For overrides all chunks go into the result, none are informative. | ||||
3321 | printOverrideString(*CCS, BeforeName, NameAndSignature); | ||||
3322 | NameAndSignature += " override"; | ||||
3323 | |||||
3324 | Result.AddTextChunk(Result.getAllocator().CopyString(BeforeName)); | ||||
3325 | Result.AddChunk(CodeCompletionString::CK_HorizontalSpace); | ||||
3326 | Result.AddTypedTextChunk(Result.getAllocator().CopyString(NameAndSignature)); | ||||
3327 | return Result.TakeString(); | ||||
3328 | } | ||||
3329 | |||||
3330 | CodeCompletionString *CodeCompletionResult::createCodeCompletionStringForDecl( | ||||
3331 | Preprocessor &PP, ASTContext &Ctx, CodeCompletionBuilder &Result, | ||||
3332 | bool IncludeBriefComments, const CodeCompletionContext &CCContext, | ||||
3333 | PrintingPolicy &Policy) { | ||||
3334 | const NamedDecl *ND = Declaration; | ||||
3335 | Result.addParentContext(ND->getDeclContext()); | ||||
3336 | |||||
3337 | if (IncludeBriefComments) { | ||||
3338 | // Add documentation comment, if it exists. | ||||
3339 | if (const RawComment *RC = getCompletionComment(Ctx, Declaration)) { | ||||
3340 | Result.addBriefComment(RC->getBriefText(Ctx)); | ||||
3341 | } | ||||
3342 | } | ||||
3343 | |||||
3344 | if (StartsNestedNameSpecifier) { | ||||
3345 | Result.AddTypedTextChunk( | ||||
3346 | Result.getAllocator().CopyString(ND->getNameAsString())); | ||||
3347 | Result.AddTextChunk("::"); | ||||
3348 | return Result.TakeString(); | ||||
3349 | } | ||||
3350 | |||||
3351 | for (const auto *I : ND->specific_attrs<AnnotateAttr>()) | ||||
3352 | Result.AddAnnotation(Result.getAllocator().CopyString(I->getAnnotation())); | ||||
3353 | |||||
3354 | AddResultTypeChunk(Ctx, Policy, ND, CCContext.getBaseType(), Result); | ||||
3355 | |||||
3356 | if (const auto *Function = dyn_cast<FunctionDecl>(ND)) { | ||||
3357 | AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative, | ||||
3358 | Ctx, Policy); | ||||
3359 | AddTypedNameChunk(Ctx, Policy, ND, Result); | ||||
3360 | Result.AddChunk(CodeCompletionString::CK_LeftParen); | ||||
3361 | AddFunctionParameterChunks(PP, Policy, Function, Result); | ||||
3362 | Result.AddChunk(CodeCompletionString::CK_RightParen); | ||||
3363 | AddFunctionTypeQualsToCompletionString(Result, Function); | ||||
3364 | return Result.TakeString(); | ||||
3365 | } | ||||
3366 | |||||
3367 | if (const FunctionTemplateDecl *FunTmpl = | ||||
3368 | dyn_cast<FunctionTemplateDecl>(ND)) { | ||||
3369 | AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative, | ||||
3370 | Ctx, Policy); | ||||
3371 | FunctionDecl *Function = FunTmpl->getTemplatedDecl(); | ||||
3372 | AddTypedNameChunk(Ctx, Policy, Function, Result); | ||||
3373 | |||||
3374 | // Figure out which template parameters are deduced (or have default | ||||
3375 | // arguments). | ||||
3376 | llvm::SmallBitVector Deduced; | ||||
3377 | Sema::MarkDeducedTemplateParameters(Ctx, FunTmpl, Deduced); | ||||
3378 | unsigned LastDeducibleArgument; | ||||
3379 | for (LastDeducibleArgument = Deduced.size(); LastDeducibleArgument > 0; | ||||
3380 | --LastDeducibleArgument) { | ||||
3381 | if (!Deduced[LastDeducibleArgument - 1]) { | ||||
3382 | // C++0x: Figure out if the template argument has a default. If so, | ||||
3383 | // the user doesn't need to type this argument. | ||||
3384 | // FIXME: We need to abstract template parameters better! | ||||
3385 | bool HasDefaultArg = false; | ||||
3386 | NamedDecl *Param = FunTmpl->getTemplateParameters()->getParam( | ||||
3387 | LastDeducibleArgument - 1); | ||||
3388 | if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param)) | ||||
3389 | HasDefaultArg = TTP->hasDefaultArgument(); | ||||
3390 | else if (NonTypeTemplateParmDecl *NTTP = | ||||
3391 | dyn_cast<NonTypeTemplateParmDecl>(Param)) | ||||
3392 | HasDefaultArg = NTTP->hasDefaultArgument(); | ||||
3393 | else { | ||||
3394 | assert(isa<TemplateTemplateParmDecl>(Param))((isa<TemplateTemplateParmDecl>(Param)) ? static_cast< void> (0) : __assert_fail ("isa<TemplateTemplateParmDecl>(Param)" , "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/clang/lib/Sema/SemaCodeComplete.cpp" , 3394, __PRETTY_FUNCTION__)); | ||||
3395 | HasDefaultArg = | ||||
3396 | cast<TemplateTemplateParmDecl>(Param)->hasDefaultArgument(); | ||||
3397 | } | ||||
3398 | |||||
3399 | if (!HasDefaultArg) | ||||
3400 | break; | ||||
3401 | } | ||||
3402 | } | ||||
3403 | |||||
3404 | if (LastDeducibleArgument) { | ||||
3405 | // Some of the function template arguments cannot be deduced from a | ||||
3406 | // function call, so we introduce an explicit template argument list | ||||
3407 | // containing all of the arguments up to the first deducible argument. | ||||
3408 | Result.AddChunk(CodeCompletionString::CK_LeftAngle); | ||||
3409 | AddTemplateParameterChunks(Ctx, Policy, FunTmpl, Result, | ||||
3410 | LastDeducibleArgument); | ||||
3411 | Result.AddChunk(CodeCompletionString::CK_RightAngle); | ||||
3412 | } | ||||
3413 | |||||
3414 | // Add the function parameters | ||||
3415 | Result.AddChunk(CodeCompletionString::CK_LeftParen); | ||||
3416 | AddFunctionParameterChunks(PP, Policy, Function, Result); | ||||
3417 | Result.AddChunk(CodeCompletionString::CK_RightParen); | ||||
3418 | AddFunctionTypeQualsToCompletionString(Result, Function); | ||||
3419 | return Result.TakeString(); | ||||
3420 | } | ||||
3421 | |||||
3422 | if (const auto *Template = dyn_cast<TemplateDecl>(ND)) { | ||||
3423 | AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative, | ||||
3424 | Ctx, Policy); | ||||
3425 | Result.AddTypedTextChunk( | ||||
3426 | Result.getAllocator().CopyString(Template->getNameAsString())); | ||||
3427 | Result.AddChunk(CodeCompletionString::CK_LeftAngle); | ||||
3428 | AddTemplateParameterChunks(Ctx, Policy, Template, Result); | ||||
3429 | Result.AddChunk(CodeCompletionString::CK_RightAngle); | ||||
3430 | return Result.TakeString(); | ||||
3431 | } | ||||
3432 | if (const auto *Method = dyn_cast<ObjCMethodDecl>(ND)) { | ||||
3433 | Selector Sel = Method->getSelector(); | ||||
3434 | if (Sel.isUnarySelector()) { | ||||
3435 | Result.AddTypedTextChunk( | ||||
3436 | Result.getAllocator().CopyString(Sel.getNameForSlot(0))); | ||||
3437 | return Result.TakeString(); | ||||
3438 | } | ||||
3439 | |||||
3440 | std::string SelName = Sel.getNameForSlot(0).str(); | ||||
3441 | SelName += ':'; | ||||
3442 | if (StartParameter == 0) | ||||
3443 | Result.AddTypedTextChunk(Result.getAllocator().CopyString(SelName)); | ||||
3444 | else { | ||||
3445 | Result.AddInformativeChunk(Result.getAllocator().CopyString(SelName)); | ||||
3446 | |||||
3447 | // If there is only one parameter, and we're past it, add an empty | ||||
3448 | // typed-text chunk since there is nothing to type. | ||||
3449 | if (Method->param_size() == 1) | ||||
3450 | Result.AddTypedTextChunk(""); | ||||
3451 | } | ||||
3452 | unsigned Idx = 0; | ||||
3453 | for (ObjCMethodDecl::param_const_iterator P = Method->param_begin(), | ||||
3454 | PEnd = Method->param_end(); | ||||
3455 | P != PEnd; (void)++P, ++Idx) { | ||||
3456 | if (Idx > 0) { | ||||
3457 | std::string Keyword; | ||||
3458 | if (Idx > StartParameter) | ||||
3459 | Result.AddChunk(CodeCompletionString::CK_HorizontalSpace); | ||||
3460 | if (IdentifierInfo *II = Sel.getIdentifierInfoForSlot(Idx)) | ||||
3461 | Keyword += II->getName(); | ||||
3462 | Keyword += ":"; | ||||
3463 | if (Idx < StartParameter || AllParametersAreInformative) | ||||
3464 | Result.AddInformativeChunk(Result.getAllocator().CopyString(Keyword)); | ||||
3465 | else | ||||
3466 | Result.AddTypedTextChunk(Result.getAllocator().CopyString(Keyword)); | ||||
3467 | } | ||||
3468 | |||||
3469 | // If we're before the starting parameter, skip the placeholder. | ||||
3470 | if (Idx < StartParameter) | ||||
3471 | continue; | ||||
3472 | |||||
3473 | std::string Arg; | ||||
3474 | QualType ParamType = (*P)->getType(); | ||||
3475 | Optional<ArrayRef<QualType>> ObjCSubsts; | ||||
3476 | if (!CCContext.getBaseType().isNull()) | ||||
3477 | ObjCSubsts = CCContext.getBaseType()->getObjCSubstitutions(Method); | ||||
3478 | |||||
3479 | if (ParamType->isBlockPointerType() && !DeclaringEntity) | ||||
3480 | Arg = FormatFunctionParameter(Policy, *P, true, | ||||
3481 | /*SuppressBlock=*/false, ObjCSubsts); | ||||
3482 | else { | ||||
3483 | if (ObjCSubsts) | ||||
3484 | ParamType = ParamType.substObjCTypeArgs( | ||||
3485 | Ctx, *ObjCSubsts, ObjCSubstitutionContext::Parameter); | ||||
3486 | Arg = "(" + formatObjCParamQualifiers((*P)->getObjCDeclQualifier(), | ||||
3487 | ParamType); | ||||
3488 | Arg += ParamType.getAsString(Policy) + ")"; | ||||
3489 | if (IdentifierInfo *II = (*P)->getIdentifier()) | ||||
3490 | if (DeclaringEntity || AllParametersAreInformative) | ||||
3491 | Arg += II->getName(); | ||||
3492 | } | ||||
3493 | |||||
3494 | if (Method->isVariadic() && (P + 1) == PEnd) | ||||
3495 | Arg += ", ..."; | ||||
3496 | |||||
3497 | if (DeclaringEntity) | ||||
3498 | Result.AddTextChunk(Result.getAllocator().CopyString(Arg)); | ||||
3499 | else if (AllParametersAreInformative) | ||||
3500 | Result.AddInformativeChunk(Result.getAllocator().CopyString(Arg)); | ||||
3501 | else | ||||
3502 | Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg)); | ||||
3503 | } | ||||
3504 | |||||
3505 | if (Method->isVariadic()) { | ||||
3506 | if (Method->param_size() == 0) { | ||||
3507 | if (DeclaringEntity) | ||||
3508 | Result.AddTextChunk(", ..."); | ||||
3509 | else if (AllParametersAreInformative) | ||||
3510 | Result.AddInformativeChunk(", ..."); | ||||
3511 | else | ||||
3512 | Result.AddPlaceholderChunk(", ..."); | ||||
3513 | } | ||||
3514 | |||||
3515 | MaybeAddSentinel(PP, Method, Result); | ||||
3516 | } | ||||
3517 | |||||
3518 | return Result.TakeString(); | ||||
3519 | } | ||||
3520 | |||||
3521 | if (Qualifier) | ||||
3522 | AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative, | ||||
3523 | Ctx, Policy); | ||||
3524 | |||||
3525 | Result.AddTypedTextChunk( | ||||
3526 | Result.getAllocator().CopyString(ND->getNameAsString())); | ||||
3527 | return Result.TakeString(); | ||||
3528 | } | ||||
3529 | |||||
3530 | const RawComment *clang::getCompletionComment(const ASTContext &Ctx, | ||||
3531 | const NamedDecl *ND) { | ||||
3532 | if (!ND) | ||||
3533 | return nullptr; | ||||
3534 | if (auto *RC = Ctx.getRawCommentForAnyRedecl(ND)) | ||||
3535 | return RC; | ||||
3536 | |||||
3537 | // Try to find comment from a property for ObjC methods. | ||||
3538 | const auto *M = dyn_cast<ObjCMethodDecl>(ND); | ||||
3539 | if (!M) | ||||
3540 | return nullptr; | ||||
3541 | const ObjCPropertyDecl *PDecl = M->findPropertyDecl(); | ||||
3542 | if (!PDecl) | ||||
3543 | return nullptr; | ||||
3544 | |||||
3545 | return Ctx.getRawCommentForAnyRedecl(PDecl); | ||||
3546 | } | ||||
3547 | |||||
3548 | const RawComment *clang::getPatternCompletionComment(const ASTContext &Ctx, | ||||
3549 | const NamedDecl *ND) { | ||||
3550 | const auto *M = dyn_cast_or_null<ObjCMethodDecl>(ND); | ||||
3551 | if (!M || !M->isPropertyAccessor()) | ||||
3552 | return nullptr; | ||||
3553 | |||||
3554 | // Provide code completion comment for self.GetterName where | ||||
3555 | // GetterName is the getter method for a property with name | ||||
3556 | // different from the property name (declared via a property | ||||
3557 | // getter attribute. | ||||
3558 | const ObjCPropertyDecl *PDecl = M->findPropertyDecl(); | ||||
3559 | if (!PDecl) | ||||
3560 | return nullptr; | ||||
3561 | if (PDecl->getGetterName() == M->getSelector() && | ||||
3562 | PDecl->getIdentifier() != M->getIdentifier()) { | ||||
3563 | if (auto *RC = Ctx.getRawCommentForAnyRedecl(M)) | ||||
3564 | return RC; | ||||
3565 | if (auto *RC = Ctx.getRawCommentForAnyRedecl(PDecl)) | ||||
3566 | return RC; | ||||
3567 | } | ||||
3568 | return nullptr; | ||||
3569 | } | ||||
3570 | |||||
3571 | const RawComment *clang::getParameterComment( | ||||
3572 | const ASTContext &Ctx, | ||||
3573 | const CodeCompleteConsumer::OverloadCandidate &Result, unsigned ArgIndex) { | ||||
3574 | auto FDecl = Result.getFunction(); | ||||
3575 | if (!FDecl) | ||||
3576 | return nullptr; | ||||
3577 | if (ArgIndex < FDecl->getNumParams()) | ||||
3578 | return Ctx.getRawCommentForAnyRedecl(FDecl->getParamDecl(ArgIndex)); | ||||
3579 | return nullptr; | ||||
3580 | } | ||||
3581 | |||||
3582 | /// Add function overload parameter chunks to the given code completion | ||||
3583 | /// string. | ||||
3584 | static void AddOverloadParameterChunks(ASTContext &Context, | ||||
3585 | const PrintingPolicy &Policy, | ||||
3586 | const FunctionDecl *Function, | ||||
3587 | const FunctionProtoType *Prototype, | ||||
3588 | CodeCompletionBuilder &Result, | ||||
3589 | unsigned CurrentArg, unsigned Start = 0, | ||||
3590 | bool InOptional = false) { | ||||
3591 | bool FirstParameter = true; | ||||
3592 | unsigned NumParams = | ||||
3593 | Function ? Function->getNumParams() : Prototype->getNumParams(); | ||||
3594 | |||||
3595 | for (unsigned P = Start; P != NumParams; ++P) { | ||||
3596 | if (Function && Function->getParamDecl(P)->hasDefaultArg() && !InOptional) { | ||||
3597 | // When we see an optional default argument, put that argument and | ||||
3598 | // the remaining default arguments into a new, optional string. | ||||
3599 | CodeCompletionBuilder Opt(Result.getAllocator(), | ||||
3600 | Result.getCodeCompletionTUInfo()); | ||||
3601 | if (!FirstParameter) | ||||
3602 | Opt.AddChunk(CodeCompletionString::CK_Comma); | ||||
3603 | // Optional sections are nested. | ||||
3604 | AddOverloadParameterChunks(Context, Policy, Function, Prototype, Opt, | ||||
3605 | CurrentArg, P, /*InOptional=*/true); | ||||
3606 | Result.AddOptionalChunk(Opt.TakeString()); | ||||
3607 | return; | ||||
3608 | } | ||||
3609 | |||||
3610 | if (FirstParameter) | ||||
3611 | FirstParameter = false; | ||||
3612 | else | ||||
3613 | Result.AddChunk(CodeCompletionString::CK_Comma); | ||||
3614 | |||||
3615 | InOptional = false; | ||||
3616 | |||||
3617 | // Format the placeholder string. | ||||
3618 | std::string Placeholder; | ||||
3619 | if (Function) { | ||||
3620 | const ParmVarDecl *Param = Function->getParamDecl(P); | ||||
3621 | Placeholder = FormatFunctionParameter(Policy, Param); | ||||
3622 | if (Param->hasDefaultArg()) | ||||
3623 | Placeholder += GetDefaultValueString(Param, Context.getSourceManager(), | ||||
3624 | Context.getLangOpts()); | ||||
3625 | } else { | ||||
3626 | Placeholder = Prototype->getParamType(P).getAsString(Policy); | ||||
3627 | } | ||||
3628 | |||||
3629 | if (P == CurrentArg) | ||||
3630 | Result.AddCurrentParameterChunk( | ||||
3631 | Result.getAllocator().CopyString(Placeholder)); | ||||
3632 | else | ||||
3633 | Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Placeholder)); | ||||
3634 | } | ||||
3635 | |||||
3636 | if (Prototype && Prototype->isVariadic()) { | ||||
3637 | CodeCompletionBuilder Opt(Result.getAllocator(), | ||||
3638 | Result.getCodeCompletionTUInfo()); | ||||
3639 | if (!FirstParameter) | ||||
3640 | Opt.AddChunk(CodeCompletionString::CK_Comma); | ||||
3641 | |||||
3642 | if (CurrentArg < NumParams) | ||||
3643 | Opt.AddPlaceholderChunk("..."); | ||||
3644 | else | ||||
3645 | Opt.AddCurrentParameterChunk("..."); | ||||
3646 | |||||
3647 | Result.AddOptionalChunk(Opt.TakeString()); | ||||
3648 | } | ||||
3649 | } | ||||
3650 | |||||
3651 | CodeCompletionString * | ||||
3652 | CodeCompleteConsumer::OverloadCandidate::CreateSignatureString( | ||||
3653 | unsigned CurrentArg, Sema &S, CodeCompletionAllocator &Allocator, | ||||
3654 | CodeCompletionTUInfo &CCTUInfo, bool IncludeBriefComments) const { | ||||
3655 | PrintingPolicy Policy = getCompletionPrintingPolicy(S); | ||||
3656 | |||||
3657 | // FIXME: Set priority, availability appropriately. | ||||
3658 | CodeCompletionBuilder Result(Allocator, CCTUInfo, 1, | ||||
3659 | CXAvailability_Available); | ||||
3660 | FunctionDecl *FDecl = getFunction(); | ||||
3661 | const FunctionProtoType *Proto = | ||||
3662 | dyn_cast<FunctionProtoType>(getFunctionType()); | ||||
3663 | if (!FDecl && !Proto) { | ||||
3664 | // Function without a prototype. Just give the return type and a | ||||
3665 | // highlighted ellipsis. | ||||
3666 | const FunctionType *FT = getFunctionType(); | ||||
3667 | Result.AddResultTypeChunk(Result.getAllocator().CopyString( | ||||
3668 | FT->getReturnType().getAsString(Policy))); | ||||
3669 | Result.AddChunk(CodeCompletionString::CK_LeftParen); | ||||
3670 | Result.AddChunk(CodeCompletionString::CK_CurrentParameter, "..."); | ||||
3671 | Result.AddChunk(CodeCompletionString::CK_RightParen); | ||||
3672 | return Result.TakeString(); | ||||
3673 | } | ||||
3674 | |||||
3675 | if (FDecl) { | ||||
3676 | if (IncludeBriefComments) { | ||||
3677 | if (auto RC = getParameterComment(S.getASTContext(), *this, CurrentArg)) | ||||
3678 | Result.addBriefComment(RC->getBriefText(S.getASTContext())); | ||||
3679 | } | ||||
3680 | AddResultTypeChunk(S.Context, Policy, FDecl, QualType(), Result); | ||||
3681 | Result.AddTextChunk( | ||||
3682 | Result.getAllocator().CopyString(FDecl->getNameAsString())); | ||||
3683 | } else { | ||||
3684 | Result.AddResultTypeChunk(Result.getAllocator().CopyString( | ||||
3685 | Proto->getReturnType().getAsString(Policy))); | ||||
3686 | } | ||||
3687 | |||||
3688 | Result.AddChunk(CodeCompletionString::CK_LeftParen); | ||||
3689 | AddOverloadParameterChunks(S.getASTContext(), Policy, FDecl, Proto, Result, | ||||
3690 | CurrentArg); | ||||
3691 | Result.AddChunk(CodeCompletionString::CK_RightParen); | ||||
3692 | |||||
3693 | return Result.TakeString(); | ||||
3694 | } | ||||
3695 | |||||
3696 | unsigned clang::getMacroUsagePriority(StringRef MacroName, | ||||
3697 | const LangOptions &LangOpts, | ||||
3698 | bool PreferredTypeIsPointer) { | ||||
3699 | unsigned Priority = CCP_Macro; | ||||
3700 | |||||
3701 | // Treat the "nil", "Nil" and "NULL" macros as null pointer constants. | ||||
3702 | if (MacroName.equals("nil") || MacroName.equals("NULL") || | ||||
3703 | MacroName.equals("Nil")) { | ||||
3704 | Priority = CCP_Constant; | ||||
3705 | if (PreferredTypeIsPointer) | ||||
3706 | Priority = Priority / CCF_SimilarTypeMatch; | ||||
3707 | } | ||||
3708 | // Treat "YES", "NO", "true", and "false" as constants. | ||||
3709 | else if (MacroName.equals("YES") || MacroName.equals("NO") || | ||||
3710 | MacroName.equals("true") || MacroName.equals("false")) | ||||
3711 | Priority = CCP_Constant; | ||||
3712 | // Treat "bool" as a type. | ||||
3713 | else if (MacroName.equals("bool")) | ||||
3714 | Priority = CCP_Type + (LangOpts.ObjC ? CCD_bool_in_ObjC : 0); | ||||
3715 | |||||
3716 | return Priority; | ||||
3717 | } | ||||
3718 | |||||
3719 | CXCursorKind clang::getCursorKindForDecl(const Decl *D) { | ||||
3720 | if (!D) | ||||
3721 | return CXCursor_UnexposedDecl; | ||||
3722 | |||||
3723 | switch (D->getKind()) { | ||||
3724 | case Decl::Enum: | ||||
3725 | return CXCursor_EnumDecl; | ||||
3726 | case Decl::EnumConstant: | ||||
3727 | return CXCursor_EnumConstantDecl; | ||||
3728 | case Decl::Field: | ||||
3729 | return CXCursor_FieldDecl; | ||||
3730 | case Decl::Function: | ||||
3731 | return CXCursor_FunctionDecl; | ||||
3732 | case Decl::ObjCCategory: | ||||
3733 | return CXCursor_ObjCCategoryDecl; | ||||
3734 | case Decl::ObjCCategoryImpl: | ||||
3735 | return CXCursor_ObjCCategoryImplDecl; | ||||
3736 | case Decl::ObjCImplementation: | ||||
3737 | return CXCursor_ObjCImplementationDecl; | ||||
3738 | |||||
3739 | case Decl::ObjCInterface: | ||||
3740 | return CXCursor_ObjCInterfaceDecl; | ||||
3741 | case Decl::ObjCIvar: | ||||
3742 | return CXCursor_ObjCIvarDecl; | ||||
3743 | case Decl::ObjCMethod: | ||||
3744 | return cast<ObjCMethodDecl>(D)->isInstanceMethod() | ||||
3745 | ? CXCursor_ObjCInstanceMethodDecl | ||||
3746 | : CXCursor_ObjCClassMethodDecl; | ||||
3747 | case Decl::CXXMethod: | ||||
3748 | return CXCursor_CXXMethod; | ||||
3749 | case Decl::CXXConstructor: | ||||
3750 | return CXCursor_Constructor; | ||||
3751 | case Decl::CXXDestructor: | ||||
3752 | return CXCursor_Destructor; | ||||
3753 | case Decl::CXXConversion: | ||||
3754 | return CXCursor_ConversionFunction; | ||||
3755 | case Decl::ObjCProperty: | ||||
3756 | return CXCursor_ObjCPropertyDecl; | ||||
3757 | case Decl::ObjCProtocol: | ||||
3758 | return CXCursor_ObjCProtocolDecl; | ||||
3759 | case Decl::ParmVar: | ||||
3760 | return CXCursor_ParmDecl; | ||||
3761 | case Decl::Typedef: | ||||
3762 | return CXCursor_TypedefDecl; | ||||
3763 | case Decl::TypeAlias: | ||||
3764 | return CXCursor_TypeAliasDecl; | ||||
3765 | case Decl::TypeAliasTemplate: | ||||
3766 | return CXCursor_TypeAliasTemplateDecl; | ||||
3767 | case Decl::Var: | ||||
3768 | return CXCursor_VarDecl; | ||||
3769 | case Decl::Namespace: | ||||
3770 | return CXCursor_Namespace; | ||||
3771 | case Decl::NamespaceAlias: | ||||
3772 | return CXCursor_NamespaceAlias; | ||||
3773 | case Decl::TemplateTypeParm: | ||||
3774 | return CXCursor_TemplateTypeParameter; | ||||
3775 | case Decl::NonTypeTemplateParm: | ||||
3776 | return CXCursor_NonTypeTemplateParameter; | ||||
3777 | case Decl::TemplateTemplateParm: | ||||
3778 | return CXCursor_TemplateTemplateParameter; | ||||
3779 | case Decl::FunctionTemplate: | ||||
3780 | return CXCursor_FunctionTemplate; | ||||
3781 | case Decl::ClassTemplate: | ||||
3782 | return CXCursor_ClassTemplate; | ||||
3783 | case Decl::AccessSpec: | ||||
3784 | return CXCursor_CXXAccessSpecifier; | ||||
3785 | case Decl::ClassTemplatePartialSpecialization: | ||||
3786 | return CXCursor_ClassTemplatePartialSpecialization; | ||||
3787 | case Decl::UsingDirective: | ||||
3788 | return CXCursor_UsingDirective; | ||||
3789 | case Decl::StaticAssert: | ||||
3790 | return CXCursor_StaticAssert; | ||||
3791 | case Decl::Friend: | ||||
3792 | return CXCursor_FriendDecl; | ||||
3793 | case Decl::TranslationUnit: | ||||
3794 | return CXCursor_TranslationUnit; | ||||
3795 | |||||
3796 | case Decl::Using: | ||||
3797 | case Decl::UnresolvedUsingValue: | ||||
3798 | case Decl::UnresolvedUsingTypename: | ||||
3799 | return CXCursor_UsingDeclaration; | ||||
3800 | |||||
3801 | case Decl::ObjCPropertyImpl: | ||||
3802 | switch (cast<ObjCPropertyImplDecl>(D)->getPropertyImplementation()) { | ||||
3803 | case ObjCPropertyImplDecl::Dynamic: | ||||
3804 | return CXCursor_ObjCDynamicDecl; | ||||
3805 | |||||
3806 | case ObjCPropertyImplDecl::Synthesize: | ||||
3807 | return CXCursor_ObjCSynthesizeDecl; | ||||
3808 | } | ||||
3809 | llvm_unreachable("Unexpected Kind!")::llvm::llvm_unreachable_internal("Unexpected Kind!", "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/clang/lib/Sema/SemaCodeComplete.cpp" , 3809); | ||||
3810 | |||||
3811 | case Decl::Import: | ||||
3812 | return CXCursor_ModuleImportDecl; | ||||
3813 | |||||
3814 | case Decl::ObjCTypeParam: | ||||
3815 | return CXCursor_TemplateTypeParameter; | ||||
3816 | |||||
3817 | default: | ||||
3818 | if (const auto *TD = dyn_cast<TagDecl>(D)) { | ||||
3819 | switch (TD->getTagKind()) { | ||||
3820 | case TTK_Interface: // fall through | ||||
3821 | case TTK_Struct: | ||||
3822 | return CXCursor_StructDecl; | ||||
3823 | case TTK_Class: | ||||
3824 | return CXCursor_ClassDecl; | ||||
3825 | case TTK_Union: | ||||
3826 | return CXCursor_UnionDecl; | ||||
3827 | case TTK_Enum: | ||||
3828 | return CXCursor_EnumDecl; | ||||
3829 | } | ||||
3830 | } | ||||
3831 | } | ||||
3832 | |||||
3833 | return CXCursor_UnexposedDecl; | ||||
3834 | } | ||||
3835 | |||||
3836 | static void AddMacroResults(Preprocessor &PP, ResultBuilder &Results, | ||||
3837 | bool LoadExternal, bool IncludeUndefined, | ||||
3838 | bool TargetTypeIsPointer = false) { | ||||
3839 | typedef CodeCompletionResult Result; | ||||
3840 | |||||
3841 | Results.EnterNewScope(); | ||||
3842 | |||||
3843 | for (Preprocessor::macro_iterator M = PP.macro_begin(LoadExternal), | ||||
3844 | MEnd = PP.macro_end(LoadExternal); | ||||
3845 | M != MEnd; ++M) { | ||||
3846 | auto MD = PP.getMacroDefinition(M->first); | ||||
3847 | if (IncludeUndefined || MD) { | ||||
3848 | MacroInfo *MI = MD.getMacroInfo(); | ||||
3849 | if (MI && MI->isUsedForHeaderGuard()) | ||||
3850 | continue; | ||||
3851 | |||||
3852 | Results.AddResult( | ||||
3853 | Result(M->first, MI, | ||||
3854 | getMacroUsagePriority(M->first->getName(), PP.getLangOpts(), | ||||
3855 | TargetTypeIsPointer))); | ||||
3856 | } | ||||
3857 | } | ||||
3858 | |||||
3859 | Results.ExitScope(); | ||||
3860 | } | ||||
3861 | |||||
3862 | static void AddPrettyFunctionResults(const LangOptions &LangOpts, | ||||
3863 | ResultBuilder &Results) { | ||||
3864 | typedef CodeCompletionResult Result; | ||||
3865 | |||||
3866 | Results.EnterNewScope(); | ||||
3867 | |||||
3868 | Results.AddResult(Result("__PRETTY_FUNCTION__", CCP_Constant)); | ||||
3869 | Results.AddResult(Result("__FUNCTION__", CCP_Constant)); | ||||
3870 | if (LangOpts.C99 || LangOpts.CPlusPlus11) | ||||
3871 | Results.AddResult(Result("__func__", CCP_Constant)); | ||||
3872 | Results.ExitScope(); | ||||
3873 | } | ||||
3874 | |||||
3875 | static void HandleCodeCompleteResults(Sema *S, | ||||
3876 | CodeCompleteConsumer *CodeCompleter, | ||||
3877 | CodeCompletionContext Context, | ||||
3878 | CodeCompletionResult *Results, | ||||
3879 | unsigned NumResults) { | ||||
3880 | if (CodeCompleter) | ||||
3881 | CodeCompleter->ProcessCodeCompleteResults(*S, Context, Results, NumResults); | ||||
3882 | } | ||||
3883 | |||||
3884 | static CodeCompletionContext | ||||
3885 | mapCodeCompletionContext(Sema &S, Sema::ParserCompletionContext PCC) { | ||||
3886 | switch (PCC) { | ||||
3887 | case Sema::PCC_Namespace: | ||||
3888 | return CodeCompletionContext::CCC_TopLevel; | ||||
3889 | |||||
3890 | case Sema::PCC_Class: | ||||
3891 | return CodeCompletionContext::CCC_ClassStructUnion; | ||||
3892 | |||||
3893 | case Sema::PCC_ObjCInterface: | ||||
3894 | return CodeCompletionContext::CCC_ObjCInterface; | ||||
3895 | |||||
3896 | case Sema::PCC_ObjCImplementation: | ||||
3897 | return CodeCompletionContext::CCC_ObjCImplementation; | ||||
3898 | |||||
3899 | case Sema::PCC_ObjCInstanceVariableList: | ||||
3900 | return CodeCompletionContext::CCC_ObjCIvarList; | ||||
3901 | |||||
3902 | case Sema::PCC_Template: | ||||
3903 | case Sema::PCC_MemberTemplate: | ||||
3904 | if (S.CurContext->isFileContext()) | ||||
3905 | return CodeCompletionContext::CCC_TopLevel; | ||||
3906 | if (S.CurContext->isRecord()) | ||||
3907 | return CodeCompletionContext::CCC_ClassStructUnion; | ||||
3908 | return CodeCompletionContext::CCC_Other; | ||||
3909 | |||||
3910 | case Sema::PCC_RecoveryInFunction: | ||||
3911 | return CodeCompletionContext::CCC_Recovery; | ||||
3912 | |||||
3913 | case Sema::PCC_ForInit: | ||||
3914 | if (S.getLangOpts().CPlusPlus || S.getLangOpts().C99 || | ||||
3915 | S.getLangOpts().ObjC) | ||||
3916 | return CodeCompletionContext::CCC_ParenthesizedExpression; | ||||
3917 | else | ||||
3918 | return CodeCompletionContext::CCC_Expression; | ||||
3919 | |||||
3920 | case Sema::PCC_Expression: | ||||
3921 | return CodeCompletionContext::CCC_Expression; | ||||
3922 | case Sema::PCC_Condition: | ||||
3923 | return CodeCompletionContext(CodeCompletionContext::CCC_Expression, | ||||
3924 | S.getASTContext().BoolTy); | ||||
3925 | |||||
3926 | case Sema::PCC_Statement: | ||||
3927 | return CodeCompletionContext::CCC_Statement; | ||||
3928 | |||||
3929 | case Sema::PCC_Type: | ||||
3930 | return CodeCompletionContext::CCC_Type; | ||||
3931 | |||||
3932 | case Sema::PCC_ParenthesizedExpression: | ||||
3933 | return CodeCompletionContext::CCC_ParenthesizedExpression; | ||||
3934 | |||||
3935 | case Sema::PCC_LocalDeclarationSpecifiers: | ||||
3936 | return CodeCompletionContext::CCC_Type; | ||||
3937 | } | ||||
3938 | |||||
3939 | llvm_unreachable("Invalid ParserCompletionContext!")::llvm::llvm_unreachable_internal("Invalid ParserCompletionContext!" , "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/clang/lib/Sema/SemaCodeComplete.cpp" , 3939); | ||||
3940 | } | ||||
3941 | |||||
3942 | /// If we're in a C++ virtual member function, add completion results | ||||
3943 | /// that invoke the functions we override, since it's common to invoke the | ||||
3944 | /// overridden function as well as adding new functionality. | ||||
3945 | /// | ||||
3946 | /// \param S The semantic analysis object for which we are generating results. | ||||
3947 | /// | ||||
3948 | /// \param InContext This context in which the nested-name-specifier preceding | ||||
3949 | /// the code-completion point | ||||
3950 | static void MaybeAddOverrideCalls(Sema &S, DeclContext *InContext, | ||||
3951 | ResultBuilder &Results) { | ||||
3952 | // Look through blocks. | ||||
3953 | DeclContext *CurContext = S.CurContext; | ||||
3954 | while (isa<BlockDecl>(CurContext)) | ||||
3955 | CurContext = CurContext->getParent(); | ||||
3956 | |||||
3957 | CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(CurContext); | ||||
3958 | if (!Method || !Method->isVirtual()) | ||||
3959 | return; | ||||
3960 | |||||
3961 | // We need to have names for all of the parameters, if we're going to | ||||
3962 | // generate a forwarding call. | ||||
3963 | for (auto P : Method->parameters()) | ||||
3964 | if (!P->getDeclName()) | ||||
3965 | return; | ||||
3966 | |||||
3967 | PrintingPolicy Policy = getCompletionPrintingPolicy(S); | ||||
3968 | for (const CXXMethodDecl *Overridden : Method->overridden_methods()) { | ||||
3969 | CodeCompletionBuilder Builder(Results.getAllocator(), | ||||
3970 | Results.getCodeCompletionTUInfo()); | ||||
3971 | if (Overridden->getCanonicalDecl() == Method->getCanonicalDecl()) | ||||
3972 | continue; | ||||
3973 | |||||
3974 | // If we need a nested-name-specifier, add one now. | ||||
3975 | if (!InContext) { | ||||
3976 | NestedNameSpecifier *NNS = getRequiredQualification( | ||||
3977 | S.Context, CurContext, Overridden->getDeclContext()); | ||||
3978 | if (NNS) { | ||||
3979 | std::string Str; | ||||
3980 | llvm::raw_string_ostream OS(Str); | ||||
3981 | NNS->print(OS, Policy); | ||||
3982 | Builder.AddTextChunk(Results.getAllocator().CopyString(OS.str())); | ||||
3983 | } | ||||
3984 | } else if (!InContext->Equals(Overridden->getDeclContext())) | ||||
3985 | continue; | ||||
3986 | |||||
3987 | Builder.AddTypedTextChunk( | ||||
3988 | Results.getAllocator().CopyString(Overridden->getNameAsString())); | ||||
3989 | Builder.AddChunk(CodeCompletionString::CK_LeftParen); | ||||
3990 | bool FirstParam = true; | ||||
3991 | for (auto P : Method->parameters()) { | ||||
3992 | if (FirstParam) | ||||
3993 | FirstParam = false; | ||||
3994 | else | ||||
3995 | Builder.AddChunk(CodeCompletionString::CK_Comma); | ||||
3996 | |||||
3997 | Builder.AddPlaceholderChunk( | ||||
3998 | Results.getAllocator().CopyString(P->getIdentifier()->getName())); | ||||
3999 | } | ||||
4000 | Builder.AddChunk(CodeCompletionString::CK_RightParen); | ||||
4001 | Results.AddResult(CodeCompletionResult( | ||||
4002 | Builder.TakeString(), CCP_SuperCompletion, CXCursor_CXXMethod, | ||||
4003 | CXAvailability_Available, Overridden)); | ||||
4004 | Results.Ignore(Overridden); | ||||
4005 | } | ||||
4006 | } | ||||
4007 | |||||
4008 | void Sema::CodeCompleteModuleImport(SourceLocation ImportLoc, | ||||
4009 | ModuleIdPath Path) { | ||||
4010 | typedef CodeCompletionResult Result; | ||||
4011 | ResultBuilder Results(*this, CodeCompleter->getAllocator(), | ||||
4012 | CodeCompleter->getCodeCompletionTUInfo(), | ||||
4013 | CodeCompletionContext::CCC_Other); | ||||
4014 | Results.EnterNewScope(); | ||||
4015 | |||||
4016 | CodeCompletionAllocator &Allocator = Results.getAllocator(); | ||||
4017 | CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo()); | ||||
4018 | typedef CodeCompletionResult Result; | ||||
4019 | if (Path.empty()) { | ||||
4020 | // Enumerate all top-level modules. | ||||
4021 | SmallVector<Module *, 8> Modules; | ||||
4022 | PP.getHeaderSearchInfo().collectAllModules(Modules); | ||||
4023 | for (unsigned I = 0, N = Modules.size(); I != N; ++I) { | ||||
4024 | Builder.AddTypedTextChunk( | ||||
4025 | Builder.getAllocator().CopyString(Modules[I]->Name)); | ||||
4026 | Results.AddResult(Result( | ||||
4027 | Builder.TakeString(), CCP_Declaration, CXCursor_ModuleImportDecl, | ||||
4028 | Modules[I]->isAvailable() ? CXAvailability_Available | ||||
4029 | : CXAvailability_NotAvailable)); | ||||
4030 | } | ||||
4031 | } else if (getLangOpts().Modules) { | ||||
4032 | // Load the named module. | ||||
4033 | Module *Mod = | ||||
4034 | PP.getModuleLoader().loadModule(ImportLoc, Path, Module::AllVisible, | ||||
4035 | /*IsInclusionDirective=*/false); | ||||
4036 | // Enumerate submodules. | ||||
4037 | if (Mod) { | ||||
4038 | for (Module::submodule_iterator Sub = Mod->submodule_begin(), | ||||
4039 | SubEnd = Mod->submodule_end(); | ||||
4040 | Sub != SubEnd; ++Sub) { | ||||
4041 | |||||
4042 | Builder.AddTypedTextChunk( | ||||
4043 | Builder.getAllocator().CopyString((*Sub)->Name)); | ||||
4044 | Results.AddResult(Result( | ||||
4045 | Builder.TakeString(), CCP_Declaration, CXCursor_ModuleImportDecl, | ||||
4046 | (*Sub)->isAvailable() ? CXAvailability_Available | ||||
4047 | : CXAvailability_NotAvailable)); | ||||
4048 | } | ||||
4049 | } | ||||
4050 | } | ||||
4051 | Results.ExitScope(); | ||||
4052 | HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), | ||||
4053 | Results.data(), Results.size()); | ||||
4054 | } | ||||
4055 | |||||
4056 | void Sema::CodeCompleteOrdinaryName(Scope *S, | ||||
4057 | ParserCompletionContext CompletionContext) { | ||||
4058 | ResultBuilder Results(*this, CodeCompleter->getAllocator(), | ||||
4059 | CodeCompleter->getCodeCompletionTUInfo(), | ||||
4060 | mapCodeCompletionContext(*this, CompletionContext)); | ||||
4061 | Results.EnterNewScope(); | ||||
4062 | |||||
4063 | // Determine how to filter results, e.g., so that the names of | ||||
4064 | // values (functions, enumerators, function templates, etc.) are | ||||
4065 | // only allowed where we can have an expression. | ||||
4066 | switch (CompletionContext) { | ||||
4067 | case PCC_Namespace: | ||||
4068 | case PCC_Class: | ||||
4069 | case PCC_ObjCInterface: | ||||
4070 | case PCC_ObjCImplementation: | ||||
4071 | case PCC_ObjCInstanceVariableList: | ||||
4072 | case PCC_Template: | ||||
4073 | case PCC_MemberTemplate: | ||||
4074 | case PCC_Type: | ||||
4075 | case PCC_LocalDeclarationSpecifiers: | ||||
4076 | Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName); | ||||
4077 | break; | ||||
4078 | |||||
4079 | case PCC_Statement: | ||||
4080 | case PCC_ParenthesizedExpression: | ||||
4081 | case PCC_Expression: | ||||
4082 | case PCC_ForInit: | ||||
4083 | case PCC_Condition: | ||||
4084 | if (WantTypesInContext(CompletionContext, getLangOpts())) | ||||
4085 | Results.setFilter(&ResultBuilder::IsOrdinaryName); | ||||
4086 | else | ||||
4087 | Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName); | ||||
4088 | |||||
4089 | if (getLangOpts().CPlusPlus) | ||||
4090 | MaybeAddOverrideCalls(*this, /*InContext=*/nullptr, Results); | ||||
4091 | break; | ||||
4092 | |||||
4093 | case PCC_RecoveryInFunction: | ||||
4094 | // Unfiltered | ||||
4095 | break; | ||||
4096 | } | ||||
4097 | |||||
4098 | // If we are in a C++ non-static member function, check the qualifiers on | ||||
4099 | // the member function to filter/prioritize the results list. | ||||
4100 | auto ThisType = getCurrentThisType(); | ||||
4101 | if (!ThisType.isNull()) | ||||
4102 | Results.setObjectTypeQualifiers(ThisType->getPointeeType().getQualifiers(), | ||||
4103 | VK_LValue); | ||||
4104 | |||||
4105 | CodeCompletionDeclConsumer Consumer(Results, CurContext); | ||||
4106 | LookupVisibleDecls(S, LookupOrdinaryName, Consumer, | ||||
4107 | CodeCompleter->includeGlobals(), | ||||
4108 | CodeCompleter->loadExternal()); | ||||
4109 | |||||
4110 | AddOrdinaryNameResults(CompletionContext, S, *this, Results); | ||||
4111 | Results.ExitScope(); | ||||
4112 | |||||
4113 | switch (CompletionContext) { | ||||
4114 | case PCC_ParenthesizedExpression: | ||||
4115 | case PCC_Expression: | ||||
4116 | case PCC_Statement: | ||||
4117 | case PCC_RecoveryInFunction: | ||||
4118 | if (S->getFnParent()) | ||||
4119 | AddPrettyFunctionResults(getLangOpts(), Results); | ||||
4120 | break; | ||||
4121 | |||||
4122 | case PCC_Namespace: | ||||
4123 | case PCC_Class: | ||||
4124 | case PCC_ObjCInterface: | ||||
4125 | case PCC_ObjCImplementation: | ||||
4126 | case PCC_ObjCInstanceVariableList: | ||||
4127 | case PCC_Template: | ||||
4128 | case PCC_MemberTemplate: | ||||
4129 | case PCC_ForInit: | ||||
4130 | case PCC_Condition: | ||||
4131 | case PCC_Type: | ||||
4132 | case PCC_LocalDeclarationSpecifiers: | ||||
4133 | break; | ||||
4134 | } | ||||
4135 | |||||
4136 | if (CodeCompleter->includeMacros()) | ||||
4137 | AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false); | ||||
4138 | |||||
4139 | HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), | ||||
4140 | Results.data(), Results.size()); | ||||
4141 | } | ||||
4142 | |||||
4143 | static void AddClassMessageCompletions(Sema &SemaRef, Scope *S, | ||||
4144 | ParsedType Receiver, | ||||
4145 | ArrayRef<IdentifierInfo *> SelIdents, | ||||
4146 | bool AtArgumentExpression, bool IsSuper, | ||||
4147 | ResultBuilder &Results); | ||||
4148 | |||||
4149 | void Sema::CodeCompleteDeclSpec(Scope *S, DeclSpec &DS, | ||||
4150 | bool AllowNonIdentifiers, | ||||
4151 | bool AllowNestedNameSpecifiers) { | ||||
4152 | typedef CodeCompletionResult Result; | ||||
4153 | ResultBuilder Results( | ||||
4154 | *this, CodeCompleter->getAllocator(), | ||||
4155 | CodeCompleter->getCodeCompletionTUInfo(), | ||||
4156 | AllowNestedNameSpecifiers | ||||
4157 | // FIXME: Try to separate codepath leading here to deduce whether we | ||||
4158 | // need an existing symbol or a new one. | ||||
4159 | ? CodeCompletionContext::CCC_SymbolOrNewName | ||||
4160 | : CodeCompletionContext::CCC_NewName); | ||||
4161 | Results.EnterNewScope(); | ||||
4162 | |||||
4163 | // Type qualifiers can come after names. | ||||
4164 | Results.AddResult(Result("const")); | ||||
4165 | Results.AddResult(Result("volatile")); | ||||
4166 | if (getLangOpts().C99) | ||||
4167 | Results.AddResult(Result("restrict")); | ||||
4168 | |||||
4169 | if (getLangOpts().CPlusPlus) { | ||||
4170 | if (getLangOpts().CPlusPlus11 && | ||||
4171 | (DS.getTypeSpecType() == DeclSpec::TST_class || | ||||
4172 | DS.getTypeSpecType() == DeclSpec::TST_struct)) | ||||
4173 | Results.AddResult("final"); | ||||
4174 | |||||
4175 | if (AllowNonIdentifiers) { | ||||
4176 | Results.AddResult(Result("operator")); | ||||
4177 | } | ||||
4178 | |||||
4179 | // Add nested-name-specifiers. | ||||
4180 | if (AllowNestedNameSpecifiers) { | ||||
4181 | Results.allowNestedNameSpecifiers(); | ||||
4182 | Results.setFilter(&ResultBuilder::IsImpossibleToSatisfy); | ||||
4183 | CodeCompletionDeclConsumer Consumer(Results, CurContext); | ||||
4184 | LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer, | ||||
4185 | CodeCompleter->includeGlobals(), | ||||
4186 | CodeCompleter->loadExternal()); | ||||
4187 | Results.setFilter(nullptr); | ||||
4188 | } | ||||
4189 | } | ||||
4190 | Results.ExitScope(); | ||||
4191 | |||||
4192 | // If we're in a context where we might have an expression (rather than a | ||||
4193 | // declaration), and what we've seen so far is an Objective-C type that could | ||||
4194 | // be a receiver of a class message, this may be a class message send with | ||||
4195 | // the initial opening bracket '[' missing. Add appropriate completions. | ||||
4196 | if (AllowNonIdentifiers && !AllowNestedNameSpecifiers && | ||||
4197 | DS.getParsedSpecifiers() == DeclSpec::PQ_TypeSpecifier && | ||||
4198 | DS.getTypeSpecType() == DeclSpec::TST_typename && | ||||
4199 | DS.getTypeSpecComplex() == DeclSpec::TSC_unspecified && | ||||
4200 | DS.getTypeSpecSign() == DeclSpec::TSS_unspecified && | ||||
4201 | !DS.isTypeAltiVecVector() && S && | ||||
4202 | (S->getFlags() & Scope::DeclScope) != 0 && | ||||
4203 | (S->getFlags() & (Scope::ClassScope | Scope::TemplateParamScope | | ||||
4204 | Scope::FunctionPrototypeScope | Scope::AtCatchScope)) == | ||||
4205 | 0) { | ||||
4206 | ParsedType T = DS.getRepAsType(); | ||||
4207 | if (!T.get().isNull() && T.get()->isObjCObjectOrInterfaceType()) | ||||
4208 | AddClassMessageCompletions(*this, S, T, None, false, false, Results); | ||||
4209 | } | ||||
4210 | |||||
4211 | // Note that we intentionally suppress macro results here, since we do not | ||||
4212 | // encourage using macros to produce the names of entities. | ||||
4213 | |||||
4214 | HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), | ||||
4215 | Results.data(), Results.size()); | ||||
4216 | } | ||||
4217 | |||||
4218 | struct Sema::CodeCompleteExpressionData { | ||||
4219 | CodeCompleteExpressionData(QualType PreferredType = QualType(), | ||||
4220 | bool IsParenthesized = false) | ||||
4221 | : PreferredType(PreferredType), IntegralConstantExpression(false), | ||||
4222 | ObjCCollection(false), IsParenthesized(IsParenthesized) {} | ||||
4223 | |||||
4224 | QualType PreferredType; | ||||
4225 | bool IntegralConstantExpression; | ||||
4226 | bool ObjCCollection; | ||||
4227 | bool IsParenthesized; | ||||
4228 | SmallVector<Decl *, 4> IgnoreDecls; | ||||
4229 | }; | ||||
4230 | |||||
4231 | namespace { | ||||
4232 | /// Information that allows to avoid completing redundant enumerators. | ||||
4233 | struct CoveredEnumerators { | ||||
4234 | llvm::SmallPtrSet<EnumConstantDecl *, 8> Seen; | ||||
4235 | NestedNameSpecifier *SuggestedQualifier = nullptr; | ||||
4236 | }; | ||||
4237 | } // namespace | ||||
4238 | |||||
4239 | static void AddEnumerators(ResultBuilder &Results, ASTContext &Context, | ||||
4240 | EnumDecl *Enum, DeclContext *CurContext, | ||||
4241 | const CoveredEnumerators &Enumerators) { | ||||
4242 | NestedNameSpecifier *Qualifier = Enumerators.SuggestedQualifier; | ||||
4243 | if (Context.getLangOpts().CPlusPlus && !Qualifier && Enumerators.Seen.empty()) { | ||||
4244 | // If there are no prior enumerators in C++, check whether we have to | ||||
4245 | // qualify the names of the enumerators that we suggest, because they | ||||
4246 | // may not be visible in this scope. | ||||
4247 | Qualifier = getRequiredQualification(Context, CurContext, Enum); | ||||
4248 | } | ||||
4249 | |||||
4250 | Results.EnterNewScope(); | ||||
4251 | for (auto *E : Enum->enumerators()) { | ||||
4252 | if (Enumerators.Seen.count(E)) | ||||
4253 | continue; | ||||
4254 | |||||
4255 | CodeCompletionResult R(E, CCP_EnumInCase, Qualifier); | ||||
4256 | Results.AddResult(R, CurContext, nullptr, false); | ||||
4257 | } | ||||
4258 | Results.ExitScope(); | ||||
4259 | } | ||||
4260 | |||||
4261 | /// Try to find a corresponding FunctionProtoType for function-like types (e.g. | ||||
4262 | /// function pointers, std::function, etc). | ||||
4263 | static const FunctionProtoType *TryDeconstructFunctionLike(QualType T) { | ||||
4264 | assert(!T.isNull())((!T.isNull()) ? static_cast<void> (0) : __assert_fail ( "!T.isNull()", "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/clang/lib/Sema/SemaCodeComplete.cpp" , 4264, __PRETTY_FUNCTION__)); | ||||
4265 | // Try to extract first template argument from std::function<> and similar. | ||||
4266 | // Note we only handle the sugared types, they closely match what users wrote. | ||||
4267 | // We explicitly choose to not handle ClassTemplateSpecializationDecl. | ||||
4268 | if (auto *Specialization = T->getAs<TemplateSpecializationType>()) { | ||||
4269 | if (Specialization->getNumArgs() != 1) | ||||
4270 | return nullptr; | ||||
4271 | const TemplateArgument &Argument = Specialization->getArg(0); | ||||
4272 | if (Argument.getKind() != TemplateArgument::Type) | ||||
4273 | return nullptr; | ||||
4274 | return Argument.getAsType()->getAs<FunctionProtoType>(); | ||||
4275 | } | ||||
4276 | // Handle other cases. | ||||
4277 | if (T->isPointerType()) | ||||
4278 | T = T->getPointeeType(); | ||||
4279 | return T->getAs<FunctionProtoType>(); | ||||
4280 | } | ||||
4281 | |||||
4282 | /// Adds a pattern completion for a lambda expression with the specified | ||||
4283 | /// parameter types and placeholders for parameter names. | ||||
4284 | static void AddLambdaCompletion(ResultBuilder &Results, | ||||
4285 | llvm::ArrayRef<QualType> Parameters, | ||||
4286 | const LangOptions &LangOpts) { | ||||
4287 | if (!Results.includeCodePatterns()) | ||||
4288 | return; | ||||
4289 | CodeCompletionBuilder Completion(Results.getAllocator(), | ||||
4290 | Results.getCodeCompletionTUInfo()); | ||||
4291 | // [](<parameters>) {} | ||||
4292 | Completion.AddChunk(CodeCompletionString::CK_LeftBracket); | ||||
4293 | Completion.AddPlaceholderChunk("="); | ||||
4294 | Completion.AddChunk(CodeCompletionString::CK_RightBracket); | ||||
4295 | if (!Parameters.empty()) { | ||||
4296 | Completion.AddChunk(CodeCompletionString::CK_LeftParen); | ||||
4297 | bool First = true; | ||||
4298 | for (auto Parameter : Parameters) { | ||||
4299 | if (!First) | ||||
4300 | Completion.AddChunk(CodeCompletionString::ChunkKind::CK_Comma); | ||||
4301 | else | ||||
4302 | First = false; | ||||
4303 | |||||
4304 | constexpr llvm::StringLiteral NamePlaceholder = "!#!NAME_GOES_HERE!#!"; | ||||
4305 | std::string Type = NamePlaceholder; | ||||
4306 | Parameter.getAsStringInternal(Type, PrintingPolicy(LangOpts)); | ||||
4307 | llvm::StringRef Prefix, Suffix; | ||||
4308 | std::tie(Prefix, Suffix) = llvm::StringRef(Type).split(NamePlaceholder); | ||||
4309 | Prefix = Prefix.rtrim(); | ||||
4310 | Suffix = Suffix.ltrim(); | ||||
4311 | |||||
4312 | Completion.AddTextChunk(Completion.getAllocator().CopyString(Prefix)); | ||||
4313 | Completion.AddChunk(CodeCompletionString::CK_HorizontalSpace); | ||||
4314 | Completion.AddPlaceholderChunk("parameter"); | ||||
4315 | Completion.AddTextChunk(Completion.getAllocator().CopyString(Suffix)); | ||||
4316 | }; | ||||
4317 | Completion.AddChunk(CodeCompletionString::CK_RightParen); | ||||
4318 | } | ||||
4319 | Completion.AddChunk(clang::CodeCompletionString::CK_HorizontalSpace); | ||||
4320 | Completion.AddChunk(CodeCompletionString::CK_LeftBrace); | ||||
4321 | Completion.AddChunk(CodeCompletionString::CK_HorizontalSpace); | ||||
4322 | Completion.AddPlaceholderChunk("body"); | ||||
4323 | Completion.AddChunk(CodeCompletionString::CK_HorizontalSpace); | ||||
4324 | Completion.AddChunk(CodeCompletionString::CK_RightBrace); | ||||
4325 | |||||
4326 | Results.AddResult(Completion.TakeString()); | ||||
4327 | } | ||||
4328 | |||||
4329 | /// Perform code-completion in an expression context when we know what | ||||
4330 | /// type we're looking for. | ||||
4331 | void Sema::CodeCompleteExpression(Scope *S, | ||||
4332 | const CodeCompleteExpressionData &Data) { | ||||
4333 | ResultBuilder Results( | ||||
4334 | *this, CodeCompleter->getAllocator(), | ||||
4335 | CodeCompleter->getCodeCompletionTUInfo(), | ||||
4336 | CodeCompletionContext( | ||||
4337 | Data.IsParenthesized | ||||
4338 | ? CodeCompletionContext::CCC_ParenthesizedExpression | ||||
4339 | : CodeCompletionContext::CCC_Expression, | ||||
4340 | Data.PreferredType)); | ||||
4341 | auto PCC = | ||||
4342 | Data.IsParenthesized ? PCC_ParenthesizedExpression : PCC_Expression; | ||||
4343 | if (Data.ObjCCollection) | ||||
4344 | Results.setFilter(&ResultBuilder::IsObjCCollection); | ||||
4345 | else if (Data.IntegralConstantExpression) | ||||
4346 | Results.setFilter(&ResultBuilder::IsIntegralConstantValue); | ||||
4347 | else if (WantTypesInContext(PCC, getLangOpts())) | ||||
4348 | Results.setFilter(&ResultBuilder::IsOrdinaryName); | ||||
4349 | else | ||||
4350 | Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName); | ||||
4351 | |||||
4352 | if (!Data.PreferredType.isNull()) | ||||
4353 | Results.setPreferredType(Data.PreferredType.getNonReferenceType()); | ||||
4354 | |||||
4355 | // Ignore any declarations that we were told that we don't care about. | ||||
4356 | for (unsigned I = 0, N = Data.IgnoreDecls.size(); I != N; ++I) | ||||
4357 | Results.Ignore(Data.IgnoreDecls[I]); | ||||
4358 | |||||
4359 | CodeCompletionDeclConsumer Consumer(Results, CurContext); | ||||
4360 | LookupVisibleDecls(S, LookupOrdinaryName, Consumer, | ||||
4361 | CodeCompleter->includeGlobals(), | ||||
4362 | CodeCompleter->loadExternal()); | ||||
4363 | |||||
4364 | Results.EnterNewScope(); | ||||
4365 | AddOrdinaryNameResults(PCC, S, *this, Results); | ||||
4366 | Results.ExitScope(); | ||||
4367 | |||||
4368 | bool PreferredTypeIsPointer = false; | ||||
4369 | if (!Data.PreferredType.isNull()) { | ||||
4370 | PreferredTypeIsPointer = Data.PreferredType->isAnyPointerType() || | ||||
4371 | Data.PreferredType->isMemberPointerType() || | ||||
4372 | Data.PreferredType->isBlockPointerType(); | ||||
4373 | if (Data.PreferredType->isEnumeralType()) { | ||||
4374 | EnumDecl *Enum = Data.PreferredType->castAs<EnumType>()->getDecl(); | ||||
4375 | if (auto *Def = Enum->getDefinition()) | ||||
4376 | Enum = Def; | ||||
4377 | // FIXME: collect covered enumerators in cases like: | ||||
4378 | // if (x == my_enum::one) { ... } else if (x == ^) {} | ||||
4379 | AddEnumerators(Results, Context, Enum, CurContext, CoveredEnumerators()); | ||||
4380 | } | ||||
4381 | } | ||||
4382 | |||||
4383 | if (S->getFnParent() && !Data.ObjCCollection && | ||||
4384 | !Data.IntegralConstantExpression) | ||||
4385 | AddPrettyFunctionResults(getLangOpts(), Results); | ||||
4386 | |||||
4387 | if (CodeCompleter->includeMacros()) | ||||
4388 | AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false, | ||||
4389 | PreferredTypeIsPointer); | ||||
4390 | |||||
4391 | // Complete a lambda expression when preferred type is a function. | ||||
4392 | if (!Data.PreferredType.isNull() && getLangOpts().CPlusPlus11) { | ||||
4393 | if (const FunctionProtoType *F = | ||||
4394 | TryDeconstructFunctionLike(Data.PreferredType)) | ||||
4395 | AddLambdaCompletion(Results, F->getParamTypes(), getLangOpts()); | ||||
4396 | } | ||||
4397 | |||||
4398 | HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), | ||||
4399 | Results.data(), Results.size()); | ||||
4400 | } | ||||
4401 | |||||
4402 | void Sema::CodeCompleteExpression(Scope *S, QualType PreferredType, | ||||
4403 | bool IsParenthesized) { | ||||
4404 | return CodeCompleteExpression( | ||||
4405 | S, CodeCompleteExpressionData(PreferredType, IsParenthesized)); | ||||
4406 | } | ||||
4407 | |||||
4408 | void Sema::CodeCompletePostfixExpression(Scope *S, ExprResult E, | ||||
4409 | QualType PreferredType) { | ||||
4410 | if (E.isInvalid()) | ||||
4411 | CodeCompleteExpression(S, PreferredType); | ||||
4412 | else if (getLangOpts().ObjC) | ||||
4413 | CodeCompleteObjCInstanceMessage(S, E.get(), None, false); | ||||
4414 | } | ||||
4415 | |||||
4416 | /// The set of properties that have already been added, referenced by | ||||
4417 | /// property name. | ||||
4418 | typedef llvm::SmallPtrSet<IdentifierInfo *, 16> AddedPropertiesSet; | ||||
4419 | |||||
4420 | /// Retrieve the container definition, if any? | ||||
4421 | static ObjCContainerDecl *getContainerDef(ObjCContainerDecl *Container) { | ||||
4422 | if (ObjCInterfaceDecl *Interface = dyn_cast<ObjCInterfaceDecl>(Container)) { | ||||
4423 | if (Interface->hasDefinition()) | ||||
4424 | return Interface->getDefinition(); | ||||
4425 | |||||
4426 | return Interface; | ||||
4427 | } | ||||
4428 | |||||
4429 | if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) { | ||||
4430 | if (Protocol->hasDefinition()) | ||||
4431 | return Protocol->getDefinition(); | ||||
4432 | |||||
4433 | return Protocol; | ||||
4434 | } | ||||
4435 | return Container; | ||||
4436 | } | ||||
4437 | |||||
4438 | /// Adds a block invocation code completion result for the given block | ||||
4439 | /// declaration \p BD. | ||||
4440 | static void AddObjCBlockCall(ASTContext &Context, const PrintingPolicy &Policy, | ||||
4441 | CodeCompletionBuilder &Builder, | ||||
4442 | const NamedDecl *BD, | ||||
4443 | const FunctionTypeLoc &BlockLoc, | ||||
4444 | const FunctionProtoTypeLoc &BlockProtoLoc) { | ||||
4445 | Builder.AddResultTypeChunk( | ||||
4446 | GetCompletionTypeString(BlockLoc.getReturnLoc().getType(), Context, | ||||
4447 | Policy, Builder.getAllocator())); | ||||
4448 | |||||
4449 | AddTypedNameChunk(Context, Policy, BD, Builder); | ||||
4450 | Builder.AddChunk(CodeCompletionString::CK_LeftParen); | ||||
4451 | |||||
4452 | if (BlockProtoLoc && BlockProtoLoc.getTypePtr()->isVariadic()) { | ||||
4453 | Builder.AddPlaceholderChunk("..."); | ||||
4454 | } else { | ||||
4455 | for (unsigned I = 0, N = BlockLoc.getNumParams(); I != N; ++I) { | ||||
4456 | if (I) | ||||
4457 | Builder.AddChunk(CodeCompletionString::CK_Comma); | ||||
4458 | |||||
4459 | // Format the placeholder string. | ||||
4460 | std::string PlaceholderStr = | ||||
4461 | FormatFunctionParameter(Policy, BlockLoc.getParam(I)); | ||||
4462 | |||||
4463 | if (I == N - 1 && BlockProtoLoc && | ||||
4464 | BlockProtoLoc.getTypePtr()->isVariadic()) | ||||
4465 | PlaceholderStr += ", ..."; | ||||
4466 | |||||
4467 | // Add the placeholder string. | ||||
4468 | Builder.AddPlaceholderChunk( | ||||
4469 | Builder.getAllocator().CopyString(PlaceholderStr)); | ||||
4470 | } | ||||
4471 | } | ||||
4472 | |||||
4473 | Builder.AddChunk(CodeCompletionString::CK_RightParen); | ||||
4474 | } | ||||
4475 | |||||
4476 | static void | ||||
4477 | AddObjCProperties(const CodeCompletionContext &CCContext, | ||||
4478 | ObjCContainerDecl *Container, bool AllowCategories, | ||||
4479 | bool AllowNullaryMethods, DeclContext *CurContext, | ||||
4480 | AddedPropertiesSet &AddedProperties, ResultBuilder &Results, | ||||
4481 | bool IsBaseExprStatement = false, | ||||
4482 | bool IsClassProperty = false, bool InOriginalClass = true) { | ||||
4483 | typedef CodeCompletionResult Result; | ||||
4484 | |||||
4485 | // Retrieve the definition. | ||||
4486 | Container = getContainerDef(Container); | ||||
4487 | |||||
4488 | // Add properties in this container. | ||||
4489 | const auto AddProperty = [&](const ObjCPropertyDecl *P) { | ||||
4490 | if (!AddedProperties.insert(P->getIdentifier()).second) | ||||
4491 | return; | ||||
4492 | |||||
4493 | // FIXME: Provide block invocation completion for non-statement | ||||
4494 | // expressions. | ||||
4495 | if (!P->getType().getTypePtr()->isBlockPointerType() || | ||||
4496 | !IsBaseExprStatement) { | ||||
4497 | Result R = Result(P, Results.getBasePriority(P), nullptr); | ||||
4498 | if (!InOriginalClass) | ||||
4499 | setInBaseClass(R); | ||||
4500 | Results.MaybeAddResult(R, CurContext); | ||||
4501 | return; | ||||
4502 | } | ||||
4503 | |||||
4504 | // Block setter and invocation completion is provided only when we are able | ||||
4505 | // to find the FunctionProtoTypeLoc with parameter names for the block. | ||||
4506 | FunctionTypeLoc BlockLoc; | ||||
4507 | FunctionProtoTypeLoc BlockProtoLoc; | ||||
4508 | findTypeLocationForBlockDecl(P->getTypeSourceInfo(), BlockLoc, | ||||
4509 | BlockProtoLoc); | ||||
4510 | if (!BlockLoc) { | ||||
4511 | Result R = Result(P, Results.getBasePriority(P), nullptr); | ||||
4512 | if (!InOriginalClass) | ||||
4513 | setInBaseClass(R); | ||||
4514 | Results.MaybeAddResult(R, CurContext); | ||||
4515 | return; | ||||
4516 | } | ||||
4517 | |||||
4518 | // The default completion result for block properties should be the block | ||||
4519 | // invocation completion when the base expression is a statement. | ||||
4520 | CodeCompletionBuilder Builder(Results.getAllocator(), | ||||
4521 | Results.getCodeCompletionTUInfo()); | ||||
4522 | AddObjCBlockCall(Container->getASTContext(), | ||||
4523 | getCompletionPrintingPolicy(Results.getSema()), Builder, P, | ||||
4524 | BlockLoc, BlockProtoLoc); | ||||
4525 | Result R = Result(Builder.TakeString(), P, Results.getBasePriority(P)); | ||||
4526 | if (!InOriginalClass) | ||||
4527 | setInBaseClass(R); | ||||
4528 | Results.MaybeAddResult(R, CurContext); | ||||
4529 | |||||
4530 | // Provide additional block setter completion iff the base expression is a | ||||
4531 | // statement and the block property is mutable. | ||||
4532 | if (!P->isReadOnly()) { | ||||
4533 | CodeCompletionBuilder Builder(Results.getAllocator(), | ||||
4534 | Results.getCodeCompletionTUInfo()); | ||||
4535 | AddResultTypeChunk(Container->getASTContext(), | ||||
4536 | getCompletionPrintingPolicy(Results.getSema()), P, | ||||
4537 | CCContext.getBaseType(), Builder); | ||||
4538 | Builder.AddTypedTextChunk( | ||||
4539 | Results.getAllocator().CopyString(P->getName())); | ||||
4540 | Builder.AddChunk(CodeCompletionString::CK_Equal); | ||||
4541 | |||||
4542 | std::string PlaceholderStr = formatBlockPlaceholder( | ||||
4543 | getCompletionPrintingPolicy(Results.getSema()), P, BlockLoc, | ||||
4544 | BlockProtoLoc, /*SuppressBlockName=*/true); | ||||
4545 | // Add the placeholder string. | ||||
4546 | Builder.AddPlaceholderChunk( | ||||
4547 | Builder.getAllocator().CopyString(PlaceholderStr)); | ||||
4548 | |||||
4549 | // When completing blocks properties that return void the default | ||||
4550 | // property completion result should show up before the setter, | ||||
4551 | // otherwise the setter completion should show up before the default | ||||
4552 | // property completion, as we normally want to use the result of the | ||||
4553 | // call. | ||||
4554 | Result R = | ||||
4555 | Result(Builder.TakeString(), P, | ||||
4556 | Results.getBasePriority(P) + | ||||
4557 | (BlockLoc.getTypePtr()->getReturnType()->isVoidType() | ||||
4558 | ? CCD_BlockPropertySetter | ||||
4559 | : -CCD_BlockPropertySetter)); | ||||
4560 | if (!InOriginalClass) | ||||
4561 | setInBaseClass(R); | ||||
4562 | Results.MaybeAddResult(R, CurContext); | ||||
4563 | } | ||||
4564 | }; | ||||
4565 | |||||
4566 | if (IsClassProperty) { | ||||
4567 | for (const auto *P : Container->class_properties()) | ||||
4568 | AddProperty(P); | ||||
4569 | } else { | ||||
4570 | for (const auto *P : Container->instance_properties()) | ||||
4571 | AddProperty(P); | ||||
4572 | } | ||||
4573 | |||||
4574 | // Add nullary methods or implicit class properties | ||||
4575 | if (AllowNullaryMethods) { | ||||
4576 | ASTContext &Context = Container->getASTContext(); | ||||
4577 | PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema()); | ||||
4578 | // Adds a method result | ||||
4579 | const auto AddMethod = [&](const ObjCMethodDecl *M) { | ||||
4580 | IdentifierInfo *Name = M->getSelector().getIdentifierInfoForSlot(0); | ||||
4581 | if (!Name) | ||||
4582 | return; | ||||
4583 | if (!AddedProperties.insert(Name).second) | ||||
4584 | return; | ||||
4585 | CodeCompletionBuilder Builder(Results.getAllocator(), | ||||
4586 | Results.getCodeCompletionTUInfo()); | ||||
4587 | AddResultTypeChunk(Context, Policy, M, CCContext.getBaseType(), Builder); | ||||
4588 | Builder.AddTypedTextChunk( | ||||
4589 | Results.getAllocator().CopyString(Name->getName())); | ||||
4590 | Result R = Result(Builder.TakeString(), M, | ||||
4591 | CCP_MemberDeclaration + CCD_MethodAsProperty); | ||||
4592 | if (!InOriginalClass) | ||||
4593 | setInBaseClass(R); | ||||
4594 | Results.MaybeAddResult(R, CurContext); | ||||
4595 | }; | ||||
4596 | |||||
4597 | if (IsClassProperty) { | ||||
4598 | for (const auto *M : Container->methods()) { | ||||
4599 | // Gather the class method that can be used as implicit property | ||||
4600 | // getters. Methods with arguments or methods that return void aren't | ||||
4601 | // added to the results as they can't be used as a getter. | ||||
4602 | if (!M->getSelector().isUnarySelector() || | ||||
4603 | M->getReturnType()->isVoidType() || M->isInstanceMethod()) | ||||
4604 | continue; | ||||
4605 | AddMethod(M); | ||||
4606 | } | ||||
4607 | } else { | ||||
4608 | for (auto *M : Container->methods()) { | ||||
4609 | if (M->getSelector().isUnarySelector()) | ||||
4610 | AddMethod(M); | ||||
4611 | } | ||||
4612 | } | ||||
4613 | } | ||||
4614 | |||||
4615 | // Add properties in referenced protocols. | ||||
4616 | if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) { | ||||
4617 | for (auto *P : Protocol->protocols()) | ||||
4618 | AddObjCProperties(CCContext, P, AllowCategories, AllowNullaryMethods, | ||||
4619 | CurContext, AddedProperties, Results, | ||||
4620 | IsBaseExprStatement, IsClassProperty, | ||||
4621 | /*InOriginalClass*/ false); | ||||
4622 | } else if (ObjCInterfaceDecl *IFace = | ||||
4623 | dyn_cast<ObjCInterfaceDecl>(Container)) { | ||||
4624 | if (AllowCategories) { | ||||
4625 | // Look through categories. | ||||
4626 | for (auto *Cat : IFace->known_categories()) | ||||
4627 | AddObjCProperties(CCContext, Cat, AllowCategories, AllowNullaryMethods, | ||||
4628 | CurContext, AddedProperties, Results, | ||||
4629 | IsBaseExprStatement, IsClassProperty, | ||||
4630 | InOriginalClass); | ||||
4631 | } | ||||
4632 | |||||
4633 | // Look through protocols. | ||||
4634 | for (auto *I : IFace->all_referenced_protocols()) | ||||
4635 | AddObjCProperties(CCContext, I, AllowCategories, AllowNullaryMethods, | ||||
4636 | CurContext, AddedProperties, Results, | ||||
4637 | IsBaseExprStatement, IsClassProperty, | ||||
4638 | /*InOriginalClass*/ false); | ||||
4639 | |||||
4640 | // Look in the superclass. | ||||
4641 | if (IFace->getSuperClass()) | ||||
4642 | AddObjCProperties(CCContext, IFace->getSuperClass(), AllowCategories, | ||||
4643 | AllowNullaryMethods, CurContext, AddedProperties, | ||||
4644 | Results, IsBaseExprStatement, IsClassProperty, | ||||
4645 | /*InOriginalClass*/ false); | ||||
4646 | } else if (const auto *Category = | ||||
4647 | dyn_cast<ObjCCategoryDecl>(Container)) { | ||||
4648 | // Look through protocols. | ||||
4649 | for (auto *P : Category->protocols()) | ||||
4650 | AddObjCProperties(CCContext, P, AllowCategories, AllowNullaryMethods, | ||||
4651 | CurContext, AddedProperties, Results, | ||||
4652 | IsBaseExprStatement, IsClassProperty, | ||||
4653 | /*InOriginalClass*/ false); | ||||
4654 | } | ||||
4655 | } | ||||
4656 | |||||
4657 | static void AddRecordMembersCompletionResults( | ||||
4658 | Sema &SemaRef, ResultBuilder &Results, Scope *S, QualType BaseType, | ||||
4659 | ExprValueKind BaseKind, RecordDecl *RD, Optional<FixItHint> AccessOpFixIt) { | ||||
4660 | // Indicate that we are performing a member access, and the cv-qualifiers | ||||
4661 | // for the base object type. | ||||
4662 | Results.setObjectTypeQualifiers(BaseType.getQualifiers(), BaseKind); | ||||
4663 | |||||
4664 | // Access to a C/C++ class, struct, or union. | ||||
4665 | Results.allowNestedNameSpecifiers(); | ||||
4666 | std::vector<FixItHint> FixIts; | ||||
4667 | if (AccessOpFixIt) | ||||
4668 | FixIts.emplace_back(AccessOpFixIt.getValue()); | ||||
4669 | CodeCompletionDeclConsumer Consumer(Results, RD, BaseType, std::move(FixIts)); | ||||
4670 | SemaRef.LookupVisibleDecls(RD, Sema::LookupMemberName, Consumer, | ||||
4671 | SemaRef.CodeCompleter->includeGlobals(), | ||||
4672 | /*IncludeDependentBases=*/true, | ||||
4673 | SemaRef.CodeCompleter->loadExternal()); | ||||
4674 | |||||
4675 | if (SemaRef.getLangOpts().CPlusPlus) { | ||||
4676 | if (!Results.empty()) { | ||||
4677 | // The "template" keyword can follow "->" or "." in the grammar. | ||||
4678 | // However, we only want to suggest the template keyword if something | ||||
4679 | // is dependent. | ||||
4680 | bool IsDependent = BaseType->isDependentType(); | ||||
4681 | if (!IsDependent) { | ||||
4682 | for (Scope *DepScope = S; DepScope; DepScope = DepScope->getParent()) | ||||
4683 | if (DeclContext *Ctx = DepScope->getEntity()) { | ||||
4684 | IsDependent = Ctx->isDependentContext(); | ||||
4685 | break; | ||||
4686 | } | ||||
4687 | } | ||||
4688 | |||||
4689 | if (IsDependent) | ||||
4690 | Results.AddResult(CodeCompletionResult("template")); | ||||
4691 | } | ||||
4692 | } | ||||
4693 | } | ||||
4694 | |||||
4695 | void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base, | ||||
4696 | Expr *OtherOpBase, | ||||
4697 | SourceLocation OpLoc, bool IsArrow, | ||||
4698 | bool IsBaseExprStatement, | ||||
4699 | QualType PreferredType) { | ||||
4700 | if (!Base || !CodeCompleter) | ||||
| |||||
4701 | return; | ||||
4702 | |||||
4703 | ExprResult ConvertedBase = PerformMemberExprBaseConversion(Base, IsArrow); | ||||
4704 | if (ConvertedBase.isInvalid()) | ||||
4705 | return; | ||||
4706 | QualType ConvertedBaseType = ConvertedBase.get()->getType(); | ||||
4707 | |||||
4708 | enum CodeCompletionContext::Kind contextKind; | ||||
4709 | |||||
4710 | if (IsArrow) { | ||||
4711 | if (const auto *Ptr = ConvertedBaseType->getAs<PointerType>()) | ||||
4712 | ConvertedBaseType = Ptr->getPointeeType(); | ||||
4713 | } | ||||
4714 | |||||
4715 | if (IsArrow
| ||||
4716 | contextKind = CodeCompletionContext::CCC_ArrowMemberAccess; | ||||
4717 | } else { | ||||
4718 | if (ConvertedBaseType->isObjCObjectPointerType() || | ||||
4719 | ConvertedBaseType->isObjCObjectOrInterfaceType()) { | ||||
4720 | contextKind = CodeCompletionContext::CCC_ObjCPropertyAccess; | ||||
4721 | } else { | ||||
4722 | contextKind = CodeCompletionContext::CCC_DotMemberAccess; | ||||
4723 | } | ||||
4724 | } | ||||
4725 | |||||
4726 | CodeCompletionContext CCContext(contextKind, ConvertedBaseType); | ||||
4727 | CCContext.setPreferredType(PreferredType); | ||||
4728 | ResultBuilder Results(*this, CodeCompleter->getAllocator(), | ||||
4729 | CodeCompleter->getCodeCompletionTUInfo(), CCContext, | ||||
4730 | &ResultBuilder::IsMember); | ||||
4731 | |||||
4732 | auto DoCompletion = [&](Expr *Base, bool IsArrow, | ||||
4733 | Optional<FixItHint> AccessOpFixIt) -> bool { | ||||
4734 | if (!Base
| ||||
4735 | return false; | ||||
4736 | |||||
4737 | ExprResult ConvertedBase = PerformMemberExprBaseConversion(Base, IsArrow); | ||||
4738 | if (ConvertedBase.isInvalid()) | ||||
4739 | return false; | ||||
4740 | Base = ConvertedBase.get(); | ||||
4741 | |||||
4742 | QualType BaseType = Base->getType(); | ||||
4743 | ExprValueKind BaseKind = Base->getValueKind(); | ||||
4744 | |||||
4745 | if (IsArrow
| ||||
4746 | if (const PointerType *Ptr = BaseType->getAs<PointerType>()) { | ||||
4747 | BaseType = Ptr->getPointeeType(); | ||||
4748 | BaseKind = VK_LValue; | ||||
4749 | } else if (BaseType->isObjCObjectPointerType()) | ||||
4750 | /*Do nothing*/; | ||||
4751 | else | ||||
4752 | return false; | ||||
4753 | } | ||||
4754 | |||||
4755 | if (const RecordType *Record
| ||||
4756 | AddRecordMembersCompletionResults(*this, Results, S, BaseType, BaseKind, | ||||
4757 | Record->getDecl(), | ||||
4758 | std::move(AccessOpFixIt)); | ||||
4759 | } else if (const auto *TST
| ||||
4760 | BaseType->getAs<TemplateSpecializationType>()) { | ||||
4761 | TemplateName TN = TST->getTemplateName(); | ||||
4762 | if (const auto *TD = | ||||
4763 | dyn_cast_or_null<ClassTemplateDecl>(TN.getAsTemplateDecl())) { | ||||
4764 | CXXRecordDecl *RD = TD->getTemplatedDecl(); | ||||
4765 | AddRecordMembersCompletionResults(*this, Results, S, BaseType, BaseKind, | ||||
4766 | RD, std::move(AccessOpFixIt)); | ||||
4767 | } | ||||
4768 | } else if (const auto *ICNT
| ||||
4769 | if (auto *RD = ICNT->getDecl()) | ||||
4770 | AddRecordMembersCompletionResults(*this, Results, S, BaseType, BaseKind, | ||||
4771 | RD, std::move(AccessOpFixIt)); | ||||
4772 | } else if (!IsArrow
| ||||
4773 | // Objective-C property reference. | ||||
4774 | AddedPropertiesSet AddedProperties; | ||||
4775 | |||||
4776 | if (const ObjCObjectPointerType *ObjCPtr = | ||||
4777 | BaseType->getAsObjCInterfacePointerType()) { | ||||
4778 | // Add property results based on our interface. | ||||
4779 | assert(ObjCPtr && "Non-NULL pointer guaranteed above!")((ObjCPtr && "Non-NULL pointer guaranteed above!") ? static_cast <void> (0) : __assert_fail ("ObjCPtr && \"Non-NULL pointer guaranteed above!\"" , "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/clang/lib/Sema/SemaCodeComplete.cpp" , 4779, __PRETTY_FUNCTION__)); | ||||
4780 | AddObjCProperties(CCContext, ObjCPtr->getInterfaceDecl(), true, | ||||
4781 | /*AllowNullaryMethods=*/true, CurContext, | ||||
4782 | AddedProperties, Results, IsBaseExprStatement); | ||||
4783 | } | ||||
4784 | |||||
4785 | // Add properties from the protocols in a qualified interface. | ||||
4786 | for (auto *I : BaseType->getAs<ObjCObjectPointerType>()->quals()) | ||||
| |||||
4787 | AddObjCProperties(CCContext, I, true, /*AllowNullaryMethods=*/true, | ||||
4788 | CurContext, AddedProperties, Results, | ||||
4789 | IsBaseExprStatement, /*IsClassProperty*/ false, | ||||
4790 | /*InOriginalClass*/ false); | ||||
4791 | } else if ((IsArrow && BaseType->isObjCObjectPointerType()) || | ||||
4792 | (!IsArrow && BaseType->isObjCObjectType())) { | ||||
4793 | // Objective-C instance variable access. | ||||
4794 | ObjCInterfaceDecl *Class = nullptr; | ||||
4795 | if (const ObjCObjectPointerType *ObjCPtr = | ||||
4796 | BaseType->getAs<ObjCObjectPointerType>()) | ||||
4797 | Class = ObjCPtr->getInterfaceDecl(); | ||||
4798 | else | ||||
4799 | Class = BaseType->getAs<ObjCObjectType>()->getInterface(); | ||||
4800 | |||||
4801 | // Add all ivars from this class and its superclasses. | ||||
4802 | if (Class) { | ||||
4803 | CodeCompletionDeclConsumer Consumer(Results, Class, BaseType); | ||||
4804 | Results.setFilter(&ResultBuilder::IsObjCIvar); | ||||
4805 | LookupVisibleDecls( | ||||
4806 | Class, LookupMemberName, Consumer, CodeCompleter->includeGlobals(), | ||||
4807 | /*IncludeDependentBases=*/false, CodeCompleter->loadExternal()); | ||||
4808 | } | ||||
4809 | } | ||||
4810 | |||||
4811 | // FIXME: How do we cope with isa? | ||||
4812 | return true; | ||||
4813 | }; | ||||
4814 | |||||
4815 | Results.EnterNewScope(); | ||||
4816 | |||||
4817 | bool CompletionSucceded = DoCompletion(Base, IsArrow, None); | ||||
4818 | if (CodeCompleter->includeFixIts()) { | ||||
4819 | const CharSourceRange OpRange = | ||||
4820 | CharSourceRange::getTokenRange(OpLoc, OpLoc); | ||||
4821 | CompletionSucceded |= DoCompletion( | ||||
4822 | OtherOpBase, !IsArrow, | ||||
4823 | FixItHint::CreateReplacement(OpRange, IsArrow ? "." : "->")); | ||||
4824 | } | ||||
4825 | |||||
4826 | Results.ExitScope(); | ||||
4827 | |||||
4828 | if (!CompletionSucceded) | ||||
4829 | return; | ||||
4830 | |||||
4831 | // Hand off the results found for code completion. | ||||
4832 | HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), | ||||
4833 | Results.data(), Results.size()); | ||||
4834 | } | ||||
4835 | |||||
4836 | void Sema::CodeCompleteObjCClassPropertyRefExpr(Scope *S, | ||||
4837 | IdentifierInfo &ClassName, | ||||
4838 | SourceLocation ClassNameLoc, | ||||
4839 | bool IsBaseExprStatement) { | ||||
4840 | IdentifierInfo *ClassNamePtr = &ClassName; | ||||
4841 | ObjCInterfaceDecl *IFace = getObjCInterfaceDecl(ClassNamePtr, ClassNameLoc); | ||||
4842 | if (!IFace) | ||||
4843 | return; | ||||
4844 | CodeCompletionContext CCContext( | ||||
4845 | CodeCompletionContext::CCC_ObjCPropertyAccess); | ||||
4846 | ResultBuilder Results(*this, CodeCompleter->getAllocator(), | ||||
4847 | CodeCompleter->getCodeCompletionTUInfo(), CCContext, | ||||
4848 | &ResultBuilder::IsMember); | ||||
4849 | Results.EnterNewScope(); | ||||
4850 | AddedPropertiesSet AddedProperties; | ||||
4851 | AddObjCProperties(CCContext, IFace, true, | ||||
4852 | /*AllowNullaryMethods=*/true, CurContext, AddedProperties, | ||||
4853 | Results, IsBaseExprStatement, | ||||
4854 | /*IsClassProperty=*/true); | ||||
4855 | Results.ExitScope(); | ||||
4856 | HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), | ||||
4857 | Results.data(), Results.size()); | ||||
4858 | } | ||||
4859 | |||||
4860 | void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) { | ||||
4861 | if (!CodeCompleter) | ||||
4862 | return; | ||||
4863 | |||||
4864 | ResultBuilder::LookupFilter Filter = nullptr; | ||||
4865 | enum CodeCompletionContext::Kind ContextKind = | ||||
4866 | CodeCompletionContext::CCC_Other; | ||||
4867 | switch ((DeclSpec::TST)TagSpec) { | ||||
4868 | case DeclSpec::TST_enum: | ||||
4869 | Filter = &ResultBuilder::IsEnum; | ||||
4870 | ContextKind = CodeCompletionContext::CCC_EnumTag; | ||||
4871 | break; | ||||
4872 | |||||
4873 | case DeclSpec::TST_union: | ||||
4874 | Filter = &ResultBuilder::IsUnion; | ||||
4875 | ContextKind = CodeCompletionContext::CCC_UnionTag; | ||||
4876 | break; | ||||
4877 | |||||
4878 | case DeclSpec::TST_struct: | ||||
4879 | case DeclSpec::TST_class: | ||||
4880 | case DeclSpec::TST_interface: | ||||
4881 | Filter = &ResultBuilder::IsClassOrStruct; | ||||
4882 | ContextKind = CodeCompletionContext::CCC_ClassOrStructTag; | ||||
4883 | break; | ||||
4884 | |||||
4885 | default: | ||||
4886 | llvm_unreachable("Unknown type specifier kind in CodeCompleteTag")::llvm::llvm_unreachable_internal("Unknown type specifier kind in CodeCompleteTag" , "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/clang/lib/Sema/SemaCodeComplete.cpp" , 4886); | ||||
4887 | } | ||||
4888 | |||||
4889 | ResultBuilder Results(*this, CodeCompleter->getAllocator(), | ||||
4890 | CodeCompleter->getCodeCompletionTUInfo(), ContextKind); | ||||
4891 | CodeCompletionDeclConsumer Consumer(Results, CurContext); | ||||
4892 | |||||
4893 | // First pass: look for tags. | ||||
4894 | Results.setFilter(Filter); | ||||
4895 | LookupVisibleDecls(S, LookupTagName, Consumer, | ||||
4896 | CodeCompleter->includeGlobals(), | ||||
4897 | CodeCompleter->loadExternal()); | ||||
4898 | |||||
4899 | if (CodeCompleter->includeGlobals()) { | ||||
4900 | // Second pass: look for nested name specifiers. | ||||
4901 | Results.setFilter(&ResultBuilder::IsNestedNameSpecifier); | ||||
4902 | LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer, | ||||
4903 | CodeCompleter->includeGlobals(), | ||||
4904 | CodeCompleter->loadExternal()); | ||||
4905 | } | ||||
4906 | |||||
4907 | HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), | ||||
4908 | Results.data(), Results.size()); | ||||
4909 | } | ||||
4910 | |||||
4911 | static void AddTypeQualifierResults(DeclSpec &DS, ResultBuilder &Results, | ||||
4912 | const LangOptions &LangOpts) { | ||||
4913 | if (!(DS.getTypeQualifiers() & DeclSpec::TQ_const)) | ||||
4914 | Results.AddResult("const"); | ||||
4915 | if (!(DS.getTypeQualifiers() & DeclSpec::TQ_volatile)) | ||||
4916 | Results.AddResult("volatile"); | ||||
4917 | if (LangOpts.C99 && !(DS.getTypeQualifiers() & DeclSpec::TQ_restrict)) | ||||
4918 | Results.AddResult("restrict"); | ||||
4919 | if (LangOpts.C11 && !(DS.getTypeQualifiers() & DeclSpec::TQ_atomic)) | ||||
4920 | Results.AddResult("_Atomic"); | ||||
4921 | if (LangOpts.MSVCCompat && !(DS.getTypeQualifiers() & DeclSpec::TQ_unaligned)) | ||||
4922 | Results.AddResult("__unaligned"); | ||||
4923 | } | ||||
4924 | |||||
4925 | void Sema::CodeCompleteTypeQualifiers(DeclSpec &DS) { | ||||
4926 | ResultBuilder Results(*this, CodeCompleter->getAllocator(), | ||||
4927 | CodeCompleter->getCodeCompletionTUInfo(), | ||||
4928 | CodeCompletionContext::CCC_TypeQualifiers); | ||||
4929 | Results.EnterNewScope(); | ||||
4930 | AddTypeQualifierResults(DS, Results, LangOpts); | ||||
4931 | Results.ExitScope(); | ||||
4932 | HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), | ||||
4933 | Results.data(), Results.size()); | ||||
4934 | } | ||||
4935 | |||||
4936 | void Sema::CodeCompleteFunctionQualifiers(DeclSpec &DS, Declarator &D, | ||||
4937 | const VirtSpecifiers *VS) { | ||||
4938 | ResultBuilder Results(*this, CodeCompleter->getAllocator(), | ||||
4939 | CodeCompleter->getCodeCompletionTUInfo(), | ||||
4940 | CodeCompletionContext::CCC_TypeQualifiers); | ||||
4941 | Results.EnterNewScope(); | ||||
4942 | AddTypeQualifierResults(DS, Results, LangOpts); | ||||
4943 | if (LangOpts.CPlusPlus11) { | ||||
4944 | Results.AddResult("noexcept"); | ||||
4945 | if (D.getContext() == DeclaratorContext::MemberContext && | ||||
4946 | !D.isCtorOrDtor() && !D.isStaticMember()) { | ||||
4947 | if (!VS || !VS->isFinalSpecified()) | ||||
4948 | Results.AddResult("final"); | ||||
4949 | if (!VS || !VS->isOverrideSpecified()) | ||||
4950 | Results.AddResult("override"); | ||||
4951 | } | ||||
4952 | } | ||||
4953 | Results.ExitScope(); | ||||
4954 | HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), | ||||
4955 | Results.data(), Results.size()); | ||||
4956 | } | ||||
4957 | |||||
4958 | void Sema::CodeCompleteBracketDeclarator(Scope *S) { | ||||
4959 | CodeCompleteExpression(S, QualType(getASTContext().getSizeType())); | ||||
4960 | } | ||||
4961 | |||||
4962 | void Sema::CodeCompleteCase(Scope *S) { | ||||
4963 | if (getCurFunction()->SwitchStack.empty() || !CodeCompleter) | ||||
4964 | return; | ||||
4965 | |||||
4966 | SwitchStmt *Switch = getCurFunction()->SwitchStack.back().getPointer(); | ||||
4967 | // Condition expression might be invalid, do not continue in this case. | ||||
4968 | if (!Switch->getCond()) | ||||
4969 | return; | ||||
4970 | QualType type = Switch->getCond()->IgnoreImplicit()->getType(); | ||||
4971 | if (!type->isEnumeralType()) { | ||||
4972 | CodeCompleteExpressionData Data(type); | ||||
4973 | Data.IntegralConstantExpression = true; | ||||
4974 | CodeCompleteExpression(S, Data); | ||||
4975 | return; | ||||
4976 | } | ||||
4977 | |||||
4978 | // Code-complete the cases of a switch statement over an enumeration type | ||||
4979 | // by providing the list of | ||||
4980 | EnumDecl *Enum = type->castAs<EnumType>()->getDecl(); | ||||
4981 | if (EnumDecl *Def = Enum->getDefinition()) | ||||
4982 | Enum = Def; | ||||
4983 | |||||
4984 | // Determine which enumerators we have already seen in the switch statement. | ||||
4985 | // FIXME: Ideally, we would also be able to look *past* the code-completion | ||||
4986 | // token, in case we are code-completing in the middle of the switch and not | ||||
4987 | // at the end. However, we aren't able to do so at the moment. | ||||
4988 | CoveredEnumerators Enumerators; | ||||
4989 | for (SwitchCase *SC = Switch->getSwitchCaseList(); SC; | ||||
4990 | SC = SC->getNextSwitchCase()) { | ||||
4991 | CaseStmt *Case = dyn_cast<CaseStmt>(SC); | ||||
4992 | if (!Case) | ||||
4993 | continue; | ||||
4994 | |||||
4995 | Expr *CaseVal = Case->getLHS()->IgnoreParenCasts(); | ||||
4996 | if (auto *DRE = dyn_cast<DeclRefExpr>(CaseVal)) | ||||
4997 | if (auto *Enumerator = | ||||
4998 | dyn_cast<EnumConstantDecl>(DRE->getDecl())) { | ||||
4999 | // We look into the AST of the case statement to determine which | ||||
5000 | // enumerator was named. Alternatively, we could compute the value of | ||||
5001 | // the integral constant expression, then compare it against the | ||||
5002 | // values of each enumerator. However, value-based approach would not | ||||
5003 | // work as well with C++ templates where enumerators declared within a | ||||
5004 | // template are type- and value-dependent. | ||||
5005 | Enumerators.Seen.insert(Enumerator); | ||||
5006 | |||||
5007 | // If this is a qualified-id, keep track of the nested-name-specifier | ||||
5008 | // so that we can reproduce it as part of code completion, e.g., | ||||
5009 | // | ||||
5010 | // switch (TagD.getKind()) { | ||||
5011 | // case TagDecl::TK_enum: | ||||
5012 | // break; | ||||
5013 | // case XXX | ||||
5014 | // | ||||
5015 | // At the XXX, our completions are TagDecl::TK_union, | ||||
5016 | // TagDecl::TK_struct, and TagDecl::TK_class, rather than TK_union, | ||||
5017 | // TK_struct, and TK_class. | ||||
5018 | Enumerators.SuggestedQualifier = DRE->getQualifier(); | ||||
5019 | } | ||||
5020 | } | ||||
5021 | |||||
5022 | // Add any enumerators that have not yet been mentioned. | ||||
5023 | ResultBuilder Results(*this, CodeCompleter->getAllocator(), | ||||
5024 | CodeCompleter->getCodeCompletionTUInfo(), | ||||
5025 | CodeCompletionContext::CCC_Expression); | ||||
5026 | AddEnumerators(Results, Context, Enum, CurContext, Enumerators); | ||||
5027 | |||||
5028 | if (CodeCompleter->includeMacros()) { | ||||
5029 | AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false); | ||||
5030 | } | ||||
5031 | HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), | ||||
5032 | Results.data(), Results.size()); | ||||
5033 | } | ||||
5034 | |||||
5035 | static bool anyNullArguments(ArrayRef<Expr *> Args) { | ||||
5036 | if (Args.size() && !Args.data()) | ||||
5037 | return true; | ||||
5038 | |||||
5039 | for (unsigned I = 0; I != Args.size(); ++I) | ||||
5040 | if (!Args[I]) | ||||
5041 | return true; | ||||
5042 | |||||
5043 | return false; | ||||
5044 | } | ||||
5045 | |||||
5046 | typedef CodeCompleteConsumer::OverloadCandidate ResultCandidate; | ||||
5047 | |||||
5048 | static void mergeCandidatesWithResults( | ||||
5049 | Sema &SemaRef, SmallVectorImpl<ResultCandidate> &Results, | ||||
5050 | OverloadCandidateSet &CandidateSet, SourceLocation Loc) { | ||||
5051 | // Sort the overload candidate set by placing the best overloads first. | ||||
5052 | llvm::stable_sort(CandidateSet, [&](const OverloadCandidate &X, | ||||
5053 | const OverloadCandidate &Y) { | ||||
5054 | return isBetterOverloadCandidate(SemaRef, X, Y, Loc, | ||||
5055 | CandidateSet.getKind()); | ||||
5056 | }); | ||||
5057 | |||||
5058 | // Add the remaining viable overload candidates as code-completion results. | ||||
5059 | for (OverloadCandidate &Candidate : CandidateSet) { | ||||
5060 | if (Candidate.Function && Candidate.Function->isDeleted()) | ||||
5061 | continue; | ||||
5062 | if (Candidate.Viable) | ||||
5063 | Results.push_back(ResultCandidate(Candidate.Function)); | ||||
5064 | } | ||||
5065 | } | ||||
5066 | |||||
5067 | /// Get the type of the Nth parameter from a given set of overload | ||||
5068 | /// candidates. | ||||
5069 | static QualType getParamType(Sema &SemaRef, | ||||
5070 | ArrayRef<ResultCandidate> Candidates, unsigned N) { | ||||
5071 | |||||
5072 | // Given the overloads 'Candidates' for a function call matching all arguments | ||||
5073 | // up to N, return the type of the Nth parameter if it is the same for all | ||||
5074 | // overload candidates. | ||||
5075 | QualType ParamType; | ||||
5076 | for (auto &Candidate : Candidates) { | ||||
5077 | if (const auto *FType = Candidate.getFunctionType()) | ||||
5078 | if (const auto *Proto = dyn_cast<FunctionProtoType>(FType)) | ||||
5079 | if (N < Proto->getNumParams()) { | ||||
5080 | if (ParamType.isNull()) | ||||
5081 | ParamType = Proto->getParamType(N); | ||||
5082 | else if (!SemaRef.Context.hasSameUnqualifiedType( | ||||
5083 | ParamType.getNonReferenceType(), | ||||
5084 | Proto->getParamType(N).getNonReferenceType())) | ||||
5085 | // Otherwise return a default-constructed QualType. | ||||
5086 | return QualType(); | ||||
5087 | } | ||||
5088 | } | ||||
5089 | |||||
5090 | return ParamType; | ||||
5091 | } | ||||
5092 | |||||
5093 | static QualType | ||||
5094 | ProduceSignatureHelp(Sema &SemaRef, Scope *S, | ||||
5095 | MutableArrayRef<ResultCandidate> Candidates, | ||||
5096 | unsigned CurrentArg, SourceLocation OpenParLoc) { | ||||
5097 | if (Candidates.empty()) | ||||
5098 | return QualType(); | ||||
5099 | SemaRef.CodeCompleter->ProcessOverloadCandidates( | ||||
5100 | SemaRef, CurrentArg, Candidates.data(), Candidates.size(), OpenParLoc); | ||||
5101 | return getParamType(SemaRef, Candidates, CurrentArg); | ||||
5102 | } | ||||
5103 | |||||
5104 | QualType Sema::ProduceCallSignatureHelp(Scope *S, Expr *Fn, | ||||
5105 | ArrayRef<Expr *> Args, | ||||
5106 | SourceLocation OpenParLoc) { | ||||
5107 | if (!CodeCompleter) | ||||
5108 | return QualType(); | ||||
5109 | |||||
5110 | // FIXME: Provide support for variadic template functions. | ||||
5111 | // Ignore type-dependent call expressions entirely. | ||||
5112 | if (!Fn || Fn->isTypeDependent() || anyNullArguments(Args) || | ||||
5113 | Expr::hasAnyTypeDependentArguments(Args)) { | ||||
5114 | return QualType(); | ||||
5115 | } | ||||
5116 | |||||
5117 | // Build an overload candidate set based on the functions we find. | ||||
5118 | SourceLocation Loc = Fn->getExprLoc(); | ||||
5119 | OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal); | ||||
5120 | |||||
5121 | SmallVector<ResultCandidate, 8> Results; | ||||
5122 | |||||
5123 | Expr *NakedFn = Fn->IgnoreParenCasts(); | ||||
5124 | if (auto ULE = dyn_cast<UnresolvedLookupExpr>(NakedFn)) | ||||
5125 | AddOverloadedCallCandidates(ULE, Args, CandidateSet, | ||||
5126 | /*PartialOverloading=*/true); | ||||
5127 | else if (auto UME = dyn_cast<UnresolvedMemberExpr>(NakedFn)) { | ||||
5128 | TemplateArgumentListInfo TemplateArgsBuffer, *TemplateArgs = nullptr; | ||||
5129 | if (UME->hasExplicitTemplateArgs()) { | ||||
5130 | UME->copyTemplateArgumentsInto(TemplateArgsBuffer); | ||||
5131 | TemplateArgs = &TemplateArgsBuffer; | ||||
5132 | } | ||||
5133 | |||||
5134 | // Add the base as first argument (use a nullptr if the base is implicit). | ||||
5135 | SmallVector<Expr *, 12> ArgExprs( | ||||
5136 | 1, UME->isImplicitAccess() ? nullptr : UME->getBase()); | ||||
5137 | ArgExprs.append(Args.begin(), Args.end()); | ||||
5138 | UnresolvedSet<8> Decls; | ||||
5139 | Decls.append(UME->decls_begin(), UME->decls_end()); | ||||
5140 | const bool FirstArgumentIsBase = !UME->isImplicitAccess() && UME->getBase(); | ||||
5141 | AddFunctionCandidates(Decls, ArgExprs, CandidateSet, TemplateArgs, | ||||
5142 | /*SuppressUserConversions=*/false, | ||||
5143 | /*PartialOverloading=*/true, FirstArgumentIsBase); | ||||
5144 | } else { | ||||
5145 | FunctionDecl *FD = nullptr; | ||||
5146 | if (auto *MCE = dyn_cast<MemberExpr>(NakedFn)) | ||||
5147 | FD = dyn_cast<FunctionDecl>(MCE->getMemberDecl()); | ||||
5148 | else if (auto *DRE = dyn_cast<DeclRefExpr>(NakedFn)) | ||||
5149 | FD = dyn_cast<FunctionDecl>(DRE->getDecl()); | ||||
5150 | if (FD) { // We check whether it's a resolved function declaration. | ||||
5151 | if (!getLangOpts().CPlusPlus || | ||||
5152 | !FD->getType()->getAs<FunctionProtoType>()) | ||||
5153 | Results.push_back(ResultCandidate(FD)); | ||||
5154 | else | ||||
5155 | AddOverloadCandidate(FD, DeclAccessPair::make(FD, FD->getAccess()), | ||||
5156 | Args, CandidateSet, | ||||
5157 | /*SuppressUserConversions=*/false, | ||||
5158 | /*PartialOverloading=*/true); | ||||
5159 | |||||
5160 | } else if (auto DC = NakedFn->getType()->getAsCXXRecordDecl()) { | ||||
5161 | // If expression's type is CXXRecordDecl, it may overload the function | ||||
5162 | // call operator, so we check if it does and add them as candidates. | ||||
5163 | // A complete type is needed to lookup for member function call operators. | ||||
5164 | if (isCompleteType(Loc, NakedFn->getType())) { | ||||
5165 | DeclarationName OpName = | ||||
5166 | Context.DeclarationNames.getCXXOperatorName(OO_Call); | ||||
5167 | LookupResult R(*this, OpName, Loc, LookupOrdinaryName); | ||||
5168 | LookupQualifiedName(R, DC); | ||||
5169 | R.suppressDiagnostics(); | ||||
5170 | SmallVector<Expr *, 12> ArgExprs(1, NakedFn); | ||||
5171 | ArgExprs.append(Args.begin(), Args.end()); | ||||
5172 | AddFunctionCandidates(R.asUnresolvedSet(), ArgExprs, CandidateSet, | ||||
5173 | /*ExplicitArgs=*/nullptr, | ||||
5174 | /*SuppressUserConversions=*/false, | ||||
5175 | /*PartialOverloading=*/true); | ||||
5176 | } | ||||
5177 | } else { | ||||
5178 | // Lastly we check whether expression's type is function pointer or | ||||
5179 | // function. | ||||
5180 | QualType T = NakedFn->getType(); | ||||
5181 | if (!T->getPointeeType().isNull()) | ||||
5182 | T = T->getPointeeType(); | ||||
5183 | |||||
5184 | if (auto FP = T->getAs<FunctionProtoType>()) { | ||||
5185 | if (!TooManyArguments(FP->getNumParams(), Args.size(), | ||||
5186 | /*PartialOverloading=*/true) || | ||||
5187 | FP->isVariadic()) | ||||
5188 | Results.push_back(ResultCandidate(FP)); | ||||
5189 | } else if (auto FT = T->getAs<FunctionType>()) | ||||
5190 | // No prototype and declaration, it may be a K & R style function. | ||||
5191 | Results.push_back(ResultCandidate(FT)); | ||||
5192 | } | ||||
5193 | } | ||||
5194 | mergeCandidatesWithResults(*this, Results, CandidateSet, Loc); | ||||
5195 | QualType ParamType = | ||||
5196 | ProduceSignatureHelp(*this, S, Results, Args.size(), OpenParLoc); | ||||
5197 | return !CandidateSet.empty() ? ParamType : QualType(); | ||||
5198 | } | ||||
5199 | |||||
5200 | QualType Sema::ProduceConstructorSignatureHelp(Scope *S, QualType Type, | ||||
5201 | SourceLocation Loc, | ||||
5202 | ArrayRef<Expr *> Args, | ||||
5203 | SourceLocation OpenParLoc) { | ||||
5204 | if (!CodeCompleter) | ||||
5205 | return QualType(); | ||||
5206 | |||||
5207 | // A complete type is needed to lookup for constructors. | ||||
5208 | CXXRecordDecl *RD = | ||||
5209 | isCompleteType(Loc, Type) ? Type->getAsCXXRecordDecl() : nullptr; | ||||
5210 | if (!RD) | ||||
5211 | return Type; | ||||
5212 | |||||
5213 | // FIXME: Provide support for member initializers. | ||||
5214 | // FIXME: Provide support for variadic template constructors. | ||||
5215 | |||||
5216 | OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal); | ||||
5217 | |||||
5218 | for (NamedDecl *C : LookupConstructors(RD)) { | ||||
5219 | if (auto *FD = dyn_cast<FunctionDecl>(C)) { | ||||
5220 | AddOverloadCandidate(FD, DeclAccessPair::make(FD, C->getAccess()), Args, | ||||
5221 | CandidateSet, | ||||
5222 | /*SuppressUserConversions=*/false, | ||||
5223 | /*PartialOverloading=*/true, | ||||
5224 | /*AllowExplicit*/ true); | ||||
5225 | } else if (auto *FTD = dyn_cast<FunctionTemplateDecl>(C)) { | ||||
5226 | AddTemplateOverloadCandidate( | ||||
5227 | FTD, DeclAccessPair::make(FTD, C->getAccess()), | ||||
5228 | /*ExplicitTemplateArgs=*/nullptr, Args, CandidateSet, | ||||
5229 | /*SuppressUserConversions=*/false, | ||||
5230 | /*PartialOverloading=*/true); | ||||
5231 | } | ||||
5232 | } | ||||
5233 | |||||
5234 | SmallVector<ResultCandidate, 8> Results; | ||||
5235 | mergeCandidatesWithResults(*this, Results, CandidateSet, Loc); | ||||
5236 | return ProduceSignatureHelp(*this, S, Results, Args.size(), OpenParLoc); | ||||
5237 | } | ||||
5238 | |||||
5239 | QualType Sema::ProduceCtorInitMemberSignatureHelp( | ||||
5240 | Scope *S, Decl *ConstructorDecl, CXXScopeSpec SS, ParsedType TemplateTypeTy, | ||||
5241 | ArrayRef<Expr *> ArgExprs, IdentifierInfo *II, SourceLocation OpenParLoc) { | ||||
5242 | if (!CodeCompleter) | ||||
5243 | return QualType(); | ||||
5244 | |||||
5245 | CXXConstructorDecl *Constructor = | ||||
5246 | dyn_cast<CXXConstructorDecl>(ConstructorDecl); | ||||
5247 | if (!Constructor) | ||||
5248 | return QualType(); | ||||
5249 | // FIXME: Add support for Base class constructors as well. | ||||
5250 | if (ValueDecl *MemberDecl = tryLookupCtorInitMemberDecl( | ||||
5251 | Constructor->getParent(), SS, TemplateTypeTy, II)) | ||||
5252 | return ProduceConstructorSignatureHelp(getCurScope(), MemberDecl->getType(), | ||||
5253 | MemberDecl->getLocation(), ArgExprs, | ||||
5254 | OpenParLoc); | ||||
5255 | return QualType(); | ||||
5256 | } | ||||
5257 | |||||
5258 | void Sema::CodeCompleteInitializer(Scope *S, Decl *D) { | ||||
5259 | ValueDecl *VD = dyn_cast_or_null<ValueDecl>(D); | ||||
5260 | if (!VD) { | ||||
5261 | CodeCompleteOrdinaryName(S, PCC_Expression); | ||||
5262 | return; | ||||
5263 | } | ||||
5264 | |||||
5265 | CodeCompleteExpressionData Data; | ||||
5266 | Data.PreferredType = VD->getType(); | ||||
5267 | // Ignore VD to avoid completing the variable itself, e.g. in 'int foo = ^'. | ||||
5268 | Data.IgnoreDecls.push_back(VD); | ||||
5269 | |||||
5270 | CodeCompleteExpression(S, Data); | ||||
5271 | } | ||||
5272 | |||||
5273 | void Sema::CodeCompleteAfterIf(Scope *S) { | ||||
5274 | ResultBuilder Results(*this, CodeCompleter->getAllocator(), | ||||
5275 | CodeCompleter->getCodeCompletionTUInfo(), | ||||
5276 | mapCodeCompletionContext(*this, PCC_Statement)); | ||||
5277 | Results.setFilter(&ResultBuilder::IsOrdinaryName); | ||||
5278 | Results.EnterNewScope(); | ||||
5279 | |||||
5280 | CodeCompletionDeclConsumer Consumer(Results, CurContext); | ||||
5281 | LookupVisibleDecls(S, LookupOrdinaryName, Consumer, | ||||
5282 | CodeCompleter->includeGlobals(), | ||||
5283 | CodeCompleter->loadExternal()); | ||||
5284 | |||||
5285 | AddOrdinaryNameResults(PCC_Statement, S, *this, Results); | ||||
5286 | |||||
5287 | // "else" block | ||||
5288 | CodeCompletionBuilder Builder(Results.getAllocator(), | ||||
5289 | Results.getCodeCompletionTUInfo()); | ||||
5290 | Builder.AddTypedTextChunk("else"); | ||||
5291 | if (Results.includeCodePatterns()) { | ||||
5292 | Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | ||||
5293 | Builder.AddChunk(CodeCompletionString::CK_LeftBrace); | ||||
5294 | Builder.AddChunk(CodeCompletionString::CK_VerticalSpace); | ||||
5295 | Builder.AddPlaceholderChunk("statements"); | ||||
5296 | Builder.AddChunk(CodeCompletionString::CK_VerticalSpace); | ||||
5297 | Builder.AddChunk(CodeCompletionString::CK_RightBrace); | ||||
5298 | } | ||||
5299 | Results.AddResult(Builder.TakeString()); | ||||
5300 | |||||
5301 | // "else if" block | ||||
5302 | Builder.AddTypedTextChunk("else if"); | ||||
5303 | Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | ||||
5304 | Builder.AddChunk(CodeCompletionString::CK_LeftParen); | ||||
5305 | if (getLangOpts().CPlusPlus) | ||||
5306 | Builder.AddPlaceholderChunk("condition"); | ||||
5307 | else | ||||
5308 | Builder.AddPlaceholderChunk("expression"); | ||||
5309 | Builder.AddChunk(CodeCompletionString::CK_RightParen); | ||||
5310 | if (Results.includeCodePatterns()) { | ||||
5311 | Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | ||||
5312 | Builder.AddChunk(CodeCompletionString::CK_LeftBrace); | ||||
5313 | Builder.AddChunk(CodeCompletionString::CK_VerticalSpace); | ||||
5314 | Builder.AddPlaceholderChunk("statements"); | ||||
5315 | Builder.AddChunk(CodeCompletionString::CK_VerticalSpace); | ||||
5316 | Builder.AddChunk(CodeCompletionString::CK_RightBrace); | ||||
5317 | } | ||||
5318 | Results.AddResult(Builder.TakeString()); | ||||
5319 | |||||
5320 | Results.ExitScope(); | ||||
5321 | |||||
5322 | if (S->getFnParent()) | ||||
5323 | AddPrettyFunctionResults(getLangOpts(), Results); | ||||
5324 | |||||
5325 | if (CodeCompleter->includeMacros()) | ||||
5326 | AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false); | ||||
5327 | |||||
5328 | HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), | ||||
5329 | Results.data(), Results.size()); | ||||
5330 | } | ||||
5331 | |||||
5332 | void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS, | ||||
5333 | bool EnteringContext, | ||||
5334 | bool IsUsingDeclaration, QualType BaseType, | ||||
5335 | QualType PreferredType) { | ||||
5336 | if (SS.isEmpty() || !CodeCompleter) | ||||
5337 | return; | ||||
5338 | |||||
5339 | CodeCompletionContext CC(CodeCompletionContext::CCC_Symbol, PreferredType); | ||||
5340 | CC.setIsUsingDeclaration(IsUsingDeclaration); | ||||
5341 | CC.setCXXScopeSpecifier(SS); | ||||
5342 | |||||
5343 | // We want to keep the scope specifier even if it's invalid (e.g. the scope | ||||
5344 | // "a::b::" is not corresponding to any context/namespace in the AST), since | ||||
5345 | // it can be useful for global code completion which have information about | ||||
5346 | // contexts/symbols that are not in the AST. | ||||
5347 | if (SS.isInvalid()) { | ||||
5348 | // As SS is invalid, we try to collect accessible contexts from the current | ||||
5349 | // scope with a dummy lookup so that the completion consumer can try to | ||||
5350 | // guess what the specified scope is. | ||||
5351 | ResultBuilder DummyResults(*this, CodeCompleter->getAllocator(), | ||||
5352 | CodeCompleter->getCodeCompletionTUInfo(), CC); | ||||
5353 | if (!PreferredType.isNull()) | ||||
5354 | DummyResults.setPreferredType(PreferredType); | ||||
5355 | if (S->getEntity()) { | ||||
5356 | CodeCompletionDeclConsumer Consumer(DummyResults, S->getEntity(), | ||||
5357 | BaseType); | ||||
5358 | LookupVisibleDecls(S, LookupOrdinaryName, Consumer, | ||||
5359 | /*IncludeGlobalScope=*/false, | ||||
5360 | /*LoadExternal=*/false); | ||||
5361 | } | ||||
5362 | HandleCodeCompleteResults(this, CodeCompleter, | ||||
5363 | DummyResults.getCompletionContext(), nullptr, 0); | ||||
5364 | return; | ||||
5365 | } | ||||
5366 | // Always pretend to enter a context to ensure that a dependent type | ||||
5367 | // resolves to a dependent record. | ||||
5368 | DeclContext *Ctx = computeDeclContext(SS, /*EnteringContext=*/true); | ||||
5369 | if (!Ctx) | ||||
5370 | return; | ||||
5371 | |||||
5372 | // Try to instantiate any non-dependent declaration contexts before | ||||
5373 | // we look in them. | ||||
5374 | if (!isDependentScopeSpecifier(SS) && RequireCompleteDeclContext(SS, Ctx)) | ||||
5375 | return; | ||||
5376 | |||||
5377 | ResultBuilder Results(*this, CodeCompleter->getAllocator(), | ||||
5378 | CodeCompleter->getCodeCompletionTUInfo(), CC); | ||||
5379 | if (!PreferredType.isNull()) | ||||
5380 | Results.setPreferredType(PreferredType); | ||||
5381 | Results.EnterNewScope(); | ||||
5382 | |||||
5383 | // The "template" keyword can follow "::" in the grammar, but only | ||||
5384 | // put it into the grammar if the nested-name-specifier is dependent. | ||||
5385 | NestedNameSpecifier *NNS = SS.getScopeRep(); | ||||
5386 | if (!Results.empty() && NNS->isDependent()) | ||||
5387 | Results.AddResult("template"); | ||||
5388 | |||||
5389 | // Add calls to overridden virtual functions, if there are any. | ||||
5390 | // | ||||
5391 | // FIXME: This isn't wonderful, because we don't know whether we're actually | ||||
5392 | // in a context that permits expressions. This is a general issue with | ||||
5393 | // qualified-id completions. | ||||
5394 | if (!EnteringContext) | ||||
5395 | MaybeAddOverrideCalls(*this, Ctx, Results); | ||||
5396 | Results.ExitScope(); | ||||
5397 | |||||
5398 | if (CodeCompleter->includeNamespaceLevelDecls() || | ||||
5399 | (!Ctx->isNamespace() && !Ctx->isTranslationUnit())) { | ||||
5400 | CodeCompletionDeclConsumer Consumer(Results, Ctx, BaseType); | ||||
5401 | LookupVisibleDecls(Ctx, LookupOrdinaryName, Consumer, | ||||
5402 | /*IncludeGlobalScope=*/true, | ||||
5403 | /*IncludeDependentBases=*/true, | ||||
5404 | CodeCompleter->loadExternal()); | ||||
5405 | } | ||||
5406 | |||||
5407 | HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), | ||||
5408 | Results.data(), Results.size()); | ||||
5409 | } | ||||
5410 | |||||
5411 | void Sema::CodeCompleteUsing(Scope *S) { | ||||
5412 | if (!CodeCompleter) | ||||
5413 | return; | ||||
5414 | |||||
5415 | // This can be both a using alias or using declaration, in the former we | ||||
5416 | // expect a new name and a symbol in the latter case. | ||||
5417 | CodeCompletionContext Context(CodeCompletionContext::CCC_SymbolOrNewName); | ||||
5418 | Context.setIsUsingDeclaration(true); | ||||
5419 | |||||
5420 | ResultBuilder Results(*this, CodeCompleter->getAllocator(), | ||||
5421 | CodeCompleter->getCodeCompletionTUInfo(), Context, | ||||
5422 | &ResultBuilder::IsNestedNameSpecifier); | ||||
5423 | Results.EnterNewScope(); | ||||
5424 | |||||
5425 | // If we aren't in class scope, we could see the "namespace" keyword. | ||||
5426 | if (!S->isClassScope()) | ||||
5427 | Results.AddResult(CodeCompletionResult("namespace")); | ||||
5428 | |||||
5429 | // After "using", we can see anything that would start a | ||||
5430 | // nested-name-specifier. | ||||
5431 | CodeCompletionDeclConsumer Consumer(Results, CurContext); | ||||
5432 | LookupVisibleDecls(S, LookupOrdinaryName, Consumer, | ||||
5433 | CodeCompleter->includeGlobals(), | ||||
5434 | CodeCompleter->loadExternal()); | ||||
5435 | Results.ExitScope(); | ||||
5436 | |||||
5437 | HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), | ||||
5438 | Results.data(), Results.size()); | ||||
5439 | } | ||||
5440 | |||||
5441 | void Sema::CodeCompleteUsingDirective(Scope *S) { | ||||
5442 | if (!CodeCompleter) | ||||
5443 | return; | ||||
5444 | |||||
5445 | // After "using namespace", we expect to see a namespace name or namespace | ||||
5446 | // alias. | ||||
5447 | ResultBuilder Results(*this, CodeCompleter->getAllocator(), | ||||
5448 | CodeCompleter->getCodeCompletionTUInfo(), | ||||
5449 | CodeCompletionContext::CCC_Namespace, | ||||
5450 | &ResultBuilder::IsNamespaceOrAlias); | ||||
5451 | Results.EnterNewScope(); | ||||
5452 | CodeCompletionDeclConsumer Consumer(Results, CurContext); | ||||
5453 | LookupVisibleDecls(S, LookupOrdinaryName, Consumer, | ||||
5454 | CodeCompleter->includeGlobals(), | ||||
5455 | CodeCompleter->loadExternal()); | ||||
5456 | Results.ExitScope(); | ||||
5457 | HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), | ||||
5458 | Results.data(), Results.size()); | ||||
5459 | } | ||||
5460 | |||||
5461 | void Sema::CodeCompleteNamespaceDecl(Scope *S) { | ||||
5462 | if (!CodeCompleter) | ||||
5463 | return; | ||||
5464 | |||||
5465 | DeclContext *Ctx = S->getEntity(); | ||||
5466 | if (!S->getParent()) | ||||
5467 | Ctx = Context.getTranslationUnitDecl(); | ||||
5468 | |||||
5469 | bool SuppressedGlobalResults = | ||||
5470 | Ctx && !CodeCompleter->includeGlobals() && isa<TranslationUnitDecl>(Ctx); | ||||
5471 | |||||
5472 | ResultBuilder Results(*this, CodeCompleter->getAllocator(), | ||||
5473 | CodeCompleter->getCodeCompletionTUInfo(), | ||||
5474 | SuppressedGlobalResults | ||||
5475 | ? CodeCompletionContext::CCC_Namespace | ||||
5476 | : CodeCompletionContext::CCC_Other, | ||||
5477 | &ResultBuilder::IsNamespace); | ||||
5478 | |||||
5479 | if (Ctx && Ctx->isFileContext() && !SuppressedGlobalResults) { | ||||
5480 | // We only want to see those namespaces that have already been defined | ||||
5481 | // within this scope, because its likely that the user is creating an | ||||
5482 | // extended namespace declaration. Keep track of the most recent | ||||
5483 | // definition of each namespace. | ||||
5484 | std::map<NamespaceDecl *, NamespaceDecl *> OrigToLatest; | ||||
5485 | for (DeclContext::specific_decl_iterator<NamespaceDecl> | ||||
5486 | NS(Ctx->decls_begin()), | ||||
5487 | NSEnd(Ctx->decls_end()); | ||||
5488 | NS != NSEnd; ++NS) | ||||
5489 | OrigToLatest[NS->getOriginalNamespace()] = *NS; | ||||
5490 | |||||
5491 | // Add the most recent definition (or extended definition) of each | ||||
5492 | // namespace to the list of results. | ||||
5493 | Results.EnterNewScope(); | ||||
5494 | for (std::map<NamespaceDecl *, NamespaceDecl *>::iterator | ||||
5495 | NS = OrigToLatest.begin(), | ||||
5496 | NSEnd = OrigToLatest.end(); | ||||
5497 | NS != NSEnd; ++NS) | ||||
5498 | Results.AddResult( | ||||
5499 | CodeCompletionResult(NS->second, Results.getBasePriority(NS->second), | ||||
5500 | nullptr), | ||||
5501 | CurContext, nullptr, false); | ||||
5502 | Results.ExitScope(); | ||||
5503 | } | ||||
5504 | |||||
5505 | HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), | ||||
5506 | Results.data(), Results.size()); | ||||
5507 | } | ||||
5508 | |||||
5509 | void Sema::CodeCompleteNamespaceAliasDecl(Scope *S) { | ||||
5510 | if (!CodeCompleter) | ||||
5511 | return; | ||||
5512 | |||||
5513 | // After "namespace", we expect to see a namespace or alias. | ||||
5514 | ResultBuilder Results(*this, CodeCompleter->getAllocator(), | ||||
5515 | CodeCompleter->getCodeCompletionTUInfo(), | ||||
5516 | CodeCompletionContext::CCC_Namespace, | ||||
5517 | &ResultBuilder::IsNamespaceOrAlias); | ||||
5518 | CodeCompletionDeclConsumer Consumer(Results, CurContext); | ||||
5519 | LookupVisibleDecls(S, LookupOrdinaryName, Consumer, | ||||
5520 | CodeCompleter->includeGlobals(), | ||||
5521 | CodeCompleter->loadExternal()); | ||||
5522 | HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), | ||||
5523 | Results.data(), Results.size()); | ||||
5524 | } | ||||
5525 | |||||
5526 | void Sema::CodeCompleteOperatorName(Scope *S) { | ||||
5527 | if (!CodeCompleter) | ||||
5528 | return; | ||||
5529 | |||||
5530 | typedef CodeCompletionResult Result; | ||||
5531 | ResultBuilder Results(*this, CodeCompleter->getAllocator(), | ||||
5532 | CodeCompleter->getCodeCompletionTUInfo(), | ||||
5533 | CodeCompletionContext::CCC_Type, | ||||
5534 | &ResultBuilder::IsType); | ||||
5535 | Results.EnterNewScope(); | ||||
5536 | |||||
5537 | // Add the names of overloadable operators. Note that OO_Conditional is not | ||||
5538 | // actually overloadable. | ||||
5539 | #define OVERLOADED_OPERATOR(Name, Spelling, Token, Unary, Binary, MemberOnly) \ | ||||
5540 | if (OO_##Name != OO_Conditional) \ | ||||
5541 | Results.AddResult(Result(Spelling)); | ||||
5542 | #include "clang/Basic/OperatorKinds.def" | ||||
5543 | |||||
5544 | // Add any type names visible from the current scope | ||||
5545 | Results.allowNestedNameSpecifiers(); | ||||
5546 | CodeCompletionDeclConsumer Consumer(Results, CurContext); | ||||
5547 | LookupVisibleDecls(S, LookupOrdinaryName, Consumer, | ||||
5548 | CodeCompleter->includeGlobals(), | ||||
5549 | CodeCompleter->loadExternal()); | ||||
5550 | |||||
5551 | // Add any type specifiers | ||||
5552 | AddTypeSpecifierResults(getLangOpts(), Results); | ||||
5553 | Results.ExitScope(); | ||||
5554 | |||||
5555 | HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), | ||||
5556 | Results.data(), Results.size()); | ||||
5557 | } | ||||
5558 | |||||
5559 | void Sema::CodeCompleteConstructorInitializer( | ||||
5560 | Decl *ConstructorD, ArrayRef<CXXCtorInitializer *> Initializers) { | ||||
5561 | if (!ConstructorD) | ||||
5562 | return; | ||||
5563 | |||||
5564 | AdjustDeclIfTemplate(ConstructorD); | ||||
5565 | |||||
5566 | auto *Constructor = dyn_cast<CXXConstructorDecl>(ConstructorD); | ||||
5567 | if (!Constructor) | ||||
5568 | return; | ||||
5569 | |||||
5570 | ResultBuilder Results(*this, CodeCompleter->getAllocator(), | ||||
5571 | CodeCompleter->getCodeCompletionTUInfo(), | ||||
5572 | CodeCompletionContext::CCC_Symbol); | ||||
5573 | Results.EnterNewScope(); | ||||
5574 | |||||
5575 | // Fill in any already-initialized fields or base classes. | ||||
5576 | llvm::SmallPtrSet<FieldDecl *, 4> InitializedFields; | ||||
5577 | llvm::SmallPtrSet<CanQualType, 4> InitializedBases; | ||||
5578 | for (unsigned I = 0, E = Initializers.size(); I != E; ++I) { | ||||
5579 | if (Initializers[I]->isBaseInitializer()) | ||||
5580 | InitializedBases.insert(Context.getCanonicalType( | ||||
5581 | QualType(Initializers[I]->getBaseClass(), 0))); | ||||
5582 | else | ||||
5583 | InitializedFields.insert( | ||||
5584 | cast<FieldDecl>(Initializers[I]->getAnyMember())); | ||||
5585 | } | ||||
5586 | |||||
5587 | // Add completions for base classes. | ||||
5588 | PrintingPolicy Policy = getCompletionPrintingPolicy(*this); | ||||
5589 | bool SawLastInitializer = Initializers.empty(); | ||||
5590 | CXXRecordDecl *ClassDecl = Constructor->getParent(); | ||||
5591 | |||||
5592 | auto GenerateCCS = [&](const NamedDecl *ND, const char *Name) { | ||||
5593 | CodeCompletionBuilder Builder(Results.getAllocator(), | ||||
5594 | Results.getCodeCompletionTUInfo()); | ||||
5595 | Builder.AddTypedTextChunk(Name); | ||||
5596 | Builder.AddChunk(CodeCompletionString::CK_LeftParen); | ||||
5597 | if (const auto *Function = dyn_cast<FunctionDecl>(ND)) | ||||
5598 | AddFunctionParameterChunks(PP, Policy, Function, Builder); | ||||
5599 | else if (const auto *FunTemplDecl = dyn_cast<FunctionTemplateDecl>(ND)) | ||||
5600 | AddFunctionParameterChunks(PP, Policy, FunTemplDecl->getTemplatedDecl(), | ||||
5601 | Builder); | ||||
5602 | Builder.AddChunk(CodeCompletionString::CK_RightParen); | ||||
5603 | return Builder.TakeString(); | ||||
5604 | }; | ||||
5605 | auto AddDefaultCtorInit = [&](const char *Name, const char *Type, | ||||
5606 | const NamedDecl *ND) { | ||||
5607 | CodeCompletionBuilder Builder(Results.getAllocator(), | ||||
5608 | Results.getCodeCompletionTUInfo()); | ||||
5609 | Builder.AddTypedTextChunk(Name); | ||||
5610 | Builder.AddChunk(CodeCompletionString::CK_LeftParen); | ||||
5611 | Builder.AddPlaceholderChunk(Type); | ||||
5612 | Builder.AddChunk(CodeCompletionString::CK_RightParen); | ||||
5613 | if (ND) { | ||||
5614 | auto CCR = CodeCompletionResult( | ||||
5615 | Builder.TakeString(), ND, | ||||
5616 | SawLastInitializer ? CCP_NextInitializer : CCP_MemberDeclaration); | ||||
5617 | if (isa<FieldDecl>(ND)) | ||||
5618 | CCR.CursorKind = CXCursor_MemberRef; | ||||
5619 | return Results.AddResult(CCR); | ||||
5620 | } | ||||
5621 | return Results.AddResult(CodeCompletionResult( | ||||
5622 | Builder.TakeString(), | ||||
5623 | SawLastInitializer ? CCP_NextInitializer : CCP_MemberDeclaration)); | ||||
5624 | }; | ||||
5625 | auto AddCtorsWithName = [&](const CXXRecordDecl *RD, unsigned int Priority, | ||||
5626 | const char *Name, const FieldDecl *FD) { | ||||
5627 | if (!RD) | ||||
5628 | return AddDefaultCtorInit(Name, | ||||
5629 | FD ? Results.getAllocator().CopyString( | ||||
5630 | FD->getType().getAsString(Policy)) | ||||
5631 | : Name, | ||||
5632 | FD); | ||||
5633 | auto Ctors = getConstructors(Context, RD); | ||||
5634 | if (Ctors.begin() == Ctors.end()) | ||||
5635 | return AddDefaultCtorInit(Name, Name, RD); | ||||
5636 | for (const NamedDecl *Ctor : Ctors) { | ||||
5637 | auto CCR = CodeCompletionResult(GenerateCCS(Ctor, Name), RD, Priority); | ||||
5638 | CCR.CursorKind = getCursorKindForDecl(Ctor); | ||||
5639 | Results.AddResult(CCR); | ||||
5640 | } | ||||
5641 | }; | ||||
5642 | auto AddBase = [&](const CXXBaseSpecifier &Base) { | ||||
5643 | const char *BaseName = | ||||
5644 | Results.getAllocator().CopyString(Base.getType().getAsString(Policy)); | ||||
5645 | const auto *RD = Base.getType()->getAsCXXRecordDecl(); | ||||
5646 | AddCtorsWithName( | ||||
5647 | RD, SawLastInitializer ? CCP_NextInitializer : CCP_MemberDeclaration, | ||||
5648 | BaseName, nullptr); | ||||
5649 | }; | ||||
5650 | auto AddField = [&](const FieldDecl *FD) { | ||||
5651 | const char *FieldName = | ||||
5652 | Results.getAllocator().CopyString(FD->getIdentifier()->getName()); | ||||
5653 | const CXXRecordDecl *RD = FD->getType()->getAsCXXRecordDecl(); | ||||
5654 | AddCtorsWithName( | ||||
5655 | RD, SawLastInitializer ? CCP_NextInitializer : CCP_MemberDeclaration, | ||||
5656 | FieldName, FD); | ||||
5657 | }; | ||||
5658 | |||||
5659 | for (const auto &Base : ClassDecl->bases()) { | ||||
5660 | if (!InitializedBases.insert(Context.getCanonicalType(Base.getType())) | ||||
5661 | .second) { | ||||
5662 | SawLastInitializer = | ||||
5663 | !Initializers.empty() && Initializers.back()->isBaseInitializer() && | ||||
5664 | Context.hasSameUnqualifiedType( | ||||
5665 | Base.getType(), QualType(Initializers.back()->getBaseClass(), 0)); | ||||
5666 | continue; | ||||
5667 | } | ||||
5668 | |||||
5669 | AddBase(Base); | ||||
5670 | SawLastInitializer = false; | ||||
5671 | } | ||||
5672 | |||||
5673 | // Add completions for virtual base classes. | ||||
5674 | for (const auto &Base : ClassDecl->vbases()) { | ||||
5675 | if (!InitializedBases.insert(Context.getCanonicalType(Base.getType())) | ||||
5676 | .second) { | ||||
5677 | SawLastInitializer = | ||||
5678 | !Initializers.empty() && Initializers.back()->isBaseInitializer() && | ||||
5679 | Context.hasSameUnqualifiedType( | ||||
5680 | Base.getType(), QualType(Initializers.back()->getBaseClass(), 0)); | ||||
5681 | continue; | ||||
5682 | } | ||||
5683 | |||||
5684 | AddBase(Base); | ||||
5685 | SawLastInitializer = false; | ||||
5686 | } | ||||
5687 | |||||
5688 | // Add completions for members. | ||||
5689 | for (auto *Field : ClassDecl->fields()) { | ||||
5690 | if (!InitializedFields.insert(cast<FieldDecl>(Field->getCanonicalDecl())) | ||||
5691 | .second) { | ||||
5692 | SawLastInitializer = !Initializers.empty() && | ||||
5693 | Initializers.back()->isAnyMemberInitializer() && | ||||
5694 | Initializers.back()->getAnyMember() == Field; | ||||
5695 | continue; | ||||
5696 | } | ||||
5697 | |||||
5698 | if (!Field->getDeclName()) | ||||
5699 | continue; | ||||
5700 | |||||
5701 | AddField(Field); | ||||
5702 | SawLastInitializer = false; | ||||
5703 | } | ||||
5704 | Results.ExitScope(); | ||||
5705 | |||||
5706 | HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), | ||||
5707 | Results.data(), Results.size()); | ||||
5708 | } | ||||
5709 | |||||
5710 | /// Determine whether this scope denotes a namespace. | ||||
5711 | static bool isNamespaceScope(Scope *S) { | ||||
5712 | DeclContext *DC = S->getEntity(); | ||||
5713 | if (!DC) | ||||
5714 | return false; | ||||
5715 | |||||
5716 | return DC->isFileContext(); | ||||
5717 | } | ||||
5718 | |||||
5719 | void Sema::CodeCompleteLambdaIntroducer(Scope *S, LambdaIntroducer &Intro, | ||||
5720 | bool AfterAmpersand) { | ||||
5721 | ResultBuilder Results(*this, CodeCompleter->getAllocator(), | ||||
5722 | CodeCompleter->getCodeCompletionTUInfo(), | ||||
5723 | CodeCompletionContext::CCC_Other); | ||||
5724 | Results.EnterNewScope(); | ||||
5725 | |||||
5726 | // Note what has already been captured. | ||||
5727 | llvm::SmallPtrSet<IdentifierInfo *, 4> Known; | ||||
5728 | bool IncludedThis = false; | ||||
5729 | for (const auto &C : Intro.Captures) { | ||||
5730 | if (C.Kind == LCK_This) { | ||||
5731 | IncludedThis = true; | ||||
5732 | continue; | ||||
5733 | } | ||||
5734 | |||||
5735 | Known.insert(C.Id); | ||||
5736 | } | ||||
5737 | |||||
5738 | // Look for other capturable variables. | ||||
5739 | for (; S && !isNamespaceScope(S); S = S->getParent()) { | ||||
5740 | for (const auto *D : S->decls()) { | ||||
5741 | const auto *Var = dyn_cast<VarDecl>(D); | ||||
5742 | if (!Var || !Var->hasLocalStorage() || Var->hasAttr<BlocksAttr>()) | ||||
5743 | continue; | ||||
5744 | |||||
5745 | if (Known.insert(Var->getIdentifier()).second) | ||||
5746 | Results.AddResult(CodeCompletionResult(Var, CCP_LocalDeclaration), | ||||
5747 | CurContext, nullptr, false); | ||||
5748 | } | ||||
5749 | } | ||||
5750 | |||||
5751 | // Add 'this', if it would be valid. | ||||
5752 | if (!IncludedThis && !AfterAmpersand && Intro.Default != LCD_ByCopy) | ||||
5753 | addThisCompletion(*this, Results); | ||||
5754 | |||||
5755 | Results.ExitScope(); | ||||
5756 | |||||
5757 | HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), | ||||
5758 | Results.data(), Results.size()); | ||||
5759 | } | ||||
5760 | |||||
5761 | /// Macro that optionally prepends an "@" to the string literal passed in via | ||||
5762 | /// Keyword, depending on whether NeedAt is true or false. | ||||
5763 | #define OBJC_AT_KEYWORD_NAME(NeedAt, Keyword)((NeedAt) ? "@" Keyword : Keyword) ((NeedAt) ? "@" Keyword : Keyword) | ||||
5764 | |||||
5765 | static void AddObjCImplementationResults(const LangOptions &LangOpts, | ||||
5766 | ResultBuilder &Results, bool NeedAt) { | ||||
5767 | typedef CodeCompletionResult Result; | ||||
5768 | // Since we have an implementation, we can end it. | ||||
5769 | Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "end")((NeedAt) ? "@" "end" : "end"))); | ||||
5770 | |||||
5771 | CodeCompletionBuilder Builder(Results.getAllocator(), | ||||
5772 | Results.getCodeCompletionTUInfo()); | ||||
5773 | if (LangOpts.ObjC) { | ||||
5774 | // @dynamic | ||||
5775 | Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "dynamic")((NeedAt) ? "@" "dynamic" : "dynamic")); | ||||
5776 | Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | ||||
5777 | Builder.AddPlaceholderChunk("property"); | ||||
5778 | Results.AddResult(Result(Builder.TakeString())); | ||||
5779 | |||||
5780 | // @synthesize | ||||
5781 | Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "synthesize")((NeedAt) ? "@" "synthesize" : "synthesize")); | ||||
5782 | Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | ||||
5783 | Builder.AddPlaceholderChunk("property"); | ||||
5784 | Results.AddResult(Result(Builder.TakeString())); | ||||
5785 | } | ||||
5786 | } | ||||
5787 | |||||
5788 | static void AddObjCInterfaceResults(const LangOptions &LangOpts, | ||||
5789 | ResultBuilder &Results, bool NeedAt) { | ||||
5790 | typedef CodeCompletionResult Result; | ||||
5791 | |||||
5792 | // Since we have an interface or protocol, we can end it. | ||||
5793 | Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "end")((NeedAt) ? "@" "end" : "end"))); | ||||
5794 | |||||
5795 | if (LangOpts.ObjC) { | ||||
5796 | // @property | ||||
5797 | Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "property")((NeedAt) ? "@" "property" : "property"))); | ||||
5798 | |||||
5799 | // @required | ||||
5800 | Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "required")((NeedAt) ? "@" "required" : "required"))); | ||||
5801 | |||||
5802 | // @optional | ||||
5803 | Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "optional")((NeedAt) ? "@" "optional" : "optional"))); | ||||
5804 | } | ||||
5805 | } | ||||
5806 | |||||
5807 | static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt) { | ||||
5808 | typedef CodeCompletionResult Result; | ||||
5809 | CodeCompletionBuilder Builder(Results.getAllocator(), | ||||
5810 | Results.getCodeCompletionTUInfo()); | ||||
5811 | |||||
5812 | // @class name ; | ||||
5813 | Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "class")((NeedAt) ? "@" "class" : "class")); | ||||
5814 | Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | ||||
5815 | Builder.AddPlaceholderChunk("name"); | ||||
5816 | Results.AddResult(Result(Builder.TakeString())); | ||||
5817 | |||||
5818 | if (Results.includeCodePatterns()) { | ||||
5819 | // @interface name | ||||
5820 | // FIXME: Could introduce the whole pattern, including superclasses and | ||||
5821 | // such. | ||||
5822 | Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "interface")((NeedAt) ? "@" "interface" : "interface")); | ||||
5823 | Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | ||||
5824 | Builder.AddPlaceholderChunk("class"); | ||||
5825 | Results.AddResult(Result(Builder.TakeString())); | ||||
5826 | |||||
5827 | // @protocol name | ||||
5828 | Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "protocol")((NeedAt) ? "@" "protocol" : "protocol")); | ||||
5829 | Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | ||||
5830 | Builder.AddPlaceholderChunk("protocol"); | ||||
5831 | Results.AddResult(Result(Builder.TakeString())); | ||||
5832 | |||||
5833 | // @implementation name | ||||
5834 | Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "implementation")((NeedAt) ? "@" "implementation" : "implementation")); | ||||
5835 | Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | ||||
5836 | Builder.AddPlaceholderChunk("class"); | ||||
5837 | Results.AddResult(Result(Builder.TakeString())); | ||||
5838 | } | ||||
5839 | |||||
5840 | // @compatibility_alias name | ||||
5841 | Builder.AddTypedTextChunk( | ||||
5842 | OBJC_AT_KEYWORD_NAME(NeedAt, "compatibility_alias")((NeedAt) ? "@" "compatibility_alias" : "compatibility_alias" )); | ||||
5843 | Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | ||||
5844 | Builder.AddPlaceholderChunk("alias"); | ||||
5845 | Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | ||||
5846 | Builder.AddPlaceholderChunk("class"); | ||||
5847 | Results.AddResult(Result(Builder.TakeString())); | ||||
5848 | |||||
5849 | if (Results.getSema().getLangOpts().Modules) { | ||||
5850 | // @import name | ||||
5851 | Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "import")((NeedAt) ? "@" "import" : "import")); | ||||
5852 | Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | ||||
5853 | Builder.AddPlaceholderChunk("module"); | ||||
5854 | Results.AddResult(Result(Builder.TakeString())); | ||||
5855 | } | ||||
5856 | } | ||||
5857 | |||||
5858 | void Sema::CodeCompleteObjCAtDirective(Scope *S) { | ||||
5859 | ResultBuilder Results(*this, CodeCompleter->getAllocator(), | ||||
5860 | CodeCompleter->getCodeCompletionTUInfo(), | ||||
5861 | CodeCompletionContext::CCC_Other); | ||||
5862 | Results.EnterNewScope(); | ||||
5863 | if (isa<ObjCImplDecl>(CurContext)) | ||||
5864 | AddObjCImplementationResults(getLangOpts(), Results, false); | ||||
5865 | else if (CurContext->isObjCContainer()) | ||||
5866 | AddObjCInterfaceResults(getLangOpts(), Results, false); | ||||
5867 | else | ||||
5868 | AddObjCTopLevelResults(Results, false); | ||||
5869 | Results.ExitScope(); | ||||
5870 | HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), | ||||
5871 | Results.data(), Results.size()); | ||||
5872 | } | ||||
5873 | |||||
5874 | static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt) { | ||||
5875 | typedef CodeCompletionResult Result; | ||||
5876 | CodeCompletionBuilder Builder(Results.getAllocator(), | ||||
5877 | Results.getCodeCompletionTUInfo()); | ||||
5878 | |||||
5879 | // @encode ( type-name ) | ||||
5880 | const char *EncodeType = "char[]"; | ||||
5881 | if (Results.getSema().getLangOpts().CPlusPlus || | ||||
5882 | Results.getSema().getLangOpts().ConstStrings) | ||||
5883 | EncodeType = "const char[]"; | ||||
5884 | Builder.AddResultTypeChunk(EncodeType); | ||||
5885 | Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "encode")((NeedAt) ? "@" "encode" : "encode")); | ||||
5886 | Builder.AddChunk(CodeCompletionString::CK_LeftParen); | ||||
5887 | Builder.AddPlaceholderChunk("type-name"); | ||||
5888 | Builder.AddChunk(CodeCompletionString::CK_RightParen); | ||||
5889 | Results.AddResult(Result(Builder.TakeString())); | ||||
5890 | |||||
5891 | // @protocol ( protocol-name ) | ||||
5892 | Builder.AddResultTypeChunk("Protocol *"); | ||||
5893 | Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "protocol")((NeedAt) ? "@" "protocol" : "protocol")); | ||||
5894 | Builder.AddChunk(CodeCompletionString::CK_LeftParen); | ||||
5895 | Builder.AddPlaceholderChunk("protocol-name"); | ||||
5896 | Builder.AddChunk(CodeCompletionString::CK_RightParen); | ||||
5897 | Results.AddResult(Result(Builder.TakeString())); | ||||
5898 | |||||
5899 | // @selector ( selector ) | ||||
5900 | Builder.AddResultTypeChunk("SEL"); | ||||
5901 | Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "selector")((NeedAt) ? "@" "selector" : "selector")); | ||||
5902 | Builder.AddChunk(CodeCompletionString::CK_LeftParen); | ||||
5903 | Builder.AddPlaceholderChunk("selector"); | ||||
5904 | Builder.AddChunk(CodeCompletionString::CK_RightParen); | ||||
5905 | Results.AddResult(Result(Builder.TakeString())); | ||||
5906 | |||||
5907 | // @"string" | ||||
5908 | Builder.AddResultTypeChunk("NSString *"); | ||||
5909 | Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "\"")((NeedAt) ? "@" "\"" : "\"")); | ||||
5910 | Builder.AddPlaceholderChunk("string"); | ||||
5911 | Builder.AddTextChunk("\""); | ||||
5912 | Results.AddResult(Result(Builder.TakeString())); | ||||
5913 | |||||
5914 | // @[objects, ...] | ||||
5915 | Builder.AddResultTypeChunk("NSArray *"); | ||||
5916 | Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "[")((NeedAt) ? "@" "[" : "[")); | ||||
5917 | Builder.AddPlaceholderChunk("objects, ..."); | ||||
5918 | Builder.AddChunk(CodeCompletionString::CK_RightBracket); | ||||
5919 | Results.AddResult(Result(Builder.TakeString())); | ||||
5920 | |||||
5921 | // @{key : object, ...} | ||||
5922 | Builder.AddResultTypeChunk("NSDictionary *"); | ||||
5923 | Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "{")((NeedAt) ? "@" "{" : "{")); | ||||
5924 | Builder.AddPlaceholderChunk("key"); | ||||
5925 | Builder.AddChunk(CodeCompletionString::CK_Colon); | ||||
5926 | Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | ||||
5927 | Builder.AddPlaceholderChunk("object, ..."); | ||||
5928 | Builder.AddChunk(CodeCompletionString::CK_RightBrace); | ||||
5929 | Results.AddResult(Result(Builder.TakeString())); | ||||
5930 | |||||
5931 | // @(expression) | ||||
5932 | Builder.AddResultTypeChunk("id"); | ||||
5933 | Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "(")((NeedAt) ? "@" "(" : "(")); | ||||
5934 | Builder.AddPlaceholderChunk("expression"); | ||||
5935 | Builder.AddChunk(CodeCompletionString::CK_RightParen); | ||||
5936 | Results.AddResult(Result(Builder.TakeString())); | ||||
5937 | } | ||||
5938 | |||||
5939 | static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt) { | ||||
5940 | typedef CodeCompletionResult Result; | ||||
5941 | CodeCompletionBuilder Builder(Results.getAllocator(), | ||||
5942 | Results.getCodeCompletionTUInfo()); | ||||
5943 | |||||
5944 | if (Results.includeCodePatterns()) { | ||||
5945 | // @try { statements } @catch ( declaration ) { statements } @finally | ||||
5946 | // { statements } | ||||
5947 | Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "try")((NeedAt) ? "@" "try" : "try")); | ||||
5948 | Builder.AddChunk(CodeCompletionString::CK_LeftBrace); | ||||
5949 | Builder.AddPlaceholderChunk("statements"); | ||||
5950 | Builder.AddChunk(CodeCompletionString::CK_RightBrace); | ||||
5951 | Builder.AddTextChunk("@catch"); | ||||
5952 | Builder.AddChunk(CodeCompletionString::CK_LeftParen); | ||||
5953 | Builder.AddPlaceholderChunk("parameter"); | ||||
5954 | Builder.AddChunk(CodeCompletionString::CK_RightParen); | ||||
5955 | Builder.AddChunk(CodeCompletionString::CK_LeftBrace); | ||||
5956 | Builder.AddPlaceholderChunk("statements"); | ||||
5957 | Builder.AddChunk(CodeCompletionString::CK_RightBrace); | ||||
5958 | Builder.AddTextChunk("@finally"); | ||||
5959 | Builder.AddChunk(CodeCompletionString::CK_LeftBrace); | ||||
5960 | Builder.AddPlaceholderChunk("statements"); | ||||
5961 | Builder.AddChunk(CodeCompletionString::CK_RightBrace); | ||||
5962 | Results.AddResult(Result(Builder.TakeString())); | ||||
5963 | } | ||||
5964 | |||||
5965 | // @throw | ||||
5966 | Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "throw")((NeedAt) ? "@" "throw" : "throw")); | ||||
5967 | Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | ||||
5968 | Builder.AddPlaceholderChunk("expression"); | ||||
5969 | Results.AddResult(Result(Builder.TakeString())); | ||||
5970 | |||||
5971 | if (Results.includeCodePatterns()) { | ||||
5972 | // @synchronized ( expression ) { statements } | ||||
5973 | Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "synchronized")((NeedAt) ? "@" "synchronized" : "synchronized")); | ||||
5974 | Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | ||||
5975 | Builder.AddChunk(CodeCompletionString::CK_LeftParen); | ||||
5976 | Builder.AddPlaceholderChunk("expression"); | ||||
5977 | Builder.AddChunk(CodeCompletionString::CK_RightParen); | ||||
5978 | Builder.AddChunk(CodeCompletionString::CK_LeftBrace); | ||||
5979 | Builder.AddPlaceholderChunk("statements"); | ||||
5980 | Builder.AddChunk(CodeCompletionString::CK_RightBrace); | ||||
5981 | Results.AddResult(Result(Builder.TakeString())); | ||||
5982 | } | ||||
5983 | } | ||||
5984 | |||||
5985 | static void AddObjCVisibilityResults(const LangOptions &LangOpts, | ||||
5986 | ResultBuilder &Results, bool NeedAt) { | ||||
5987 | typedef CodeCompletionResult Result; | ||||
5988 | Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "private")((NeedAt) ? "@" "private" : "private"))); | ||||
5989 | Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "protected")((NeedAt) ? "@" "protected" : "protected"))); | ||||
5990 | Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "public")((NeedAt) ? "@" "public" : "public"))); | ||||
5991 | if (LangOpts.ObjC) | ||||
5992 | Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "package")((NeedAt) ? "@" "package" : "package"))); | ||||
5993 | } | ||||
5994 | |||||
5995 | void Sema::CodeCompleteObjCAtVisibility(Scope *S) { | ||||
5996 | ResultBuilder Results(*this, CodeCompleter->getAllocator(), | ||||
5997 | CodeCompleter->getCodeCompletionTUInfo(), | ||||
5998 | CodeCompletionContext::CCC_Other); | ||||
5999 | Results.EnterNewScope(); | ||||
6000 | AddObjCVisibilityResults(getLangOpts(), Results, false); | ||||
6001 | Results.ExitScope(); | ||||
6002 | HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), | ||||
6003 | Results.data(), Results.size()); | ||||
6004 | } | ||||
6005 | |||||
6006 | void Sema::CodeCompleteObjCAtStatement(Scope *S) { | ||||
6007 | ResultBuilder Results(*this, CodeCompleter->getAllocator(), | ||||
6008 | CodeCompleter->getCodeCompletionTUInfo(), | ||||
6009 | CodeCompletionContext::CCC_Other); | ||||
6010 | Results.EnterNewScope(); | ||||
6011 | AddObjCStatementResults(Results, false); | ||||
6012 | AddObjCExpressionResults(Results, false); | ||||
6013 | Results.ExitScope(); | ||||
6014 | HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), | ||||
6015 | Results.data(), Results.size()); | ||||
6016 | } | ||||
6017 | |||||
6018 | void Sema::CodeCompleteObjCAtExpression(Scope *S) { | ||||
6019 | ResultBuilder Results(*this, CodeCompleter->getAllocator(), | ||||
6020 | CodeCompleter->getCodeCompletionTUInfo(), | ||||
6021 | CodeCompletionContext::CCC_Other); | ||||
6022 | Results.EnterNewScope(); | ||||
6023 | AddObjCExpressionResults(Results, false); | ||||
6024 | Results.ExitScope(); | ||||
6025 | HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), | ||||
6026 | Results.data(), Results.size()); | ||||
6027 | } | ||||
6028 | |||||
6029 | /// Determine whether the addition of the given flag to an Objective-C | ||||
6030 | /// property's attributes will cause a conflict. | ||||
6031 | static bool ObjCPropertyFlagConflicts(unsigned Attributes, unsigned NewFlag) { | ||||
6032 | // Check if we've already added this flag. | ||||
6033 | if (Attributes & NewFlag) | ||||
6034 | return true; | ||||
6035 | |||||
6036 | Attributes |= NewFlag; | ||||
6037 | |||||
6038 | // Check for collisions with "readonly". | ||||
6039 | if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) && | ||||
6040 | (Attributes & ObjCDeclSpec::DQ_PR_readwrite)) | ||||
6041 | return true; | ||||
6042 | |||||
6043 | // Check for more than one of { assign, copy, retain, strong, weak }. | ||||
6044 | unsigned AssignCopyRetMask = | ||||
6045 | Attributes & | ||||
6046 | (ObjCDeclSpec::DQ_PR_assign | ObjCDeclSpec::DQ_PR_unsafe_unretained | | ||||
6047 | ObjCDeclSpec::DQ_PR_copy | ObjCDeclSpec::DQ_PR_retain | | ||||
6048 | ObjCDeclSpec::DQ_PR_strong | ObjCDeclSpec::DQ_PR_weak); | ||||
6049 | if (AssignCopyRetMask && AssignCopyRetMask != ObjCDeclSpec::DQ_PR_assign && | ||||
6050 | AssignCopyRetMask != ObjCDeclSpec::DQ_PR_unsafe_unretained && | ||||
6051 | AssignCopyRetMask != ObjCDeclSpec::DQ_PR_copy && | ||||
6052 | AssignCopyRetMask != ObjCDeclSpec::DQ_PR_retain && | ||||
6053 | AssignCopyRetMask != ObjCDeclSpec::DQ_PR_strong && | ||||
6054 | AssignCopyRetMask != ObjCDeclSpec::DQ_PR_weak) | ||||
6055 | return true; | ||||
6056 | |||||
6057 | return false; | ||||
6058 | } | ||||
6059 | |||||
6060 | void Sema::CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS) { | ||||
6061 | if (!CodeCompleter) | ||||
6062 | return; | ||||
6063 | |||||
6064 | unsigned Attributes = ODS.getPropertyAttributes(); | ||||
6065 | |||||
6066 | ResultBuilder Results(*this, CodeCompleter->getAllocator(), | ||||
6067 | CodeCompleter->getCodeCompletionTUInfo(), | ||||
6068 | CodeCompletionContext::CCC_Other); | ||||
6069 | Results.EnterNewScope(); | ||||
6070 | if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readonly)) | ||||
6071 | Results.AddResult(CodeCompletionResult("readonly")); | ||||
6072 | if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_assign)) | ||||
6073 | Results.AddResult(CodeCompletionResult("assign")); | ||||
6074 | if (!ObjCPropertyFlagConflicts(Attributes, | ||||
6075 | ObjCDeclSpec::DQ_PR_unsafe_unretained)) | ||||
6076 | Results.AddResult(CodeCompletionResult("unsafe_unretained")); | ||||
6077 | if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readwrite)) | ||||
6078 | Results.AddResult(CodeCompletionResult("readwrite")); | ||||
6079 | if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_retain)) | ||||
6080 | Results.AddResult(CodeCompletionResult("retain")); | ||||
6081 | if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_strong)) | ||||
6082 | Results.AddResult(CodeCompletionResult("strong")); | ||||
6083 | if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_copy)) | ||||
6084 | Results.AddResult(CodeCompletionResult("copy")); | ||||
6085 | if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_nonatomic)) | ||||
6086 | Results.AddResult(CodeCompletionResult("nonatomic")); | ||||
6087 | if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_atomic)) | ||||
6088 | Results.AddResult(CodeCompletionResult("atomic")); | ||||
6089 | |||||
6090 | // Only suggest "weak" if we're compiling for ARC-with-weak-references or GC. | ||||
6091 | if (getLangOpts().ObjCWeak || getLangOpts().getGC() != LangOptions::NonGC) | ||||