brintos

brintos / llvm-project-archived public Read only

0
0
Text · 41.6 KiB · 08835ea Raw
1284 lines · cpp
1//===- USRGeneration.cpp - Routines for USR generation --------------------===//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 "clang/Index/USRGeneration.h"10#include "clang/AST/ASTContext.h"11#include "clang/AST/Attr.h"12#include "clang/AST/DeclCXX.h"13#include "clang/AST/DeclTemplate.h"14#include "clang/AST/DeclVisitor.h"15#include "clang/AST/ODRHash.h"16#include "clang/Lex/PreprocessingRecord.h"17#include "llvm/Support/Path.h"18#include "llvm/Support/raw_ostream.h"19 20using namespace clang;21using namespace clang::index;22 23//===----------------------------------------------------------------------===//24// USR generation.25//===----------------------------------------------------------------------===//26 27/// \returns true on error.28static bool printLoc(llvm::raw_ostream &OS, SourceLocation Loc,29                     const SourceManager &SM, bool IncludeOffset) {30  if (Loc.isInvalid()) {31    return true;32  }33  Loc = SM.getExpansionLoc(Loc);34  const FileIDAndOffset &Decomposed = SM.getDecomposedLoc(Loc);35  OptionalFileEntryRef FE = SM.getFileEntryRefForID(Decomposed.first);36  if (FE) {37    OS << llvm::sys::path::filename(FE->getName());38  } else {39    // This case really isn't interesting.40    return true;41  }42  if (IncludeOffset) {43    // Use the offest into the FileID to represent the location.  Using44    // a line/column can cause us to look back at the original source file,45    // which is expensive.46    OS << '@' << Decomposed.second;47  }48  return false;49}50 51static StringRef GetExternalSourceContainer(const NamedDecl *D) {52  if (!D)53    return StringRef();54  if (auto *attr = D->getExternalSourceSymbolAttr()) {55    return attr->getDefinedIn();56  }57  return StringRef();58}59 60namespace {61class USRGenerator : public ConstDeclVisitor<USRGenerator> {62  SmallVectorImpl<char> &Buf;63  llvm::raw_svector_ostream Out;64  ASTContext *Context;65  const LangOptions &LangOpts;66  bool IgnoreResults = false;67  bool generatedLoc = false;68 69  llvm::DenseMap<const Type *, unsigned> TypeSubstitutions;70 71public:72  USRGenerator(ASTContext *Ctx, SmallVectorImpl<char> &Buf,73               const LangOptions &LangOpts)74      : Buf(Buf), Out(Buf), Context(Ctx), LangOpts(LangOpts) {75    // Add the USR space prefix.76    Out << getUSRSpacePrefix();77  }78 79  bool ignoreResults() const { return IgnoreResults; }80 81  // Visitation methods from generating USRs from AST elements.82  void VisitDeclContext(const DeclContext *D);83  void VisitFieldDecl(const FieldDecl *D);84  void VisitFunctionDecl(const FunctionDecl *D);85  void VisitNamedDecl(const NamedDecl *D);86  void VisitNamespaceDecl(const NamespaceDecl *D);87  void VisitNamespaceAliasDecl(const NamespaceAliasDecl *D);88  void VisitFunctionTemplateDecl(const FunctionTemplateDecl *D);89  void VisitClassTemplateDecl(const ClassTemplateDecl *D);90  void VisitObjCContainerDecl(const ObjCContainerDecl *CD,91                              const ObjCCategoryDecl *CatD = nullptr);92  void VisitObjCMethodDecl(const ObjCMethodDecl *MD);93  void VisitObjCPropertyDecl(const ObjCPropertyDecl *D);94  void VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D);95  void VisitTagDecl(const TagDecl *D);96  void VisitTypedefDecl(const TypedefDecl *D);97  void VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D);98  void VisitVarDecl(const VarDecl *D);99  void VisitBindingDecl(const BindingDecl *D);100  void VisitNonTypeTemplateParmDecl(const NonTypeTemplateParmDecl *D);101  void VisitTemplateTemplateParmDecl(const TemplateTemplateParmDecl *D);102  void VisitUnresolvedUsingValueDecl(const UnresolvedUsingValueDecl *D);103  void VisitUnresolvedUsingTypenameDecl(const UnresolvedUsingTypenameDecl *D);104  void VisitConceptDecl(const ConceptDecl *D);105 106  void VisitLinkageSpecDecl(const LinkageSpecDecl *D) {107    IgnoreResults = true; // No USRs for linkage specs themselves.108  }109 110  void VisitUsingDirectiveDecl(const UsingDirectiveDecl *D) {111    IgnoreResults = true;112  }113 114  void VisitUsingDecl(const UsingDecl *D) {115    VisitDeclContext(D->getDeclContext());116    Out << "@UD@";117 118    bool EmittedDeclName = !EmitDeclName(D);119    assert(EmittedDeclName && "EmitDeclName can not fail for UsingDecls");120    (void)EmittedDeclName;121  }122 123  bool ShouldGenerateLocation(const NamedDecl *D);124 125  bool isLocal(const NamedDecl *D) {126    return D->getParentFunctionOrMethod() != nullptr;127  }128 129  void GenExtSymbolContainer(const NamedDecl *D);130 131  /// Generate the string component containing the location of the132  ///  declaration.133  bool GenLoc(const Decl *D, bool IncludeOffset);134 135  /// String generation methods used both by the visitation methods136  /// and from other clients that want to directly generate USRs.  These137  /// methods do not construct complete USRs (which incorporate the parents138  /// of an AST element), but only the fragments concerning the AST element139  /// itself.140 141  /// Generate a USR for an Objective-C class.142  void GenObjCClass(StringRef cls, StringRef ExtSymDefinedIn,143                    StringRef CategoryContextExtSymbolDefinedIn) {144    generateUSRForObjCClass(cls, Out, ExtSymDefinedIn,145                            CategoryContextExtSymbolDefinedIn);146  }147 148  /// Generate a USR for an Objective-C class category.149  void GenObjCCategory(StringRef cls, StringRef cat,150                       StringRef clsExt, StringRef catExt) {151    generateUSRForObjCCategory(cls, cat, Out, clsExt, catExt);152  }153 154  /// Generate a USR fragment for an Objective-C property.155  void GenObjCProperty(StringRef prop, bool isClassProp) {156    generateUSRForObjCProperty(prop, isClassProp, Out);157  }158 159  /// Generate a USR for an Objective-C protocol.160  void GenObjCProtocol(StringRef prot, StringRef ext) {161    generateUSRForObjCProtocol(prot, Out, ext);162  }163 164  void VisitType(QualType T);165  void VisitTemplateParameterList(const TemplateParameterList *Params);166  void VisitTemplateName(TemplateName Name);167  void VisitTemplateArgument(const TemplateArgument &Arg);168 169  void VisitMSGuidDecl(const MSGuidDecl *D);170 171  /// Emit a Decl's name using NamedDecl::printName() and return true if172  ///  the decl had no name.173  bool EmitDeclName(const NamedDecl *D);174};175} // end anonymous namespace176 177//===----------------------------------------------------------------------===//178// Generating USRs from ASTS.179//===----------------------------------------------------------------------===//180 181bool USRGenerator::EmitDeclName(const NamedDecl *D) {182  DeclarationName N = D->getDeclName();183  if (N.isEmpty())184    return true;185  Out << N;186  return false;187}188 189bool USRGenerator::ShouldGenerateLocation(const NamedDecl *D) {190  if (D->isExternallyVisible())191    return false;192  if (D->getParentFunctionOrMethod())193    return true;194  SourceLocation Loc = D->getLocation();195  if (Loc.isInvalid())196    return false;197  const SourceManager &SM = Context->getSourceManager();198  return !SM.isInSystemHeader(Loc);199}200 201void USRGenerator::VisitDeclContext(const DeclContext *DC) {202  if (const NamedDecl *D = dyn_cast<NamedDecl>(DC))203    Visit(D);204  else if (isa<LinkageSpecDecl>(DC)) // Linkage specs are transparent in USRs.205    VisitDeclContext(DC->getParent());206}207 208void USRGenerator::VisitFieldDecl(const FieldDecl *D) {209  // The USR for an ivar declared in a class extension is based on the210  // ObjCInterfaceDecl, not the ObjCCategoryDecl.211  if (const ObjCInterfaceDecl *ID = Context->getObjContainingInterface(D))212    Visit(ID);213  else214    VisitDeclContext(D->getDeclContext());215  Out << (isa<ObjCIvarDecl>(D) ? "@" : "@FI@");216  if (EmitDeclName(D)) {217    // Bit fields can be anonymous.218    IgnoreResults = true;219    return;220  }221}222 223void USRGenerator::VisitFunctionDecl(const FunctionDecl *D) {224  if (ShouldGenerateLocation(D) && GenLoc(D, /*IncludeOffset=*/isLocal(D)))225    return;226 227  if (D->getType().isNull()) {228    IgnoreResults = true;229    return;230  }231 232  const unsigned StartSize = Buf.size();233  VisitDeclContext(D->getDeclContext());234  if (Buf.size() == StartSize)235    GenExtSymbolContainer(D);236 237  bool IsTemplate = false;238  if (FunctionTemplateDecl *FunTmpl = D->getDescribedFunctionTemplate()) {239    IsTemplate = true;240    Out << "@FT@";241    VisitTemplateParameterList(FunTmpl->getTemplateParameters());242  } else243    Out << "@F@";244 245  PrintingPolicy Policy(LangOpts);246  // Forward references can have different template argument names. Suppress the247  // template argument names in constructors to make their USR more stable.248  Policy.SuppressTemplateArgsInCXXConstructors = true;249  D->getDeclName().print(Out, Policy);250 251  if ((!LangOpts.CPlusPlus || D->isExternC()) &&252      !D->hasAttr<OverloadableAttr>())253    return;254 255  if (D->isFunctionTemplateSpecialization()) {256    Out << '<';257    if (const TemplateArgumentList *SpecArgs =258            D->getTemplateSpecializationArgs()) {259      for (const auto &Arg : SpecArgs->asArray()) {260        Out << '#';261        VisitTemplateArgument(Arg);262      }263    } else if (const ASTTemplateArgumentListInfo *SpecArgsWritten =264                   D->getTemplateSpecializationArgsAsWritten()) {265      for (const auto &ArgLoc : SpecArgsWritten->arguments()) {266        Out << '#';267        VisitTemplateArgument(ArgLoc.getArgument());268      }269    }270    Out << '>';271  }272 273  QualType CanonicalType = D->getType().getCanonicalType();274  // Mangle in type information for the arguments.275  if (const auto *FPT = CanonicalType->getAs<FunctionProtoType>()) {276    for (QualType PT : FPT->param_types()) {277      Out << '#';278      VisitType(PT);279    }280  }281  if (D->isVariadic())282    Out << '.';283  if (IsTemplate) {284    // Function templates can be overloaded by return type, for example:285    // \code286    //   template <class T> typename T::A foo() {}287    //   template <class T> typename T::B foo() {}288    // \endcode289    Out << '#';290    VisitType(D->getReturnType());291  }292  Out << '#';293  if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {294    if (MD->isStatic())295      Out << 'S';296    // FIXME: OpenCL: Need to consider address spaces297    if (unsigned quals = MD->getMethodQualifiers().getCVRUQualifiers())298      Out << (char)('0' + quals);299    switch (MD->getRefQualifier()) {300    case RQ_None: break;301    case RQ_LValue: Out << '&'; break;302    case RQ_RValue: Out << "&&"; break;303    }304  }305}306 307void USRGenerator::VisitNamedDecl(const NamedDecl *D) {308  VisitDeclContext(D->getDeclContext());309  Out << "@";310 311  if (EmitDeclName(D)) {312    // The string can be empty if the declaration has no name; e.g., it is313    // the ParmDecl with no name for declaration of a function pointer type,314    // e.g.: void  (*f)(void *);315    // In this case, don't generate a USR.316    IgnoreResults = true;317  }318}319 320void USRGenerator::VisitVarDecl(const VarDecl *D) {321  // VarDecls can be declared 'extern' within a function or method body,322  // but their enclosing DeclContext is the function, not the TU.  We need323  // to check the storage class to correctly generate the USR.324  if (ShouldGenerateLocation(D) && GenLoc(D, /*IncludeOffset=*/isLocal(D)))325    return;326 327  VisitDeclContext(D->getDeclContext());328 329  if (VarTemplateDecl *VarTmpl = D->getDescribedVarTemplate()) {330    Out << "@VT";331    VisitTemplateParameterList(VarTmpl->getTemplateParameters());332  } else if (const VarTemplatePartialSpecializationDecl *PartialSpec333             = dyn_cast<VarTemplatePartialSpecializationDecl>(D)) {334    Out << "@VP";335    VisitTemplateParameterList(PartialSpec->getTemplateParameters());336  }337 338  // Variables always have simple names.339  StringRef s = D->getName();340 341  // The string can be empty if the declaration has no name; e.g., it is342  // the ParmDecl with no name for declaration of a function pointer type, e.g.:343  //    void  (*f)(void *);344  // In this case, don't generate a USR.345  if (s.empty())346    IgnoreResults = true;347  else348    Out << '@' << s;349 350  // For a template specialization, mangle the template arguments.351  if (const VarTemplateSpecializationDecl *Spec352                              = dyn_cast<VarTemplateSpecializationDecl>(D)) {353    const TemplateArgumentList &Args = Spec->getTemplateArgs();354    Out << '>';355    for (unsigned I = 0, N = Args.size(); I != N; ++I) {356      Out << '#';357      VisitTemplateArgument(Args.get(I));358    }359  }360}361 362void USRGenerator::VisitBindingDecl(const BindingDecl *D) {363  if (isLocal(D) && GenLoc(D, /*IncludeOffset=*/true))364    return;365  VisitNamedDecl(D);366}367 368void USRGenerator::VisitNonTypeTemplateParmDecl(369                                        const NonTypeTemplateParmDecl *D) {370  GenLoc(D, /*IncludeOffset=*/true);371}372 373void USRGenerator::VisitTemplateTemplateParmDecl(374                                        const TemplateTemplateParmDecl *D) {375  GenLoc(D, /*IncludeOffset=*/true);376}377 378void USRGenerator::VisitNamespaceDecl(const NamespaceDecl *D) {379  if (IgnoreResults)380    return;381  VisitDeclContext(D->getDeclContext());382  if (D->isAnonymousNamespace()) {383    Out << "@aN";384    return;385  }386  Out << "@N@" << D->getName();387}388 389void USRGenerator::VisitFunctionTemplateDecl(const FunctionTemplateDecl *D) {390  VisitFunctionDecl(D->getTemplatedDecl());391}392 393void USRGenerator::VisitClassTemplateDecl(const ClassTemplateDecl *D) {394  VisitTagDecl(D->getTemplatedDecl());395}396 397void USRGenerator::VisitNamespaceAliasDecl(const NamespaceAliasDecl *D) {398  VisitDeclContext(D->getDeclContext());399  if (!IgnoreResults)400    Out << "@NA@" << D->getName();401}402 403static const ObjCCategoryDecl *getCategoryContext(const NamedDecl *D) {404  if (auto *CD = dyn_cast<ObjCCategoryDecl>(D->getDeclContext()))405    return CD;406  if (auto *ICD = dyn_cast<ObjCCategoryImplDecl>(D->getDeclContext()))407    return ICD->getCategoryDecl();408  return nullptr;409}410 411void USRGenerator::VisitObjCMethodDecl(const ObjCMethodDecl *D) {412  const DeclContext *container = D->getDeclContext();413  if (const ObjCProtocolDecl *pd = dyn_cast<ObjCProtocolDecl>(container)) {414    Visit(pd);415  }416  else {417    // The USR for a method declared in a class extension or category is based on418    // the ObjCInterfaceDecl, not the ObjCCategoryDecl.419    const ObjCInterfaceDecl *ID = D->getClassInterface();420    if (!ID) {421      IgnoreResults = true;422      return;423    }424    auto *CD = getCategoryContext(D);425    VisitObjCContainerDecl(ID, CD);426  }427  // Ideally we would use 'GenObjCMethod', but this is such a hot path428  // for Objective-C code that we don't want to use429  // DeclarationName::getAsString().430  Out << (D->isInstanceMethod() ? "(im)" : "(cm)")431      << DeclarationName(D->getSelector());432}433 434void USRGenerator::VisitObjCContainerDecl(const ObjCContainerDecl *D,435                                          const ObjCCategoryDecl *CatD) {436  switch (D->getKind()) {437    default:438      llvm_unreachable("Invalid ObjC container.");439    case Decl::ObjCInterface:440    case Decl::ObjCImplementation:441      GenObjCClass(D->getName(), GetExternalSourceContainer(D),442                   GetExternalSourceContainer(CatD));443      break;444    case Decl::ObjCCategory: {445      const ObjCCategoryDecl *CD = cast<ObjCCategoryDecl>(D);446      const ObjCInterfaceDecl *ID = CD->getClassInterface();447      if (!ID) {448        // Handle invalid code where the @interface might not449        // have been specified.450        // FIXME: We should be able to generate this USR even if the451        // @interface isn't available.452        IgnoreResults = true;453        return;454      }455      // Specially handle class extensions, which are anonymous categories.456      // We want to mangle in the location to uniquely distinguish them.457      if (CD->IsClassExtension()) {458        Out << "objc(ext)" << ID->getName() << '@';459        GenLoc(CD, /*IncludeOffset=*/true);460      }461      else462        GenObjCCategory(ID->getName(), CD->getName(),463                        GetExternalSourceContainer(ID),464                        GetExternalSourceContainer(CD));465 466      break;467    }468    case Decl::ObjCCategoryImpl: {469      const ObjCCategoryImplDecl *CD = cast<ObjCCategoryImplDecl>(D);470      const ObjCInterfaceDecl *ID = CD->getClassInterface();471      if (!ID) {472        // Handle invalid code where the @interface might not473        // have been specified.474        // FIXME: We should be able to generate this USR even if the475        // @interface isn't available.476        IgnoreResults = true;477        return;478      }479      GenObjCCategory(ID->getName(), CD->getName(),480                      GetExternalSourceContainer(ID),481                      GetExternalSourceContainer(CD));482      break;483    }484    case Decl::ObjCProtocol: {485      const ObjCProtocolDecl *PD = cast<ObjCProtocolDecl>(D);486      GenObjCProtocol(PD->getName(), GetExternalSourceContainer(PD));487      break;488    }489  }490}491 492void USRGenerator::VisitObjCPropertyDecl(const ObjCPropertyDecl *D) {493  // The USR for a property declared in a class extension or category is based494  // on the ObjCInterfaceDecl, not the ObjCCategoryDecl.495  if (const ObjCInterfaceDecl *ID = Context->getObjContainingInterface(D))496    VisitObjCContainerDecl(ID, getCategoryContext(D));497  else498    Visit(cast<Decl>(D->getDeclContext()));499  GenObjCProperty(D->getName(), D->isClassProperty());500}501 502void USRGenerator::VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D) {503  if (ObjCPropertyDecl *PD = D->getPropertyDecl()) {504    VisitObjCPropertyDecl(PD);505    return;506  }507 508  IgnoreResults = true;509}510 511void USRGenerator::VisitTagDecl(const TagDecl *D) {512  // Add the location of the tag decl to handle resolution across513  // translation units.514  if (!isa<EnumDecl>(D) &&515      ShouldGenerateLocation(D) && GenLoc(D, /*IncludeOffset=*/isLocal(D)))516    return;517 518  GenExtSymbolContainer(D);519 520  D = D->getCanonicalDecl();521  VisitDeclContext(D->getDeclContext());522 523  bool AlreadyStarted = false;524  if (const CXXRecordDecl *CXXRecord = dyn_cast<CXXRecordDecl>(D)) {525    if (ClassTemplateDecl *ClassTmpl = CXXRecord->getDescribedClassTemplate()) {526      AlreadyStarted = true;527 528      switch (D->getTagKind()) {529      case TagTypeKind::Interface:530      case TagTypeKind::Class:531      case TagTypeKind::Struct:532        Out << "@ST";533        break;534      case TagTypeKind::Union:535        Out << "@UT";536        break;537      case TagTypeKind::Enum:538        llvm_unreachable("enum template");539      }540      VisitTemplateParameterList(ClassTmpl->getTemplateParameters());541    } else if (const ClassTemplatePartialSpecializationDecl *PartialSpec542                = dyn_cast<ClassTemplatePartialSpecializationDecl>(CXXRecord)) {543      AlreadyStarted = true;544 545      switch (D->getTagKind()) {546      case TagTypeKind::Interface:547      case TagTypeKind::Class:548      case TagTypeKind::Struct:549        Out << "@SP";550        break;551      case TagTypeKind::Union:552        Out << "@UP";553        break;554      case TagTypeKind::Enum:555        llvm_unreachable("enum partial specialization");556      }557      VisitTemplateParameterList(PartialSpec->getTemplateParameters());558    }559  }560 561  if (!AlreadyStarted) {562    switch (D->getTagKind()) {563    case TagTypeKind::Interface:564    case TagTypeKind::Class:565    case TagTypeKind::Struct:566      Out << "@S";567      break;568    case TagTypeKind::Union:569      Out << "@U";570      break;571    case TagTypeKind::Enum:572      Out << "@E";573      break;574    }575  }576 577  Out << '@';578  assert(Buf.size() > 0);579  const unsigned off = Buf.size() - 1;580 581  if (EmitDeclName(D)) {582    if (const TypedefNameDecl *TD = D->getTypedefNameForAnonDecl()) {583      Buf[off] = 'A';584      Out << '@' << *TD;585    } else {586      if (D->isEmbeddedInDeclarator() && !D->isFreeStanding()) {587        printLoc(Out, D->getLocation(), Context->getSourceManager(), true);588      } else {589        Buf[off] = 'a';590        if (auto *ED = dyn_cast<EnumDecl>(D)) {591          // Distinguish USRs of anonymous enums by using their first592          // enumerator.593          auto enum_range = ED->enumerators();594          if (enum_range.begin() != enum_range.end()) {595            Out << '@' << **enum_range.begin();596          }597        }598      }599    }600  }601 602  // For a class template specialization, mangle the template arguments.603  if (const ClassTemplateSpecializationDecl *Spec604                              = dyn_cast<ClassTemplateSpecializationDecl>(D)) {605    const TemplateArgumentList &Args = Spec->getTemplateArgs();606    Out << '>';607    for (unsigned I = 0, N = Args.size(); I != N; ++I) {608      Out << '#';609      VisitTemplateArgument(Args.get(I));610    }611  }612}613 614void USRGenerator::VisitTypedefDecl(const TypedefDecl *D) {615  if (ShouldGenerateLocation(D) && GenLoc(D, /*IncludeOffset=*/isLocal(D)))616    return;617  const DeclContext *DC = D->getDeclContext();618  if (const NamedDecl *DCN = dyn_cast<NamedDecl>(DC))619    Visit(DCN);620  Out << "@T@";621  Out << D->getName();622}623 624void USRGenerator::VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D) {625  GenLoc(D, /*IncludeOffset=*/true);626}627 628void USRGenerator::GenExtSymbolContainer(const NamedDecl *D) {629  StringRef Container = GetExternalSourceContainer(D);630  if (!Container.empty())631    Out << "@M@" << Container;632}633 634bool USRGenerator::GenLoc(const Decl *D, bool IncludeOffset) {635  if (generatedLoc)636    return IgnoreResults;637  generatedLoc = true;638 639  // Guard against null declarations in invalid code.640  if (!D) {641    IgnoreResults = true;642    return true;643  }644 645  // Use the location of canonical decl.646  D = D->getCanonicalDecl();647 648  IgnoreResults =649      IgnoreResults || printLoc(Out, D->getBeginLoc(),650                                Context->getSourceManager(), IncludeOffset);651 652  return IgnoreResults;653}654 655static void printQualifier(llvm::raw_ostream &Out, const LangOptions &LangOpts,656                           NestedNameSpecifier NNS) {657  // FIXME: Encode the qualifier, don't just print it.658  PrintingPolicy PO(LangOpts);659  PO.SuppressTagKeyword = true;660  PO.SuppressUnwrittenScope = true;661  PO.ConstantArraySizeAsWritten = false;662  PO.AnonymousTagLocations = false;663  NNS.print(Out, PO);664}665 666void USRGenerator::VisitType(QualType T) {667  // This method mangles in USR information for types.  It can possibly668  // just reuse the naming-mangling logic used by codegen, although the669  // requirements for USRs might not be the same.670  ASTContext &Ctx = *Context;671 672  do {673    T = Ctx.getCanonicalType(T);674    Qualifiers Q = T.getQualifiers();675    unsigned qVal = 0;676    if (Q.hasConst())677      qVal |= 0x1;678    if (Q.hasVolatile())679      qVal |= 0x2;680    if (Q.hasRestrict())681      qVal |= 0x4;682    if(qVal)683      Out << ((char) ('0' + qVal));684 685    // Mangle in ObjC GC qualifiers?686 687    if (const PackExpansionType *Expansion = T->getAs<PackExpansionType>()) {688      Out << 'P';689      T = Expansion->getPattern();690    }691 692    if (const BuiltinType *BT = T->getAs<BuiltinType>()) {693      switch (BT->getKind()) {694        case BuiltinType::Void:695          Out << 'v'; break;696        case BuiltinType::Bool:697          Out << 'b'; break;698        case BuiltinType::UChar:699          Out << 'c'; break;700        case BuiltinType::Char8:701          Out << 'u'; break;702        case BuiltinType::Char16:703          Out << 'q'; break;704        case BuiltinType::Char32:705          Out << 'w'; break;706        case BuiltinType::UShort:707          Out << 's'; break;708        case BuiltinType::UInt:709          Out << 'i'; break;710        case BuiltinType::ULong:711          Out << 'l'; break;712        case BuiltinType::ULongLong:713          Out << 'k'; break;714        case BuiltinType::UInt128:715          Out << 'j'; break;716        case BuiltinType::Char_U:717        case BuiltinType::Char_S:718          Out << 'C'; break;719        case BuiltinType::SChar:720          Out << 'r'; break;721        case BuiltinType::WChar_S:722        case BuiltinType::WChar_U:723          Out << 'W'; break;724        case BuiltinType::Short:725          Out << 'S'; break;726        case BuiltinType::Int:727          Out << 'I'; break;728        case BuiltinType::Long:729          Out << 'L'; break;730        case BuiltinType::LongLong:731          Out << 'K'; break;732        case BuiltinType::Int128:733          Out << 'J'; break;734        case BuiltinType::Float16:735        case BuiltinType::Half:736          Out << 'h'; break;737        case BuiltinType::Float:738          Out << 'f'; break;739        case BuiltinType::Double:740          Out << 'd'; break;741        case BuiltinType::LongDouble:742          Out << 'D'; break;743        case BuiltinType::Float128:744          Out << 'Q'; break;745        case BuiltinType::NullPtr:746          Out << 'n'; break;747#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \748        case BuiltinType::Id: \749          Out << "@BT@" << #Suffix << "_" << #ImgType; break;750#include "clang/Basic/OpenCLImageTypes.def"751#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \752        case BuiltinType::Id: \753          Out << "@BT@" << #ExtType; break;754#include "clang/Basic/OpenCLExtensionTypes.def"755        case BuiltinType::OCLEvent:756          Out << "@BT@OCLEvent"; break;757        case BuiltinType::OCLClkEvent:758          Out << "@BT@OCLClkEvent"; break;759        case BuiltinType::OCLQueue:760          Out << "@BT@OCLQueue"; break;761        case BuiltinType::OCLReserveID:762          Out << "@BT@OCLReserveID"; break;763        case BuiltinType::OCLSampler:764          Out << "@BT@OCLSampler"; break;765#define SVE_TYPE(Name, Id, SingletonId)                                        \766  case BuiltinType::Id:                                                        \767    Out << "@BT@" << #Name;                                                    \768    break;769#include "clang/Basic/AArch64ACLETypes.def"770#define PPC_VECTOR_TYPE(Name, Id, Size) \771        case BuiltinType::Id: \772          Out << "@BT@" << #Name; break;773#include "clang/Basic/PPCTypes.def"774#define RVV_TYPE(Name, Id, SingletonId) \775        case BuiltinType::Id: \776          Out << "@BT@" << Name; break;777#include "clang/Basic/RISCVVTypes.def"778#define WASM_TYPE(Name, Id, SingletonId) case BuiltinType::Id:779#include "clang/Basic/WebAssemblyReferenceTypes.def"780#define AMDGPU_TYPE(Name, Id, SingletonId, Width, Align)                       \781  case BuiltinType::Id:                                                        \782    Out << "@BT@" << #Name;                                                    \783    break;784#include "clang/Basic/AMDGPUTypes.def"785#define HLSL_INTANGIBLE_TYPE(Name, Id, SingletonId)                            \786  case BuiltinType::Id:                                                        \787    Out << "@BT@" << #Name;                                                    \788    break;789#include "clang/Basic/HLSLIntangibleTypes.def"790        case BuiltinType::ShortAccum:791          Out << "@BT@ShortAccum"; break;792        case BuiltinType::Accum:793          Out << "@BT@Accum"; break;794        case BuiltinType::LongAccum:795          Out << "@BT@LongAccum"; break;796        case BuiltinType::UShortAccum:797          Out << "@BT@UShortAccum"; break;798        case BuiltinType::UAccum:799          Out << "@BT@UAccum"; break;800        case BuiltinType::ULongAccum:801          Out << "@BT@ULongAccum"; break;802        case BuiltinType::ShortFract:803          Out << "@BT@ShortFract"; break;804        case BuiltinType::Fract:805          Out << "@BT@Fract"; break;806        case BuiltinType::LongFract:807          Out << "@BT@LongFract"; break;808        case BuiltinType::UShortFract:809          Out << "@BT@UShortFract"; break;810        case BuiltinType::UFract:811          Out << "@BT@UFract"; break;812        case BuiltinType::ULongFract:813          Out << "@BT@ULongFract"; break;814        case BuiltinType::SatShortAccum:815          Out << "@BT@SatShortAccum"; break;816        case BuiltinType::SatAccum:817          Out << "@BT@SatAccum"; break;818        case BuiltinType::SatLongAccum:819          Out << "@BT@SatLongAccum"; break;820        case BuiltinType::SatUShortAccum:821          Out << "@BT@SatUShortAccum"; break;822        case BuiltinType::SatUAccum:823          Out << "@BT@SatUAccum"; break;824        case BuiltinType::SatULongAccum:825          Out << "@BT@SatULongAccum"; break;826        case BuiltinType::SatShortFract:827          Out << "@BT@SatShortFract"; break;828        case BuiltinType::SatFract:829          Out << "@BT@SatFract"; break;830        case BuiltinType::SatLongFract:831          Out << "@BT@SatLongFract"; break;832        case BuiltinType::SatUShortFract:833          Out << "@BT@SatUShortFract"; break;834        case BuiltinType::SatUFract:835          Out << "@BT@SatUFract"; break;836        case BuiltinType::SatULongFract:837          Out << "@BT@SatULongFract"; break;838        case BuiltinType::BFloat16:839          Out << "@BT@__bf16"; break;840        case BuiltinType::Ibm128:841          Out << "@BT@__ibm128"; break;842        case BuiltinType::ObjCId:843          Out << 'o'; break;844        case BuiltinType::ObjCClass:845          Out << 'O'; break;846        case BuiltinType::ObjCSel:847          Out << 'e'; break;848#define BUILTIN_TYPE(Id, SingletonId)849#define PLACEHOLDER_TYPE(Id, SingletonId) case BuiltinType::Id:850#include "clang/AST/BuiltinTypes.def"851        case BuiltinType::Dependent:852          // If you're adding a new builtin type, please add its name prefixed853          // with "@BT@" to `Out` (see cases above).854          IgnoreResults = true;855          break;856      }857      return;858    }859 860    // If we have already seen this (non-built-in) type, use a substitution861    // encoding.  Otherwise, record this as a substitution.862    auto [Substitution, Inserted] =863        TypeSubstitutions.try_emplace(T.getTypePtr(), TypeSubstitutions.size());864    if (!Inserted) {865      Out << 'S' << Substitution->second << '_';866      return;867    }868 869    if (const PointerType *PT = T->getAs<PointerType>()) {870      Out << '*';871      T = PT->getPointeeType();872      continue;873    }874    if (const ObjCObjectPointerType *OPT = T->getAs<ObjCObjectPointerType>()) {875      Out << '*';876      T = OPT->getPointeeType();877      continue;878    }879    if (const RValueReferenceType *RT = T->getAs<RValueReferenceType>()) {880      Out << "&&";881      T = RT->getPointeeType();882      continue;883    }884    if (const ReferenceType *RT = T->getAs<ReferenceType>()) {885      Out << '&';886      T = RT->getPointeeType();887      continue;888    }889    if (const FunctionProtoType *FT = T->getAs<FunctionProtoType>()) {890      Out << 'F';891      VisitType(FT->getReturnType());892      Out << '(';893      for (const auto &I : FT->param_types()) {894        Out << '#';895        VisitType(I);896      }897      Out << ')';898      if (FT->isVariadic())899        Out << '.';900      return;901    }902    if (const BlockPointerType *BT = T->getAs<BlockPointerType>()) {903      Out << 'B';904      T = BT->getPointeeType();905      continue;906    }907    if (const ComplexType *CT = T->getAs<ComplexType>()) {908      Out << '<';909      T = CT->getElementType();910      continue;911    }912    if (const TagType *TT = T->getAs<TagType>()) {913      if (const auto *ICNT = dyn_cast<InjectedClassNameType>(TT)) {914        T = ICNT->getDecl()->getCanonicalTemplateSpecializationType(Ctx);915      } else {916        Out << '$';917        VisitTagDecl(TT->getDecl());918        return;919      }920    }921    if (const ObjCInterfaceType *OIT = T->getAs<ObjCInterfaceType>()) {922      Out << '$';923      VisitObjCInterfaceDecl(OIT->getDecl());924      return;925    }926    if (const ObjCObjectType *OIT = T->getAs<ObjCObjectType>()) {927      Out << 'Q';928      VisitType(OIT->getBaseType());929      for (auto *Prot : OIT->getProtocols())930        VisitObjCProtocolDecl(Prot);931      return;932    }933    if (const TemplateTypeParmType *TTP =934            T->getAsCanonical<TemplateTypeParmType>()) {935      Out << 't' << TTP->getDepth() << '.' << TTP->getIndex();936      return;937    }938    if (const TemplateSpecializationType *Spec939                                    = T->getAs<TemplateSpecializationType>()) {940      Out << '>';941      VisitTemplateName(Spec->getTemplateName());942      Out << Spec->template_arguments().size();943      for (const auto &Arg : Spec->template_arguments())944        VisitTemplateArgument(Arg);945      return;946    }947    if (const DependentNameType *DNT = T->getAs<DependentNameType>()) {948      Out << '^';949      printQualifier(Out, LangOpts, DNT->getQualifier());950      Out << ':' << DNT->getIdentifier()->getName();951      return;952    }953    if (const auto *VT = T->getAs<VectorType>()) {954      Out << (T->isExtVectorType() ? ']' : '[');955      Out << VT->getNumElements();956      T = VT->getElementType();957      continue;958    }959    if (const auto *const AT = dyn_cast<ArrayType>(T)) {960      Out << '{';961      switch (AT->getSizeModifier()) {962      case ArraySizeModifier::Static:963        Out << 's';964        break;965      case ArraySizeModifier::Star:966        Out << '*';967        break;968      case ArraySizeModifier::Normal:969        Out << 'n';970        break;971      }972      if (const auto *const CAT = dyn_cast<ConstantArrayType>(T))973        Out << CAT->getSize();974 975      T = AT->getElementType();976      continue;977    }978 979    // Unhandled type.980    Out << ' ';981    break;982  } while (true);983}984 985void USRGenerator::VisitTemplateParameterList(986                                         const TemplateParameterList *Params) {987  if (!Params)988    return;989  Out << '>' << Params->size();990  for (TemplateParameterList::const_iterator P = Params->begin(),991                                          PEnd = Params->end();992       P != PEnd; ++P) {993    Out << '#';994    if (isa<TemplateTypeParmDecl>(*P)) {995      if (cast<TemplateTypeParmDecl>(*P)->isParameterPack())996        Out<< 'p';997      Out << 'T';998      continue;999    }1000 1001    if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(*P)) {1002      if (NTTP->isParameterPack())1003        Out << 'p';1004      Out << 'N';1005      VisitType(NTTP->getType());1006      continue;1007    }1008 1009    TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*P);1010    if (TTP->isParameterPack())1011      Out << 'p';1012    Out << 't';1013    VisitTemplateParameterList(TTP->getTemplateParameters());1014  }1015}1016 1017void USRGenerator::VisitTemplateName(TemplateName Name) {1018  if (TemplateDecl *Template = Name.getAsTemplateDecl()) {1019    if (TemplateTemplateParmDecl *TTP1020                              = dyn_cast<TemplateTemplateParmDecl>(Template)) {1021      Out << 't' << TTP->getDepth() << '.' << TTP->getIndex();1022      return;1023    }1024 1025    Visit(Template);1026    return;1027  }1028 1029  // FIXME: Visit dependent template names.1030}1031 1032void USRGenerator::VisitTemplateArgument(const TemplateArgument &Arg) {1033  switch (Arg.getKind()) {1034  case TemplateArgument::Null:1035    break;1036 1037  case TemplateArgument::Declaration:1038    Visit(Arg.getAsDecl());1039    break;1040 1041  case TemplateArgument::NullPtr:1042    break;1043 1044  case TemplateArgument::TemplateExpansion:1045    Out << 'P'; // pack expansion of...1046    [[fallthrough]];1047  case TemplateArgument::Template:1048    VisitTemplateName(Arg.getAsTemplateOrTemplatePattern());1049    break;1050 1051  case TemplateArgument::Expression:1052    // FIXME: Visit expressions.1053    break;1054 1055  case TemplateArgument::Pack:1056    Out << 'p' << Arg.pack_size();1057    for (const auto &P : Arg.pack_elements())1058      VisitTemplateArgument(P);1059    break;1060 1061  case TemplateArgument::Type:1062    VisitType(Arg.getAsType());1063    break;1064 1065  case TemplateArgument::Integral:1066    Out << 'V';1067    VisitType(Arg.getIntegralType());1068    Out << Arg.getAsIntegral();1069    break;1070 1071  case TemplateArgument::StructuralValue: {1072    Out << 'S';1073    VisitType(Arg.getStructuralValueType());1074    ODRHash Hash{};1075    Hash.AddStructuralValue(Arg.getAsStructuralValue());1076    Out << Hash.CalculateHash();1077    break;1078  }1079  }1080}1081 1082void USRGenerator::VisitUnresolvedUsingValueDecl(const UnresolvedUsingValueDecl *D) {1083  if (ShouldGenerateLocation(D) && GenLoc(D, /*IncludeOffset=*/isLocal(D)))1084    return;1085  VisitDeclContext(D->getDeclContext());1086  Out << "@UUV@";1087  printQualifier(Out, LangOpts, D->getQualifier());1088  EmitDeclName(D);1089}1090 1091void USRGenerator::VisitUnresolvedUsingTypenameDecl(const UnresolvedUsingTypenameDecl *D) {1092  if (ShouldGenerateLocation(D) && GenLoc(D, /*IncludeOffset=*/isLocal(D)))1093    return;1094  VisitDeclContext(D->getDeclContext());1095  Out << "@UUT@";1096  printQualifier(Out, LangOpts, D->getQualifier());1097  Out << D->getName(); // Simple name.1098}1099 1100void USRGenerator::VisitConceptDecl(const ConceptDecl *D) {1101  if (ShouldGenerateLocation(D) && GenLoc(D, /*IncludeOffset=*/isLocal(D)))1102    return;1103  VisitDeclContext(D->getDeclContext());1104  Out << "@CT@";1105  EmitDeclName(D);1106}1107 1108void USRGenerator::VisitMSGuidDecl(const MSGuidDecl *D) {1109  VisitDeclContext(D->getDeclContext());1110  Out << "@MG@";1111  D->NamedDecl::printName(Out);1112}1113 1114//===----------------------------------------------------------------------===//1115// USR generation functions.1116//===----------------------------------------------------------------------===//1117 1118static void combineClassAndCategoryExtContainers(StringRef ClsSymDefinedIn,1119                                                 StringRef CatSymDefinedIn,1120                                                 raw_ostream &OS) {1121  if (ClsSymDefinedIn.empty() && CatSymDefinedIn.empty())1122    return;1123  if (CatSymDefinedIn.empty()) {1124    OS << "@M@" << ClsSymDefinedIn << '@';1125    return;1126  }1127  OS << "@CM@" << CatSymDefinedIn << '@';1128  if (ClsSymDefinedIn != CatSymDefinedIn) {1129    OS << ClsSymDefinedIn << '@';1130  }1131}1132 1133void clang::index::generateUSRForObjCClass(StringRef Cls, raw_ostream &OS,1134                                           StringRef ExtSymDefinedIn,1135                                  StringRef CategoryContextExtSymbolDefinedIn) {1136  combineClassAndCategoryExtContainers(ExtSymDefinedIn,1137                                       CategoryContextExtSymbolDefinedIn, OS);1138  OS << "objc(cs)" << Cls;1139}1140 1141void clang::index::generateUSRForObjCCategory(StringRef Cls, StringRef Cat,1142                                              raw_ostream &OS,1143                                              StringRef ClsSymDefinedIn,1144                                              StringRef CatSymDefinedIn) {1145  combineClassAndCategoryExtContainers(ClsSymDefinedIn, CatSymDefinedIn, OS);1146  OS << "objc(cy)" << Cls << '@' << Cat;1147}1148 1149void clang::index::generateUSRForObjCIvar(StringRef Ivar, raw_ostream &OS) {1150  OS << '@' << Ivar;1151}1152 1153void clang::index::generateUSRForObjCMethod(StringRef Sel,1154                                            bool IsInstanceMethod,1155                                            raw_ostream &OS) {1156  OS << (IsInstanceMethod ? "(im)" : "(cm)") << Sel;1157}1158 1159void clang::index::generateUSRForObjCProperty(StringRef Prop, bool isClassProp,1160                                              raw_ostream &OS) {1161  OS << (isClassProp ? "(cpy)" : "(py)") << Prop;1162}1163 1164void clang::index::generateUSRForObjCProtocol(StringRef Prot, raw_ostream &OS,1165                                              StringRef ExtSymDefinedIn) {1166  if (!ExtSymDefinedIn.empty())1167    OS << "@M@" << ExtSymDefinedIn << '@';1168  OS << "objc(pl)" << Prot;1169}1170 1171void clang::index::generateUSRForGlobalEnum(StringRef EnumName, raw_ostream &OS,1172                                            StringRef ExtSymDefinedIn) {1173  if (!ExtSymDefinedIn.empty())1174    OS << "@M@" << ExtSymDefinedIn;1175  OS << "@E@" << EnumName;1176}1177 1178void clang::index::generateUSRForEnumConstant(StringRef EnumConstantName,1179                                              raw_ostream &OS) {1180  OS << '@' << EnumConstantName;1181}1182 1183bool clang::index::generateUSRForDecl(const Decl *D,1184                                      SmallVectorImpl<char> &Buf) {1185  if (!D)1186    return true;1187  return generateUSRForDecl(D, Buf, D->getASTContext().getLangOpts());1188}1189 1190bool clang::index::generateUSRForDecl(const Decl *D, SmallVectorImpl<char> &Buf,1191                                      const LangOptions &LangOpts) {1192  if (!D)1193    return true;1194  // We don't ignore decls with invalid source locations. Implicit decls, like1195  // C++'s operator new function, can have invalid locations but it is fine to1196  // create USRs that can identify them.1197 1198  // Check if the declaration has explicit external USR specified.1199  auto *CD = D->getCanonicalDecl();1200  if (auto *ExternalSymAttr = CD->getAttr<ExternalSourceSymbolAttr>()) {1201    if (!ExternalSymAttr->getUSR().empty()) {1202      llvm::raw_svector_ostream Out(Buf);1203      Out << ExternalSymAttr->getUSR();1204      return false;1205    }1206  }1207  USRGenerator UG(&D->getASTContext(), Buf, LangOpts);1208  UG.Visit(D);1209  return UG.ignoreResults();1210}1211 1212bool clang::index::generateUSRForMacro(const MacroDefinitionRecord *MD,1213                                       const SourceManager &SM,1214                                       SmallVectorImpl<char> &Buf) {1215  if (!MD)1216    return true;1217  return generateUSRForMacro(MD->getName()->getName(), MD->getLocation(),1218                             SM, Buf);1219 1220}1221 1222bool clang::index::generateUSRForMacro(StringRef MacroName, SourceLocation Loc,1223                                       const SourceManager &SM,1224                                       SmallVectorImpl<char> &Buf) {1225  if (MacroName.empty())1226    return true;1227 1228  llvm::raw_svector_ostream Out(Buf);1229 1230  // Assume that system headers are sane.  Don't put source location1231  // information into the USR if the macro comes from a system header.1232  bool ShouldGenerateLocation = Loc.isValid() && !SM.isInSystemHeader(Loc);1233 1234  Out << getUSRSpacePrefix();1235  if (ShouldGenerateLocation)1236    printLoc(Out, Loc, SM, /*IncludeOffset=*/true);1237  Out << "@macro@";1238  Out << MacroName;1239  return false;1240}1241 1242bool clang::index::generateUSRForType(QualType T, ASTContext &Ctx,1243                                      SmallVectorImpl<char> &Buf) {1244  return generateUSRForType(T, Ctx, Buf, Ctx.getLangOpts());1245}1246 1247bool clang::index::generateUSRForType(QualType T, ASTContext &Ctx,1248                                      SmallVectorImpl<char> &Buf,1249                                      const LangOptions &LangOpts) {1250  if (T.isNull())1251    return true;1252  T = T.getCanonicalType();1253 1254  USRGenerator UG(&Ctx, Buf, LangOpts);1255  UG.VisitType(T);1256  return UG.ignoreResults();1257}1258 1259bool clang::index::generateFullUSRForModule(const Module *Mod,1260                                            raw_ostream &OS) {1261  if (!Mod->Parent)1262    return generateFullUSRForTopLevelModuleName(Mod->Name, OS);1263  if (generateFullUSRForModule(Mod->Parent, OS))1264    return true;1265  return generateUSRFragmentForModule(Mod, OS);1266}1267 1268bool clang::index::generateFullUSRForTopLevelModuleName(StringRef ModName,1269                                                        raw_ostream &OS) {1270  OS << getUSRSpacePrefix();1271  return generateUSRFragmentForModuleName(ModName, OS);1272}1273 1274bool clang::index::generateUSRFragmentForModule(const Module *Mod,1275                                                raw_ostream &OS) {1276  return generateUSRFragmentForModuleName(Mod->Name, OS);1277}1278 1279bool clang::index::generateUSRFragmentForModuleName(StringRef ModName,1280                                                    raw_ostream &OS) {1281  OS << "@M@" << ModName;1282  return false;1283}1284