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 "FindTarget.h" 12 #include "SourceCode.h" 13 #include "clang/AST/ASTContext.h" 14 #include "clang/AST/ASTTypeTraits.h" 15 #include "clang/AST/Decl.h" 16 #include "clang/AST/DeclBase.h" 17 #include "clang/AST/DeclCXX.h" 18 #include "clang/AST/DeclTemplate.h" 19 #include "clang/AST/DeclarationName.h" 20 #include "clang/AST/NestedNameSpecifier.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/SourceLocation.h" 27 #include "clang/Basic/SourceManager.h" 28 #include "clang/Basic/Specifiers.h" 29 #include "clang/Index/USRGeneration.h" 30 #include "llvm/ADT/ArrayRef.h" 31 #include "llvm/ADT/Optional.h" 32 #include "llvm/ADT/STLExtras.h" 33 #include "llvm/ADT/StringRef.h" 34 #include "llvm/Support/Casting.h" 35 #include "llvm/Support/ScopedPrinter.h" 36 #include "llvm/Support/raw_ostream.h" 37 #include <string> 38 #include <vector> 39 40 namespace clang { 41 namespace clangd { 42 43 namespace { 44 llvm::Optional<llvm::ArrayRef<TemplateArgumentLoc>> 45 getTemplateSpecializationArgLocs(const NamedDecl &ND) { 46 if (auto *Func = llvm::dyn_cast<FunctionDecl>(&ND)) { 47 if (const ASTTemplateArgumentListInfo *Args = 48 Func->getTemplateSpecializationArgsAsWritten()) 49 return Args->arguments(); 50 } else if (auto *Cls = 51 llvm::dyn_cast<ClassTemplatePartialSpecializationDecl>(&ND)) { 52 if (auto *Args = Cls->getTemplateArgsAsWritten()) 53 return Args->arguments(); 54 } else if (auto *Var = 55 llvm::dyn_cast<VarTemplatePartialSpecializationDecl>(&ND)) { 56 if (auto *Args = Var->getTemplateArgsAsWritten()) 57 return Args->arguments(); 58 } else if (auto *Var = llvm::dyn_cast<VarTemplateSpecializationDecl>(&ND)) 59 return Var->getTemplateArgsInfo().arguments(); 60 // We return None for ClassTemplateSpecializationDecls because it does not 61 // contain TemplateArgumentLoc information. 62 return llvm::None; 63 } 64 65 template <class T> 66 bool 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 73 bool 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. 82 llvm::DenseSet<const NamespaceDecl *> 83 getUsingNamespaceDirectives(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. 105 std::string 106 getQualification(ASTContext &Context, const DeclContext *DestContext, 107 const DeclContext *SourceContext, 108 llvm::function_ref<bool(NestedNameSpecifier *)> IsVisible) { 109 std::vector<const NestedNameSpecifier *> Parents; 110 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 NestedNameSpecifier *NNS = nullptr; 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 (void)ReachedNS; 122 NNS = NestedNameSpecifier::Create(Context, nullptr, false, 123 TD->getTypeForDecl()); 124 } else if (auto *NSD = llvm::dyn_cast<NamespaceDecl>(CurContext)) { 125 ReachedNS = true; 126 NNS = NestedNameSpecifier::Create(Context, nullptr, NSD); 127 // Anonymous and inline namespace names are not spelled while qualifying 128 // a name, so skip those. 129 if (NSD->isAnonymousNamespace() || NSD->isInlineNamespace()) 130 continue; 131 } else { 132 // Other types of contexts cannot be spelled in code, just skip over 133 // them. 134 continue; 135 } 136 // Stop if this namespace is already visible at DestContext. 137 if (IsVisible(NNS)) 138 break; 139 140 Parents.push_back(NNS); 141 } 142 143 // Go over name-specifiers in reverse order to create necessary qualification, 144 // since we stored inner-most parent first. 145 std::string Result; 146 llvm::raw_string_ostream OS(Result); 147 for (const auto *Parent : llvm::reverse(Parents)) 148 Parent->print(OS, Context.getPrintingPolicy()); 149 return OS.str(); 150 } 151 152 } // namespace 153 154 bool isImplicitTemplateInstantiation(const NamedDecl *D) { 155 return isTemplateSpecializationKind(D, TSK_ImplicitInstantiation); 156 } 157 158 bool isExplicitTemplateSpecialization(const NamedDecl *D) { 159 return isTemplateSpecializationKind(D, TSK_ExplicitSpecialization); 160 } 161 162 bool isImplementationDetail(const Decl *D) { 163 return !isSpelledInSource(D->getLocation(), 164 D->getASTContext().getSourceManager()); 165 } 166 167 SourceLocation nameLocation(const clang::Decl &D, const SourceManager &SM) { 168 auto L = D.getLocation(); 169 if (isSpelledInSource(L, SM)) 170 return SM.getSpellingLoc(L); 171 return SM.getExpansionLoc(L); 172 } 173 174 std::string printQualifiedName(const NamedDecl &ND) { 175 std::string QName; 176 llvm::raw_string_ostream OS(QName); 177 PrintingPolicy Policy(ND.getASTContext().getLangOpts()); 178 // Note that inline namespaces are treated as transparent scopes. This 179 // reflects the way they're most commonly used for lookup. Ideally we'd 180 // include them, but at query time it's hard to find all the inline 181 // namespaces to query: the preamble doesn't have a dedicated list. 182 Policy.SuppressUnwrittenScope = true; 183 ND.printQualifiedName(OS, Policy); 184 OS.flush(); 185 assert(!StringRef(QName).startswith("::")); 186 return QName; 187 } 188 189 static bool isAnonymous(const DeclarationName &N) { 190 return N.isIdentifier() && !N.getAsIdentifierInfo(); 191 } 192 193 NestedNameSpecifierLoc getQualifierLoc(const NamedDecl &ND) { 194 if (auto *V = llvm::dyn_cast<DeclaratorDecl>(&ND)) 195 return V->getQualifierLoc(); 196 if (auto *T = llvm::dyn_cast<TagDecl>(&ND)) 197 return T->getQualifierLoc(); 198 return NestedNameSpecifierLoc(); 199 } 200 201 std::string printUsingNamespaceName(const ASTContext &Ctx, 202 const UsingDirectiveDecl &D) { 203 PrintingPolicy PP(Ctx.getLangOpts()); 204 std::string Name; 205 llvm::raw_string_ostream Out(Name); 206 207 if (auto *Qual = D.getQualifier()) 208 Qual->print(Out, PP); 209 D.getNominatedNamespaceAsWritten()->printName(Out); 210 return Out.str(); 211 } 212 213 std::string printName(const ASTContext &Ctx, const NamedDecl &ND) { 214 std::string Name; 215 llvm::raw_string_ostream Out(Name); 216 PrintingPolicy PP(Ctx.getLangOpts()); 217 // We don't consider a class template's args part of the constructor name. 218 PP.SuppressTemplateArgsInCXXConstructors = true; 219 220 // Handle 'using namespace'. They all have the same name - <using-directive>. 221 if (auto *UD = llvm::dyn_cast<UsingDirectiveDecl>(&ND)) { 222 Out << "using namespace "; 223 if (auto *Qual = UD->getQualifier()) 224 Qual->print(Out, PP); 225 UD->getNominatedNamespaceAsWritten()->printName(Out); 226 return Out.str(); 227 } 228 229 if (isAnonymous(ND.getDeclName())) { 230 // Come up with a presentation for an anonymous entity. 231 if (isa<NamespaceDecl>(ND)) 232 return "(anonymous namespace)"; 233 if (auto *Cls = llvm::dyn_cast<RecordDecl>(&ND)) { 234 if (Cls->isLambda()) 235 return "(lambda)"; 236 return ("(anonymous " + Cls->getKindName() + ")").str(); 237 } 238 if (isa<EnumDecl>(ND)) 239 return "(anonymous enum)"; 240 return "(anonymous)"; 241 } 242 243 // Print nested name qualifier if it was written in the source code. 244 if (auto *Qualifier = getQualifierLoc(ND).getNestedNameSpecifier()) 245 Qualifier->print(Out, PP); 246 // Print the name itself. 247 ND.getDeclName().print(Out, PP); 248 // Print template arguments. 249 Out << printTemplateSpecializationArgs(ND); 250 251 return Out.str(); 252 } 253 254 std::string printTemplateSpecializationArgs(const NamedDecl &ND) { 255 std::string TemplateArgs; 256 llvm::raw_string_ostream OS(TemplateArgs); 257 PrintingPolicy Policy(ND.getASTContext().getLangOpts()); 258 if (llvm::Optional<llvm::ArrayRef<TemplateArgumentLoc>> Args = 259 getTemplateSpecializationArgLocs(ND)) { 260 printTemplateArgumentList(OS, *Args, Policy); 261 } else if (auto *Cls = llvm::dyn_cast<ClassTemplateSpecializationDecl>(&ND)) { 262 if (const TypeSourceInfo *TSI = Cls->getTypeAsWritten()) { 263 // ClassTemplateSpecializationDecls do not contain 264 // TemplateArgumentTypeLocs, they only have TemplateArgumentTypes. So we 265 // create a new argument location list from TypeSourceInfo. 266 auto STL = TSI->getTypeLoc().getAs<TemplateSpecializationTypeLoc>(); 267 llvm::SmallVector<TemplateArgumentLoc> ArgLocs; 268 ArgLocs.reserve(STL.getNumArgs()); 269 for (unsigned I = 0; I < STL.getNumArgs(); ++I) 270 ArgLocs.push_back(STL.getArgLoc(I)); 271 printTemplateArgumentList(OS, ArgLocs, Policy); 272 } else { 273 // FIXME: Fix cases when getTypeAsWritten returns null inside clang AST, 274 // e.g. friend decls. Currently we fallback to Template Arguments without 275 // location information. 276 printTemplateArgumentList(OS, Cls->getTemplateArgs().asArray(), Policy); 277 } 278 } 279 OS.flush(); 280 return TemplateArgs; 281 } 282 283 std::string printNamespaceScope(const DeclContext &DC) { 284 for (const auto *Ctx = &DC; Ctx != nullptr; Ctx = Ctx->getParent()) 285 if (const auto *NS = dyn_cast<NamespaceDecl>(Ctx)) 286 if (!NS->isAnonymousNamespace() && !NS->isInlineNamespace()) 287 return printQualifiedName(*NS) + "::"; 288 return ""; 289 } 290 291 static llvm::StringRef 292 getNameOrErrForObjCInterface(const ObjCInterfaceDecl *ID) { 293 return ID ? ID->getName() : "<<error-type>>"; 294 } 295 296 std::string printObjCMethod(const ObjCMethodDecl &Method) { 297 std::string Name; 298 llvm::raw_string_ostream OS(Name); 299 300 OS << (Method.isInstanceMethod() ? '-' : '+') << '['; 301 302 // Should always be true. 303 if (const ObjCContainerDecl *C = 304 dyn_cast<ObjCContainerDecl>(Method.getDeclContext())) 305 OS << printObjCContainer(*C); 306 307 Method.getSelector().print(OS << ' '); 308 if (Method.isVariadic()) 309 OS << ", ..."; 310 311 OS << ']'; 312 OS.flush(); 313 return Name; 314 } 315 316 std::string printObjCContainer(const ObjCContainerDecl &C) { 317 if (const ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(&C)) { 318 std::string Name; 319 llvm::raw_string_ostream OS(Name); 320 const ObjCInterfaceDecl *Class = Category->getClassInterface(); 321 OS << getNameOrErrForObjCInterface(Class) << '(' << Category->getName() 322 << ')'; 323 OS.flush(); 324 return Name; 325 } 326 if (const ObjCCategoryImplDecl *CID = dyn_cast<ObjCCategoryImplDecl>(&C)) { 327 std::string Name; 328 llvm::raw_string_ostream OS(Name); 329 const ObjCInterfaceDecl *Class = CID->getClassInterface(); 330 OS << getNameOrErrForObjCInterface(Class) << '(' << CID->getName() << ')'; 331 OS.flush(); 332 return Name; 333 } 334 return C.getNameAsString(); 335 } 336 337 SymbolID getSymbolID(const Decl *D) { 338 llvm::SmallString<128> USR; 339 if (index::generateUSRForDecl(D, USR)) 340 return {}; 341 return SymbolID(USR); 342 } 343 344 SymbolID getSymbolID(const llvm::StringRef MacroName, const MacroInfo *MI, 345 const SourceManager &SM) { 346 if (MI == nullptr) 347 return {}; 348 llvm::SmallString<128> USR; 349 if (index::generateUSRForMacro(MacroName, MI->getDefinitionLoc(), SM, USR)) 350 return {}; 351 return SymbolID(USR); 352 } 353 354 std::string printType(const QualType QT, const DeclContext &CurContext) { 355 std::string Result; 356 llvm::raw_string_ostream OS(Result); 357 PrintingPolicy PP(CurContext.getParentASTContext().getPrintingPolicy()); 358 PP.SuppressTagKeyword = true; 359 PP.SuppressUnwrittenScope = true; 360 361 class PrintCB : public PrintingCallbacks { 362 public: 363 PrintCB(const DeclContext *CurContext) : CurContext(CurContext) {} 364 virtual ~PrintCB() {} 365 virtual bool isScopeVisible(const DeclContext *DC) const override { 366 return DC->Encloses(CurContext); 367 } 368 369 private: 370 const DeclContext *CurContext; 371 }; 372 PrintCB PCB(&CurContext); 373 PP.Callbacks = &PCB; 374 375 QT.print(OS, PP); 376 return OS.str(); 377 } 378 379 bool hasReservedName(const Decl &D) { 380 if (const auto *ND = llvm::dyn_cast<NamedDecl>(&D)) 381 if (const auto *II = ND->getIdentifier()) 382 return isReservedName(II->getName()); 383 return false; 384 } 385 386 bool hasReservedScope(const DeclContext &DC) { 387 for (const DeclContext *D = &DC; D; D = D->getParent()) { 388 if (D->isTransparentContext() || D->isInlineNamespace()) 389 continue; 390 if (const auto *ND = llvm::dyn_cast<NamedDecl>(D)) 391 if (hasReservedName(*ND)) 392 return true; 393 } 394 return false; 395 } 396 397 QualType declaredType(const TypeDecl *D) { 398 if (const auto *CTSD = llvm::dyn_cast<ClassTemplateSpecializationDecl>(D)) 399 if (const auto *TSI = CTSD->getTypeAsWritten()) 400 return TSI->getType(); 401 return D->getASTContext().getTypeDeclType(D); 402 } 403 404 namespace { 405 /// Computes the deduced type at a given location by visiting the relevant 406 /// nodes. We use this to display the actual type when hovering over an "auto" 407 /// keyword or "decltype()" expression. 408 /// FIXME: This could have been a lot simpler by visiting AutoTypeLocs but it 409 /// seems that the AutoTypeLocs that can be visited along with their AutoType do 410 /// not have the deduced type set. Instead, we have to go to the appropriate 411 /// DeclaratorDecl/FunctionDecl and work our back to the AutoType that does have 412 /// a deduced type set. The AST should be improved to simplify this scenario. 413 class DeducedTypeVisitor : public RecursiveASTVisitor<DeducedTypeVisitor> { 414 SourceLocation SearchedLocation; 415 416 public: 417 DeducedTypeVisitor(SourceLocation SearchedLocation) 418 : SearchedLocation(SearchedLocation) {} 419 420 // Handle auto initializers: 421 //- auto i = 1; 422 //- decltype(auto) i = 1; 423 //- auto& i = 1; 424 //- auto* i = &a; 425 bool VisitDeclaratorDecl(DeclaratorDecl *D) { 426 if (!D->getTypeSourceInfo() || 427 D->getTypeSourceInfo()->getTypeLoc().getBeginLoc() != SearchedLocation) 428 return true; 429 430 if (auto *AT = D->getType()->getContainedAutoType()) { 431 DeducedType = AT->desugar(); 432 } 433 return true; 434 } 435 436 // Handle auto return types: 437 //- auto foo() {} 438 //- auto& foo() {} 439 //- auto foo() -> int {} 440 //- auto foo() -> decltype(1+1) {} 441 //- operator auto() const { return 10; } 442 bool VisitFunctionDecl(FunctionDecl *D) { 443 if (!D->getTypeSourceInfo()) 444 return true; 445 // Loc of auto in return type (c++14). 446 auto CurLoc = D->getReturnTypeSourceRange().getBegin(); 447 // Loc of "auto" in operator auto() 448 if (CurLoc.isInvalid() && isa<CXXConversionDecl>(D)) 449 CurLoc = D->getTypeSourceInfo()->getTypeLoc().getBeginLoc(); 450 // Loc of "auto" in function with trailing return type (c++11). 451 if (CurLoc.isInvalid()) 452 CurLoc = D->getSourceRange().getBegin(); 453 if (CurLoc != SearchedLocation) 454 return true; 455 456 const AutoType *AT = D->getReturnType()->getContainedAutoType(); 457 if (AT && !AT->getDeducedType().isNull()) { 458 DeducedType = AT->getDeducedType(); 459 } else if (auto *DT = dyn_cast<DecltypeType>(D->getReturnType())) { 460 // auto in a trailing return type just points to a DecltypeType and 461 // getContainedAutoType does not unwrap it. 462 if (!DT->getUnderlyingType().isNull()) 463 DeducedType = DT->getUnderlyingType(); 464 } else if (!D->getReturnType().isNull()) { 465 DeducedType = D->getReturnType(); 466 } 467 return true; 468 } 469 470 // Handle non-auto decltype, e.g.: 471 // - auto foo() -> decltype(expr) {} 472 // - decltype(expr); 473 bool VisitDecltypeTypeLoc(DecltypeTypeLoc TL) { 474 if (TL.getBeginLoc() != SearchedLocation) 475 return true; 476 477 // A DecltypeType's underlying type can be another DecltypeType! E.g. 478 // int I = 0; 479 // decltype(I) J = I; 480 // decltype(J) K = J; 481 const DecltypeType *DT = dyn_cast<DecltypeType>(TL.getTypePtr()); 482 while (DT && !DT->getUnderlyingType().isNull()) { 483 DeducedType = DT->getUnderlyingType(); 484 DT = dyn_cast<DecltypeType>(DeducedType.getTypePtr()); 485 } 486 return true; 487 } 488 489 QualType DeducedType; 490 }; 491 } // namespace 492 493 llvm::Optional<QualType> getDeducedType(ASTContext &ASTCtx, 494 SourceLocation Loc) { 495 if (!Loc.isValid()) 496 return {}; 497 DeducedTypeVisitor V(Loc); 498 V.TraverseAST(ASTCtx); 499 if (V.DeducedType.isNull()) 500 return llvm::None; 501 return V.DeducedType; 502 } 503 504 std::vector<const Attr *> getAttributes(const DynTypedNode &N) { 505 std::vector<const Attr *> Result; 506 if (const auto *TL = N.get<TypeLoc>()) { 507 for (AttributedTypeLoc ATL = TL->getAs<AttributedTypeLoc>(); !ATL.isNull(); 508 ATL = ATL.getModifiedLoc().getAs<AttributedTypeLoc>()) { 509 if (const Attr *A = ATL.getAttr()) 510 Result.push_back(A); 511 assert(!ATL.getModifiedLoc().isNull()); 512 } 513 } 514 if (const auto *S = N.get<AttributedStmt>()) { 515 for (; S != nullptr; S = dyn_cast<AttributedStmt>(S->getSubStmt())) 516 for (const Attr *A : S->getAttrs()) 517 if (A) 518 Result.push_back(A); 519 } 520 if (const auto *D = N.get<Decl>()) { 521 for (const Attr *A : D->attrs()) 522 if (A) 523 Result.push_back(A); 524 } 525 return Result; 526 } 527 528 std::string getQualification(ASTContext &Context, 529 const DeclContext *DestContext, 530 SourceLocation InsertionPoint, 531 const NamedDecl *ND) { 532 auto VisibleNamespaceDecls = 533 getUsingNamespaceDirectives(DestContext, InsertionPoint); 534 return getQualification( 535 Context, DestContext, ND->getDeclContext(), 536 [&](NestedNameSpecifier *NNS) { 537 if (NNS->getKind() != NestedNameSpecifier::Namespace) 538 return false; 539 const auto *CanonNSD = NNS->getAsNamespace()->getCanonicalDecl(); 540 return llvm::any_of(VisibleNamespaceDecls, 541 [CanonNSD](const NamespaceDecl *NSD) { 542 return NSD->getCanonicalDecl() == CanonNSD; 543 }); 544 }); 545 } 546 547 std::string getQualification(ASTContext &Context, 548 const DeclContext *DestContext, 549 const NamedDecl *ND, 550 llvm::ArrayRef<std::string> VisibleNamespaces) { 551 for (llvm::StringRef NS : VisibleNamespaces) { 552 assert(NS.endswith("::")); 553 (void)NS; 554 } 555 return getQualification( 556 Context, DestContext, ND->getDeclContext(), 557 [&](NestedNameSpecifier *NNS) { 558 return llvm::any_of(VisibleNamespaces, [&](llvm::StringRef Namespace) { 559 std::string NS; 560 llvm::raw_string_ostream OS(NS); 561 NNS->print(OS, Context.getPrintingPolicy()); 562 return OS.str() == Namespace; 563 }); 564 }); 565 } 566 567 bool hasUnstableLinkage(const Decl *D) { 568 // Linkage of a ValueDecl depends on the type. 569 // If that's not deduced yet, deducing it may change the linkage. 570 auto *VD = llvm::dyn_cast_or_null<ValueDecl>(D); 571 return VD && !VD->getType().isNull() && VD->getType()->isUndeducedType(); 572 } 573 574 bool isDeeplyNested(const Decl *D, unsigned MaxDepth) { 575 size_t ContextDepth = 0; 576 for (auto *Ctx = D->getDeclContext(); Ctx && !Ctx->isTranslationUnit(); 577 Ctx = Ctx->getParent()) { 578 if (++ContextDepth == MaxDepth) 579 return true; 580 } 581 return false; 582 } 583 } // namespace clangd 584 } // namespace clang 585