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