File: | build/source/clang-tools-extra/clangd/AST.cpp |
Warning: | line 747, column 14 Called C++ object pointer is null |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | //===--- AST.cpp - Utility AST functions -----------------------*- 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 | #include "AST.h" | |||
10 | ||||
11 | #include "SourceCode.h" | |||
12 | #include "clang/AST/ASTContext.h" | |||
13 | #include "clang/AST/ASTTypeTraits.h" | |||
14 | #include "clang/AST/Decl.h" | |||
15 | #include "clang/AST/DeclBase.h" | |||
16 | #include "clang/AST/DeclCXX.h" | |||
17 | #include "clang/AST/DeclObjC.h" | |||
18 | #include "clang/AST/DeclTemplate.h" | |||
19 | #include "clang/AST/DeclarationName.h" | |||
20 | #include "clang/AST/ExprCXX.h" | |||
21 | #include "clang/AST/NestedNameSpecifier.h" | |||
22 | #include "clang/AST/PrettyPrinter.h" | |||
23 | #include "clang/AST/RecursiveASTVisitor.h" | |||
24 | #include "clang/AST/Stmt.h" | |||
25 | #include "clang/AST/TemplateBase.h" | |||
26 | #include "clang/AST/TypeLoc.h" | |||
27 | #include "clang/Basic/Builtins.h" | |||
28 | #include "clang/Basic/SourceLocation.h" | |||
29 | #include "clang/Basic/SourceManager.h" | |||
30 | #include "clang/Basic/Specifiers.h" | |||
31 | #include "clang/Index/USRGeneration.h" | |||
32 | #include "llvm/ADT/ArrayRef.h" | |||
33 | #include "llvm/ADT/STLExtras.h" | |||
34 | #include "llvm/ADT/SmallSet.h" | |||
35 | #include "llvm/ADT/StringRef.h" | |||
36 | #include "llvm/Support/Casting.h" | |||
37 | #include "llvm/Support/raw_ostream.h" | |||
38 | #include <iterator> | |||
39 | #include <optional> | |||
40 | #include <string> | |||
41 | #include <vector> | |||
42 | ||||
43 | namespace clang { | |||
44 | namespace clangd { | |||
45 | ||||
46 | namespace { | |||
47 | std::optional<llvm::ArrayRef<TemplateArgumentLoc>> | |||
48 | getTemplateSpecializationArgLocs(const NamedDecl &ND) { | |||
49 | if (auto *Func = llvm::dyn_cast<FunctionDecl>(&ND)) { | |||
50 | if (const ASTTemplateArgumentListInfo *Args = | |||
51 | Func->getTemplateSpecializationArgsAsWritten()) | |||
52 | return Args->arguments(); | |||
53 | } else if (auto *Cls = | |||
54 | llvm::dyn_cast<ClassTemplatePartialSpecializationDecl>(&ND)) { | |||
55 | if (auto *Args = Cls->getTemplateArgsAsWritten()) | |||
56 | return Args->arguments(); | |||
57 | } else if (auto *Var = | |||
58 | llvm::dyn_cast<VarTemplatePartialSpecializationDecl>(&ND)) { | |||
59 | if (auto *Args = Var->getTemplateArgsAsWritten()) | |||
60 | return Args->arguments(); | |||
61 | } else if (auto *Var = llvm::dyn_cast<VarTemplateSpecializationDecl>(&ND)) { | |||
62 | if (auto *Args = Var->getTemplateArgsInfo()) | |||
63 | return Args->arguments(); | |||
64 | } | |||
65 | // We return std::nullopt for ClassTemplateSpecializationDecls because it does | |||
66 | // not contain TemplateArgumentLoc information. | |||
67 | return std::nullopt; | |||
68 | } | |||
69 | ||||
70 | template <class T> | |||
71 | bool isTemplateSpecializationKind(const NamedDecl *D, | |||
72 | TemplateSpecializationKind Kind) { | |||
73 | if (const auto *TD = dyn_cast<T>(D)) | |||
74 | return TD->getTemplateSpecializationKind() == Kind; | |||
75 | return false; | |||
76 | } | |||
77 | ||||
78 | bool isTemplateSpecializationKind(const NamedDecl *D, | |||
79 | TemplateSpecializationKind Kind) { | |||
80 | return isTemplateSpecializationKind<FunctionDecl>(D, Kind) || | |||
81 | isTemplateSpecializationKind<CXXRecordDecl>(D, Kind) || | |||
82 | isTemplateSpecializationKind<VarDecl>(D, Kind); | |||
83 | } | |||
84 | ||||
85 | // Store all UsingDirectiveDecls in parent contexts of DestContext, that were | |||
86 | // introduced before InsertionPoint. | |||
87 | llvm::DenseSet<const NamespaceDecl *> | |||
88 | getUsingNamespaceDirectives(const DeclContext *DestContext, | |||
89 | SourceLocation Until) { | |||
90 | const auto &SM = DestContext->getParentASTContext().getSourceManager(); | |||
91 | llvm::DenseSet<const NamespaceDecl *> VisibleNamespaceDecls; | |||
92 | for (const auto *DC = DestContext; DC; DC = DC->getLookupParent()) { | |||
93 | for (const auto *D : DC->decls()) { | |||
94 | if (!SM.isWrittenInSameFile(D->getLocation(), Until) || | |||
95 | !SM.isBeforeInTranslationUnit(D->getLocation(), Until)) | |||
96 | continue; | |||
97 | if (auto *UDD = llvm::dyn_cast<UsingDirectiveDecl>(D)) | |||
98 | VisibleNamespaceDecls.insert( | |||
99 | UDD->getNominatedNamespace()->getCanonicalDecl()); | |||
100 | } | |||
101 | } | |||
102 | return VisibleNamespaceDecls; | |||
103 | } | |||
104 | ||||
105 | // Goes over all parents of SourceContext until we find a common ancestor for | |||
106 | // DestContext and SourceContext. Any qualifier including and above common | |||
107 | // ancestor is redundant, therefore we stop at lowest common ancestor. | |||
108 | // In addition to that stops early whenever IsVisible returns true. This can be | |||
109 | // used to implement support for "using namespace" decls. | |||
110 | std::string | |||
111 | getQualification(ASTContext &Context, const DeclContext *DestContext, | |||
112 | const DeclContext *SourceContext, | |||
113 | llvm::function_ref<bool(NestedNameSpecifier *)> IsVisible) { | |||
114 | std::vector<const NestedNameSpecifier *> Parents; | |||
115 | bool ReachedNS = false; | |||
116 | for (const DeclContext *CurContext = SourceContext; CurContext; | |||
117 | CurContext = CurContext->getLookupParent()) { | |||
118 | // Stop once we reach a common ancestor. | |||
119 | if (CurContext->Encloses(DestContext)) | |||
120 | break; | |||
121 | ||||
122 | NestedNameSpecifier *NNS = nullptr; | |||
123 | if (auto *TD = llvm::dyn_cast<TagDecl>(CurContext)) { | |||
124 | // There can't be any more tag parents after hitting a namespace. | |||
125 | assert(!ReachedNS)(static_cast <bool> (!ReachedNS) ? void (0) : __assert_fail ("!ReachedNS", "clang-tools-extra/clangd/AST.cpp", 125, __extension__ __PRETTY_FUNCTION__)); | |||
126 | (void)ReachedNS; | |||
127 | NNS = NestedNameSpecifier::Create(Context, nullptr, false, | |||
128 | TD->getTypeForDecl()); | |||
129 | } else if (auto *NSD = llvm::dyn_cast<NamespaceDecl>(CurContext)) { | |||
130 | ReachedNS = true; | |||
131 | NNS = NestedNameSpecifier::Create(Context, nullptr, NSD); | |||
132 | // Anonymous and inline namespace names are not spelled while qualifying | |||
133 | // a name, so skip those. | |||
134 | if (NSD->isAnonymousNamespace() || NSD->isInlineNamespace()) | |||
135 | continue; | |||
136 | } else { | |||
137 | // Other types of contexts cannot be spelled in code, just skip over | |||
138 | // them. | |||
139 | continue; | |||
140 | } | |||
141 | // Stop if this namespace is already visible at DestContext. | |||
142 | if (IsVisible(NNS)) | |||
143 | break; | |||
144 | ||||
145 | Parents.push_back(NNS); | |||
146 | } | |||
147 | ||||
148 | // Go over name-specifiers in reverse order to create necessary qualification, | |||
149 | // since we stored inner-most parent first. | |||
150 | std::string Result; | |||
151 | llvm::raw_string_ostream OS(Result); | |||
152 | for (const auto *Parent : llvm::reverse(Parents)) | |||
153 | Parent->print(OS, Context.getPrintingPolicy()); | |||
154 | return OS.str(); | |||
155 | } | |||
156 | ||||
157 | } // namespace | |||
158 | ||||
159 | bool isImplicitTemplateInstantiation(const NamedDecl *D) { | |||
160 | return isTemplateSpecializationKind(D, TSK_ImplicitInstantiation); | |||
161 | } | |||
162 | ||||
163 | bool isExplicitTemplateSpecialization(const NamedDecl *D) { | |||
164 | return isTemplateSpecializationKind(D, TSK_ExplicitSpecialization); | |||
165 | } | |||
166 | ||||
167 | bool isImplementationDetail(const Decl *D) { | |||
168 | return !isSpelledInSource(D->getLocation(), | |||
169 | D->getASTContext().getSourceManager()); | |||
170 | } | |||
171 | ||||
172 | SourceLocation nameLocation(const clang::Decl &D, const SourceManager &SM) { | |||
173 | auto L = D.getLocation(); | |||
174 | // For `- (void)foo` we want `foo` not the `-`. | |||
175 | if (const auto *MD = dyn_cast<ObjCMethodDecl>(&D)) | |||
176 | L = MD->getSelectorStartLoc(); | |||
177 | if (isSpelledInSource(L, SM)) | |||
178 | return SM.getSpellingLoc(L); | |||
179 | return SM.getExpansionLoc(L); | |||
180 | } | |||
181 | ||||
182 | std::string printQualifiedName(const NamedDecl &ND) { | |||
183 | std::string QName; | |||
184 | llvm::raw_string_ostream OS(QName); | |||
185 | PrintingPolicy Policy(ND.getASTContext().getLangOpts()); | |||
186 | // Note that inline namespaces are treated as transparent scopes. This | |||
187 | // reflects the way they're most commonly used for lookup. Ideally we'd | |||
188 | // include them, but at query time it's hard to find all the inline | |||
189 | // namespaces to query: the preamble doesn't have a dedicated list. | |||
190 | Policy.SuppressUnwrittenScope = true; | |||
191 | // (unnamed struct), not (unnamed struct at /path/to/foo.cc:42:1). | |||
192 | // In clangd, context is usually available and paths are mostly noise. | |||
193 | Policy.AnonymousTagLocations = false; | |||
194 | ND.printQualifiedName(OS, Policy); | |||
195 | OS.flush(); | |||
196 | assert(!StringRef(QName).startswith("::"))(static_cast <bool> (!StringRef(QName).startswith("::") ) ? void (0) : __assert_fail ("!StringRef(QName).startswith(\"::\")" , "clang-tools-extra/clangd/AST.cpp", 196, __extension__ __PRETTY_FUNCTION__ )); | |||
197 | return QName; | |||
198 | } | |||
199 | ||||
200 | static bool isAnonymous(const DeclarationName &N) { | |||
201 | return N.isIdentifier() && !N.getAsIdentifierInfo(); | |||
202 | } | |||
203 | ||||
204 | NestedNameSpecifierLoc getQualifierLoc(const NamedDecl &ND) { | |||
205 | if (auto *V = llvm::dyn_cast<DeclaratorDecl>(&ND)) | |||
206 | return V->getQualifierLoc(); | |||
207 | if (auto *T = llvm::dyn_cast<TagDecl>(&ND)) | |||
208 | return T->getQualifierLoc(); | |||
209 | return NestedNameSpecifierLoc(); | |||
210 | } | |||
211 | ||||
212 | std::string printUsingNamespaceName(const ASTContext &Ctx, | |||
213 | const UsingDirectiveDecl &D) { | |||
214 | PrintingPolicy PP(Ctx.getLangOpts()); | |||
215 | std::string Name; | |||
216 | llvm::raw_string_ostream Out(Name); | |||
217 | ||||
218 | if (auto *Qual = D.getQualifier()) | |||
219 | Qual->print(Out, PP); | |||
220 | D.getNominatedNamespaceAsWritten()->printName(Out); | |||
221 | return Out.str(); | |||
222 | } | |||
223 | ||||
224 | std::string printName(const ASTContext &Ctx, const NamedDecl &ND) { | |||
225 | std::string Name; | |||
226 | llvm::raw_string_ostream Out(Name); | |||
227 | PrintingPolicy PP(Ctx.getLangOpts()); | |||
228 | // We don't consider a class template's args part of the constructor name. | |||
229 | PP.SuppressTemplateArgsInCXXConstructors = true; | |||
230 | ||||
231 | // Handle 'using namespace'. They all have the same name - <using-directive>. | |||
232 | if (auto *UD = llvm::dyn_cast<UsingDirectiveDecl>(&ND)) { | |||
233 | Out << "using namespace "; | |||
234 | if (auto *Qual = UD->getQualifier()) | |||
235 | Qual->print(Out, PP); | |||
236 | UD->getNominatedNamespaceAsWritten()->printName(Out); | |||
237 | return Out.str(); | |||
238 | } | |||
239 | ||||
240 | if (isAnonymous(ND.getDeclName())) { | |||
241 | // Come up with a presentation for an anonymous entity. | |||
242 | if (isa<NamespaceDecl>(ND)) | |||
243 | return "(anonymous namespace)"; | |||
244 | if (auto *Cls = llvm::dyn_cast<RecordDecl>(&ND)) { | |||
245 | if (Cls->isLambda()) | |||
246 | return "(lambda)"; | |||
247 | return ("(anonymous " + Cls->getKindName() + ")").str(); | |||
248 | } | |||
249 | if (isa<EnumDecl>(ND)) | |||
250 | return "(anonymous enum)"; | |||
251 | return "(anonymous)"; | |||
252 | } | |||
253 | ||||
254 | // Print nested name qualifier if it was written in the source code. | |||
255 | if (auto *Qualifier = getQualifierLoc(ND).getNestedNameSpecifier()) | |||
256 | Qualifier->print(Out, PP); | |||
257 | // Print the name itself. | |||
258 | ND.getDeclName().print(Out, PP); | |||
259 | // Print template arguments. | |||
260 | Out << printTemplateSpecializationArgs(ND); | |||
261 | ||||
262 | return Out.str(); | |||
263 | } | |||
264 | ||||
265 | std::string printTemplateSpecializationArgs(const NamedDecl &ND) { | |||
266 | std::string TemplateArgs; | |||
267 | llvm::raw_string_ostream OS(TemplateArgs); | |||
268 | PrintingPolicy Policy(ND.getASTContext().getLangOpts()); | |||
269 | if (std::optional<llvm::ArrayRef<TemplateArgumentLoc>> Args = | |||
270 | getTemplateSpecializationArgLocs(ND)) { | |||
271 | printTemplateArgumentList(OS, *Args, Policy); | |||
272 | } else if (auto *Cls = llvm::dyn_cast<ClassTemplateSpecializationDecl>(&ND)) { | |||
273 | if (const TypeSourceInfo *TSI = Cls->getTypeAsWritten()) { | |||
274 | // ClassTemplateSpecializationDecls do not contain | |||
275 | // TemplateArgumentTypeLocs, they only have TemplateArgumentTypes. So we | |||
276 | // create a new argument location list from TypeSourceInfo. | |||
277 | auto STL = TSI->getTypeLoc().getAs<TemplateSpecializationTypeLoc>(); | |||
278 | llvm::SmallVector<TemplateArgumentLoc> ArgLocs; | |||
279 | ArgLocs.reserve(STL.getNumArgs()); | |||
280 | for (unsigned I = 0; I < STL.getNumArgs(); ++I) | |||
281 | ArgLocs.push_back(STL.getArgLoc(I)); | |||
282 | printTemplateArgumentList(OS, ArgLocs, Policy); | |||
283 | } else { | |||
284 | // FIXME: Fix cases when getTypeAsWritten returns null inside clang AST, | |||
285 | // e.g. friend decls. Currently we fallback to Template Arguments without | |||
286 | // location information. | |||
287 | printTemplateArgumentList(OS, Cls->getTemplateArgs().asArray(), Policy); | |||
288 | } | |||
289 | } | |||
290 | OS.flush(); | |||
291 | return TemplateArgs; | |||
292 | } | |||
293 | ||||
294 | std::string printNamespaceScope(const DeclContext &DC) { | |||
295 | for (const auto *Ctx = &DC; Ctx != nullptr; Ctx = Ctx->getParent()) | |||
296 | if (const auto *NS = dyn_cast<NamespaceDecl>(Ctx)) | |||
297 | if (!NS->isAnonymousNamespace() && !NS->isInlineNamespace()) | |||
298 | return printQualifiedName(*NS) + "::"; | |||
299 | return ""; | |||
300 | } | |||
301 | ||||
302 | static llvm::StringRef | |||
303 | getNameOrErrForObjCInterface(const ObjCInterfaceDecl *ID) { | |||
304 | return ID ? ID->getName() : "<<error-type>>"; | |||
305 | } | |||
306 | ||||
307 | std::string printObjCMethod(const ObjCMethodDecl &Method) { | |||
308 | std::string Name; | |||
309 | llvm::raw_string_ostream OS(Name); | |||
310 | ||||
311 | OS << (Method.isInstanceMethod() ? '-' : '+') << '['; | |||
312 | ||||
313 | // Should always be true. | |||
314 | if (const ObjCContainerDecl *C = | |||
315 | dyn_cast<ObjCContainerDecl>(Method.getDeclContext())) | |||
316 | OS << printObjCContainer(*C); | |||
317 | ||||
318 | Method.getSelector().print(OS << ' '); | |||
319 | if (Method.isVariadic()) | |||
320 | OS << ", ..."; | |||
321 | ||||
322 | OS << ']'; | |||
323 | OS.flush(); | |||
324 | return Name; | |||
325 | } | |||
326 | ||||
327 | std::string printObjCContainer(const ObjCContainerDecl &C) { | |||
328 | if (const ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(&C)) { | |||
329 | std::string Name; | |||
330 | llvm::raw_string_ostream OS(Name); | |||
331 | const ObjCInterfaceDecl *Class = Category->getClassInterface(); | |||
332 | OS << getNameOrErrForObjCInterface(Class) << '(' << Category->getName() | |||
333 | << ')'; | |||
334 | OS.flush(); | |||
335 | return Name; | |||
336 | } | |||
337 | if (const ObjCCategoryImplDecl *CID = dyn_cast<ObjCCategoryImplDecl>(&C)) { | |||
338 | std::string Name; | |||
339 | llvm::raw_string_ostream OS(Name); | |||
340 | const ObjCInterfaceDecl *Class = CID->getClassInterface(); | |||
341 | OS << getNameOrErrForObjCInterface(Class) << '(' << CID->getName() << ')'; | |||
342 | OS.flush(); | |||
343 | return Name; | |||
344 | } | |||
345 | return C.getNameAsString(); | |||
346 | } | |||
347 | ||||
348 | SymbolID getSymbolID(const Decl *D) { | |||
349 | llvm::SmallString<128> USR; | |||
350 | if (index::generateUSRForDecl(D, USR)) | |||
351 | return {}; | |||
352 | return SymbolID(USR); | |||
353 | } | |||
354 | ||||
355 | SymbolID getSymbolID(const llvm::StringRef MacroName, const MacroInfo *MI, | |||
356 | const SourceManager &SM) { | |||
357 | if (MI == nullptr) | |||
358 | return {}; | |||
359 | llvm::SmallString<128> USR; | |||
360 | if (index::generateUSRForMacro(MacroName, MI->getDefinitionLoc(), SM, USR)) | |||
361 | return {}; | |||
362 | return SymbolID(USR); | |||
363 | } | |||
364 | ||||
365 | const ObjCImplDecl *getCorrespondingObjCImpl(const ObjCContainerDecl *D) { | |||
366 | if (const auto *ID = dyn_cast<ObjCInterfaceDecl>(D)) | |||
367 | return ID->getImplementation(); | |||
368 | if (const auto *CD = dyn_cast<ObjCCategoryDecl>(D)) { | |||
369 | if (CD->IsClassExtension()) { | |||
370 | if (const auto *ID = CD->getClassInterface()) | |||
371 | return ID->getImplementation(); | |||
372 | return nullptr; | |||
373 | } | |||
374 | return CD->getImplementation(); | |||
375 | } | |||
376 | return nullptr; | |||
377 | } | |||
378 | ||||
379 | Symbol::IncludeDirective | |||
380 | preferredIncludeDirective(llvm::StringRef FileName, const LangOptions &LangOpts, | |||
381 | ArrayRef<Inclusion> MainFileIncludes, | |||
382 | ArrayRef<const Decl *> TopLevelDecls) { | |||
383 | // Always prefer #include for non-ObjC code. | |||
384 | if (!LangOpts.ObjC) | |||
385 | return Symbol::IncludeDirective::Include; | |||
386 | // If this is not a header file and has ObjC set as the language, prefer | |||
387 | // #import. | |||
388 | if (!isHeaderFile(FileName, LangOpts)) | |||
389 | return Symbol::IncludeDirective::Import; | |||
390 | ||||
391 | // Headers lack proper compile flags most of the time, so we might treat a | |||
392 | // header as ObjC accidentally. Perform some extra checks to make sure this | |||
393 | // works. | |||
394 | ||||
395 | // Any file with a #import, should keep #import-ing. | |||
396 | for (auto &Inc : MainFileIncludes) | |||
397 | if (Inc.Directive == tok::pp_import) | |||
398 | return Symbol::IncludeDirective::Import; | |||
399 | ||||
400 | // Any file declaring an ObjC decl should also be #import-ing. | |||
401 | // No need to look over the references, as the file doesn't have any #imports, | |||
402 | // it must be declaring interesting ObjC-like decls. | |||
403 | for (const Decl *D : TopLevelDecls) | |||
404 | if (isa<ObjCContainerDecl, ObjCIvarDecl, ObjCMethodDecl, ObjCPropertyDecl>( | |||
405 | D)) | |||
406 | return Symbol::IncludeDirective::Import; | |||
407 | ||||
408 | return Symbol::IncludeDirective::Include; | |||
409 | } | |||
410 | ||||
411 | std::string printType(const QualType QT, const DeclContext &CurContext, | |||
412 | const llvm::StringRef Placeholder) { | |||
413 | std::string Result; | |||
414 | llvm::raw_string_ostream OS(Result); | |||
415 | PrintingPolicy PP(CurContext.getParentASTContext().getPrintingPolicy()); | |||
416 | PP.SuppressTagKeyword = true; | |||
417 | PP.SuppressUnwrittenScope = true; | |||
418 | ||||
419 | class PrintCB : public PrintingCallbacks { | |||
420 | public: | |||
421 | PrintCB(const DeclContext *CurContext) : CurContext(CurContext) {} | |||
422 | virtual ~PrintCB() {} | |||
423 | bool isScopeVisible(const DeclContext *DC) const override { | |||
424 | return DC->Encloses(CurContext); | |||
425 | } | |||
426 | ||||
427 | private: | |||
428 | const DeclContext *CurContext; | |||
429 | }; | |||
430 | PrintCB PCB(&CurContext); | |||
431 | PP.Callbacks = &PCB; | |||
432 | ||||
433 | QT.print(OS, PP, Placeholder); | |||
434 | return OS.str(); | |||
435 | } | |||
436 | ||||
437 | bool hasReservedName(const Decl &D) { | |||
438 | if (const auto *ND = llvm::dyn_cast<NamedDecl>(&D)) | |||
439 | if (const auto *II = ND->getIdentifier()) | |||
440 | return isReservedName(II->getName()); | |||
441 | return false; | |||
442 | } | |||
443 | ||||
444 | bool hasReservedScope(const DeclContext &DC) { | |||
445 | for (const DeclContext *D = &DC; D; D = D->getParent()) { | |||
446 | if (D->isTransparentContext() || D->isInlineNamespace()) | |||
447 | continue; | |||
448 | if (const auto *ND = llvm::dyn_cast<NamedDecl>(D)) | |||
449 | if (hasReservedName(*ND)) | |||
450 | return true; | |||
451 | } | |||
452 | return false; | |||
453 | } | |||
454 | ||||
455 | QualType declaredType(const TypeDecl *D) { | |||
456 | if (const auto *CTSD = llvm::dyn_cast<ClassTemplateSpecializationDecl>(D)) | |||
457 | if (const auto *TSI = CTSD->getTypeAsWritten()) | |||
458 | return TSI->getType(); | |||
459 | return D->getASTContext().getTypeDeclType(D); | |||
460 | } | |||
461 | ||||
462 | namespace { | |||
463 | /// Computes the deduced type at a given location by visiting the relevant | |||
464 | /// nodes. We use this to display the actual type when hovering over an "auto" | |||
465 | /// keyword or "decltype()" expression. | |||
466 | /// FIXME: This could have been a lot simpler by visiting AutoTypeLocs but it | |||
467 | /// seems that the AutoTypeLocs that can be visited along with their AutoType do | |||
468 | /// not have the deduced type set. Instead, we have to go to the appropriate | |||
469 | /// DeclaratorDecl/FunctionDecl and work our back to the AutoType that does have | |||
470 | /// a deduced type set. The AST should be improved to simplify this scenario. | |||
471 | class DeducedTypeVisitor : public RecursiveASTVisitor<DeducedTypeVisitor> { | |||
472 | SourceLocation SearchedLocation; | |||
473 | ||||
474 | public: | |||
475 | DeducedTypeVisitor(SourceLocation SearchedLocation) | |||
476 | : SearchedLocation(SearchedLocation) {} | |||
477 | ||||
478 | // Handle auto initializers: | |||
479 | //- auto i = 1; | |||
480 | //- decltype(auto) i = 1; | |||
481 | //- auto& i = 1; | |||
482 | //- auto* i = &a; | |||
483 | bool VisitDeclaratorDecl(DeclaratorDecl *D) { | |||
484 | if (!D->getTypeSourceInfo() || | |||
485 | D->getTypeSourceInfo()->getTypeLoc().getBeginLoc() != SearchedLocation) | |||
486 | return true; | |||
487 | ||||
488 | if (auto *AT = D->getType()->getContainedAutoType()) { | |||
489 | DeducedType = AT->desugar(); | |||
490 | } | |||
491 | return true; | |||
492 | } | |||
493 | ||||
494 | // Handle auto return types: | |||
495 | //- auto foo() {} | |||
496 | //- auto& foo() {} | |||
497 | //- auto foo() -> int {} | |||
498 | //- auto foo() -> decltype(1+1) {} | |||
499 | //- operator auto() const { return 10; } | |||
500 | bool VisitFunctionDecl(FunctionDecl *D) { | |||
501 | if (!D->getTypeSourceInfo()) | |||
502 | return true; | |||
503 | // Loc of auto in return type (c++14). | |||
504 | auto CurLoc = D->getReturnTypeSourceRange().getBegin(); | |||
505 | // Loc of "auto" in operator auto() | |||
506 | if (CurLoc.isInvalid() && isa<CXXConversionDecl>(D)) | |||
507 | CurLoc = D->getTypeSourceInfo()->getTypeLoc().getBeginLoc(); | |||
508 | // Loc of "auto" in function with trailing return type (c++11). | |||
509 | if (CurLoc.isInvalid()) | |||
510 | CurLoc = D->getSourceRange().getBegin(); | |||
511 | if (CurLoc != SearchedLocation) | |||
512 | return true; | |||
513 | ||||
514 | const AutoType *AT = D->getReturnType()->getContainedAutoType(); | |||
515 | if (AT && !AT->getDeducedType().isNull()) { | |||
516 | DeducedType = AT->getDeducedType(); | |||
517 | } else if (auto *DT = dyn_cast<DecltypeType>(D->getReturnType())) { | |||
518 | // auto in a trailing return type just points to a DecltypeType and | |||
519 | // getContainedAutoType does not unwrap it. | |||
520 | if (!DT->getUnderlyingType().isNull()) | |||
521 | DeducedType = DT->getUnderlyingType(); | |||
522 | } else if (!D->getReturnType().isNull()) { | |||
523 | DeducedType = D->getReturnType(); | |||
524 | } | |||
525 | return true; | |||
526 | } | |||
527 | ||||
528 | // Handle non-auto decltype, e.g.: | |||
529 | // - auto foo() -> decltype(expr) {} | |||
530 | // - decltype(expr); | |||
531 | bool VisitDecltypeTypeLoc(DecltypeTypeLoc TL) { | |||
532 | if (TL.getBeginLoc() != SearchedLocation) | |||
533 | return true; | |||
534 | ||||
535 | // A DecltypeType's underlying type can be another DecltypeType! E.g. | |||
536 | // int I = 0; | |||
537 | // decltype(I) J = I; | |||
538 | // decltype(J) K = J; | |||
539 | const DecltypeType *DT = dyn_cast<DecltypeType>(TL.getTypePtr()); | |||
540 | while (DT && !DT->getUnderlyingType().isNull()) { | |||
541 | DeducedType = DT->getUnderlyingType(); | |||
542 | DT = dyn_cast<DecltypeType>(DeducedType.getTypePtr()); | |||
543 | } | |||
544 | return true; | |||
545 | } | |||
546 | ||||
547 | // Handle functions/lambdas with `auto` typed parameters. | |||
548 | // We deduce the type if there's exactly one instantiation visible. | |||
549 | bool VisitParmVarDecl(ParmVarDecl *PVD) { | |||
550 | if (!PVD->getType()->isDependentType()) | |||
551 | return true; | |||
552 | // 'auto' here does not name an AutoType, but an implicit template param. | |||
553 | TemplateTypeParmTypeLoc Auto = | |||
554 | getContainedAutoParamType(PVD->getTypeSourceInfo()->getTypeLoc()); | |||
555 | if (Auto.isNull() || Auto.getNameLoc() != SearchedLocation) | |||
556 | return true; | |||
557 | ||||
558 | // We expect the TTP to be attached to this function template. | |||
559 | // Find the template and the param index. | |||
560 | auto *Templated = llvm::dyn_cast<FunctionDecl>(PVD->getDeclContext()); | |||
561 | if (!Templated) | |||
562 | return true; | |||
563 | auto *FTD = Templated->getDescribedFunctionTemplate(); | |||
564 | if (!FTD) | |||
565 | return true; | |||
566 | int ParamIndex = paramIndex(*FTD, *Auto.getDecl()); | |||
567 | if (ParamIndex < 0) { | |||
568 | assert(false && "auto TTP is not from enclosing function?")(static_cast <bool> (false && "auto TTP is not from enclosing function?" ) ? void (0) : __assert_fail ("false && \"auto TTP is not from enclosing function?\"" , "clang-tools-extra/clangd/AST.cpp", 568, __extension__ __PRETTY_FUNCTION__ )); | |||
569 | return true; | |||
570 | } | |||
571 | ||||
572 | // Now find the instantiation and the deduced template type arg. | |||
573 | auto *Instantiation = | |||
574 | llvm::dyn_cast_or_null<FunctionDecl>(getOnlyInstantiation(Templated)); | |||
575 | if (!Instantiation) | |||
576 | return true; | |||
577 | const auto *Args = Instantiation->getTemplateSpecializationArgs(); | |||
578 | if (Args->size() != FTD->getTemplateParameters()->size()) | |||
579 | return true; // no weird variadic stuff | |||
580 | DeducedType = Args->get(ParamIndex).getAsType(); | |||
581 | return true; | |||
582 | } | |||
583 | ||||
584 | static int paramIndex(const TemplateDecl &TD, NamedDecl &Param) { | |||
585 | unsigned I = 0; | |||
586 | for (auto *ND : *TD.getTemplateParameters()) { | |||
587 | if (&Param == ND) | |||
588 | return I; | |||
589 | ++I; | |||
590 | } | |||
591 | return -1; | |||
592 | } | |||
593 | ||||
594 | QualType DeducedType; | |||
595 | }; | |||
596 | } // namespace | |||
597 | ||||
598 | std::optional<QualType> getDeducedType(ASTContext &ASTCtx, SourceLocation Loc) { | |||
599 | if (!Loc.isValid()) | |||
600 | return {}; | |||
601 | DeducedTypeVisitor V(Loc); | |||
602 | V.TraverseAST(ASTCtx); | |||
603 | if (V.DeducedType.isNull()) | |||
604 | return std::nullopt; | |||
605 | return V.DeducedType; | |||
606 | } | |||
607 | ||||
608 | TemplateTypeParmTypeLoc getContainedAutoParamType(TypeLoc TL) { | |||
609 | if (auto QTL = TL.getAs<QualifiedTypeLoc>()) | |||
610 | return getContainedAutoParamType(QTL.getUnqualifiedLoc()); | |||
611 | if (llvm::isa<PointerType, ReferenceType, ParenType>(TL.getTypePtr())) | |||
612 | return getContainedAutoParamType(TL.getNextTypeLoc()); | |||
613 | if (auto FTL = TL.getAs<FunctionTypeLoc>()) | |||
614 | return getContainedAutoParamType(FTL.getReturnLoc()); | |||
615 | if (auto TTPTL = TL.getAs<TemplateTypeParmTypeLoc>()) { | |||
616 | if (TTPTL.getTypePtr()->getDecl()->isImplicit()) | |||
617 | return TTPTL; | |||
618 | } | |||
619 | return {}; | |||
620 | } | |||
621 | ||||
622 | template <typename TemplateDeclTy> | |||
623 | static NamedDecl *getOnlyInstantiationImpl(TemplateDeclTy *TD) { | |||
624 | NamedDecl *Only = nullptr; | |||
625 | for (auto *Spec : TD->specializations()) { | |||
626 | if (Spec->getTemplateSpecializationKind() == TSK_ExplicitSpecialization) | |||
627 | continue; | |||
628 | if (Only != nullptr) | |||
629 | return nullptr; | |||
630 | Only = Spec; | |||
631 | } | |||
632 | return Only; | |||
633 | } | |||
634 | ||||
635 | NamedDecl *getOnlyInstantiation(NamedDecl *TemplatedDecl) { | |||
636 | if (TemplateDecl *TD = TemplatedDecl->getDescribedTemplate()) { | |||
637 | if (auto *CTD = llvm::dyn_cast<ClassTemplateDecl>(TD)) | |||
638 | return getOnlyInstantiationImpl(CTD); | |||
639 | if (auto *FTD = llvm::dyn_cast<FunctionTemplateDecl>(TD)) | |||
640 | return getOnlyInstantiationImpl(FTD); | |||
641 | if (auto *VTD = llvm::dyn_cast<VarTemplateDecl>(TD)) | |||
642 | return getOnlyInstantiationImpl(VTD); | |||
643 | } | |||
644 | return nullptr; | |||
645 | } | |||
646 | ||||
647 | std::vector<const Attr *> getAttributes(const DynTypedNode &N) { | |||
648 | std::vector<const Attr *> Result; | |||
649 | if (const auto *TL = N.get<TypeLoc>()) { | |||
650 | for (AttributedTypeLoc ATL = TL->getAs<AttributedTypeLoc>(); !ATL.isNull(); | |||
651 | ATL = ATL.getModifiedLoc().getAs<AttributedTypeLoc>()) { | |||
652 | if (const Attr *A = ATL.getAttr()) | |||
653 | Result.push_back(A); | |||
654 | assert(!ATL.getModifiedLoc().isNull())(static_cast <bool> (!ATL.getModifiedLoc().isNull()) ? void (0) : __assert_fail ("!ATL.getModifiedLoc().isNull()", "clang-tools-extra/clangd/AST.cpp" , 654, __extension__ __PRETTY_FUNCTION__)); | |||
655 | } | |||
656 | } | |||
657 | if (const auto *S = N.get<AttributedStmt>()) { | |||
658 | for (; S != nullptr; S = dyn_cast<AttributedStmt>(S->getSubStmt())) | |||
659 | for (const Attr *A : S->getAttrs()) | |||
660 | if (A) | |||
661 | Result.push_back(A); | |||
662 | } | |||
663 | if (const auto *D = N.get<Decl>()) { | |||
664 | for (const Attr *A : D->attrs()) | |||
665 | if (A) | |||
666 | Result.push_back(A); | |||
667 | } | |||
668 | return Result; | |||
669 | } | |||
670 | ||||
671 | std::string getQualification(ASTContext &Context, | |||
672 | const DeclContext *DestContext, | |||
673 | SourceLocation InsertionPoint, | |||
674 | const NamedDecl *ND) { | |||
675 | auto VisibleNamespaceDecls = | |||
676 | getUsingNamespaceDirectives(DestContext, InsertionPoint); | |||
677 | return getQualification( | |||
678 | Context, DestContext, ND->getDeclContext(), | |||
679 | [&](NestedNameSpecifier *NNS) { | |||
680 | if (NNS->getKind() != NestedNameSpecifier::Namespace) | |||
681 | return false; | |||
682 | const auto *CanonNSD = NNS->getAsNamespace()->getCanonicalDecl(); | |||
683 | return llvm::any_of(VisibleNamespaceDecls, | |||
684 | [CanonNSD](const NamespaceDecl *NSD) { | |||
685 | return NSD->getCanonicalDecl() == CanonNSD; | |||
686 | }); | |||
687 | }); | |||
688 | } | |||
689 | ||||
690 | std::string getQualification(ASTContext &Context, | |||
691 | const DeclContext *DestContext, | |||
692 | const NamedDecl *ND, | |||
693 | llvm::ArrayRef<std::string> VisibleNamespaces) { | |||
694 | for (llvm::StringRef NS : VisibleNamespaces) { | |||
695 | assert(NS.endswith("::"))(static_cast <bool> (NS.endswith("::")) ? void (0) : __assert_fail ("NS.endswith(\"::\")", "clang-tools-extra/clangd/AST.cpp", 695 , __extension__ __PRETTY_FUNCTION__)); | |||
696 | (void)NS; | |||
697 | } | |||
698 | return getQualification( | |||
699 | Context, DestContext, ND->getDeclContext(), | |||
700 | [&](NestedNameSpecifier *NNS) { | |||
701 | return llvm::any_of(VisibleNamespaces, [&](llvm::StringRef Namespace) { | |||
702 | std::string NS; | |||
703 | llvm::raw_string_ostream OS(NS); | |||
704 | NNS->print(OS, Context.getPrintingPolicy()); | |||
705 | return OS.str() == Namespace; | |||
706 | }); | |||
707 | }); | |||
708 | } | |||
709 | ||||
710 | bool hasUnstableLinkage(const Decl *D) { | |||
711 | // Linkage of a ValueDecl depends on the type. | |||
712 | // If that's not deduced yet, deducing it may change the linkage. | |||
713 | auto *VD = llvm::dyn_cast_or_null<ValueDecl>(D); | |||
714 | return VD && !VD->getType().isNull() && VD->getType()->isUndeducedType(); | |||
715 | } | |||
716 | ||||
717 | bool isDeeplyNested(const Decl *D, unsigned MaxDepth) { | |||
718 | size_t ContextDepth = 0; | |||
719 | for (auto *Ctx = D->getDeclContext(); Ctx && !Ctx->isTranslationUnit(); | |||
720 | Ctx = Ctx->getParent()) { | |||
721 | if (++ContextDepth == MaxDepth) | |||
722 | return true; | |||
723 | } | |||
724 | return false; | |||
725 | } | |||
726 | ||||
727 | namespace { | |||
728 | ||||
729 | // returns true for `X` in `template <typename... X> void foo()` | |||
730 | bool isTemplateTypeParameterPack(NamedDecl *D) { | |||
731 | if (const auto *TTPD = dyn_cast<TemplateTypeParmDecl>(D)) { | |||
732 | return TTPD->isParameterPack(); | |||
733 | } | |||
734 | return false; | |||
735 | } | |||
736 | ||||
737 | // Returns the template parameter pack type from an instantiated function | |||
738 | // template, if it exists, nullptr otherwise. | |||
739 | const TemplateTypeParmType *getFunctionPackType(const FunctionDecl *Callee) { | |||
740 | if (const auto *TemplateDecl = Callee->getPrimaryTemplate()) { | |||
741 | auto TemplateParams = TemplateDecl->getTemplateParameters()->asArray(); | |||
742 | // find the template parameter pack from the back | |||
743 | const auto It = std::find_if(TemplateParams.rbegin(), TemplateParams.rend(), | |||
744 | isTemplateTypeParameterPack); | |||
745 | if (It != TemplateParams.rend()) { | |||
746 | const auto *TTPD = dyn_cast<TemplateTypeParmDecl>(*It); | |||
747 | return TTPD->getTypeForDecl()->castAs<TemplateTypeParmType>(); | |||
| ||||
748 | } | |||
749 | } | |||
750 | return nullptr; | |||
751 | } | |||
752 | ||||
753 | // Returns the template parameter pack type that this parameter was expanded | |||
754 | // from (if in the Args... or Args&... or Args&&... form), if this is the case, | |||
755 | // nullptr otherwise. | |||
756 | const TemplateTypeParmType *getUnderylingPackType(const ParmVarDecl *Param) { | |||
757 | const auto *PlainType = Param->getType().getTypePtr(); | |||
758 | if (auto *RT = dyn_cast<ReferenceType>(PlainType)) | |||
759 | PlainType = RT->getPointeeTypeAsWritten().getTypePtr(); | |||
760 | if (const auto *SubstType = dyn_cast<SubstTemplateTypeParmType>(PlainType)) { | |||
761 | const auto *ReplacedParameter = SubstType->getReplacedParameter(); | |||
762 | if (ReplacedParameter->isParameterPack()) { | |||
763 | return ReplacedParameter->getTypeForDecl() | |||
764 | ->castAs<TemplateTypeParmType>(); | |||
765 | } | |||
766 | } | |||
767 | return nullptr; | |||
768 | } | |||
769 | ||||
770 | // This visitor walks over the body of an instantiated function template. | |||
771 | // The template accepts a parameter pack and the visitor records whether | |||
772 | // the pack parameters were forwarded to another call. For example, given: | |||
773 | // | |||
774 | // template <typename T, typename... Args> | |||
775 | // auto make_unique(Args... args) { | |||
776 | // return unique_ptr<T>(new T(args...)); | |||
777 | // } | |||
778 | // | |||
779 | // When called as `make_unique<std::string>(2, 'x')` this yields a function | |||
780 | // `make_unique<std::string, int, char>` with two parameters. | |||
781 | // The visitor records that those two parameters are forwarded to the | |||
782 | // `constructor std::string(int, char);`. | |||
783 | // | |||
784 | // This information is recorded in the `ForwardingInfo` split into fully | |||
785 | // resolved parameters (passed as argument to a parameter that is not an | |||
786 | // expanded template type parameter pack) and forwarding parameters (passed to a | |||
787 | // parameter that is an expanded template type parameter pack). | |||
788 | class ForwardingCallVisitor | |||
789 | : public RecursiveASTVisitor<ForwardingCallVisitor> { | |||
790 | public: | |||
791 | ForwardingCallVisitor(ArrayRef<const ParmVarDecl *> Parameters) | |||
792 | : Parameters{Parameters}, PackType{getUnderylingPackType( | |||
793 | Parameters.front())} {} | |||
794 | ||||
795 | bool VisitCallExpr(CallExpr *E) { | |||
796 | auto *Callee = getCalleeDeclOrUniqueOverload(E); | |||
797 | if (Callee) { | |||
798 | handleCall(Callee, E->arguments()); | |||
799 | } | |||
800 | return !Info.has_value(); | |||
801 | } | |||
802 | ||||
803 | bool VisitCXXConstructExpr(CXXConstructExpr *E) { | |||
804 | auto *Callee = E->getConstructor(); | |||
805 | if (Callee) { | |||
806 | handleCall(Callee, E->arguments()); | |||
807 | } | |||
808 | return !Info.has_value(); | |||
809 | } | |||
810 | ||||
811 | // The expanded parameter pack to be resolved | |||
812 | ArrayRef<const ParmVarDecl *> Parameters; | |||
813 | // The type of the parameter pack | |||
814 | const TemplateTypeParmType *PackType; | |||
815 | ||||
816 | struct ForwardingInfo { | |||
817 | // If the parameters were resolved to another FunctionDecl, these are its | |||
818 | // first non-variadic parameters (i.e. the first entries of the parameter | |||
819 | // pack that are passed as arguments bound to a non-pack parameter.) | |||
820 | ArrayRef<const ParmVarDecl *> Head; | |||
821 | // If the parameters were resolved to another FunctionDecl, these are its | |||
822 | // variadic parameters (i.e. the entries of the parameter pack that are | |||
823 | // passed as arguments bound to a pack parameter.) | |||
824 | ArrayRef<const ParmVarDecl *> Pack; | |||
825 | // If the parameters were resolved to another FunctionDecl, these are its | |||
826 | // last non-variadic parameters (i.e. the last entries of the parameter pack | |||
827 | // that are passed as arguments bound to a non-pack parameter.) | |||
828 | ArrayRef<const ParmVarDecl *> Tail; | |||
829 | // If the parameters were resolved to another forwarding FunctionDecl, this | |||
830 | // is it. | |||
831 | std::optional<FunctionDecl *> PackTarget; | |||
832 | }; | |||
833 | ||||
834 | // The output of this visitor | |||
835 | std::optional<ForwardingInfo> Info; | |||
836 | ||||
837 | private: | |||
838 | // inspects the given callee with the given args to check whether it | |||
839 | // contains Parameters, and sets Info accordingly. | |||
840 | void handleCall(FunctionDecl *Callee, typename CallExpr::arg_range Args) { | |||
841 | // Skip functions with less parameters, they can't be the target. | |||
842 | if (Callee->parameters().size() < Parameters.size()) | |||
843 | return; | |||
844 | if (llvm::any_of(Args, | |||
845 | [](const Expr *E) { return isa<PackExpansionExpr>(E); })) { | |||
846 | return; | |||
847 | } | |||
848 | auto PackLocation = findPack(Args); | |||
849 | if (!PackLocation) | |||
850 | return; | |||
851 | ArrayRef<ParmVarDecl *> MatchingParams = | |||
852 | Callee->parameters().slice(*PackLocation, Parameters.size()); | |||
853 | // Check whether the function has a parameter pack as the last template | |||
854 | // parameter | |||
855 | if (const auto *TTPT = getFunctionPackType(Callee)) { | |||
856 | // In this case: Separate the parameters into head, pack and tail | |||
857 | auto IsExpandedPack = [&](const ParmVarDecl *P) { | |||
858 | return getUnderylingPackType(P) == TTPT; | |||
859 | }; | |||
860 | ForwardingInfo FI; | |||
861 | FI.Head = MatchingParams.take_until(IsExpandedPack); | |||
862 | FI.Pack = | |||
863 | MatchingParams.drop_front(FI.Head.size()).take_while(IsExpandedPack); | |||
864 | FI.Tail = MatchingParams.drop_front(FI.Head.size() + FI.Pack.size()); | |||
865 | FI.PackTarget = Callee; | |||
866 | Info = FI; | |||
867 | return; | |||
868 | } | |||
869 | // Default case: assume all parameters were fully resolved | |||
870 | ForwardingInfo FI; | |||
871 | FI.Head = MatchingParams; | |||
872 | Info = FI; | |||
873 | } | |||
874 | ||||
875 | // Returns the beginning of the expanded pack represented by Parameters | |||
876 | // in the given arguments, if it is there. | |||
877 | std::optional<size_t> findPack(typename CallExpr::arg_range Args) { | |||
878 | // find the argument directly referring to the first parameter | |||
879 | assert(Parameters.size() <= static_cast<size_t>(llvm::size(Args)))(static_cast <bool> (Parameters.size() <= static_cast <size_t>(llvm::size(Args))) ? void (0) : __assert_fail ( "Parameters.size() <= static_cast<size_t>(llvm::size(Args))" , "clang-tools-extra/clangd/AST.cpp", 879, __extension__ __PRETTY_FUNCTION__ )); | |||
880 | for (auto Begin = Args.begin(), End = Args.end() - Parameters.size() + 1; | |||
881 | Begin != End; ++Begin) { | |||
882 | if (const auto *RefArg = unwrapForward(*Begin)) { | |||
883 | if (Parameters.front() != RefArg->getDecl()) | |||
884 | continue; | |||
885 | // Check that this expands all the way until the last parameter. | |||
886 | // It's enough to look at the last parameter, because it isn't possible | |||
887 | // to expand without expanding all of them. | |||
888 | auto ParamEnd = Begin + Parameters.size() - 1; | |||
889 | RefArg = unwrapForward(*ParamEnd); | |||
890 | if (!RefArg || Parameters.back() != RefArg->getDecl()) | |||
891 | continue; | |||
892 | return std::distance(Args.begin(), Begin); | |||
893 | } | |||
894 | } | |||
895 | return std::nullopt; | |||
896 | } | |||
897 | ||||
898 | static FunctionDecl *getCalleeDeclOrUniqueOverload(CallExpr *E) { | |||
899 | Decl *CalleeDecl = E->getCalleeDecl(); | |||
900 | auto *Callee = dyn_cast_or_null<FunctionDecl>(CalleeDecl); | |||
901 | if (!Callee) { | |||
902 | if (auto *Lookup = dyn_cast<UnresolvedLookupExpr>(E->getCallee())) { | |||
903 | Callee = resolveOverload(Lookup, E); | |||
904 | } | |||
905 | } | |||
906 | // Ignore the callee if the number of arguments is wrong (deal with va_args) | |||
907 | if (Callee && Callee->getNumParams() == E->getNumArgs()) | |||
908 | return Callee; | |||
909 | return nullptr; | |||
910 | } | |||
911 | ||||
912 | static FunctionDecl *resolveOverload(UnresolvedLookupExpr *Lookup, | |||
913 | CallExpr *E) { | |||
914 | FunctionDecl *MatchingDecl = nullptr; | |||
915 | if (!Lookup->requiresADL()) { | |||
916 | // Check whether there is a single overload with this number of | |||
917 | // parameters | |||
918 | for (auto *Candidate : Lookup->decls()) { | |||
919 | if (auto *FuncCandidate = dyn_cast_or_null<FunctionDecl>(Candidate)) { | |||
920 | if (FuncCandidate->getNumParams() == E->getNumArgs()) { | |||
921 | if (MatchingDecl) { | |||
922 | // there are multiple candidates - abort | |||
923 | return nullptr; | |||
924 | } | |||
925 | MatchingDecl = FuncCandidate; | |||
926 | } | |||
927 | } | |||
928 | } | |||
929 | } | |||
930 | return MatchingDecl; | |||
931 | } | |||
932 | ||||
933 | // Tries to get to the underlying argument by unwrapping implicit nodes and | |||
934 | // std::forward. | |||
935 | static const DeclRefExpr *unwrapForward(const Expr *E) { | |||
936 | E = E->IgnoreImplicitAsWritten(); | |||
937 | // There might be an implicit copy/move constructor call on top of the | |||
938 | // forwarded arg. | |||
939 | // FIXME: Maybe mark implicit calls in the AST to properly filter here. | |||
940 | if (const auto *Const = dyn_cast<CXXConstructExpr>(E)) | |||
941 | if (Const->getConstructor()->isCopyOrMoveConstructor()) | |||
942 | E = Const->getArg(0)->IgnoreImplicitAsWritten(); | |||
943 | if (const auto *Call = dyn_cast<CallExpr>(E)) { | |||
944 | const auto Callee = Call->getBuiltinCallee(); | |||
945 | if (Callee == Builtin::BIforward) { | |||
946 | return dyn_cast<DeclRefExpr>( | |||
947 | Call->getArg(0)->IgnoreImplicitAsWritten()); | |||
948 | } | |||
949 | } | |||
950 | return dyn_cast<DeclRefExpr>(E); | |||
951 | } | |||
952 | }; | |||
953 | ||||
954 | } // namespace | |||
955 | ||||
956 | SmallVector<const ParmVarDecl *> | |||
957 | resolveForwardingParameters(const FunctionDecl *D, unsigned MaxDepth) { | |||
958 | auto Parameters = D->parameters(); | |||
959 | // If the function has a template parameter pack | |||
960 | if (const auto *TTPT = getFunctionPackType(D)) { | |||
| ||||
961 | // Split the parameters into head, pack and tail | |||
962 | auto IsExpandedPack = [TTPT](const ParmVarDecl *P) { | |||
963 | return getUnderylingPackType(P) == TTPT; | |||
964 | }; | |||
965 | ArrayRef<const ParmVarDecl *> Head = Parameters.take_until(IsExpandedPack); | |||
966 | ArrayRef<const ParmVarDecl *> Pack = | |||
967 | Parameters.drop_front(Head.size()).take_while(IsExpandedPack); | |||
968 | ArrayRef<const ParmVarDecl *> Tail = | |||
969 | Parameters.drop_front(Head.size() + Pack.size()); | |||
970 | SmallVector<const ParmVarDecl *> Result(Parameters.size()); | |||
971 | // Fill in non-pack parameters | |||
972 | auto HeadIt = std::copy(Head.begin(), Head.end(), Result.begin()); | |||
973 | auto TailIt = std::copy(Tail.rbegin(), Tail.rend(), Result.rbegin()); | |||
974 | // Recurse on pack parameters | |||
975 | size_t Depth = 0; | |||
976 | const FunctionDecl *CurrentFunction = D; | |||
977 | llvm::SmallSet<const FunctionTemplateDecl *, 4> SeenTemplates; | |||
978 | if (const auto *Template = D->getPrimaryTemplate()) { | |||
979 | SeenTemplates.insert(Template); | |||
980 | } | |||
981 | while (!Pack.empty() && CurrentFunction && Depth < MaxDepth) { | |||
982 | // Find call expressions involving the pack | |||
983 | ForwardingCallVisitor V{Pack}; | |||
984 | V.TraverseStmt(CurrentFunction->getBody()); | |||
985 | if (!V.Info) { | |||
986 | break; | |||
987 | } | |||
988 | // If we found something: Fill in non-pack parameters | |||
989 | auto Info = *V.Info; | |||
990 | HeadIt = std::copy(Info.Head.begin(), Info.Head.end(), HeadIt); | |||
991 | TailIt = std::copy(Info.Tail.rbegin(), Info.Tail.rend(), TailIt); | |||
992 | // Prepare next recursion level | |||
993 | Pack = Info.Pack; | |||
994 | CurrentFunction = Info.PackTarget.value_or(nullptr); | |||
995 | Depth++; | |||
996 | // If we are recursing into a previously encountered function: Abort | |||
997 | if (CurrentFunction) { | |||
998 | if (const auto *Template = CurrentFunction->getPrimaryTemplate()) { | |||
999 | bool NewFunction = SeenTemplates.insert(Template).second; | |||
1000 | if (!NewFunction) { | |||
1001 | return {Parameters.begin(), Parameters.end()}; | |||
1002 | } | |||
1003 | } | |||
1004 | } | |||
1005 | } | |||
1006 | // Fill in the remaining unresolved pack parameters | |||
1007 | HeadIt = std::copy(Pack.begin(), Pack.end(), HeadIt); | |||
1008 | assert(TailIt.base() == HeadIt)(static_cast <bool> (TailIt.base() == HeadIt) ? void (0 ) : __assert_fail ("TailIt.base() == HeadIt", "clang-tools-extra/clangd/AST.cpp" , 1008, __extension__ __PRETTY_FUNCTION__)); | |||
1009 | return Result; | |||
1010 | } | |||
1011 | return {Parameters.begin(), Parameters.end()}; | |||
1012 | } | |||
1013 | ||||
1014 | bool isExpandedFromParameterPack(const ParmVarDecl *D) { | |||
1015 | return getUnderylingPackType(D) != nullptr; | |||
1016 | } | |||
1017 | ||||
1018 | } // namespace clangd | |||
1019 | } // namespace clang |