brintos

brintos / llvm-project-archived public Read only

0
0
Text · 45.9 KiB · f80f732 Raw
1176 lines · cpp
1//===--- FindTarget.cpp - What does an AST node refer to? -----------------===//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-exception6//7//===----------------------------------------------------------------------===//8 9#include "FindTarget.h"10#include "AST.h"11#include "support/Logger.h"12#include "clang/AST/ASTConcept.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/DeclTemplate.h"18#include "clang/AST/DeclVisitor.h"19#include "clang/AST/DeclarationName.h"20#include "clang/AST/Expr.h"21#include "clang/AST/ExprCXX.h"22#include "clang/AST/ExprConcepts.h"23#include "clang/AST/ExprObjC.h"24#include "clang/AST/NestedNameSpecifier.h"25#include "clang/AST/PrettyPrinter.h"26#include "clang/AST/RecursiveASTVisitor.h"27#include "clang/AST/StmtVisitor.h"28#include "clang/AST/TemplateBase.h"29#include "clang/AST/Type.h"30#include "clang/AST/TypeLoc.h"31#include "clang/AST/TypeLocVisitor.h"32#include "clang/AST/TypeVisitor.h"33#include "clang/Basic/LangOptions.h"34#include "clang/Basic/SourceLocation.h"35#include "clang/Basic/SourceManager.h"36#include "clang/Basic/Specifiers.h"37#include "clang/Sema/HeuristicResolver.h"38#include "llvm/ADT/STLExtras.h"39#include "llvm/ADT/SmallVector.h"40#include "llvm/ADT/StringExtras.h"41#include "llvm/Support/Casting.h"42#include "llvm/Support/Compiler.h"43#include "llvm/Support/raw_ostream.h"44#include <iterator>45#include <string>46#include <utility>47#include <vector>48 49namespace clang {50namespace clangd {51namespace {52 53[[maybe_unused]] std::string nodeToString(const DynTypedNode &N) {54  std::string S = std::string(N.getNodeKind().asStringRef());55  {56    llvm::raw_string_ostream OS(S);57    OS << ": ";58    N.print(OS, PrintingPolicy(LangOptions()));59  }60  llvm::replace(S, '\n', ' ');61  return S;62}63 64const NamedDecl *getTemplatePattern(const NamedDecl *D) {65  if (const CXXRecordDecl *CRD = dyn_cast<CXXRecordDecl>(D)) {66    if (const auto *Result = CRD->getTemplateInstantiationPattern())67      return Result;68    // getTemplateInstantiationPattern returns null if the Specialization is69    // incomplete (e.g. the type didn't need to be complete), fall back to the70    // primary template.71    if (CRD->getTemplateSpecializationKind() == TSK_Undeclared)72      if (const auto *Spec = dyn_cast<ClassTemplateSpecializationDecl>(CRD))73        return Spec->getSpecializedTemplate()->getTemplatedDecl();74  } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {75    return FD->getTemplateInstantiationPattern();76  } else if (auto *VD = dyn_cast<VarDecl>(D)) {77    // Hmm: getTIP returns its arg if it's not an instantiation?!78    VarDecl *T = VD->getTemplateInstantiationPattern();79    return (T == D) ? nullptr : T;80  } else if (const auto *ED = dyn_cast<EnumDecl>(D)) {81    return ED->getInstantiatedFromMemberEnum();82  } else if (isa<FieldDecl>(D) || isa<TypedefNameDecl>(D)) {83    if (const auto *Parent = llvm::dyn_cast<NamedDecl>(D->getDeclContext()))84      if (const DeclContext *ParentPat =85              dyn_cast_or_null<DeclContext>(getTemplatePattern(Parent)))86        for (const NamedDecl *BaseND : ParentPat->lookup(D->getDeclName()))87          if (!BaseND->isImplicit() && BaseND->getKind() == D->getKind())88            return BaseND;89  } else if (const auto *ECD = dyn_cast<EnumConstantDecl>(D)) {90    if (const auto *ED = dyn_cast<EnumDecl>(ECD->getDeclContext())) {91      if (const EnumDecl *Pattern = ED->getInstantiatedFromMemberEnum()) {92        for (const NamedDecl *BaseECD : Pattern->lookup(ECD->getDeclName()))93          return BaseECD;94      }95    }96  }97  return nullptr;98}99 100// Returns true if the `TypedefNameDecl` should not be reported.101bool shouldSkipTypedef(const TypedefNameDecl *TD) {102  // These should be treated as keywords rather than decls - the typedef is an103  // odd implementation detail.104  if (TD == TD->getASTContext().getObjCInstanceTypeDecl() ||105      TD == TD->getASTContext().getObjCIdDecl())106    return true;107  return false;108}109 110// TargetFinder locates the entities that an AST node refers to.111//112// Typically this is (possibly) one declaration and (possibly) one type, but113// may be more:114//  - for ambiguous nodes like OverloadExpr115//  - if we want to include e.g. both typedefs and the underlying type116//117// This is organized as a set of mutually recursive helpers for particular node118// types, but for most nodes this is a short walk rather than a deep traversal.119//120// It's tempting to do e.g. typedef resolution as a second normalization step,121// after finding the 'primary' decl etc. But we do this monolithically instead122// because:123//  - normalization may require these traversals again (e.g. unwrapping a124//    typedef reveals a decltype which must be traversed)125//  - it doesn't simplify that much, e.g. the first stage must still be able126//    to yield multiple decls to handle OverloadExpr127//  - there are cases where it's required for correctness. e.g:128//      template<class X> using pvec = vector<x*>; pvec<int> x;129//    There's no Decl `pvec<int>`, we must choose `pvec<X>` or `vector<int*>`130//    and both are lossy. We must know upfront what the caller ultimately wants.131struct TargetFinder {132  using RelSet = DeclRelationSet;133  using Rel = DeclRelation;134 135private:136  const HeuristicResolver *Resolver;137  llvm::SmallDenseMap<const NamedDecl *,138                      std::pair<RelSet, /*InsertionOrder*/ size_t>>139      Decls;140  llvm::SmallDenseMap<const Decl *, RelSet> Seen;141  RelSet Flags;142 143  template <typename T> void debug(T &Node, RelSet Flags) {144    dlog("visit [{0}] {1}", Flags, nodeToString(DynTypedNode::create(Node)));145  }146 147  void report(const NamedDecl *D, RelSet Flags) {148    dlog("--> [{0}] {1}", Flags, nodeToString(DynTypedNode::create(*D)));149    auto It = Decls.try_emplace(D, std::make_pair(Flags, Decls.size()));150    // If already exists, update the flags.151    if (!It.second)152      It.first->second.first |= Flags;153  }154 155public:156  TargetFinder(const HeuristicResolver *Resolver) : Resolver(Resolver) {}157 158  llvm::SmallVector<std::pair<const NamedDecl *, RelSet>, 1> takeDecls() const {159    using ValTy = std::pair<const NamedDecl *, RelSet>;160    llvm::SmallVector<ValTy, 1> Result;161    Result.resize(Decls.size());162    for (const auto &Elem : Decls)163      Result[Elem.second.second] = {Elem.first, Elem.second.first};164    return Result;165  }166 167  void add(const Decl *Dcl, RelSet Flags) {168    const NamedDecl *D = llvm::dyn_cast_or_null<NamedDecl>(Dcl);169    if (!D)170      return;171    debug(*D, Flags);172 173    // Avoid recursion (which can arise in the presence of heuristic174    // resolution of dependent names) by exiting early if we have175    // already seen this decl with all flags in Flags.176    auto Res = Seen.try_emplace(D);177    if (!Res.second && Res.first->second.contains(Flags))178      return;179    Res.first->second |= Flags;180 181    if (const UsingDirectiveDecl *UDD = llvm::dyn_cast<UsingDirectiveDecl>(D))182      D = UDD->getNominatedNamespaceAsWritten();183 184    if (const TypedefNameDecl *TND = dyn_cast<TypedefNameDecl>(D)) {185      add(TND->getUnderlyingType(), Flags | Rel::Underlying);186      Flags |= Rel::Alias; // continue with the alias.187    } else if (const UsingDecl *UD = dyn_cast<UsingDecl>(D)) {188      // no Underlying as this is a non-renaming alias.189      for (const UsingShadowDecl *S : UD->shadows())190        add(S->getUnderlyingDecl(), Flags);191      Flags |= Rel::Alias; // continue with the alias.192    } else if (const UsingEnumDecl *UED = dyn_cast<UsingEnumDecl>(D)) {193      // UsingEnumDecl is not an alias at all, just a reference.194      D = UED->getEnumDecl();195    } else if (const auto *NAD = dyn_cast<NamespaceAliasDecl>(D)) {196      add(NAD->getUnderlyingDecl(), Flags | Rel::Underlying);197      Flags |= Rel::Alias; // continue with the alias198    } else if (const UnresolvedUsingValueDecl *UUVD =199                   dyn_cast<UnresolvedUsingValueDecl>(D)) {200      if (Resolver) {201        for (const NamedDecl *Target : Resolver->resolveUsingValueDecl(UUVD)) {202          add(Target, Flags); // no Underlying as this is a non-renaming alias203        }204      }205      Flags |= Rel::Alias; // continue with the alias206    } else if (isa<UnresolvedUsingTypenameDecl>(D)) {207      // FIXME: improve common dependent scope using name lookup in primary208      // templates.209      Flags |= Rel::Alias;210    } else if (const UsingShadowDecl *USD = dyn_cast<UsingShadowDecl>(D)) {211      // Include the introducing UsingDecl, but don't traverse it. This may end212      // up including *all* shadows, which we don't want.213      // Don't apply this logic to UsingEnumDecl, which can't easily be214      // conflated with the aliases it introduces.215      if (llvm::isa<UsingDecl>(USD->getIntroducer()))216        report(USD->getIntroducer(), Flags | Rel::Alias);217      // Shadow decls are synthetic and not themselves interesting.218      // Record the underlying decl instead, if allowed.219      D = USD->getTargetDecl();220    } else if (const auto *DG = dyn_cast<CXXDeductionGuideDecl>(D)) {221      D = DG->getDeducedTemplate();222    } else if (const ObjCImplementationDecl *IID =223                   dyn_cast<ObjCImplementationDecl>(D)) {224      // Treat ObjC{Interface,Implementation}Decl as if they were a decl/def225      // pair as long as the interface isn't implicit.226      if (const auto *CID = IID->getClassInterface())227        if (const auto *DD = CID->getDefinition())228          if (!DD->isImplicitInterfaceDecl())229            D = DD;230    } else if (const ObjCCategoryImplDecl *CID =231                   dyn_cast<ObjCCategoryImplDecl>(D)) {232      // Treat ObjC{Category,CategoryImpl}Decl as if they were a decl/def pair.233      D = CID->getCategoryDecl();234    }235    if (!D)236      return;237 238    if (const Decl *Pat = getTemplatePattern(D)) {239      assert(Pat != D);240      add(Pat, Flags | Rel::TemplatePattern);241      // Now continue with the instantiation.242      Flags |= Rel::TemplateInstantiation;243    }244 245    report(D, Flags);246  }247 248  void add(const Stmt *S, RelSet Flags) {249    if (!S)250      return;251    debug(*S, Flags);252    struct Visitor : public ConstStmtVisitor<Visitor> {253      TargetFinder &Outer;254      RelSet Flags;255      Visitor(TargetFinder &Outer, RelSet Flags) : Outer(Outer), Flags(Flags) {}256 257      void VisitCallExpr(const CallExpr *CE) {258        Outer.add(CE->getCalleeDecl(), Flags);259      }260      void VisitConceptSpecializationExpr(const ConceptSpecializationExpr *E) {261        Outer.add(E->getConceptReference(), Flags);262      }263      void VisitDeclRefExpr(const DeclRefExpr *DRE) {264        const Decl *D = DRE->getDecl();265        // UsingShadowDecl allows us to record the UsingDecl.266        // getFoundDecl() returns the wrong thing in other cases (templates).267        if (auto *USD = llvm::dyn_cast<UsingShadowDecl>(DRE->getFoundDecl()))268          D = USD;269        Outer.add(D, Flags);270      }271      void VisitMemberExpr(const MemberExpr *ME) {272        const Decl *D = ME->getMemberDecl();273        if (auto *USD =274                llvm::dyn_cast<UsingShadowDecl>(ME->getFoundDecl().getDecl()))275          D = USD;276        Outer.add(D, Flags);277      }278      void VisitOverloadExpr(const OverloadExpr *OE) {279        for (auto *D : OE->decls())280          Outer.add(D, Flags);281      }282      void VisitSizeOfPackExpr(const SizeOfPackExpr *SE) {283        Outer.add(SE->getPack(), Flags);284      }285      void VisitCXXConstructExpr(const CXXConstructExpr *CCE) {286        Outer.add(CCE->getConstructor(), Flags);287      }288      void VisitDesignatedInitExpr(const DesignatedInitExpr *DIE) {289        for (const DesignatedInitExpr::Designator &D :290             llvm::reverse(DIE->designators()))291          if (D.isFieldDesignator()) {292            Outer.add(D.getFieldDecl(), Flags);293            // We don't know which designator was intended, we assume the outer.294            break;295          }296      }297      void VisitGotoStmt(const GotoStmt *Goto) {298        if (auto *LabelDecl = Goto->getLabel())299          Outer.add(LabelDecl, Flags);300      }301      void VisitLabelStmt(const LabelStmt *Label) {302        if (auto *LabelDecl = Label->getDecl())303          Outer.add(LabelDecl, Flags);304      }305      void306      VisitCXXDependentScopeMemberExpr(const CXXDependentScopeMemberExpr *E) {307        if (Outer.Resolver) {308          for (const NamedDecl *D : Outer.Resolver->resolveMemberExpr(E)) {309            Outer.add(D, Flags);310          }311        }312      }313      void VisitDependentScopeDeclRefExpr(const DependentScopeDeclRefExpr *E) {314        if (Outer.Resolver) {315          for (const NamedDecl *D : Outer.Resolver->resolveDeclRefExpr(E)) {316            Outer.add(D, Flags);317          }318        }319      }320      void VisitObjCIvarRefExpr(const ObjCIvarRefExpr *OIRE) {321        Outer.add(OIRE->getDecl(), Flags);322      }323      void VisitObjCMessageExpr(const ObjCMessageExpr *OME) {324        Outer.add(OME->getMethodDecl(), Flags);325      }326      void VisitObjCPropertyRefExpr(const ObjCPropertyRefExpr *OPRE) {327        if (OPRE->isExplicitProperty())328          Outer.add(OPRE->getExplicitProperty(), Flags);329        else {330          if (OPRE->isMessagingGetter())331            Outer.add(OPRE->getImplicitPropertyGetter(), Flags);332          if (OPRE->isMessagingSetter())333            Outer.add(OPRE->getImplicitPropertySetter(), Flags);334        }335      }336      void VisitObjCProtocolExpr(const ObjCProtocolExpr *OPE) {337        Outer.add(OPE->getProtocol(), Flags);338      }339      void VisitOpaqueValueExpr(const OpaqueValueExpr *OVE) {340        Outer.add(OVE->getSourceExpr(), Flags);341      }342      void VisitPseudoObjectExpr(const PseudoObjectExpr *POE) {343        Outer.add(POE->getSyntacticForm(), Flags);344      }345      void VisitCXXNewExpr(const CXXNewExpr *CNE) {346        Outer.add(CNE->getOperatorNew(), Flags);347      }348      void VisitCXXDeleteExpr(const CXXDeleteExpr *CDE) {349        Outer.add(CDE->getOperatorDelete(), Flags);350      }351      void352      VisitCXXRewrittenBinaryOperator(const CXXRewrittenBinaryOperator *RBO) {353        Outer.add(RBO->getDecomposedForm().InnerBinOp, Flags);354      }355    };356    Visitor(*this, Flags).Visit(S);357  }358 359  void add(QualType T, RelSet Flags) {360    if (T.isNull())361      return;362    debug(T, Flags);363    struct Visitor : public TypeVisitor<Visitor> {364      TargetFinder &Outer;365      RelSet Flags;366      Visitor(TargetFinder &Outer, RelSet Flags) : Outer(Outer), Flags(Flags) {}367 368      void VisitTagType(const TagType *TT) {369        Outer.add(cast<TagType>(TT)->getDecl(), Flags);370      }371 372      void VisitUsingType(const UsingType *ET) {373        Outer.add(ET->getDecl(), Flags);374      }375 376      void VisitDecltypeType(const DecltypeType *DTT) {377        Outer.add(DTT->getUnderlyingType(), Flags | Rel::Underlying);378      }379      void VisitDeducedType(const DeducedType *DT) {380        // FIXME: In practice this doesn't work: the AutoType you find inside381        // TypeLoc never has a deduced type. https://llvm.org/PR42914382        Outer.add(DT->getDeducedType(), Flags);383      }384      void VisitUnresolvedUsingType(const UnresolvedUsingType *UUT) {385        Outer.add(UUT->getDecl(), Flags);386      }387      void VisitDeducedTemplateSpecializationType(388          const DeducedTemplateSpecializationType *DTST) {389        if (const auto *USD = DTST->getTemplateName().getAsUsingShadowDecl())390          Outer.add(USD, Flags);391 392        // FIXME: This is a workaround for https://llvm.org/PR42914,393        // which is causing DTST->getDeducedType() to be empty. We394        // fall back to the template pattern and miss the instantiation395        // even when it's known in principle. Once that bug is fixed,396        // the following code can be removed (the existing handling in397        // VisitDeducedType() is sufficient).398        if (auto *TD = DTST->getTemplateName().getAsTemplateDecl())399          Outer.add(TD->getTemplatedDecl(), Flags | Rel::TemplatePattern);400      }401      void VisitDependentNameType(const DependentNameType *DNT) {402        if (Outer.Resolver) {403          for (const NamedDecl *ND :404               Outer.Resolver->resolveDependentNameType(DNT)) {405            Outer.add(ND, Flags);406          }407        }408      }409      void VisitTypedefType(const TypedefType *TT) {410        if (shouldSkipTypedef(TT->getDecl()))411          return;412        Outer.add(TT->getDecl(), Flags);413      }414      void415      VisitTemplateSpecializationType(const TemplateSpecializationType *TST) {416        // Have to handle these case-by-case.417 418        if (const auto *UTN = TST->getTemplateName().getAsUsingShadowDecl())419          Outer.add(UTN, Flags);420 421        // templated type aliases: there's no specialized/instantiated using422        // decl to point to. So try to find a decl for the underlying type423        // (after substitution), and failing that point to the (templated) using424        // decl.425        if (TST->isTypeAlias()) {426          Outer.add(TST->getAliasedType(), Flags | Rel::Underlying);427          // Don't *traverse* the alias, which would result in traversing the428          // template of the underlying type.429 430          TemplateDecl *TD = TST->getTemplateName().getAsTemplateDecl();431          // Builtin templates e.g. __make_integer_seq, __type_pack_element432          // are such that they don't have alias *decls*. Even then, we still433          // traverse their desugared *types* so that instantiated decls are434          // collected.435          if (llvm::isa<BuiltinTemplateDecl>(TD))436            return;437          Outer.report(TD->getTemplatedDecl(),438                       Flags | Rel::Alias | Rel::TemplatePattern);439        }440        // specializations of template template parameters aren't instantiated441        // into decls, so they must refer to the parameter itself.442        else if (const auto *Parm =443                     llvm::dyn_cast_or_null<TemplateTemplateParmDecl>(444                         TST->getTemplateName().getAsTemplateDecl()))445          Outer.add(Parm, Flags);446        // class template specializations have a (specialized) CXXRecordDecl.447        else if (const CXXRecordDecl *RD = TST->getAsCXXRecordDecl())448          Outer.add(RD, Flags); // add(Decl) will despecialize if needed.449        else if (auto *TD = TST->getTemplateName().getAsTemplateDecl())450          // fallback: the (un-specialized) declaration from primary template.451          Outer.add(TD->getTemplatedDecl(), Flags | Rel::TemplatePattern);452        else if (Outer.Resolver)453          for (const NamedDecl *ND :454               Outer.Resolver->resolveTemplateSpecializationType(TST))455            Outer.add(ND, Flags);456      }457      void458      VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType *STTPT) {459        Outer.add(STTPT->getReplacementType(), Flags);460      }461      void VisitTemplateTypeParmType(const TemplateTypeParmType *TTPT) {462        Outer.add(TTPT->getDecl(), Flags);463      }464      void VisitObjCInterfaceType(const ObjCInterfaceType *OIT) {465        Outer.add(OIT->getDecl(), Flags);466      }467    };468    Visitor(*this, Flags).Visit(T.getTypePtr());469  }470 471  void add(NestedNameSpecifier NNS, RelSet Flags) {472    if (!NNS)473      return;474    debug(NNS, Flags);475    switch (NNS.getKind()) {476    case NestedNameSpecifier::Kind::Namespace:477      add(NNS.getAsNamespaceAndPrefix().Namespace, Flags);478      return;479    case NestedNameSpecifier::Kind::Type:480      add(QualType(NNS.getAsType(), 0), Flags);481      return;482    case NestedNameSpecifier::Kind::Global:483      // This should be TUDecl, but we can't get a pointer to it!484      return;485    case NestedNameSpecifier::Kind::MicrosoftSuper:486      add(NNS.getAsMicrosoftSuper(), Flags);487      return;488    case NestedNameSpecifier::Kind::Null:489      llvm_unreachable("unexpected null nested name specifier");490    }491    llvm_unreachable("unhandled NestedNameSpecifier::Kind");492  }493 494  void add(const CXXCtorInitializer *CCI, RelSet Flags) {495    if (!CCI)496      return;497    debug(*CCI, Flags);498 499    if (CCI->isAnyMemberInitializer())500      add(CCI->getAnyMember(), Flags);501    // Constructor calls contain a TypeLoc node, so we don't handle them here.502  }503 504  void add(const TemplateArgument &Arg, RelSet Flags) {505    // Only used for template template arguments.506    // For type and non-type template arguments, SelectionTree507    // will hit a more specific node (e.g. a TypeLoc or a508    // DeclRefExpr).509    if (Arg.getKind() == TemplateArgument::Template ||510        Arg.getKind() == TemplateArgument::TemplateExpansion) {511      if (TemplateDecl *TD =512              Arg.getAsTemplateOrTemplatePattern().getAsTemplateDecl()) {513        report(TD, Flags);514      }515      if (const auto *USD =516              Arg.getAsTemplateOrTemplatePattern().getAsUsingShadowDecl())517        add(USD, Flags);518    }519  }520 521  void add(const ConceptReference *CR, RelSet Flags) {522    add(CR->getNamedConcept(), Flags);523  }524};525 526} // namespace527 528llvm::SmallVector<std::pair<const NamedDecl *, DeclRelationSet>, 1>529allTargetDecls(const DynTypedNode &N, const HeuristicResolver *Resolver) {530  dlog("allTargetDecls({0})", nodeToString(N));531  TargetFinder Finder(Resolver);532  DeclRelationSet Flags;533  if (const Decl *D = N.get<Decl>())534    Finder.add(D, Flags);535  else if (const Stmt *S = N.get<Stmt>())536    Finder.add(S, Flags);537  else if (const NestedNameSpecifierLoc *NNSL = N.get<NestedNameSpecifierLoc>())538    Finder.add(NNSL->getNestedNameSpecifier(), Flags);539  else if (const NestedNameSpecifier *NNS = N.get<NestedNameSpecifier>())540    Finder.add(*NNS, Flags);541  else if (const TypeLoc *TL = N.get<TypeLoc>())542    Finder.add(TL->getType(), Flags);543  else if (const QualType *QT = N.get<QualType>())544    Finder.add(*QT, Flags);545  else if (const CXXCtorInitializer *CCI = N.get<CXXCtorInitializer>())546    Finder.add(CCI, Flags);547  else if (const TemplateArgumentLoc *TAL = N.get<TemplateArgumentLoc>())548    Finder.add(TAL->getArgument(), Flags);549  else if (const CXXBaseSpecifier *CBS = N.get<CXXBaseSpecifier>())550    Finder.add(CBS->getTypeSourceInfo()->getType(), Flags);551  else if (const ObjCProtocolLoc *PL = N.get<ObjCProtocolLoc>())552    Finder.add(PL->getProtocol(), Flags);553  else if (const ConceptReference *CR = N.get<ConceptReference>())554    Finder.add(CR, Flags);555  return Finder.takeDecls();556}557 558llvm::SmallVector<const NamedDecl *, 1>559targetDecl(const DynTypedNode &N, DeclRelationSet Mask,560           const HeuristicResolver *Resolver) {561  llvm::SmallVector<const NamedDecl *, 1> Result;562  for (const auto &Entry : allTargetDecls(N, Resolver)) {563    if (!(Entry.second & ~Mask))564      Result.push_back(Entry.first);565  }566  return Result;567}568 569llvm::SmallVector<const NamedDecl *, 1>570explicitReferenceTargets(DynTypedNode N, DeclRelationSet Mask,571                         const HeuristicResolver *Resolver) {572  assert(!(Mask & (DeclRelation::TemplatePattern |573                   DeclRelation::TemplateInstantiation)) &&574         "explicitReferenceTargets handles templates on its own");575  auto Decls = allTargetDecls(N, Resolver);576 577  // We prefer to return template instantiation, but fallback to template578  // pattern if instantiation is not available.579  Mask |= DeclRelation::TemplatePattern | DeclRelation::TemplateInstantiation;580 581  llvm::SmallVector<const NamedDecl *, 1> TemplatePatterns;582  llvm::SmallVector<const NamedDecl *, 1> Targets;583  bool SeenTemplateInstantiations = false;584  for (auto &D : Decls) {585    if (D.second & ~Mask)586      continue;587    if (D.second & DeclRelation::TemplatePattern) {588      TemplatePatterns.push_back(D.first);589      continue;590    }591    if (D.second & DeclRelation::TemplateInstantiation)592      SeenTemplateInstantiations = true;593    Targets.push_back(D.first);594  }595  if (!SeenTemplateInstantiations)596    Targets.insert(Targets.end(), TemplatePatterns.begin(),597                   TemplatePatterns.end());598  return Targets;599}600 601namespace {602llvm::SmallVector<ReferenceLoc> refInDecl(const Decl *D,603                                          const HeuristicResolver *Resolver) {604  struct Visitor : ConstDeclVisitor<Visitor> {605    Visitor(const HeuristicResolver *Resolver) : Resolver(Resolver) {}606 607    const HeuristicResolver *Resolver;608    llvm::SmallVector<ReferenceLoc> Refs;609 610    void VisitUsingDirectiveDecl(const UsingDirectiveDecl *D) {611      // We want to keep it as non-declaration references, as the612      // "using namespace" declaration doesn't have a name.613      Refs.push_back(ReferenceLoc{D->getQualifierLoc(),614                                  D->getIdentLocation(),615                                  /*IsDecl=*/false,616                                  {D->getNominatedNamespaceAsWritten()}});617    }618 619    void VisitUsingDecl(const UsingDecl *D) {620      // "using ns::identifier;" is a non-declaration reference.621      Refs.push_back(ReferenceLoc{622          D->getQualifierLoc(), D->getLocation(), /*IsDecl=*/false,623          explicitReferenceTargets(DynTypedNode::create(*D),624                                   DeclRelation::Underlying, Resolver)});625    }626 627    void VisitUsingEnumDecl(const UsingEnumDecl *D) {628      // "using enum ns::E" is a non-declaration reference.629      // The reference is covered by the embedded typeloc.630      // Don't use the default VisitNamedDecl, which would report a declaration.631    }632 633    void VisitNamespaceAliasDecl(const NamespaceAliasDecl *D) {634      // For namespace alias, "namespace Foo = Target;", we add two references.635      // Add a declaration reference for Foo.636      VisitNamedDecl(D);637      // Add a non-declaration reference for Target.638      Refs.push_back(ReferenceLoc{D->getQualifierLoc(),639                                  D->getTargetNameLoc(),640                                  /*IsDecl=*/false,641                                  {D->getAliasedNamespace()}});642    }643 644    void VisitNamedDecl(const NamedDecl *ND) {645      // We choose to ignore {Class, Function, Var, TypeAlias}TemplateDecls. As646      // as their underlying decls, covering the same range, will be visited.647      if (llvm::isa<ClassTemplateDecl>(ND) ||648          llvm::isa<FunctionTemplateDecl>(ND) ||649          llvm::isa<VarTemplateDecl>(ND) ||650          llvm::isa<TypeAliasTemplateDecl>(ND))651        return;652      // FIXME: decide on how to surface destructors when we need them.653      if (llvm::isa<CXXDestructorDecl>(ND))654        return;655      // Filter anonymous decls, name location will point outside the name token656      // and the clients are not prepared to handle that.657      if (ND->getDeclName().isIdentifier() &&658          !ND->getDeclName().getAsIdentifierInfo())659        return;660      Refs.push_back(ReferenceLoc{getQualifierLoc(*ND),661                                  ND->getLocation(),662                                  /*IsDecl=*/true,663                                  {ND}});664    }665 666    void VisitCXXDeductionGuideDecl(const CXXDeductionGuideDecl *DG) {667      // The class template name in a deduction guide targets the class668      // template.669      Refs.push_back(ReferenceLoc{DG->getQualifierLoc(),670                                  DG->getNameInfo().getLoc(),671                                  /*IsDecl=*/false,672                                  {DG->getDeducedTemplate()}});673    }674 675    void VisitObjCMethodDecl(const ObjCMethodDecl *OMD) {676      // The name may have several tokens, we can only report the first.677      Refs.push_back(ReferenceLoc{NestedNameSpecifierLoc(),678                                  OMD->getSelectorStartLoc(),679                                  /*IsDecl=*/true,680                                  {OMD}});681    }682 683    void VisitObjCCategoryDecl(const ObjCCategoryDecl *OCD) {684      // getLocation is the extended class's location, not the category's.685      Refs.push_back(ReferenceLoc{NestedNameSpecifierLoc(),686                                  OCD->getLocation(),687                                  /*IsDecl=*/false,688                                  {OCD->getClassInterface()}});689      Refs.push_back(ReferenceLoc{NestedNameSpecifierLoc(),690                                  OCD->getCategoryNameLoc(),691                                  /*IsDecl=*/true,692                                  {OCD}});693    }694 695    void VisitObjCCategoryImplDecl(const ObjCCategoryImplDecl *OCID) {696      Refs.push_back(ReferenceLoc{NestedNameSpecifierLoc(),697                                  OCID->getLocation(),698                                  /*IsDecl=*/false,699                                  {OCID->getClassInterface()}});700      Refs.push_back(ReferenceLoc{NestedNameSpecifierLoc(),701                                  OCID->getCategoryNameLoc(),702                                  /*IsDecl=*/false,703                                  {OCID->getCategoryDecl()}});704      Refs.push_back(ReferenceLoc{NestedNameSpecifierLoc(),705                                  OCID->getCategoryNameLoc(),706                                  /*IsDecl=*/true,707                                  {OCID}});708    }709 710    void VisitObjCImplementationDecl(const ObjCImplementationDecl *OIMD) {711      Refs.push_back(ReferenceLoc{NestedNameSpecifierLoc(),712                                  OIMD->getLocation(),713                                  /*IsDecl=*/false,714                                  {OIMD->getClassInterface()}});715      Refs.push_back(ReferenceLoc{NestedNameSpecifierLoc(),716                                  OIMD->getLocation(),717                                  /*IsDecl=*/true,718                                  {OIMD}});719    }720  };721 722  Visitor V{Resolver};723  V.Visit(D);724  return V.Refs;725}726 727llvm::SmallVector<ReferenceLoc> refInStmt(const Stmt *S,728                                          const HeuristicResolver *Resolver) {729  struct Visitor : ConstStmtVisitor<Visitor> {730    Visitor(const HeuristicResolver *Resolver) : Resolver(Resolver) {}731 732    const HeuristicResolver *Resolver;733    // FIXME: handle more complicated cases: more ObjC, designated initializers.734    llvm::SmallVector<ReferenceLoc> Refs;735 736    void VisitDeclRefExpr(const DeclRefExpr *E) {737      Refs.push_back(ReferenceLoc{E->getQualifierLoc(),738                                  E->getNameInfo().getLoc(),739                                  /*IsDecl=*/false,740                                  {E->getFoundDecl()}});741    }742 743    void VisitDependentScopeDeclRefExpr(const DependentScopeDeclRefExpr *E) {744      Refs.push_back(ReferenceLoc{745          E->getQualifierLoc(), E->getNameInfo().getLoc(), /*IsDecl=*/false,746          explicitReferenceTargets(DynTypedNode::create(*E), {}, Resolver)});747    }748 749    void VisitMemberExpr(const MemberExpr *E) {750      // Skip destructor calls to avoid duplication: TypeLoc within will be751      // visited separately.752      if (llvm::isa<CXXDestructorDecl>(E->getFoundDecl().getDecl()))753        return;754      Refs.push_back(ReferenceLoc{E->getQualifierLoc(),755                                  E->getMemberNameInfo().getLoc(),756                                  /*IsDecl=*/false,757                                  {E->getFoundDecl()}});758    }759 760    void761    VisitCXXDependentScopeMemberExpr(const CXXDependentScopeMemberExpr *E) {762      Refs.push_back(ReferenceLoc{763          E->getQualifierLoc(), E->getMemberNameInfo().getLoc(),764          /*IsDecl=*/false,765          explicitReferenceTargets(DynTypedNode::create(*E), {}, Resolver)});766    }767 768    void VisitOverloadExpr(const OverloadExpr *E) {769      Refs.push_back(ReferenceLoc{E->getQualifierLoc(),770                                  E->getNameInfo().getLoc(),771                                  /*IsDecl=*/false,772                                  llvm::SmallVector<const NamedDecl *, 1>(773                                      E->decls().begin(), E->decls().end())});774    }775 776    void VisitSizeOfPackExpr(const SizeOfPackExpr *E) {777      Refs.push_back(ReferenceLoc{NestedNameSpecifierLoc(),778                                  E->getPackLoc(),779                                  /*IsDecl=*/false,780                                  {E->getPack()}});781    }782 783    void VisitObjCPropertyRefExpr(const ObjCPropertyRefExpr *E) {784      Refs.push_back(ReferenceLoc{785          NestedNameSpecifierLoc(), E->getLocation(),786          /*IsDecl=*/false,787          // Select the getter, setter, or @property depending on the call.788          explicitReferenceTargets(DynTypedNode::create(*E), {}, Resolver)});789    }790 791    void VisitObjCIvarRefExpr(const ObjCIvarRefExpr *OIRE) {792      Refs.push_back(ReferenceLoc{NestedNameSpecifierLoc(),793                                  OIRE->getLocation(),794                                  /*IsDecl=*/false,795                                  {OIRE->getDecl()}});796    }797 798    void VisitObjCMessageExpr(const ObjCMessageExpr *E) {799      // The name may have several tokens, we can only report the first.800      Refs.push_back(ReferenceLoc{NestedNameSpecifierLoc(),801                                  E->getSelectorStartLoc(),802                                  /*IsDecl=*/false,803                                  {E->getMethodDecl()}});804    }805 806    void VisitDesignatedInitExpr(const DesignatedInitExpr *DIE) {807      for (const DesignatedInitExpr::Designator &D : DIE->designators()) {808        if (!D.isFieldDesignator())809          continue;810 811        Refs.push_back(ReferenceLoc{NestedNameSpecifierLoc(),812                                    D.getFieldLoc(),813                                    /*IsDecl=*/false,814                                    {D.getFieldDecl()}});815      }816    }817 818    void VisitGotoStmt(const GotoStmt *GS) {819      Refs.push_back(ReferenceLoc{NestedNameSpecifierLoc(),820                                  GS->getLabelLoc(),821                                  /*IsDecl=*/false,822                                  {GS->getLabel()}});823    }824 825    void VisitLabelStmt(const LabelStmt *LS) {826      Refs.push_back(ReferenceLoc{NestedNameSpecifierLoc(),827                                  LS->getIdentLoc(),828                                  /*IsDecl=*/true,829                                  {LS->getDecl()}});830    }831  };832 833  Visitor V{Resolver};834  V.Visit(S);835  return V.Refs;836}837 838llvm::SmallVector<ReferenceLoc>839refInTypeLoc(TypeLoc L, const HeuristicResolver *Resolver) {840  struct Visitor : TypeLocVisitor<Visitor> {841    Visitor(const HeuristicResolver *Resolver) : Resolver(Resolver) {}842 843    const HeuristicResolver *Resolver;844    llvm::SmallVector<ReferenceLoc> Refs;845 846    void VisitUnresolvedUsingTypeLoc(UnresolvedUsingTypeLoc L) {847      Refs.push_back(ReferenceLoc{L.getQualifierLoc(),848                                  L.getLocalSourceRange().getBegin(),849                                  /*IsDecl=*/false,850                                  {L.getDecl()}});851    }852 853    void VisitUsingTypeLoc(UsingTypeLoc L) {854      Refs.push_back(ReferenceLoc{L.getQualifierLoc(),855                                  L.getLocalSourceRange().getBegin(),856                                  /*IsDecl=*/false,857                                  {L.getDecl()}});858    }859 860    void VisitTagTypeLoc(TagTypeLoc L) {861      Refs.push_back(ReferenceLoc{L.getQualifierLoc(),862                                  L.getNameLoc(),863                                  /*IsDecl=*/false,864                                  {L.getDecl()}});865    }866 867    void VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc L) {868      Refs.push_back(ReferenceLoc{NestedNameSpecifierLoc(),869                                  L.getNameLoc(),870                                  /*IsDecl=*/false,871                                  {L.getDecl()}});872    }873 874    void VisitTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc L) {875      // We must ensure template type aliases are included in results if they876      // were written in the source code, e.g. in877      //    template <class T> using valias = vector<T>;878      //    ^valias<int> x;879      // 'explicitReferenceTargets' will return:880      //    1. valias with mask 'Alias'.881      //    2. 'vector<int>' with mask 'Underlying'.882      //  we want to return only #1 in this case.883      Refs.push_back(ReferenceLoc{884          L.getQualifierLoc(), L.getTemplateNameLoc(), /*IsDecl=*/false,885          explicitReferenceTargets(DynTypedNode::create(L.getType()),886                                   DeclRelation::Alias, Resolver)});887    }888    void VisitDeducedTemplateSpecializationTypeLoc(889        DeducedTemplateSpecializationTypeLoc L) {890      Refs.push_back(ReferenceLoc{891          L.getQualifierLoc(), L.getNameLoc(), /*IsDecl=*/false,892          explicitReferenceTargets(DynTypedNode::create(L.getType()),893                                   DeclRelation::Alias, Resolver)});894    }895 896    void VisitDependentNameTypeLoc(DependentNameTypeLoc L) {897      Refs.push_back(898          ReferenceLoc{L.getQualifierLoc(), L.getNameLoc(),899                       /*IsDecl=*/false,900                       explicitReferenceTargets(901                           DynTypedNode::create(L.getType()), {}, Resolver)});902    }903 904    void VisitTypedefTypeLoc(TypedefTypeLoc L) {905      if (shouldSkipTypedef(L.getDecl()))906        return;907      Refs.push_back(ReferenceLoc{L.getQualifierLoc(),908                                  L.getNameLoc(),909                                  /*IsDecl=*/false,910                                  {L.getDecl()}});911    }912 913    void VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc L) {914      Refs.push_back(ReferenceLoc{NestedNameSpecifierLoc(),915                                  L.getNameLoc(),916                                  /*IsDecl=*/false,917                                  {L.getIFaceDecl()}});918    }919  };920 921  Visitor V{Resolver};922  V.Visit(L.getUnqualifiedLoc());923  return V.Refs;924}925 926class ExplicitReferenceCollector927    : public RecursiveASTVisitor<ExplicitReferenceCollector> {928public:929  ExplicitReferenceCollector(llvm::function_ref<void(ReferenceLoc)> Out,930                             const HeuristicResolver *Resolver)931      : Out(Out), Resolver(Resolver) {932    assert(Out);933  }934 935  bool VisitTypeLoc(TypeLoc TTL) {936    if (TypeLocsToSkip.count(TTL.getBeginLoc()))937      return true;938    visitNode(DynTypedNode::create(TTL));939    return true;940  }941 942  bool VisitStmt(Stmt *S) {943    visitNode(DynTypedNode::create(*S));944    return true;945  }946 947  bool TraverseOpaqueValueExpr(OpaqueValueExpr *OVE) {948    visitNode(DynTypedNode::create(*OVE));949    // Not clear why the source expression is skipped by default...950    // FIXME: can we just make RecursiveASTVisitor do this?951    return RecursiveASTVisitor::TraverseStmt(OVE->getSourceExpr());952  }953 954  bool TraversePseudoObjectExpr(PseudoObjectExpr *POE) {955    visitNode(DynTypedNode::create(*POE));956    // Traverse only the syntactic form to find the *written* references.957    // (The semantic form also contains lots of duplication)958    return RecursiveASTVisitor::TraverseStmt(POE->getSyntacticForm());959  }960 961  // We re-define Traverse*, since there's no corresponding Visit*.962  // TemplateArgumentLoc is the only way to get locations for references to963  // template template parameters.964  bool TraverseTemplateArgumentLoc(TemplateArgumentLoc A) {965    switch (A.getArgument().getKind()) {966    case TemplateArgument::Template:967    case TemplateArgument::TemplateExpansion:968      reportReference(ReferenceLoc{A.getTemplateQualifierLoc(),969                                   A.getTemplateNameLoc(),970                                   /*IsDecl=*/false,971                                   {A.getArgument()972                                        .getAsTemplateOrTemplatePattern()973                                        .getAsTemplateDecl()}},974                      DynTypedNode::create(A.getArgument()));975      break;976    case TemplateArgument::Declaration:977      break; // FIXME: can this actually happen in TemplateArgumentLoc?978    case TemplateArgument::Integral:979    case TemplateArgument::Null:980    case TemplateArgument::NullPtr:981      break; // no references.982    case TemplateArgument::Pack:983    case TemplateArgument::Type:984    case TemplateArgument::Expression:985    case TemplateArgument::StructuralValue:986      break; // Handled by VisitType and VisitExpression.987    };988    return RecursiveASTVisitor::TraverseTemplateArgumentLoc(A);989  }990 991  bool VisitDecl(Decl *D) {992    visitNode(DynTypedNode::create(*D));993    return true;994  }995 996  // We have to use Traverse* because there is no corresponding Visit*.997  bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc L) {998    if (!L.getNestedNameSpecifier())999      return true;1000    visitNode(DynTypedNode::create(L));1001    // Inner type is missing information about its qualifier, skip it.1002    if (auto TL = L.getAsTypeLoc())1003      TypeLocsToSkip.insert(TL.getBeginLoc());1004    return RecursiveASTVisitor::TraverseNestedNameSpecifierLoc(L);1005  }1006 1007  bool TraverseObjCProtocolLoc(ObjCProtocolLoc ProtocolLoc) {1008    visitNode(DynTypedNode::create(ProtocolLoc));1009    return true;1010  }1011 1012  bool TraverseConstructorInitializer(CXXCtorInitializer *Init) {1013    visitNode(DynTypedNode::create(*Init));1014    return RecursiveASTVisitor::TraverseConstructorInitializer(Init);1015  }1016 1017  bool VisitConceptReference(const ConceptReference *CR) {1018    visitNode(DynTypedNode::create(*CR));1019    return true;1020  }1021 1022private:1023  /// Obtain information about a reference directly defined in \p N. Does not1024  /// recurse into child nodes, e.g. do not expect references for constructor1025  /// initializers1026  ///1027  /// Any of the fields in the returned structure can be empty, but not all of1028  /// them, e.g.1029  ///   - for implicitly generated nodes (e.g. MemberExpr from range-based-for),1030  ///     source location information may be missing,1031  ///   - for dependent code, targets may be empty.1032  ///1033  /// (!) For the purposes of this function declarations are not considered to1034  ///     be references. However, declarations can have references inside them,1035  ///     e.g. 'namespace foo = std' references namespace 'std' and this1036  ///     function will return the corresponding reference.1037  llvm::SmallVector<ReferenceLoc> explicitReference(DynTypedNode N) {1038    if (auto *D = N.get<Decl>())1039      return refInDecl(D, Resolver);1040    if (auto *S = N.get<Stmt>())1041      return refInStmt(S, Resolver);1042    if (auto *NNSL = N.get<NestedNameSpecifierLoc>()) {1043      if (TypeLoc TL = NNSL->getAsTypeLoc())1044        return refInTypeLoc(TL, Resolver);1045      // (!) 'DeclRelation::Alias' ensures we do not lose namespace aliases.1046      NestedNameSpecifierLoc Qualifier = NNSL->getAsNamespaceAndPrefix().Prefix;1047      SourceLocation NameLoc = NNSL->getLocalBeginLoc();1048      return {1049          ReferenceLoc{Qualifier, NameLoc, false,1050                       explicitReferenceTargets(1051                           DynTypedNode::create(NNSL->getNestedNameSpecifier()),1052                           DeclRelation::Alias, Resolver)}};1053    }1054    if (const TypeLoc *TL = N.get<TypeLoc>())1055      return refInTypeLoc(*TL, Resolver);1056    if (const CXXCtorInitializer *CCI = N.get<CXXCtorInitializer>()) {1057      // Other type initializers (e.g. base initializer) are handled by visiting1058      // the typeLoc.1059      if (CCI->isAnyMemberInitializer()) {1060        return {ReferenceLoc{NestedNameSpecifierLoc(),1061                             CCI->getMemberLocation(),1062                             /*IsDecl=*/false,1063                             {CCI->getAnyMember()}}};1064      }1065    }1066    if (const ObjCProtocolLoc *PL = N.get<ObjCProtocolLoc>())1067      return {ReferenceLoc{NestedNameSpecifierLoc(),1068                           PL->getLocation(),1069                           /*IsDecl=*/false,1070                           {PL->getProtocol()}}};1071    if (const ConceptReference *CR = N.get<ConceptReference>())1072      return {ReferenceLoc{CR->getNestedNameSpecifierLoc(),1073                           CR->getConceptNameLoc(),1074                           /*IsDecl=*/false,1075                           {CR->getNamedConcept()}}};1076 1077    // We do not have location information for other nodes (QualType, etc)1078    return {};1079  }1080 1081  void visitNode(DynTypedNode N) {1082    for (auto &R : explicitReference(N))1083      reportReference(std::move(R), N);1084  }1085 1086  void reportReference(ReferenceLoc &&Ref, DynTypedNode N) {1087    // Strip null targets that can arise from invalid code.1088    // (This avoids having to check for null everywhere we insert)1089    llvm::erase(Ref.Targets, nullptr);1090    // Our promise is to return only references from the source code. If we lack1091    // location information, skip these nodes.1092    // Normally this should not happen in practice, unless there are bugs in the1093    // traversals or users started the traversal at an implicit node.1094    if (Ref.NameLoc.isInvalid()) {1095      dlog("invalid location at node {0}", nodeToString(N));1096      return;1097    }1098    Out(Ref);1099  }1100 1101  llvm::function_ref<void(ReferenceLoc)> Out;1102  const HeuristicResolver *Resolver;1103  /// TypeLocs starting at these locations must be skipped, see1104  /// TraverseElaboratedTypeSpecifierLoc for details.1105  llvm::DenseSet<SourceLocation> TypeLocsToSkip;1106};1107} // namespace1108 1109void findExplicitReferences(const Stmt *S,1110                            llvm::function_ref<void(ReferenceLoc)> Out,1111                            const HeuristicResolver *Resolver) {1112  assert(S);1113  ExplicitReferenceCollector(Out, Resolver).TraverseStmt(const_cast<Stmt *>(S));1114}1115void findExplicitReferences(const Decl *D,1116                            llvm::function_ref<void(ReferenceLoc)> Out,1117                            const HeuristicResolver *Resolver) {1118  assert(D);1119  ExplicitReferenceCollector(Out, Resolver).TraverseDecl(const_cast<Decl *>(D));1120}1121void findExplicitReferences(const ASTContext &AST,1122                            llvm::function_ref<void(ReferenceLoc)> Out,1123                            const HeuristicResolver *Resolver) {1124  ExplicitReferenceCollector(Out, Resolver)1125      .TraverseAST(const_cast<ASTContext &>(AST));1126}1127 1128llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, DeclRelation R) {1129  switch (R) {1130#define REL_CASE(X)                                                            \1131  case DeclRelation::X:                                                        \1132    return OS << #X;1133    REL_CASE(Alias);1134    REL_CASE(Underlying);1135    REL_CASE(TemplateInstantiation);1136    REL_CASE(TemplatePattern);1137#undef REL_CASE1138  }1139  llvm_unreachable("Unhandled DeclRelation enum");1140}1141llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, DeclRelationSet RS) {1142  const char *Sep = "";1143  for (unsigned I = 0; I < RS.S.size(); ++I) {1144    if (RS.S.test(I)) {1145      OS << Sep << static_cast<DeclRelation>(I);1146      Sep = "|";1147    }1148  }1149  return OS;1150}1151 1152llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, ReferenceLoc R) {1153  // note we cannot print R.NameLoc without a source manager.1154  OS << "targets = {";1155  llvm::SmallVector<std::string> Targets;1156  for (const NamedDecl *T : R.Targets) {1157    llvm::raw_string_ostream Target(Targets.emplace_back());1158    Target << printQualifiedName(*T) << printTemplateSpecializationArgs(*T);1159  }1160  llvm::sort(Targets);1161  OS << llvm::join(Targets, ", ");1162  OS << "}";1163  if (R.Qualifier) {1164    OS << ", qualifier = '";1165    R.Qualifier.getNestedNameSpecifier().print(OS,1166                                               PrintingPolicy(LangOptions()));1167    OS << "'";1168  }1169  if (R.IsDecl)1170    OS << ", decl";1171  return OS;1172}1173 1174} // namespace clangd1175} // namespace clang1176