10b57cec5SDimitry Andric //===- USRGeneration.cpp - Routines for USR generation --------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "clang/Index/USRGeneration.h"
100b57cec5SDimitry Andric #include "clang/AST/ASTContext.h"
11480093f4SDimitry Andric #include "clang/AST/Attr.h"
125f757f3fSDimitry Andric #include "clang/AST/DeclCXX.h"
130b57cec5SDimitry Andric #include "clang/AST/DeclTemplate.h"
140b57cec5SDimitry Andric #include "clang/AST/DeclVisitor.h"
157a6dacacSDimitry Andric #include "clang/AST/ODRHash.h"
165ffd83dbSDimitry Andric #include "clang/Basic/FileManager.h"
170b57cec5SDimitry Andric #include "clang/Lex/PreprocessingRecord.h"
180b57cec5SDimitry Andric #include "llvm/Support/Path.h"
190b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
200b57cec5SDimitry Andric 
210b57cec5SDimitry Andric using namespace clang;
220b57cec5SDimitry Andric using namespace clang::index;
230b57cec5SDimitry Andric 
240b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
250b57cec5SDimitry Andric // USR generation.
260b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
270b57cec5SDimitry Andric 
280b57cec5SDimitry Andric /// \returns true on error.
printLoc(llvm::raw_ostream & OS,SourceLocation Loc,const SourceManager & SM,bool IncludeOffset)290b57cec5SDimitry Andric static bool printLoc(llvm::raw_ostream &OS, SourceLocation Loc,
300b57cec5SDimitry Andric                      const SourceManager &SM, bool IncludeOffset) {
310b57cec5SDimitry Andric   if (Loc.isInvalid()) {
320b57cec5SDimitry Andric     return true;
330b57cec5SDimitry Andric   }
340b57cec5SDimitry Andric   Loc = SM.getExpansionLoc(Loc);
350b57cec5SDimitry Andric   const std::pair<FileID, unsigned> &Decomposed = SM.getDecomposedLoc(Loc);
365f757f3fSDimitry Andric   OptionalFileEntryRef FE = SM.getFileEntryRefForID(Decomposed.first);
370b57cec5SDimitry Andric   if (FE) {
380b57cec5SDimitry Andric     OS << llvm::sys::path::filename(FE->getName());
390b57cec5SDimitry Andric   } else {
400b57cec5SDimitry Andric     // This case really isn't interesting.
410b57cec5SDimitry Andric     return true;
420b57cec5SDimitry Andric   }
430b57cec5SDimitry Andric   if (IncludeOffset) {
440b57cec5SDimitry Andric     // Use the offest into the FileID to represent the location.  Using
450b57cec5SDimitry Andric     // a line/column can cause us to look back at the original source file,
460b57cec5SDimitry Andric     // which is expensive.
470b57cec5SDimitry Andric     OS << '@' << Decomposed.second;
480b57cec5SDimitry Andric   }
490b57cec5SDimitry Andric   return false;
500b57cec5SDimitry Andric }
510b57cec5SDimitry Andric 
GetExternalSourceContainer(const NamedDecl * D)520b57cec5SDimitry Andric static StringRef GetExternalSourceContainer(const NamedDecl *D) {
530b57cec5SDimitry Andric   if (!D)
540b57cec5SDimitry Andric     return StringRef();
550b57cec5SDimitry Andric   if (auto *attr = D->getExternalSourceSymbolAttr()) {
560b57cec5SDimitry Andric     return attr->getDefinedIn();
570b57cec5SDimitry Andric   }
580b57cec5SDimitry Andric   return StringRef();
590b57cec5SDimitry Andric }
600b57cec5SDimitry Andric 
610b57cec5SDimitry Andric namespace {
620b57cec5SDimitry Andric class USRGenerator : public ConstDeclVisitor<USRGenerator> {
630b57cec5SDimitry Andric   SmallVectorImpl<char> &Buf;
640b57cec5SDimitry Andric   llvm::raw_svector_ostream Out;
650b57cec5SDimitry Andric   bool IgnoreResults;
660b57cec5SDimitry Andric   ASTContext *Context;
670b57cec5SDimitry Andric   bool generatedLoc;
680b57cec5SDimitry Andric 
690b57cec5SDimitry Andric   llvm::DenseMap<const Type *, unsigned> TypeSubstitutions;
700b57cec5SDimitry Andric 
710b57cec5SDimitry Andric public:
USRGenerator(ASTContext * Ctx,SmallVectorImpl<char> & Buf)720b57cec5SDimitry Andric   explicit USRGenerator(ASTContext *Ctx, SmallVectorImpl<char> &Buf)
730b57cec5SDimitry Andric   : Buf(Buf),
740b57cec5SDimitry Andric     Out(Buf),
750b57cec5SDimitry Andric     IgnoreResults(false),
760b57cec5SDimitry Andric     Context(Ctx),
770b57cec5SDimitry Andric     generatedLoc(false)
780b57cec5SDimitry Andric   {
790b57cec5SDimitry Andric     // Add the USR space prefix.
800b57cec5SDimitry Andric     Out << getUSRSpacePrefix();
810b57cec5SDimitry Andric   }
820b57cec5SDimitry Andric 
ignoreResults() const830b57cec5SDimitry Andric   bool ignoreResults() const { return IgnoreResults; }
840b57cec5SDimitry Andric 
850b57cec5SDimitry Andric   // Visitation methods from generating USRs from AST elements.
860b57cec5SDimitry Andric   void VisitDeclContext(const DeclContext *D);
870b57cec5SDimitry Andric   void VisitFieldDecl(const FieldDecl *D);
880b57cec5SDimitry Andric   void VisitFunctionDecl(const FunctionDecl *D);
890b57cec5SDimitry Andric   void VisitNamedDecl(const NamedDecl *D);
900b57cec5SDimitry Andric   void VisitNamespaceDecl(const NamespaceDecl *D);
910b57cec5SDimitry Andric   void VisitNamespaceAliasDecl(const NamespaceAliasDecl *D);
920b57cec5SDimitry Andric   void VisitFunctionTemplateDecl(const FunctionTemplateDecl *D);
930b57cec5SDimitry Andric   void VisitClassTemplateDecl(const ClassTemplateDecl *D);
940b57cec5SDimitry Andric   void VisitObjCContainerDecl(const ObjCContainerDecl *CD,
950b57cec5SDimitry Andric                               const ObjCCategoryDecl *CatD = nullptr);
960b57cec5SDimitry Andric   void VisitObjCMethodDecl(const ObjCMethodDecl *MD);
970b57cec5SDimitry Andric   void VisitObjCPropertyDecl(const ObjCPropertyDecl *D);
980b57cec5SDimitry Andric   void VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D);
990b57cec5SDimitry Andric   void VisitTagDecl(const TagDecl *D);
1000b57cec5SDimitry Andric   void VisitTypedefDecl(const TypedefDecl *D);
1010b57cec5SDimitry Andric   void VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D);
1020b57cec5SDimitry Andric   void VisitVarDecl(const VarDecl *D);
1030b57cec5SDimitry Andric   void VisitBindingDecl(const BindingDecl *D);
1040b57cec5SDimitry Andric   void VisitNonTypeTemplateParmDecl(const NonTypeTemplateParmDecl *D);
1050b57cec5SDimitry Andric   void VisitTemplateTemplateParmDecl(const TemplateTemplateParmDecl *D);
1060b57cec5SDimitry Andric   void VisitUnresolvedUsingValueDecl(const UnresolvedUsingValueDecl *D);
1070b57cec5SDimitry Andric   void VisitUnresolvedUsingTypenameDecl(const UnresolvedUsingTypenameDecl *D);
10881ad6265SDimitry Andric   void VisitConceptDecl(const ConceptDecl *D);
1090b57cec5SDimitry Andric 
VisitLinkageSpecDecl(const LinkageSpecDecl * D)1100b57cec5SDimitry Andric   void VisitLinkageSpecDecl(const LinkageSpecDecl *D) {
1110b57cec5SDimitry Andric     IgnoreResults = true; // No USRs for linkage specs themselves.
1120b57cec5SDimitry Andric   }
1130b57cec5SDimitry Andric 
VisitUsingDirectiveDecl(const UsingDirectiveDecl * D)1140b57cec5SDimitry Andric   void VisitUsingDirectiveDecl(const UsingDirectiveDecl *D) {
1150b57cec5SDimitry Andric     IgnoreResults = true;
1160b57cec5SDimitry Andric   }
1170b57cec5SDimitry Andric 
VisitUsingDecl(const UsingDecl * D)1180b57cec5SDimitry Andric   void VisitUsingDecl(const UsingDecl *D) {
1190b57cec5SDimitry Andric     VisitDeclContext(D->getDeclContext());
1200b57cec5SDimitry Andric     Out << "@UD@";
1210b57cec5SDimitry Andric 
1220b57cec5SDimitry Andric     bool EmittedDeclName = !EmitDeclName(D);
1230b57cec5SDimitry Andric     assert(EmittedDeclName && "EmitDeclName can not fail for UsingDecls");
1240b57cec5SDimitry Andric     (void)EmittedDeclName;
1250b57cec5SDimitry Andric   }
1260b57cec5SDimitry Andric 
1270b57cec5SDimitry Andric   bool ShouldGenerateLocation(const NamedDecl *D);
1280b57cec5SDimitry Andric 
isLocal(const NamedDecl * D)1290b57cec5SDimitry Andric   bool isLocal(const NamedDecl *D) {
1300b57cec5SDimitry Andric     return D->getParentFunctionOrMethod() != nullptr;
1310b57cec5SDimitry Andric   }
1320b57cec5SDimitry Andric 
1330b57cec5SDimitry Andric   void GenExtSymbolContainer(const NamedDecl *D);
1340b57cec5SDimitry Andric 
1350b57cec5SDimitry Andric   /// Generate the string component containing the location of the
1360b57cec5SDimitry Andric   ///  declaration.
1370b57cec5SDimitry Andric   bool GenLoc(const Decl *D, bool IncludeOffset);
1380b57cec5SDimitry Andric 
1390b57cec5SDimitry Andric   /// String generation methods used both by the visitation methods
1400b57cec5SDimitry Andric   /// and from other clients that want to directly generate USRs.  These
1410b57cec5SDimitry Andric   /// methods do not construct complete USRs (which incorporate the parents
1420b57cec5SDimitry Andric   /// of an AST element), but only the fragments concerning the AST element
1430b57cec5SDimitry Andric   /// itself.
1440b57cec5SDimitry Andric 
1450b57cec5SDimitry Andric   /// Generate a USR for an Objective-C class.
GenObjCClass(StringRef cls,StringRef ExtSymDefinedIn,StringRef CategoryContextExtSymbolDefinedIn)1460b57cec5SDimitry Andric   void GenObjCClass(StringRef cls, StringRef ExtSymDefinedIn,
1470b57cec5SDimitry Andric                     StringRef CategoryContextExtSymbolDefinedIn) {
1480b57cec5SDimitry Andric     generateUSRForObjCClass(cls, Out, ExtSymDefinedIn,
1490b57cec5SDimitry Andric                             CategoryContextExtSymbolDefinedIn);
1500b57cec5SDimitry Andric   }
1510b57cec5SDimitry Andric 
1520b57cec5SDimitry Andric   /// Generate a USR for an Objective-C class category.
GenObjCCategory(StringRef cls,StringRef cat,StringRef clsExt,StringRef catExt)1530b57cec5SDimitry Andric   void GenObjCCategory(StringRef cls, StringRef cat,
1540b57cec5SDimitry Andric                        StringRef clsExt, StringRef catExt) {
1550b57cec5SDimitry Andric     generateUSRForObjCCategory(cls, cat, Out, clsExt, catExt);
1560b57cec5SDimitry Andric   }
1570b57cec5SDimitry Andric 
1580b57cec5SDimitry Andric   /// Generate a USR fragment for an Objective-C property.
GenObjCProperty(StringRef prop,bool isClassProp)1590b57cec5SDimitry Andric   void GenObjCProperty(StringRef prop, bool isClassProp) {
1600b57cec5SDimitry Andric     generateUSRForObjCProperty(prop, isClassProp, Out);
1610b57cec5SDimitry Andric   }
1620b57cec5SDimitry Andric 
1630b57cec5SDimitry Andric   /// Generate a USR for an Objective-C protocol.
GenObjCProtocol(StringRef prot,StringRef ext)1640b57cec5SDimitry Andric   void GenObjCProtocol(StringRef prot, StringRef ext) {
1650b57cec5SDimitry Andric     generateUSRForObjCProtocol(prot, Out, ext);
1660b57cec5SDimitry Andric   }
1670b57cec5SDimitry Andric 
1680b57cec5SDimitry Andric   void VisitType(QualType T);
1690b57cec5SDimitry Andric   void VisitTemplateParameterList(const TemplateParameterList *Params);
1700b57cec5SDimitry Andric   void VisitTemplateName(TemplateName Name);
1710b57cec5SDimitry Andric   void VisitTemplateArgument(const TemplateArgument &Arg);
1720b57cec5SDimitry Andric 
173bdd1243dSDimitry Andric   void VisitMSGuidDecl(const MSGuidDecl *D);
174bdd1243dSDimitry Andric 
1750b57cec5SDimitry Andric   /// Emit a Decl's name using NamedDecl::printName() and return true if
1760b57cec5SDimitry Andric   ///  the decl had no name.
1770b57cec5SDimitry Andric   bool EmitDeclName(const NamedDecl *D);
1780b57cec5SDimitry Andric };
1790b57cec5SDimitry Andric } // end anonymous namespace
1800b57cec5SDimitry Andric 
1810b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
1820b57cec5SDimitry Andric // Generating USRs from ASTS.
1830b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
1840b57cec5SDimitry Andric 
EmitDeclName(const NamedDecl * D)1850b57cec5SDimitry Andric bool USRGenerator::EmitDeclName(const NamedDecl *D) {
186bdd1243dSDimitry Andric   DeclarationName N = D->getDeclName();
187bdd1243dSDimitry Andric   if (N.isEmpty())
188bdd1243dSDimitry Andric     return true;
189bdd1243dSDimitry Andric   Out << N;
190bdd1243dSDimitry Andric   return false;
1910b57cec5SDimitry Andric }
1920b57cec5SDimitry Andric 
ShouldGenerateLocation(const NamedDecl * D)1930b57cec5SDimitry Andric bool USRGenerator::ShouldGenerateLocation(const NamedDecl *D) {
1940b57cec5SDimitry Andric   if (D->isExternallyVisible())
1950b57cec5SDimitry Andric     return false;
1960b57cec5SDimitry Andric   if (D->getParentFunctionOrMethod())
1970b57cec5SDimitry Andric     return true;
1980b57cec5SDimitry Andric   SourceLocation Loc = D->getLocation();
1990b57cec5SDimitry Andric   if (Loc.isInvalid())
2000b57cec5SDimitry Andric     return false;
2010b57cec5SDimitry Andric   const SourceManager &SM = Context->getSourceManager();
2020b57cec5SDimitry Andric   return !SM.isInSystemHeader(Loc);
2030b57cec5SDimitry Andric }
2040b57cec5SDimitry Andric 
VisitDeclContext(const DeclContext * DC)2050b57cec5SDimitry Andric void USRGenerator::VisitDeclContext(const DeclContext *DC) {
2060b57cec5SDimitry Andric   if (const NamedDecl *D = dyn_cast<NamedDecl>(DC))
2070b57cec5SDimitry Andric     Visit(D);
2080b57cec5SDimitry Andric   else if (isa<LinkageSpecDecl>(DC)) // Linkage specs are transparent in USRs.
2090b57cec5SDimitry Andric     VisitDeclContext(DC->getParent());
2100b57cec5SDimitry Andric }
2110b57cec5SDimitry Andric 
VisitFieldDecl(const FieldDecl * D)2120b57cec5SDimitry Andric void USRGenerator::VisitFieldDecl(const FieldDecl *D) {
2130b57cec5SDimitry Andric   // The USR for an ivar declared in a class extension is based on the
2140b57cec5SDimitry Andric   // ObjCInterfaceDecl, not the ObjCCategoryDecl.
2150b57cec5SDimitry Andric   if (const ObjCInterfaceDecl *ID = Context->getObjContainingInterface(D))
2160b57cec5SDimitry Andric     Visit(ID);
2170b57cec5SDimitry Andric   else
2180b57cec5SDimitry Andric     VisitDeclContext(D->getDeclContext());
2190b57cec5SDimitry Andric   Out << (isa<ObjCIvarDecl>(D) ? "@" : "@FI@");
2200b57cec5SDimitry Andric   if (EmitDeclName(D)) {
2210b57cec5SDimitry Andric     // Bit fields can be anonymous.
2220b57cec5SDimitry Andric     IgnoreResults = true;
2230b57cec5SDimitry Andric     return;
2240b57cec5SDimitry Andric   }
2250b57cec5SDimitry Andric }
2260b57cec5SDimitry Andric 
VisitFunctionDecl(const FunctionDecl * D)2270b57cec5SDimitry Andric void USRGenerator::VisitFunctionDecl(const FunctionDecl *D) {
2280b57cec5SDimitry Andric   if (ShouldGenerateLocation(D) && GenLoc(D, /*IncludeOffset=*/isLocal(D)))
2290b57cec5SDimitry Andric     return;
2300b57cec5SDimitry Andric 
23106c3fb27SDimitry Andric   if (D->getType().isNull()) {
23206c3fb27SDimitry Andric     IgnoreResults = true;
23306c3fb27SDimitry Andric     return;
23406c3fb27SDimitry Andric   }
23506c3fb27SDimitry Andric 
2360b57cec5SDimitry Andric   const unsigned StartSize = Buf.size();
2370b57cec5SDimitry Andric   VisitDeclContext(D->getDeclContext());
2380b57cec5SDimitry Andric   if (Buf.size() == StartSize)
2390b57cec5SDimitry Andric     GenExtSymbolContainer(D);
2400b57cec5SDimitry Andric 
2410b57cec5SDimitry Andric   bool IsTemplate = false;
2420b57cec5SDimitry Andric   if (FunctionTemplateDecl *FunTmpl = D->getDescribedFunctionTemplate()) {
2430b57cec5SDimitry Andric     IsTemplate = true;
2440b57cec5SDimitry Andric     Out << "@FT@";
2450b57cec5SDimitry Andric     VisitTemplateParameterList(FunTmpl->getTemplateParameters());
2460b57cec5SDimitry Andric   } else
2470b57cec5SDimitry Andric     Out << "@F@";
2480b57cec5SDimitry Andric 
2490b57cec5SDimitry Andric   PrintingPolicy Policy(Context->getLangOpts());
2500b57cec5SDimitry Andric   // Forward references can have different template argument names. Suppress the
2510b57cec5SDimitry Andric   // template argument names in constructors to make their USR more stable.
2520b57cec5SDimitry Andric   Policy.SuppressTemplateArgsInCXXConstructors = true;
2530b57cec5SDimitry Andric   D->getDeclName().print(Out, Policy);
2540b57cec5SDimitry Andric 
2550b57cec5SDimitry Andric   ASTContext &Ctx = *Context;
2560b57cec5SDimitry Andric   if ((!Ctx.getLangOpts().CPlusPlus || D->isExternC()) &&
2570b57cec5SDimitry Andric       !D->hasAttr<OverloadableAttr>())
2580b57cec5SDimitry Andric     return;
2590b57cec5SDimitry Andric 
2600b57cec5SDimitry Andric   if (const TemplateArgumentList *
2610b57cec5SDimitry Andric         SpecArgs = D->getTemplateSpecializationArgs()) {
2620b57cec5SDimitry Andric     Out << '<';
2630b57cec5SDimitry Andric     for (unsigned I = 0, N = SpecArgs->size(); I != N; ++I) {
2640b57cec5SDimitry Andric       Out << '#';
2650b57cec5SDimitry Andric       VisitTemplateArgument(SpecArgs->get(I));
2660b57cec5SDimitry Andric     }
2670b57cec5SDimitry Andric     Out << '>';
2680b57cec5SDimitry Andric   }
2690b57cec5SDimitry Andric 
2700b57cec5SDimitry Andric   // Mangle in type information for the arguments.
271bdd1243dSDimitry Andric   for (auto *PD : D->parameters()) {
2720b57cec5SDimitry Andric     Out << '#';
2730b57cec5SDimitry Andric     VisitType(PD->getType());
2740b57cec5SDimitry Andric   }
2750b57cec5SDimitry Andric   if (D->isVariadic())
2760b57cec5SDimitry Andric     Out << '.';
2770b57cec5SDimitry Andric   if (IsTemplate) {
2780b57cec5SDimitry Andric     // Function templates can be overloaded by return type, for example:
2790b57cec5SDimitry Andric     // \code
2800b57cec5SDimitry Andric     //   template <class T> typename T::A foo() {}
2810b57cec5SDimitry Andric     //   template <class T> typename T::B foo() {}
2820b57cec5SDimitry Andric     // \endcode
2830b57cec5SDimitry Andric     Out << '#';
2840b57cec5SDimitry Andric     VisitType(D->getReturnType());
2850b57cec5SDimitry Andric   }
2860b57cec5SDimitry Andric   Out << '#';
2870b57cec5SDimitry Andric   if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {
2880b57cec5SDimitry Andric     if (MD->isStatic())
2890b57cec5SDimitry Andric       Out << 'S';
2900b57cec5SDimitry Andric     // FIXME: OpenCL: Need to consider address spaces
2910b57cec5SDimitry Andric     if (unsigned quals = MD->getMethodQualifiers().getCVRUQualifiers())
2920b57cec5SDimitry Andric       Out << (char)('0' + quals);
2930b57cec5SDimitry Andric     switch (MD->getRefQualifier()) {
2940b57cec5SDimitry Andric     case RQ_None: break;
2950b57cec5SDimitry Andric     case RQ_LValue: Out << '&'; break;
2960b57cec5SDimitry Andric     case RQ_RValue: Out << "&&"; break;
2970b57cec5SDimitry Andric     }
2980b57cec5SDimitry Andric   }
2990b57cec5SDimitry Andric }
3000b57cec5SDimitry Andric 
VisitNamedDecl(const NamedDecl * D)3010b57cec5SDimitry Andric void USRGenerator::VisitNamedDecl(const NamedDecl *D) {
3020b57cec5SDimitry Andric   VisitDeclContext(D->getDeclContext());
3030b57cec5SDimitry Andric   Out << "@";
3040b57cec5SDimitry Andric 
3050b57cec5SDimitry Andric   if (EmitDeclName(D)) {
3060b57cec5SDimitry Andric     // The string can be empty if the declaration has no name; e.g., it is
3070b57cec5SDimitry Andric     // the ParmDecl with no name for declaration of a function pointer type,
3080b57cec5SDimitry Andric     // e.g.: void  (*f)(void *);
3090b57cec5SDimitry Andric     // In this case, don't generate a USR.
3100b57cec5SDimitry Andric     IgnoreResults = true;
3110b57cec5SDimitry Andric   }
3120b57cec5SDimitry Andric }
3130b57cec5SDimitry Andric 
VisitVarDecl(const VarDecl * D)3140b57cec5SDimitry Andric void USRGenerator::VisitVarDecl(const VarDecl *D) {
3150b57cec5SDimitry Andric   // VarDecls can be declared 'extern' within a function or method body,
3160b57cec5SDimitry Andric   // but their enclosing DeclContext is the function, not the TU.  We need
3170b57cec5SDimitry Andric   // to check the storage class to correctly generate the USR.
3180b57cec5SDimitry Andric   if (ShouldGenerateLocation(D) && GenLoc(D, /*IncludeOffset=*/isLocal(D)))
3190b57cec5SDimitry Andric     return;
3200b57cec5SDimitry Andric 
3210b57cec5SDimitry Andric   VisitDeclContext(D->getDeclContext());
3220b57cec5SDimitry Andric 
3230b57cec5SDimitry Andric   if (VarTemplateDecl *VarTmpl = D->getDescribedVarTemplate()) {
3240b57cec5SDimitry Andric     Out << "@VT";
3250b57cec5SDimitry Andric     VisitTemplateParameterList(VarTmpl->getTemplateParameters());
3260b57cec5SDimitry Andric   } else if (const VarTemplatePartialSpecializationDecl *PartialSpec
3270b57cec5SDimitry Andric              = dyn_cast<VarTemplatePartialSpecializationDecl>(D)) {
3280b57cec5SDimitry Andric     Out << "@VP";
3290b57cec5SDimitry Andric     VisitTemplateParameterList(PartialSpec->getTemplateParameters());
3300b57cec5SDimitry Andric   }
3310b57cec5SDimitry Andric 
3320b57cec5SDimitry Andric   // Variables always have simple names.
3330b57cec5SDimitry Andric   StringRef s = D->getName();
3340b57cec5SDimitry Andric 
3350b57cec5SDimitry Andric   // The string can be empty if the declaration has no name; e.g., it is
3360b57cec5SDimitry Andric   // the ParmDecl with no name for declaration of a function pointer type, e.g.:
3370b57cec5SDimitry Andric   //    void  (*f)(void *);
3380b57cec5SDimitry Andric   // In this case, don't generate a USR.
3390b57cec5SDimitry Andric   if (s.empty())
3400b57cec5SDimitry Andric     IgnoreResults = true;
3410b57cec5SDimitry Andric   else
3420b57cec5SDimitry Andric     Out << '@' << s;
3430b57cec5SDimitry Andric 
3440b57cec5SDimitry Andric   // For a template specialization, mangle the template arguments.
3450b57cec5SDimitry Andric   if (const VarTemplateSpecializationDecl *Spec
3460b57cec5SDimitry Andric                               = dyn_cast<VarTemplateSpecializationDecl>(D)) {
3470b57cec5SDimitry Andric     const TemplateArgumentList &Args = Spec->getTemplateArgs();
3480b57cec5SDimitry Andric     Out << '>';
3490b57cec5SDimitry Andric     for (unsigned I = 0, N = Args.size(); I != N; ++I) {
3500b57cec5SDimitry Andric       Out << '#';
3510b57cec5SDimitry Andric       VisitTemplateArgument(Args.get(I));
3520b57cec5SDimitry Andric     }
3530b57cec5SDimitry Andric   }
3540b57cec5SDimitry Andric }
3550b57cec5SDimitry Andric 
VisitBindingDecl(const BindingDecl * D)3560b57cec5SDimitry Andric void USRGenerator::VisitBindingDecl(const BindingDecl *D) {
3570b57cec5SDimitry Andric   if (isLocal(D) && GenLoc(D, /*IncludeOffset=*/true))
3580b57cec5SDimitry Andric     return;
3590b57cec5SDimitry Andric   VisitNamedDecl(D);
3600b57cec5SDimitry Andric }
3610b57cec5SDimitry Andric 
VisitNonTypeTemplateParmDecl(const NonTypeTemplateParmDecl * D)3620b57cec5SDimitry Andric void USRGenerator::VisitNonTypeTemplateParmDecl(
3630b57cec5SDimitry Andric                                         const NonTypeTemplateParmDecl *D) {
3640b57cec5SDimitry Andric   GenLoc(D, /*IncludeOffset=*/true);
3650b57cec5SDimitry Andric }
3660b57cec5SDimitry Andric 
VisitTemplateTemplateParmDecl(const TemplateTemplateParmDecl * D)3670b57cec5SDimitry Andric void USRGenerator::VisitTemplateTemplateParmDecl(
3680b57cec5SDimitry Andric                                         const TemplateTemplateParmDecl *D) {
3690b57cec5SDimitry Andric   GenLoc(D, /*IncludeOffset=*/true);
3700b57cec5SDimitry Andric }
3710b57cec5SDimitry Andric 
VisitNamespaceDecl(const NamespaceDecl * D)3720b57cec5SDimitry Andric void USRGenerator::VisitNamespaceDecl(const NamespaceDecl *D) {
3735f757f3fSDimitry Andric   if (IgnoreResults)
3745f757f3fSDimitry Andric     return;
3755f757f3fSDimitry Andric   VisitDeclContext(D->getDeclContext());
3760b57cec5SDimitry Andric   if (D->isAnonymousNamespace()) {
3770b57cec5SDimitry Andric     Out << "@aN";
3780b57cec5SDimitry Andric     return;
3790b57cec5SDimitry Andric   }
3800b57cec5SDimitry Andric   Out << "@N@" << D->getName();
3810b57cec5SDimitry Andric }
3820b57cec5SDimitry Andric 
VisitFunctionTemplateDecl(const FunctionTemplateDecl * D)3830b57cec5SDimitry Andric void USRGenerator::VisitFunctionTemplateDecl(const FunctionTemplateDecl *D) {
3840b57cec5SDimitry Andric   VisitFunctionDecl(D->getTemplatedDecl());
3850b57cec5SDimitry Andric }
3860b57cec5SDimitry Andric 
VisitClassTemplateDecl(const ClassTemplateDecl * D)3870b57cec5SDimitry Andric void USRGenerator::VisitClassTemplateDecl(const ClassTemplateDecl *D) {
3880b57cec5SDimitry Andric   VisitTagDecl(D->getTemplatedDecl());
3890b57cec5SDimitry Andric }
3900b57cec5SDimitry Andric 
VisitNamespaceAliasDecl(const NamespaceAliasDecl * D)3910b57cec5SDimitry Andric void USRGenerator::VisitNamespaceAliasDecl(const NamespaceAliasDecl *D) {
3920b57cec5SDimitry Andric   VisitDeclContext(D->getDeclContext());
3930b57cec5SDimitry Andric   if (!IgnoreResults)
3940b57cec5SDimitry Andric     Out << "@NA@" << D->getName();
3950b57cec5SDimitry Andric }
3960b57cec5SDimitry Andric 
getCategoryContext(const NamedDecl * D)3975ffd83dbSDimitry Andric static const ObjCCategoryDecl *getCategoryContext(const NamedDecl *D) {
3985ffd83dbSDimitry Andric   if (auto *CD = dyn_cast<ObjCCategoryDecl>(D->getDeclContext()))
3995ffd83dbSDimitry Andric     return CD;
4005ffd83dbSDimitry Andric   if (auto *ICD = dyn_cast<ObjCCategoryImplDecl>(D->getDeclContext()))
4015ffd83dbSDimitry Andric     return ICD->getCategoryDecl();
4025ffd83dbSDimitry Andric   return nullptr;
4035ffd83dbSDimitry Andric }
4045ffd83dbSDimitry Andric 
VisitObjCMethodDecl(const ObjCMethodDecl * D)4050b57cec5SDimitry Andric void USRGenerator::VisitObjCMethodDecl(const ObjCMethodDecl *D) {
4060b57cec5SDimitry Andric   const DeclContext *container = D->getDeclContext();
4070b57cec5SDimitry Andric   if (const ObjCProtocolDecl *pd = dyn_cast<ObjCProtocolDecl>(container)) {
4080b57cec5SDimitry Andric     Visit(pd);
4090b57cec5SDimitry Andric   }
4100b57cec5SDimitry Andric   else {
4110b57cec5SDimitry Andric     // The USR for a method declared in a class extension or category is based on
4120b57cec5SDimitry Andric     // the ObjCInterfaceDecl, not the ObjCCategoryDecl.
4130b57cec5SDimitry Andric     const ObjCInterfaceDecl *ID = D->getClassInterface();
4140b57cec5SDimitry Andric     if (!ID) {
4150b57cec5SDimitry Andric       IgnoreResults = true;
4160b57cec5SDimitry Andric       return;
4170b57cec5SDimitry Andric     }
4180b57cec5SDimitry Andric     auto *CD = getCategoryContext(D);
4190b57cec5SDimitry Andric     VisitObjCContainerDecl(ID, CD);
4200b57cec5SDimitry Andric   }
4210b57cec5SDimitry Andric   // Ideally we would use 'GenObjCMethod', but this is such a hot path
4220b57cec5SDimitry Andric   // for Objective-C code that we don't want to use
4230b57cec5SDimitry Andric   // DeclarationName::getAsString().
4240b57cec5SDimitry Andric   Out << (D->isInstanceMethod() ? "(im)" : "(cm)")
4250b57cec5SDimitry Andric       << DeclarationName(D->getSelector());
4260b57cec5SDimitry Andric }
4270b57cec5SDimitry Andric 
VisitObjCContainerDecl(const ObjCContainerDecl * D,const ObjCCategoryDecl * CatD)4280b57cec5SDimitry Andric void USRGenerator::VisitObjCContainerDecl(const ObjCContainerDecl *D,
4290b57cec5SDimitry Andric                                           const ObjCCategoryDecl *CatD) {
4300b57cec5SDimitry Andric   switch (D->getKind()) {
4310b57cec5SDimitry Andric     default:
4320b57cec5SDimitry Andric       llvm_unreachable("Invalid ObjC container.");
4330b57cec5SDimitry Andric     case Decl::ObjCInterface:
4340b57cec5SDimitry Andric     case Decl::ObjCImplementation:
4350b57cec5SDimitry Andric       GenObjCClass(D->getName(), GetExternalSourceContainer(D),
4360b57cec5SDimitry Andric                    GetExternalSourceContainer(CatD));
4370b57cec5SDimitry Andric       break;
4380b57cec5SDimitry Andric     case Decl::ObjCCategory: {
4390b57cec5SDimitry Andric       const ObjCCategoryDecl *CD = cast<ObjCCategoryDecl>(D);
4400b57cec5SDimitry Andric       const ObjCInterfaceDecl *ID = CD->getClassInterface();
4410b57cec5SDimitry Andric       if (!ID) {
4420b57cec5SDimitry Andric         // Handle invalid code where the @interface might not
4430b57cec5SDimitry Andric         // have been specified.
4440b57cec5SDimitry Andric         // FIXME: We should be able to generate this USR even if the
4450b57cec5SDimitry Andric         // @interface isn't available.
4460b57cec5SDimitry Andric         IgnoreResults = true;
4470b57cec5SDimitry Andric         return;
4480b57cec5SDimitry Andric       }
4490b57cec5SDimitry Andric       // Specially handle class extensions, which are anonymous categories.
4500b57cec5SDimitry Andric       // We want to mangle in the location to uniquely distinguish them.
4510b57cec5SDimitry Andric       if (CD->IsClassExtension()) {
4520b57cec5SDimitry Andric         Out << "objc(ext)" << ID->getName() << '@';
4530b57cec5SDimitry Andric         GenLoc(CD, /*IncludeOffset=*/true);
4540b57cec5SDimitry Andric       }
4550b57cec5SDimitry Andric       else
4560b57cec5SDimitry Andric         GenObjCCategory(ID->getName(), CD->getName(),
4570b57cec5SDimitry Andric                         GetExternalSourceContainer(ID),
4580b57cec5SDimitry Andric                         GetExternalSourceContainer(CD));
4590b57cec5SDimitry Andric 
4600b57cec5SDimitry Andric       break;
4610b57cec5SDimitry Andric     }
4620b57cec5SDimitry Andric     case Decl::ObjCCategoryImpl: {
4630b57cec5SDimitry Andric       const ObjCCategoryImplDecl *CD = cast<ObjCCategoryImplDecl>(D);
4640b57cec5SDimitry Andric       const ObjCInterfaceDecl *ID = CD->getClassInterface();
4650b57cec5SDimitry Andric       if (!ID) {
4660b57cec5SDimitry Andric         // Handle invalid code where the @interface might not
4670b57cec5SDimitry Andric         // have been specified.
4680b57cec5SDimitry Andric         // FIXME: We should be able to generate this USR even if the
4690b57cec5SDimitry Andric         // @interface isn't available.
4700b57cec5SDimitry Andric         IgnoreResults = true;
4710b57cec5SDimitry Andric         return;
4720b57cec5SDimitry Andric       }
4730b57cec5SDimitry Andric       GenObjCCategory(ID->getName(), CD->getName(),
4740b57cec5SDimitry Andric                       GetExternalSourceContainer(ID),
4750b57cec5SDimitry Andric                       GetExternalSourceContainer(CD));
4760b57cec5SDimitry Andric       break;
4770b57cec5SDimitry Andric     }
4780b57cec5SDimitry Andric     case Decl::ObjCProtocol: {
4790b57cec5SDimitry Andric       const ObjCProtocolDecl *PD = cast<ObjCProtocolDecl>(D);
4800b57cec5SDimitry Andric       GenObjCProtocol(PD->getName(), GetExternalSourceContainer(PD));
4810b57cec5SDimitry Andric       break;
4820b57cec5SDimitry Andric     }
4830b57cec5SDimitry Andric   }
4840b57cec5SDimitry Andric }
4850b57cec5SDimitry Andric 
VisitObjCPropertyDecl(const ObjCPropertyDecl * D)4860b57cec5SDimitry Andric void USRGenerator::VisitObjCPropertyDecl(const ObjCPropertyDecl *D) {
4870b57cec5SDimitry Andric   // The USR for a property declared in a class extension or category is based
4880b57cec5SDimitry Andric   // on the ObjCInterfaceDecl, not the ObjCCategoryDecl.
4890b57cec5SDimitry Andric   if (const ObjCInterfaceDecl *ID = Context->getObjContainingInterface(D))
4905ffd83dbSDimitry Andric     VisitObjCContainerDecl(ID, getCategoryContext(D));
4910b57cec5SDimitry Andric   else
4920b57cec5SDimitry Andric     Visit(cast<Decl>(D->getDeclContext()));
4930b57cec5SDimitry Andric   GenObjCProperty(D->getName(), D->isClassProperty());
4940b57cec5SDimitry Andric }
4950b57cec5SDimitry Andric 
VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl * D)4960b57cec5SDimitry Andric void USRGenerator::VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D) {
4970b57cec5SDimitry Andric   if (ObjCPropertyDecl *PD = D->getPropertyDecl()) {
4980b57cec5SDimitry Andric     VisitObjCPropertyDecl(PD);
4990b57cec5SDimitry Andric     return;
5000b57cec5SDimitry Andric   }
5010b57cec5SDimitry Andric 
5020b57cec5SDimitry Andric   IgnoreResults = true;
5030b57cec5SDimitry Andric }
5040b57cec5SDimitry Andric 
VisitTagDecl(const TagDecl * D)5050b57cec5SDimitry Andric void USRGenerator::VisitTagDecl(const TagDecl *D) {
5060b57cec5SDimitry Andric   // Add the location of the tag decl to handle resolution across
5070b57cec5SDimitry Andric   // translation units.
5080b57cec5SDimitry Andric   if (!isa<EnumDecl>(D) &&
5090b57cec5SDimitry Andric       ShouldGenerateLocation(D) && GenLoc(D, /*IncludeOffset=*/isLocal(D)))
5100b57cec5SDimitry Andric     return;
5110b57cec5SDimitry Andric 
5120b57cec5SDimitry Andric   GenExtSymbolContainer(D);
5130b57cec5SDimitry Andric 
5140b57cec5SDimitry Andric   D = D->getCanonicalDecl();
5150b57cec5SDimitry Andric   VisitDeclContext(D->getDeclContext());
5160b57cec5SDimitry Andric 
5170b57cec5SDimitry Andric   bool AlreadyStarted = false;
5180b57cec5SDimitry Andric   if (const CXXRecordDecl *CXXRecord = dyn_cast<CXXRecordDecl>(D)) {
5190b57cec5SDimitry Andric     if (ClassTemplateDecl *ClassTmpl = CXXRecord->getDescribedClassTemplate()) {
5200b57cec5SDimitry Andric       AlreadyStarted = true;
5210b57cec5SDimitry Andric 
5220b57cec5SDimitry Andric       switch (D->getTagKind()) {
5235f757f3fSDimitry Andric       case TagTypeKind::Interface:
5245f757f3fSDimitry Andric       case TagTypeKind::Class:
5255f757f3fSDimitry Andric       case TagTypeKind::Struct:
5265f757f3fSDimitry Andric         Out << "@ST";
5275f757f3fSDimitry Andric         break;
5285f757f3fSDimitry Andric       case TagTypeKind::Union:
5295f757f3fSDimitry Andric         Out << "@UT";
5305f757f3fSDimitry Andric         break;
5315f757f3fSDimitry Andric       case TagTypeKind::Enum:
5325f757f3fSDimitry Andric         llvm_unreachable("enum template");
5330b57cec5SDimitry Andric       }
5340b57cec5SDimitry Andric       VisitTemplateParameterList(ClassTmpl->getTemplateParameters());
5350b57cec5SDimitry Andric     } else if (const ClassTemplatePartialSpecializationDecl *PartialSpec
5360b57cec5SDimitry Andric                 = dyn_cast<ClassTemplatePartialSpecializationDecl>(CXXRecord)) {
5370b57cec5SDimitry Andric       AlreadyStarted = true;
5380b57cec5SDimitry Andric 
5390b57cec5SDimitry Andric       switch (D->getTagKind()) {
5405f757f3fSDimitry Andric       case TagTypeKind::Interface:
5415f757f3fSDimitry Andric       case TagTypeKind::Class:
5425f757f3fSDimitry Andric       case TagTypeKind::Struct:
5435f757f3fSDimitry Andric         Out << "@SP";
5445f757f3fSDimitry Andric         break;
5455f757f3fSDimitry Andric       case TagTypeKind::Union:
5465f757f3fSDimitry Andric         Out << "@UP";
5475f757f3fSDimitry Andric         break;
5485f757f3fSDimitry Andric       case TagTypeKind::Enum:
5495f757f3fSDimitry Andric         llvm_unreachable("enum partial specialization");
5500b57cec5SDimitry Andric       }
5510b57cec5SDimitry Andric       VisitTemplateParameterList(PartialSpec->getTemplateParameters());
5520b57cec5SDimitry Andric     }
5530b57cec5SDimitry Andric   }
5540b57cec5SDimitry Andric 
5550b57cec5SDimitry Andric   if (!AlreadyStarted) {
5560b57cec5SDimitry Andric     switch (D->getTagKind()) {
5575f757f3fSDimitry Andric     case TagTypeKind::Interface:
5585f757f3fSDimitry Andric     case TagTypeKind::Class:
5595f757f3fSDimitry Andric     case TagTypeKind::Struct:
5605f757f3fSDimitry Andric       Out << "@S";
5615f757f3fSDimitry Andric       break;
5625f757f3fSDimitry Andric     case TagTypeKind::Union:
5635f757f3fSDimitry Andric       Out << "@U";
5645f757f3fSDimitry Andric       break;
5655f757f3fSDimitry Andric     case TagTypeKind::Enum:
5665f757f3fSDimitry Andric       Out << "@E";
5675f757f3fSDimitry Andric       break;
5680b57cec5SDimitry Andric     }
5690b57cec5SDimitry Andric   }
5700b57cec5SDimitry Andric 
5710b57cec5SDimitry Andric   Out << '@';
5720b57cec5SDimitry Andric   assert(Buf.size() > 0);
5730b57cec5SDimitry Andric   const unsigned off = Buf.size() - 1;
5740b57cec5SDimitry Andric 
5750b57cec5SDimitry Andric   if (EmitDeclName(D)) {
5760b57cec5SDimitry Andric     if (const TypedefNameDecl *TD = D->getTypedefNameForAnonDecl()) {
5770b57cec5SDimitry Andric       Buf[off] = 'A';
5780b57cec5SDimitry Andric       Out << '@' << *TD;
57981ad6265SDimitry Andric     } else {
5800b57cec5SDimitry Andric       if (D->isEmbeddedInDeclarator() && !D->isFreeStanding()) {
5810b57cec5SDimitry Andric         printLoc(Out, D->getLocation(), Context->getSourceManager(), true);
5820b57cec5SDimitry Andric       } else {
5830b57cec5SDimitry Andric         Buf[off] = 'a';
5840b57cec5SDimitry Andric         if (auto *ED = dyn_cast<EnumDecl>(D)) {
58581ad6265SDimitry Andric           // Distinguish USRs of anonymous enums by using their first
58681ad6265SDimitry Andric           // enumerator.
5870b57cec5SDimitry Andric           auto enum_range = ED->enumerators();
5880b57cec5SDimitry Andric           if (enum_range.begin() != enum_range.end()) {
5890b57cec5SDimitry Andric             Out << '@' << **enum_range.begin();
5900b57cec5SDimitry Andric           }
5910b57cec5SDimitry Andric         }
5920b57cec5SDimitry Andric       }
5930b57cec5SDimitry Andric     }
5940b57cec5SDimitry Andric   }
5950b57cec5SDimitry Andric 
5960b57cec5SDimitry Andric   // For a class template specialization, mangle the template arguments.
5970b57cec5SDimitry Andric   if (const ClassTemplateSpecializationDecl *Spec
5980b57cec5SDimitry Andric                               = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
5990b57cec5SDimitry Andric     const TemplateArgumentList &Args = Spec->getTemplateArgs();
6000b57cec5SDimitry Andric     Out << '>';
6010b57cec5SDimitry Andric     for (unsigned I = 0, N = Args.size(); I != N; ++I) {
6020b57cec5SDimitry Andric       Out << '#';
6030b57cec5SDimitry Andric       VisitTemplateArgument(Args.get(I));
6040b57cec5SDimitry Andric     }
6050b57cec5SDimitry Andric   }
6060b57cec5SDimitry Andric }
6070b57cec5SDimitry Andric 
VisitTypedefDecl(const TypedefDecl * D)6080b57cec5SDimitry Andric void USRGenerator::VisitTypedefDecl(const TypedefDecl *D) {
6090b57cec5SDimitry Andric   if (ShouldGenerateLocation(D) && GenLoc(D, /*IncludeOffset=*/isLocal(D)))
6100b57cec5SDimitry Andric     return;
6110b57cec5SDimitry Andric   const DeclContext *DC = D->getDeclContext();
6120b57cec5SDimitry Andric   if (const NamedDecl *DCN = dyn_cast<NamedDecl>(DC))
6130b57cec5SDimitry Andric     Visit(DCN);
6140b57cec5SDimitry Andric   Out << "@T@";
6150b57cec5SDimitry Andric   Out << D->getName();
6160b57cec5SDimitry Andric }
6170b57cec5SDimitry Andric 
VisitTemplateTypeParmDecl(const TemplateTypeParmDecl * D)6180b57cec5SDimitry Andric void USRGenerator::VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D) {
6190b57cec5SDimitry Andric   GenLoc(D, /*IncludeOffset=*/true);
6200b57cec5SDimitry Andric }
6210b57cec5SDimitry Andric 
GenExtSymbolContainer(const NamedDecl * D)6220b57cec5SDimitry Andric void USRGenerator::GenExtSymbolContainer(const NamedDecl *D) {
6230b57cec5SDimitry Andric   StringRef Container = GetExternalSourceContainer(D);
6240b57cec5SDimitry Andric   if (!Container.empty())
6250b57cec5SDimitry Andric     Out << "@M@" << Container;
6260b57cec5SDimitry Andric }
6270b57cec5SDimitry Andric 
GenLoc(const Decl * D,bool IncludeOffset)6280b57cec5SDimitry Andric bool USRGenerator::GenLoc(const Decl *D, bool IncludeOffset) {
6290b57cec5SDimitry Andric   if (generatedLoc)
6300b57cec5SDimitry Andric     return IgnoreResults;
6310b57cec5SDimitry Andric   generatedLoc = true;
6320b57cec5SDimitry Andric 
6330b57cec5SDimitry Andric   // Guard against null declarations in invalid code.
6340b57cec5SDimitry Andric   if (!D) {
6350b57cec5SDimitry Andric     IgnoreResults = true;
6360b57cec5SDimitry Andric     return true;
6370b57cec5SDimitry Andric   }
6380b57cec5SDimitry Andric 
6390b57cec5SDimitry Andric   // Use the location of canonical decl.
6400b57cec5SDimitry Andric   D = D->getCanonicalDecl();
6410b57cec5SDimitry Andric 
6420b57cec5SDimitry Andric   IgnoreResults =
6430b57cec5SDimitry Andric       IgnoreResults || printLoc(Out, D->getBeginLoc(),
6440b57cec5SDimitry Andric                                 Context->getSourceManager(), IncludeOffset);
6450b57cec5SDimitry Andric 
6460b57cec5SDimitry Andric   return IgnoreResults;
6470b57cec5SDimitry Andric }
6480b57cec5SDimitry Andric 
printQualifier(llvm::raw_ostream & Out,ASTContext & Ctx,NestedNameSpecifier * NNS)6490b57cec5SDimitry Andric static void printQualifier(llvm::raw_ostream &Out, ASTContext &Ctx, NestedNameSpecifier *NNS) {
6500b57cec5SDimitry Andric   // FIXME: Encode the qualifier, don't just print it.
6510b57cec5SDimitry Andric   PrintingPolicy PO(Ctx.getLangOpts());
6520b57cec5SDimitry Andric   PO.SuppressTagKeyword = true;
6530b57cec5SDimitry Andric   PO.SuppressUnwrittenScope = true;
6540b57cec5SDimitry Andric   PO.ConstantArraySizeAsWritten = false;
6550b57cec5SDimitry Andric   PO.AnonymousTagLocations = false;
6560b57cec5SDimitry Andric   NNS->print(Out, PO);
6570b57cec5SDimitry Andric }
6580b57cec5SDimitry Andric 
VisitType(QualType T)6590b57cec5SDimitry Andric void USRGenerator::VisitType(QualType T) {
6600b57cec5SDimitry Andric   // This method mangles in USR information for types.  It can possibly
6610b57cec5SDimitry Andric   // just reuse the naming-mangling logic used by codegen, although the
6620b57cec5SDimitry Andric   // requirements for USRs might not be the same.
6630b57cec5SDimitry Andric   ASTContext &Ctx = *Context;
6640b57cec5SDimitry Andric 
6650b57cec5SDimitry Andric   do {
6660b57cec5SDimitry Andric     T = Ctx.getCanonicalType(T);
6670b57cec5SDimitry Andric     Qualifiers Q = T.getQualifiers();
6680b57cec5SDimitry Andric     unsigned qVal = 0;
6690b57cec5SDimitry Andric     if (Q.hasConst())
6700b57cec5SDimitry Andric       qVal |= 0x1;
6710b57cec5SDimitry Andric     if (Q.hasVolatile())
6720b57cec5SDimitry Andric       qVal |= 0x2;
6730b57cec5SDimitry Andric     if (Q.hasRestrict())
6740b57cec5SDimitry Andric       qVal |= 0x4;
6750b57cec5SDimitry Andric     if(qVal)
6760b57cec5SDimitry Andric       Out << ((char) ('0' + qVal));
6770b57cec5SDimitry Andric 
6780b57cec5SDimitry Andric     // Mangle in ObjC GC qualifiers?
6790b57cec5SDimitry Andric 
6800b57cec5SDimitry Andric     if (const PackExpansionType *Expansion = T->getAs<PackExpansionType>()) {
6810b57cec5SDimitry Andric       Out << 'P';
6820b57cec5SDimitry Andric       T = Expansion->getPattern();
6830b57cec5SDimitry Andric     }
6840b57cec5SDimitry Andric 
6850b57cec5SDimitry Andric     if (const BuiltinType *BT = T->getAs<BuiltinType>()) {
6860b57cec5SDimitry Andric       switch (BT->getKind()) {
6870b57cec5SDimitry Andric         case BuiltinType::Void:
688bdd1243dSDimitry Andric           Out << 'v'; break;
6890b57cec5SDimitry Andric         case BuiltinType::Bool:
690bdd1243dSDimitry Andric           Out << 'b'; break;
6910b57cec5SDimitry Andric         case BuiltinType::UChar:
692bdd1243dSDimitry Andric           Out << 'c'; break;
6930b57cec5SDimitry Andric         case BuiltinType::Char8:
694bdd1243dSDimitry Andric           Out << 'u'; break;
6950b57cec5SDimitry Andric         case BuiltinType::Char16:
696bdd1243dSDimitry Andric           Out << 'q'; break;
6970b57cec5SDimitry Andric         case BuiltinType::Char32:
698bdd1243dSDimitry Andric           Out << 'w'; break;
6990b57cec5SDimitry Andric         case BuiltinType::UShort:
700bdd1243dSDimitry Andric           Out << 's'; break;
7010b57cec5SDimitry Andric         case BuiltinType::UInt:
702bdd1243dSDimitry Andric           Out << 'i'; break;
7030b57cec5SDimitry Andric         case BuiltinType::ULong:
704bdd1243dSDimitry Andric           Out << 'l'; break;
7050b57cec5SDimitry Andric         case BuiltinType::ULongLong:
706bdd1243dSDimitry Andric           Out << 'k'; break;
7070b57cec5SDimitry Andric         case BuiltinType::UInt128:
708bdd1243dSDimitry Andric           Out << 'j'; break;
7090b57cec5SDimitry Andric         case BuiltinType::Char_U:
7100b57cec5SDimitry Andric         case BuiltinType::Char_S:
711bdd1243dSDimitry Andric           Out << 'C'; break;
7120b57cec5SDimitry Andric         case BuiltinType::SChar:
713bdd1243dSDimitry Andric           Out << 'r'; break;
7140b57cec5SDimitry Andric         case BuiltinType::WChar_S:
7150b57cec5SDimitry Andric         case BuiltinType::WChar_U:
716bdd1243dSDimitry Andric           Out << 'W'; break;
7170b57cec5SDimitry Andric         case BuiltinType::Short:
718bdd1243dSDimitry Andric           Out << 'S'; break;
7190b57cec5SDimitry Andric         case BuiltinType::Int:
720bdd1243dSDimitry Andric           Out << 'I'; break;
7210b57cec5SDimitry Andric         case BuiltinType::Long:
722bdd1243dSDimitry Andric           Out << 'L'; break;
7230b57cec5SDimitry Andric         case BuiltinType::LongLong:
724bdd1243dSDimitry Andric           Out << 'K'; break;
7250b57cec5SDimitry Andric         case BuiltinType::Int128:
726bdd1243dSDimitry Andric           Out << 'J'; break;
7270b57cec5SDimitry Andric         case BuiltinType::Float16:
7280b57cec5SDimitry Andric         case BuiltinType::Half:
729bdd1243dSDimitry Andric           Out << 'h'; break;
7300b57cec5SDimitry Andric         case BuiltinType::Float:
731bdd1243dSDimitry Andric           Out << 'f'; break;
7320b57cec5SDimitry Andric         case BuiltinType::Double:
733bdd1243dSDimitry Andric           Out << 'd'; break;
7340b57cec5SDimitry Andric         case BuiltinType::LongDouble:
735bdd1243dSDimitry Andric           Out << 'D'; break;
7360b57cec5SDimitry Andric         case BuiltinType::Float128:
737bdd1243dSDimitry Andric           Out << 'Q'; break;
7380b57cec5SDimitry Andric         case BuiltinType::NullPtr:
739bdd1243dSDimitry Andric           Out << 'n'; break;
740bdd1243dSDimitry Andric #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
741bdd1243dSDimitry Andric         case BuiltinType::Id: \
742bdd1243dSDimitry Andric           Out << "@BT@" << #Suffix << "_" << #ImgType; break;
743bdd1243dSDimitry Andric #include "clang/Basic/OpenCLImageTypes.def"
744bdd1243dSDimitry Andric #define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
745bdd1243dSDimitry Andric         case BuiltinType::Id: \
746bdd1243dSDimitry Andric           Out << "@BT@" << #ExtType; break;
747bdd1243dSDimitry Andric #include "clang/Basic/OpenCLExtensionTypes.def"
748bdd1243dSDimitry Andric         case BuiltinType::OCLEvent:
749bdd1243dSDimitry Andric           Out << "@BT@OCLEvent"; break;
750bdd1243dSDimitry Andric         case BuiltinType::OCLClkEvent:
751bdd1243dSDimitry Andric           Out << "@BT@OCLClkEvent"; break;
752bdd1243dSDimitry Andric         case BuiltinType::OCLQueue:
753bdd1243dSDimitry Andric           Out << "@BT@OCLQueue"; break;
754bdd1243dSDimitry Andric         case BuiltinType::OCLReserveID:
755bdd1243dSDimitry Andric           Out << "@BT@OCLReserveID"; break;
756bdd1243dSDimitry Andric         case BuiltinType::OCLSampler:
757bdd1243dSDimitry Andric           Out << "@BT@OCLSampler"; break;
758bdd1243dSDimitry Andric #define SVE_TYPE(Name, Id, SingletonId) \
759bdd1243dSDimitry Andric         case BuiltinType::Id: \
760bdd1243dSDimitry Andric           Out << "@BT@" << Name; break;
761bdd1243dSDimitry Andric #include "clang/Basic/AArch64SVEACLETypes.def"
762bdd1243dSDimitry Andric #define PPC_VECTOR_TYPE(Name, Id, Size) \
763bdd1243dSDimitry Andric         case BuiltinType::Id: \
764bdd1243dSDimitry Andric           Out << "@BT@" << #Name; break;
765bdd1243dSDimitry Andric #include "clang/Basic/PPCTypes.def"
766bdd1243dSDimitry Andric #define RVV_TYPE(Name, Id, SingletonId) \
767bdd1243dSDimitry Andric         case BuiltinType::Id: \
768bdd1243dSDimitry Andric           Out << "@BT@" << Name; break;
769bdd1243dSDimitry Andric #include "clang/Basic/RISCVVTypes.def"
77006c3fb27SDimitry Andric #define WASM_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
77106c3fb27SDimitry Andric #include "clang/Basic/WebAssemblyReferenceTypes.def"
772bdd1243dSDimitry Andric         case BuiltinType::ShortAccum:
773bdd1243dSDimitry Andric           Out << "@BT@ShortAccum"; break;
774bdd1243dSDimitry Andric         case BuiltinType::Accum:
775bdd1243dSDimitry Andric           Out << "@BT@Accum"; break;
776bdd1243dSDimitry Andric         case BuiltinType::LongAccum:
777bdd1243dSDimitry Andric           Out << "@BT@LongAccum"; break;
778bdd1243dSDimitry Andric         case BuiltinType::UShortAccum:
779bdd1243dSDimitry Andric           Out << "@BT@UShortAccum"; break;
780bdd1243dSDimitry Andric         case BuiltinType::UAccum:
781bdd1243dSDimitry Andric           Out << "@BT@UAccum"; break;
782bdd1243dSDimitry Andric         case BuiltinType::ULongAccum:
783bdd1243dSDimitry Andric           Out << "@BT@ULongAccum"; break;
784bdd1243dSDimitry Andric         case BuiltinType::ShortFract:
785bdd1243dSDimitry Andric           Out << "@BT@ShortFract"; break;
786bdd1243dSDimitry Andric         case BuiltinType::Fract:
787bdd1243dSDimitry Andric           Out << "@BT@Fract"; break;
788bdd1243dSDimitry Andric         case BuiltinType::LongFract:
789bdd1243dSDimitry Andric           Out << "@BT@LongFract"; break;
790bdd1243dSDimitry Andric         case BuiltinType::UShortFract:
791bdd1243dSDimitry Andric           Out << "@BT@UShortFract"; break;
792bdd1243dSDimitry Andric         case BuiltinType::UFract:
793bdd1243dSDimitry Andric           Out << "@BT@UFract"; break;
794bdd1243dSDimitry Andric         case BuiltinType::ULongFract:
795bdd1243dSDimitry Andric           Out << "@BT@ULongFract"; break;
796bdd1243dSDimitry Andric         case BuiltinType::SatShortAccum:
797bdd1243dSDimitry Andric           Out << "@BT@SatShortAccum"; break;
798bdd1243dSDimitry Andric         case BuiltinType::SatAccum:
799bdd1243dSDimitry Andric           Out << "@BT@SatAccum"; break;
800bdd1243dSDimitry Andric         case BuiltinType::SatLongAccum:
801bdd1243dSDimitry Andric           Out << "@BT@SatLongAccum"; break;
802bdd1243dSDimitry Andric         case BuiltinType::SatUShortAccum:
803bdd1243dSDimitry Andric           Out << "@BT@SatUShortAccum"; break;
804bdd1243dSDimitry Andric         case BuiltinType::SatUAccum:
805bdd1243dSDimitry Andric           Out << "@BT@SatUAccum"; break;
806bdd1243dSDimitry Andric         case BuiltinType::SatULongAccum:
807bdd1243dSDimitry Andric           Out << "@BT@SatULongAccum"; break;
808bdd1243dSDimitry Andric         case BuiltinType::SatShortFract:
809bdd1243dSDimitry Andric           Out << "@BT@SatShortFract"; break;
810bdd1243dSDimitry Andric         case BuiltinType::SatFract:
811bdd1243dSDimitry Andric           Out << "@BT@SatFract"; break;
812bdd1243dSDimitry Andric         case BuiltinType::SatLongFract:
813bdd1243dSDimitry Andric           Out << "@BT@SatLongFract"; break;
814bdd1243dSDimitry Andric         case BuiltinType::SatUShortFract:
815bdd1243dSDimitry Andric           Out << "@BT@SatUShortFract"; break;
816bdd1243dSDimitry Andric         case BuiltinType::SatUFract:
817bdd1243dSDimitry Andric           Out << "@BT@SatUFract"; break;
818bdd1243dSDimitry Andric         case BuiltinType::SatULongFract:
819bdd1243dSDimitry Andric           Out << "@BT@SatULongFract"; break;
820bdd1243dSDimitry Andric         case BuiltinType::BFloat16:
821bdd1243dSDimitry Andric           Out << "@BT@__bf16"; break;
822bdd1243dSDimitry Andric         case BuiltinType::Ibm128:
823bdd1243dSDimitry Andric           Out << "@BT@__ibm128"; break;
824bdd1243dSDimitry Andric         case BuiltinType::ObjCId:
825bdd1243dSDimitry Andric           Out << 'o'; break;
826bdd1243dSDimitry Andric         case BuiltinType::ObjCClass:
827bdd1243dSDimitry Andric           Out << 'O'; break;
828bdd1243dSDimitry Andric         case BuiltinType::ObjCSel:
829bdd1243dSDimitry Andric           Out << 'e'; break;
8300b57cec5SDimitry Andric #define BUILTIN_TYPE(Id, SingletonId)
8310b57cec5SDimitry Andric #define PLACEHOLDER_TYPE(Id, SingletonId) case BuiltinType::Id:
8320b57cec5SDimitry Andric #include "clang/AST/BuiltinTypes.def"
8330b57cec5SDimitry Andric         case BuiltinType::Dependent:
834bdd1243dSDimitry Andric           // If you're adding a new builtin type, please add its name prefixed
835bdd1243dSDimitry Andric           // with "@BT@" to `Out` (see cases above).
8360b57cec5SDimitry Andric           IgnoreResults = true;
837bdd1243dSDimitry Andric           break;
8380b57cec5SDimitry Andric       }
8390b57cec5SDimitry Andric       return;
8400b57cec5SDimitry Andric     }
8410b57cec5SDimitry Andric 
8420b57cec5SDimitry Andric     // If we have already seen this (non-built-in) type, use a substitution
8430b57cec5SDimitry Andric     // encoding.
8440b57cec5SDimitry Andric     llvm::DenseMap<const Type *, unsigned>::iterator Substitution
8450b57cec5SDimitry Andric       = TypeSubstitutions.find(T.getTypePtr());
8460b57cec5SDimitry Andric     if (Substitution != TypeSubstitutions.end()) {
8470b57cec5SDimitry Andric       Out << 'S' << Substitution->second << '_';
8480b57cec5SDimitry Andric       return;
8490b57cec5SDimitry Andric     } else {
8500b57cec5SDimitry Andric       // Record this as a substitution.
8510b57cec5SDimitry Andric       unsigned Number = TypeSubstitutions.size();
8520b57cec5SDimitry Andric       TypeSubstitutions[T.getTypePtr()] = Number;
8530b57cec5SDimitry Andric     }
8540b57cec5SDimitry Andric 
8550b57cec5SDimitry Andric     if (const PointerType *PT = T->getAs<PointerType>()) {
8560b57cec5SDimitry Andric       Out << '*';
8570b57cec5SDimitry Andric       T = PT->getPointeeType();
8580b57cec5SDimitry Andric       continue;
8590b57cec5SDimitry Andric     }
8600b57cec5SDimitry Andric     if (const ObjCObjectPointerType *OPT = T->getAs<ObjCObjectPointerType>()) {
8610b57cec5SDimitry Andric       Out << '*';
8620b57cec5SDimitry Andric       T = OPT->getPointeeType();
8630b57cec5SDimitry Andric       continue;
8640b57cec5SDimitry Andric     }
8650b57cec5SDimitry Andric     if (const RValueReferenceType *RT = T->getAs<RValueReferenceType>()) {
8660b57cec5SDimitry Andric       Out << "&&";
8670b57cec5SDimitry Andric       T = RT->getPointeeType();
8680b57cec5SDimitry Andric       continue;
8690b57cec5SDimitry Andric     }
8700b57cec5SDimitry Andric     if (const ReferenceType *RT = T->getAs<ReferenceType>()) {
8710b57cec5SDimitry Andric       Out << '&';
8720b57cec5SDimitry Andric       T = RT->getPointeeType();
8730b57cec5SDimitry Andric       continue;
8740b57cec5SDimitry Andric     }
8750b57cec5SDimitry Andric     if (const FunctionProtoType *FT = T->getAs<FunctionProtoType>()) {
8760b57cec5SDimitry Andric       Out << 'F';
8770b57cec5SDimitry Andric       VisitType(FT->getReturnType());
8780b57cec5SDimitry Andric       Out << '(';
8790b57cec5SDimitry Andric       for (const auto &I : FT->param_types()) {
8800b57cec5SDimitry Andric         Out << '#';
8810b57cec5SDimitry Andric         VisitType(I);
8820b57cec5SDimitry Andric       }
8830b57cec5SDimitry Andric       Out << ')';
8840b57cec5SDimitry Andric       if (FT->isVariadic())
8850b57cec5SDimitry Andric         Out << '.';
8860b57cec5SDimitry Andric       return;
8870b57cec5SDimitry Andric     }
8880b57cec5SDimitry Andric     if (const BlockPointerType *BT = T->getAs<BlockPointerType>()) {
8890b57cec5SDimitry Andric       Out << 'B';
8900b57cec5SDimitry Andric       T = BT->getPointeeType();
8910b57cec5SDimitry Andric       continue;
8920b57cec5SDimitry Andric     }
8930b57cec5SDimitry Andric     if (const ComplexType *CT = T->getAs<ComplexType>()) {
8940b57cec5SDimitry Andric       Out << '<';
8950b57cec5SDimitry Andric       T = CT->getElementType();
8960b57cec5SDimitry Andric       continue;
8970b57cec5SDimitry Andric     }
8980b57cec5SDimitry Andric     if (const TagType *TT = T->getAs<TagType>()) {
8990b57cec5SDimitry Andric       Out << '$';
9000b57cec5SDimitry Andric       VisitTagDecl(TT->getDecl());
9010b57cec5SDimitry Andric       return;
9020b57cec5SDimitry Andric     }
9030b57cec5SDimitry Andric     if (const ObjCInterfaceType *OIT = T->getAs<ObjCInterfaceType>()) {
9040b57cec5SDimitry Andric       Out << '$';
9050b57cec5SDimitry Andric       VisitObjCInterfaceDecl(OIT->getDecl());
9060b57cec5SDimitry Andric       return;
9070b57cec5SDimitry Andric     }
9080b57cec5SDimitry Andric     if (const ObjCObjectType *OIT = T->getAs<ObjCObjectType>()) {
9090b57cec5SDimitry Andric       Out << 'Q';
9100b57cec5SDimitry Andric       VisitType(OIT->getBaseType());
9110b57cec5SDimitry Andric       for (auto *Prot : OIT->getProtocols())
9120b57cec5SDimitry Andric         VisitObjCProtocolDecl(Prot);
9130b57cec5SDimitry Andric       return;
9140b57cec5SDimitry Andric     }
9150b57cec5SDimitry Andric     if (const TemplateTypeParmType *TTP = T->getAs<TemplateTypeParmType>()) {
9160b57cec5SDimitry Andric       Out << 't' << TTP->getDepth() << '.' << TTP->getIndex();
9170b57cec5SDimitry Andric       return;
9180b57cec5SDimitry Andric     }
9190b57cec5SDimitry Andric     if (const TemplateSpecializationType *Spec
9200b57cec5SDimitry Andric                                     = T->getAs<TemplateSpecializationType>()) {
9210b57cec5SDimitry Andric       Out << '>';
9220b57cec5SDimitry Andric       VisitTemplateName(Spec->getTemplateName());
923bdd1243dSDimitry Andric       Out << Spec->template_arguments().size();
924bdd1243dSDimitry Andric       for (const auto &Arg : Spec->template_arguments())
925bdd1243dSDimitry Andric         VisitTemplateArgument(Arg);
9260b57cec5SDimitry Andric       return;
9270b57cec5SDimitry Andric     }
9280b57cec5SDimitry Andric     if (const DependentNameType *DNT = T->getAs<DependentNameType>()) {
9290b57cec5SDimitry Andric       Out << '^';
9300b57cec5SDimitry Andric       printQualifier(Out, Ctx, DNT->getQualifier());
9310b57cec5SDimitry Andric       Out << ':' << DNT->getIdentifier()->getName();
9320b57cec5SDimitry Andric       return;
9330b57cec5SDimitry Andric     }
9340b57cec5SDimitry Andric     if (const InjectedClassNameType *InjT = T->getAs<InjectedClassNameType>()) {
9350b57cec5SDimitry Andric       T = InjT->getInjectedSpecializationType();
9360b57cec5SDimitry Andric       continue;
9370b57cec5SDimitry Andric     }
9380b57cec5SDimitry Andric     if (const auto *VT = T->getAs<VectorType>()) {
9390b57cec5SDimitry Andric       Out << (T->isExtVectorType() ? ']' : '[');
9400b57cec5SDimitry Andric       Out << VT->getNumElements();
9410b57cec5SDimitry Andric       T = VT->getElementType();
9420b57cec5SDimitry Andric       continue;
9430b57cec5SDimitry Andric     }
9440b57cec5SDimitry Andric     if (const auto *const AT = dyn_cast<ArrayType>(T)) {
9450b57cec5SDimitry Andric       Out << '{';
9460b57cec5SDimitry Andric       switch (AT->getSizeModifier()) {
9475f757f3fSDimitry Andric       case ArraySizeModifier::Static:
9480b57cec5SDimitry Andric         Out << 's';
9490b57cec5SDimitry Andric         break;
9505f757f3fSDimitry Andric       case ArraySizeModifier::Star:
9510b57cec5SDimitry Andric         Out << '*';
9520b57cec5SDimitry Andric         break;
9535f757f3fSDimitry Andric       case ArraySizeModifier::Normal:
9540b57cec5SDimitry Andric         Out << 'n';
9550b57cec5SDimitry Andric         break;
9560b57cec5SDimitry Andric       }
9570b57cec5SDimitry Andric       if (const auto *const CAT = dyn_cast<ConstantArrayType>(T))
9580b57cec5SDimitry Andric         Out << CAT->getSize();
9590b57cec5SDimitry Andric 
9600b57cec5SDimitry Andric       T = AT->getElementType();
9610b57cec5SDimitry Andric       continue;
9620b57cec5SDimitry Andric     }
9630b57cec5SDimitry Andric 
9640b57cec5SDimitry Andric     // Unhandled type.
9650b57cec5SDimitry Andric     Out << ' ';
9660b57cec5SDimitry Andric     break;
9670b57cec5SDimitry Andric   } while (true);
9680b57cec5SDimitry Andric }
9690b57cec5SDimitry Andric 
VisitTemplateParameterList(const TemplateParameterList * Params)9700b57cec5SDimitry Andric void USRGenerator::VisitTemplateParameterList(
9710b57cec5SDimitry Andric                                          const TemplateParameterList *Params) {
9720b57cec5SDimitry Andric   if (!Params)
9730b57cec5SDimitry Andric     return;
9740b57cec5SDimitry Andric   Out << '>' << Params->size();
9750b57cec5SDimitry Andric   for (TemplateParameterList::const_iterator P = Params->begin(),
9760b57cec5SDimitry Andric                                           PEnd = Params->end();
9770b57cec5SDimitry Andric        P != PEnd; ++P) {
9780b57cec5SDimitry Andric     Out << '#';
9790b57cec5SDimitry Andric     if (isa<TemplateTypeParmDecl>(*P)) {
9800b57cec5SDimitry Andric       if (cast<TemplateTypeParmDecl>(*P)->isParameterPack())
9810b57cec5SDimitry Andric         Out<< 'p';
9820b57cec5SDimitry Andric       Out << 'T';
9830b57cec5SDimitry Andric       continue;
9840b57cec5SDimitry Andric     }
9850b57cec5SDimitry Andric 
9860b57cec5SDimitry Andric     if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(*P)) {
9870b57cec5SDimitry Andric       if (NTTP->isParameterPack())
9880b57cec5SDimitry Andric         Out << 'p';
9890b57cec5SDimitry Andric       Out << 'N';
9900b57cec5SDimitry Andric       VisitType(NTTP->getType());
9910b57cec5SDimitry Andric       continue;
9920b57cec5SDimitry Andric     }
9930b57cec5SDimitry Andric 
9940b57cec5SDimitry Andric     TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*P);
9950b57cec5SDimitry Andric     if (TTP->isParameterPack())
9960b57cec5SDimitry Andric       Out << 'p';
9970b57cec5SDimitry Andric     Out << 't';
9980b57cec5SDimitry Andric     VisitTemplateParameterList(TTP->getTemplateParameters());
9990b57cec5SDimitry Andric   }
10000b57cec5SDimitry Andric }
10010b57cec5SDimitry Andric 
VisitTemplateName(TemplateName Name)10020b57cec5SDimitry Andric void USRGenerator::VisitTemplateName(TemplateName Name) {
10030b57cec5SDimitry Andric   if (TemplateDecl *Template = Name.getAsTemplateDecl()) {
10040b57cec5SDimitry Andric     if (TemplateTemplateParmDecl *TTP
10050b57cec5SDimitry Andric                               = dyn_cast<TemplateTemplateParmDecl>(Template)) {
10060b57cec5SDimitry Andric       Out << 't' << TTP->getDepth() << '.' << TTP->getIndex();
10070b57cec5SDimitry Andric       return;
10080b57cec5SDimitry Andric     }
10090b57cec5SDimitry Andric 
10100b57cec5SDimitry Andric     Visit(Template);
10110b57cec5SDimitry Andric     return;
10120b57cec5SDimitry Andric   }
10130b57cec5SDimitry Andric 
10140b57cec5SDimitry Andric   // FIXME: Visit dependent template names.
10150b57cec5SDimitry Andric }
10160b57cec5SDimitry Andric 
VisitTemplateArgument(const TemplateArgument & Arg)10170b57cec5SDimitry Andric void USRGenerator::VisitTemplateArgument(const TemplateArgument &Arg) {
10180b57cec5SDimitry Andric   switch (Arg.getKind()) {
10190b57cec5SDimitry Andric   case TemplateArgument::Null:
10200b57cec5SDimitry Andric     break;
10210b57cec5SDimitry Andric 
10220b57cec5SDimitry Andric   case TemplateArgument::Declaration:
10230b57cec5SDimitry Andric     Visit(Arg.getAsDecl());
10240b57cec5SDimitry Andric     break;
10250b57cec5SDimitry Andric 
10260b57cec5SDimitry Andric   case TemplateArgument::NullPtr:
10270b57cec5SDimitry Andric     break;
10280b57cec5SDimitry Andric 
10290b57cec5SDimitry Andric   case TemplateArgument::TemplateExpansion:
10300b57cec5SDimitry Andric     Out << 'P'; // pack expansion of...
1031bdd1243dSDimitry Andric     [[fallthrough]];
10320b57cec5SDimitry Andric   case TemplateArgument::Template:
10330b57cec5SDimitry Andric     VisitTemplateName(Arg.getAsTemplateOrTemplatePattern());
10340b57cec5SDimitry Andric     break;
10350b57cec5SDimitry Andric 
10360b57cec5SDimitry Andric   case TemplateArgument::Expression:
10370b57cec5SDimitry Andric     // FIXME: Visit expressions.
10380b57cec5SDimitry Andric     break;
10390b57cec5SDimitry Andric 
10400b57cec5SDimitry Andric   case TemplateArgument::Pack:
10410b57cec5SDimitry Andric     Out << 'p' << Arg.pack_size();
10420b57cec5SDimitry Andric     for (const auto &P : Arg.pack_elements())
10430b57cec5SDimitry Andric       VisitTemplateArgument(P);
10440b57cec5SDimitry Andric     break;
10450b57cec5SDimitry Andric 
10460b57cec5SDimitry Andric   case TemplateArgument::Type:
10470b57cec5SDimitry Andric     VisitType(Arg.getAsType());
10480b57cec5SDimitry Andric     break;
10490b57cec5SDimitry Andric 
10500b57cec5SDimitry Andric   case TemplateArgument::Integral:
10510b57cec5SDimitry Andric     Out << 'V';
10520b57cec5SDimitry Andric     VisitType(Arg.getIntegralType());
10530b57cec5SDimitry Andric     Out << Arg.getAsIntegral();
10540b57cec5SDimitry Andric     break;
10557a6dacacSDimitry Andric 
10567a6dacacSDimitry Andric   case TemplateArgument::StructuralValue: {
10577a6dacacSDimitry Andric     Out << 'S';
10587a6dacacSDimitry Andric     VisitType(Arg.getStructuralValueType());
10597a6dacacSDimitry Andric     ODRHash Hash{};
10607a6dacacSDimitry Andric     Hash.AddStructuralValue(Arg.getAsStructuralValue());
10617a6dacacSDimitry Andric     Out << Hash.CalculateHash();
10627a6dacacSDimitry Andric     break;
10637a6dacacSDimitry Andric   }
10640b57cec5SDimitry Andric   }
10650b57cec5SDimitry Andric }
10660b57cec5SDimitry Andric 
VisitUnresolvedUsingValueDecl(const UnresolvedUsingValueDecl * D)10670b57cec5SDimitry Andric void USRGenerator::VisitUnresolvedUsingValueDecl(const UnresolvedUsingValueDecl *D) {
10680b57cec5SDimitry Andric   if (ShouldGenerateLocation(D) && GenLoc(D, /*IncludeOffset=*/isLocal(D)))
10690b57cec5SDimitry Andric     return;
10700b57cec5SDimitry Andric   VisitDeclContext(D->getDeclContext());
10710b57cec5SDimitry Andric   Out << "@UUV@";
10720b57cec5SDimitry Andric   printQualifier(Out, D->getASTContext(), D->getQualifier());
10730b57cec5SDimitry Andric   EmitDeclName(D);
10740b57cec5SDimitry Andric }
10750b57cec5SDimitry Andric 
VisitUnresolvedUsingTypenameDecl(const UnresolvedUsingTypenameDecl * D)10760b57cec5SDimitry Andric void USRGenerator::VisitUnresolvedUsingTypenameDecl(const UnresolvedUsingTypenameDecl *D) {
10770b57cec5SDimitry Andric   if (ShouldGenerateLocation(D) && GenLoc(D, /*IncludeOffset=*/isLocal(D)))
10780b57cec5SDimitry Andric     return;
10790b57cec5SDimitry Andric   VisitDeclContext(D->getDeclContext());
10800b57cec5SDimitry Andric   Out << "@UUT@";
10810b57cec5SDimitry Andric   printQualifier(Out, D->getASTContext(), D->getQualifier());
10820b57cec5SDimitry Andric   Out << D->getName(); // Simple name.
10830b57cec5SDimitry Andric }
10840b57cec5SDimitry Andric 
VisitConceptDecl(const ConceptDecl * D)108581ad6265SDimitry Andric void USRGenerator::VisitConceptDecl(const ConceptDecl *D) {
108681ad6265SDimitry Andric   if (ShouldGenerateLocation(D) && GenLoc(D, /*IncludeOffset=*/isLocal(D)))
108781ad6265SDimitry Andric     return;
108881ad6265SDimitry Andric   VisitDeclContext(D->getDeclContext());
108981ad6265SDimitry Andric   Out << "@CT@";
109081ad6265SDimitry Andric   EmitDeclName(D);
109181ad6265SDimitry Andric }
10920b57cec5SDimitry Andric 
VisitMSGuidDecl(const MSGuidDecl * D)1093bdd1243dSDimitry Andric void USRGenerator::VisitMSGuidDecl(const MSGuidDecl *D) {
1094bdd1243dSDimitry Andric   VisitDeclContext(D->getDeclContext());
1095bdd1243dSDimitry Andric   Out << "@MG@";
1096bdd1243dSDimitry Andric   D->NamedDecl::printName(Out);
1097bdd1243dSDimitry Andric }
1098bdd1243dSDimitry Andric 
10990b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
11000b57cec5SDimitry Andric // USR generation functions.
11010b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
11020b57cec5SDimitry Andric 
combineClassAndCategoryExtContainers(StringRef ClsSymDefinedIn,StringRef CatSymDefinedIn,raw_ostream & OS)11030b57cec5SDimitry Andric static void combineClassAndCategoryExtContainers(StringRef ClsSymDefinedIn,
11040b57cec5SDimitry Andric                                                  StringRef CatSymDefinedIn,
11050b57cec5SDimitry Andric                                                  raw_ostream &OS) {
11060b57cec5SDimitry Andric   if (ClsSymDefinedIn.empty() && CatSymDefinedIn.empty())
11070b57cec5SDimitry Andric     return;
11080b57cec5SDimitry Andric   if (CatSymDefinedIn.empty()) {
11090b57cec5SDimitry Andric     OS << "@M@" << ClsSymDefinedIn << '@';
11100b57cec5SDimitry Andric     return;
11110b57cec5SDimitry Andric   }
11120b57cec5SDimitry Andric   OS << "@CM@" << CatSymDefinedIn << '@';
11130b57cec5SDimitry Andric   if (ClsSymDefinedIn != CatSymDefinedIn) {
11140b57cec5SDimitry Andric     OS << ClsSymDefinedIn << '@';
11150b57cec5SDimitry Andric   }
11160b57cec5SDimitry Andric }
11170b57cec5SDimitry Andric 
generateUSRForObjCClass(StringRef Cls,raw_ostream & OS,StringRef ExtSymDefinedIn,StringRef CategoryContextExtSymbolDefinedIn)11180b57cec5SDimitry Andric void clang::index::generateUSRForObjCClass(StringRef Cls, raw_ostream &OS,
11190b57cec5SDimitry Andric                                            StringRef ExtSymDefinedIn,
11200b57cec5SDimitry Andric                                   StringRef CategoryContextExtSymbolDefinedIn) {
11210b57cec5SDimitry Andric   combineClassAndCategoryExtContainers(ExtSymDefinedIn,
11220b57cec5SDimitry Andric                                        CategoryContextExtSymbolDefinedIn, OS);
11230b57cec5SDimitry Andric   OS << "objc(cs)" << Cls;
11240b57cec5SDimitry Andric }
11250b57cec5SDimitry Andric 
generateUSRForObjCCategory(StringRef Cls,StringRef Cat,raw_ostream & OS,StringRef ClsSymDefinedIn,StringRef CatSymDefinedIn)11260b57cec5SDimitry Andric void clang::index::generateUSRForObjCCategory(StringRef Cls, StringRef Cat,
11270b57cec5SDimitry Andric                                               raw_ostream &OS,
11280b57cec5SDimitry Andric                                               StringRef ClsSymDefinedIn,
11290b57cec5SDimitry Andric                                               StringRef CatSymDefinedIn) {
11300b57cec5SDimitry Andric   combineClassAndCategoryExtContainers(ClsSymDefinedIn, CatSymDefinedIn, OS);
11310b57cec5SDimitry Andric   OS << "objc(cy)" << Cls << '@' << Cat;
11320b57cec5SDimitry Andric }
11330b57cec5SDimitry Andric 
generateUSRForObjCIvar(StringRef Ivar,raw_ostream & OS)11340b57cec5SDimitry Andric void clang::index::generateUSRForObjCIvar(StringRef Ivar, raw_ostream &OS) {
11350b57cec5SDimitry Andric   OS << '@' << Ivar;
11360b57cec5SDimitry Andric }
11370b57cec5SDimitry Andric 
generateUSRForObjCMethod(StringRef Sel,bool IsInstanceMethod,raw_ostream & OS)11380b57cec5SDimitry Andric void clang::index::generateUSRForObjCMethod(StringRef Sel,
11390b57cec5SDimitry Andric                                             bool IsInstanceMethod,
11400b57cec5SDimitry Andric                                             raw_ostream &OS) {
11410b57cec5SDimitry Andric   OS << (IsInstanceMethod ? "(im)" : "(cm)") << Sel;
11420b57cec5SDimitry Andric }
11430b57cec5SDimitry Andric 
generateUSRForObjCProperty(StringRef Prop,bool isClassProp,raw_ostream & OS)11440b57cec5SDimitry Andric void clang::index::generateUSRForObjCProperty(StringRef Prop, bool isClassProp,
11450b57cec5SDimitry Andric                                               raw_ostream &OS) {
11460b57cec5SDimitry Andric   OS << (isClassProp ? "(cpy)" : "(py)") << Prop;
11470b57cec5SDimitry Andric }
11480b57cec5SDimitry Andric 
generateUSRForObjCProtocol(StringRef Prot,raw_ostream & OS,StringRef ExtSymDefinedIn)11490b57cec5SDimitry Andric void clang::index::generateUSRForObjCProtocol(StringRef Prot, raw_ostream &OS,
11500b57cec5SDimitry Andric                                               StringRef ExtSymDefinedIn) {
11510b57cec5SDimitry Andric   if (!ExtSymDefinedIn.empty())
11520b57cec5SDimitry Andric     OS << "@M@" << ExtSymDefinedIn << '@';
11530b57cec5SDimitry Andric   OS << "objc(pl)" << Prot;
11540b57cec5SDimitry Andric }
11550b57cec5SDimitry Andric 
generateUSRForGlobalEnum(StringRef EnumName,raw_ostream & OS,StringRef ExtSymDefinedIn)11560b57cec5SDimitry Andric void clang::index::generateUSRForGlobalEnum(StringRef EnumName, raw_ostream &OS,
11570b57cec5SDimitry Andric                                             StringRef ExtSymDefinedIn) {
11580b57cec5SDimitry Andric   if (!ExtSymDefinedIn.empty())
11590b57cec5SDimitry Andric     OS << "@M@" << ExtSymDefinedIn;
11600b57cec5SDimitry Andric   OS << "@E@" << EnumName;
11610b57cec5SDimitry Andric }
11620b57cec5SDimitry Andric 
generateUSRForEnumConstant(StringRef EnumConstantName,raw_ostream & OS)11630b57cec5SDimitry Andric void clang::index::generateUSRForEnumConstant(StringRef EnumConstantName,
11640b57cec5SDimitry Andric                                               raw_ostream &OS) {
11650b57cec5SDimitry Andric   OS << '@' << EnumConstantName;
11660b57cec5SDimitry Andric }
11670b57cec5SDimitry Andric 
generateUSRForDecl(const Decl * D,SmallVectorImpl<char> & Buf)11680b57cec5SDimitry Andric bool clang::index::generateUSRForDecl(const Decl *D,
11690b57cec5SDimitry Andric                                       SmallVectorImpl<char> &Buf) {
11700b57cec5SDimitry Andric   if (!D)
11710b57cec5SDimitry Andric     return true;
11720b57cec5SDimitry Andric   // We don't ignore decls with invalid source locations. Implicit decls, like
11730b57cec5SDimitry Andric   // C++'s operator new function, can have invalid locations but it is fine to
11740b57cec5SDimitry Andric   // create USRs that can identify them.
11750b57cec5SDimitry Andric 
117606c3fb27SDimitry Andric   // Check if the declaration has explicit external USR specified.
117706c3fb27SDimitry Andric   auto *CD = D->getCanonicalDecl();
117806c3fb27SDimitry Andric   if (auto *ExternalSymAttr = CD->getAttr<ExternalSourceSymbolAttr>()) {
117906c3fb27SDimitry Andric     if (!ExternalSymAttr->getUSR().empty()) {
118006c3fb27SDimitry Andric       llvm::raw_svector_ostream Out(Buf);
118106c3fb27SDimitry Andric       Out << ExternalSymAttr->getUSR();
118206c3fb27SDimitry Andric       return false;
118306c3fb27SDimitry Andric     }
118406c3fb27SDimitry Andric   }
11850b57cec5SDimitry Andric   USRGenerator UG(&D->getASTContext(), Buf);
11860b57cec5SDimitry Andric   UG.Visit(D);
11870b57cec5SDimitry Andric   return UG.ignoreResults();
11880b57cec5SDimitry Andric }
11890b57cec5SDimitry Andric 
generateUSRForMacro(const MacroDefinitionRecord * MD,const SourceManager & SM,SmallVectorImpl<char> & Buf)11900b57cec5SDimitry Andric bool clang::index::generateUSRForMacro(const MacroDefinitionRecord *MD,
11910b57cec5SDimitry Andric                                        const SourceManager &SM,
11920b57cec5SDimitry Andric                                        SmallVectorImpl<char> &Buf) {
11930b57cec5SDimitry Andric   if (!MD)
11940b57cec5SDimitry Andric     return true;
11950b57cec5SDimitry Andric   return generateUSRForMacro(MD->getName()->getName(), MD->getLocation(),
11960b57cec5SDimitry Andric                              SM, Buf);
11970b57cec5SDimitry Andric 
11980b57cec5SDimitry Andric }
11990b57cec5SDimitry Andric 
generateUSRForMacro(StringRef MacroName,SourceLocation Loc,const SourceManager & SM,SmallVectorImpl<char> & Buf)12000b57cec5SDimitry Andric bool clang::index::generateUSRForMacro(StringRef MacroName, SourceLocation Loc,
12010b57cec5SDimitry Andric                                        const SourceManager &SM,
12020b57cec5SDimitry Andric                                        SmallVectorImpl<char> &Buf) {
1203fe6060f1SDimitry Andric   if (MacroName.empty())
12040b57cec5SDimitry Andric     return true;
12050b57cec5SDimitry Andric 
12060b57cec5SDimitry Andric   llvm::raw_svector_ostream Out(Buf);
12070b57cec5SDimitry Andric 
12080b57cec5SDimitry Andric   // Assume that system headers are sane.  Don't put source location
12090b57cec5SDimitry Andric   // information into the USR if the macro comes from a system header.
1210fe6060f1SDimitry Andric   bool ShouldGenerateLocation = Loc.isValid() && !SM.isInSystemHeader(Loc);
12110b57cec5SDimitry Andric 
12120b57cec5SDimitry Andric   Out << getUSRSpacePrefix();
12130b57cec5SDimitry Andric   if (ShouldGenerateLocation)
12140b57cec5SDimitry Andric     printLoc(Out, Loc, SM, /*IncludeOffset=*/true);
12150b57cec5SDimitry Andric   Out << "@macro@";
12160b57cec5SDimitry Andric   Out << MacroName;
12170b57cec5SDimitry Andric   return false;
12180b57cec5SDimitry Andric }
12190b57cec5SDimitry Andric 
generateUSRForType(QualType T,ASTContext & Ctx,SmallVectorImpl<char> & Buf)12200b57cec5SDimitry Andric bool clang::index::generateUSRForType(QualType T, ASTContext &Ctx,
12210b57cec5SDimitry Andric                                       SmallVectorImpl<char> &Buf) {
12220b57cec5SDimitry Andric   if (T.isNull())
12230b57cec5SDimitry Andric     return true;
12240b57cec5SDimitry Andric   T = T.getCanonicalType();
12250b57cec5SDimitry Andric 
12260b57cec5SDimitry Andric   USRGenerator UG(&Ctx, Buf);
12270b57cec5SDimitry Andric   UG.VisitType(T);
12280b57cec5SDimitry Andric   return UG.ignoreResults();
12290b57cec5SDimitry Andric }
12300b57cec5SDimitry Andric 
generateFullUSRForModule(const Module * Mod,raw_ostream & OS)12310b57cec5SDimitry Andric bool clang::index::generateFullUSRForModule(const Module *Mod,
12320b57cec5SDimitry Andric                                             raw_ostream &OS) {
12330b57cec5SDimitry Andric   if (!Mod->Parent)
12340b57cec5SDimitry Andric     return generateFullUSRForTopLevelModuleName(Mod->Name, OS);
12350b57cec5SDimitry Andric   if (generateFullUSRForModule(Mod->Parent, OS))
12360b57cec5SDimitry Andric     return true;
12370b57cec5SDimitry Andric   return generateUSRFragmentForModule(Mod, OS);
12380b57cec5SDimitry Andric }
12390b57cec5SDimitry Andric 
generateFullUSRForTopLevelModuleName(StringRef ModName,raw_ostream & OS)12400b57cec5SDimitry Andric bool clang::index::generateFullUSRForTopLevelModuleName(StringRef ModName,
12410b57cec5SDimitry Andric                                                         raw_ostream &OS) {
12420b57cec5SDimitry Andric   OS << getUSRSpacePrefix();
12430b57cec5SDimitry Andric   return generateUSRFragmentForModuleName(ModName, OS);
12440b57cec5SDimitry Andric }
12450b57cec5SDimitry Andric 
generateUSRFragmentForModule(const Module * Mod,raw_ostream & OS)12460b57cec5SDimitry Andric bool clang::index::generateUSRFragmentForModule(const Module *Mod,
12470b57cec5SDimitry Andric                                                 raw_ostream &OS) {
12480b57cec5SDimitry Andric   return generateUSRFragmentForModuleName(Mod->Name, OS);
12490b57cec5SDimitry Andric }
12500b57cec5SDimitry Andric 
generateUSRFragmentForModuleName(StringRef ModName,raw_ostream & OS)12510b57cec5SDimitry Andric bool clang::index::generateUSRFragmentForModuleName(StringRef ModName,
12520b57cec5SDimitry Andric                                                     raw_ostream &OS) {
12530b57cec5SDimitry Andric   OS << "@M@" << ModName;
12540b57cec5SDimitry Andric   return false;
12550b57cec5SDimitry Andric }
1256