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