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