xref: /freebsd-src/contrib/llvm-project/clang/lib/Index/USRGeneration.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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.
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 
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:
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 
830b57cec5SDimitry 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 
1100b57cec5SDimitry Andric   void VisitLinkageSpecDecl(const LinkageSpecDecl *D) {
1110b57cec5SDimitry Andric     IgnoreResults = true; // No USRs for linkage specs themselves.
1120b57cec5SDimitry Andric   }
1130b57cec5SDimitry Andric 
1140b57cec5SDimitry Andric   void VisitUsingDirectiveDecl(const UsingDirectiveDecl *D) {
1150b57cec5SDimitry Andric     IgnoreResults = true;
1160b57cec5SDimitry Andric   }
1170b57cec5SDimitry Andric 
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 
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.
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.
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.
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.
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 
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 
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 
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 
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 
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 
260*0fca6ea1SDimitry Andric   if (D->isFunctionTemplateSpecialization()) {
2610b57cec5SDimitry Andric     Out << '<';
262*0fca6ea1SDimitry Andric     if (const TemplateArgumentList *SpecArgs =
263*0fca6ea1SDimitry Andric             D->getTemplateSpecializationArgs()) {
264*0fca6ea1SDimitry Andric       for (const auto &Arg : SpecArgs->asArray()) {
2650b57cec5SDimitry Andric         Out << '#';
266*0fca6ea1SDimitry Andric         VisitTemplateArgument(Arg);
267*0fca6ea1SDimitry Andric       }
268*0fca6ea1SDimitry Andric     } else if (const ASTTemplateArgumentListInfo *SpecArgsWritten =
269*0fca6ea1SDimitry Andric                    D->getTemplateSpecializationArgsAsWritten()) {
270*0fca6ea1SDimitry Andric       for (const auto &ArgLoc : SpecArgsWritten->arguments()) {
271*0fca6ea1SDimitry Andric         Out << '#';
272*0fca6ea1SDimitry Andric         VisitTemplateArgument(ArgLoc.getArgument());
273*0fca6ea1SDimitry Andric       }
2740b57cec5SDimitry Andric     }
2750b57cec5SDimitry Andric     Out << '>';
2760b57cec5SDimitry Andric   }
2770b57cec5SDimitry Andric 
278*0fca6ea1SDimitry Andric   QualType CanonicalType = D->getType().getCanonicalType();
2790b57cec5SDimitry Andric   // Mangle in type information for the arguments.
280*0fca6ea1SDimitry Andric   if (const auto *FPT = CanonicalType->getAs<FunctionProtoType>()) {
281*0fca6ea1SDimitry Andric     for (QualType PT : FPT->param_types()) {
2820b57cec5SDimitry Andric       Out << '#';
283*0fca6ea1SDimitry Andric       VisitType(PT);
284*0fca6ea1SDimitry Andric     }
2850b57cec5SDimitry Andric   }
2860b57cec5SDimitry Andric   if (D->isVariadic())
2870b57cec5SDimitry Andric     Out << '.';
2880b57cec5SDimitry Andric   if (IsTemplate) {
2890b57cec5SDimitry Andric     // Function templates can be overloaded by return type, for example:
2900b57cec5SDimitry Andric     // \code
2910b57cec5SDimitry Andric     //   template <class T> typename T::A foo() {}
2920b57cec5SDimitry Andric     //   template <class T> typename T::B foo() {}
2930b57cec5SDimitry Andric     // \endcode
2940b57cec5SDimitry Andric     Out << '#';
2950b57cec5SDimitry Andric     VisitType(D->getReturnType());
2960b57cec5SDimitry Andric   }
2970b57cec5SDimitry Andric   Out << '#';
2980b57cec5SDimitry Andric   if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {
2990b57cec5SDimitry Andric     if (MD->isStatic())
3000b57cec5SDimitry Andric       Out << 'S';
3010b57cec5SDimitry Andric     // FIXME: OpenCL: Need to consider address spaces
3020b57cec5SDimitry Andric     if (unsigned quals = MD->getMethodQualifiers().getCVRUQualifiers())
3030b57cec5SDimitry Andric       Out << (char)('0' + quals);
3040b57cec5SDimitry Andric     switch (MD->getRefQualifier()) {
3050b57cec5SDimitry Andric     case RQ_None: break;
3060b57cec5SDimitry Andric     case RQ_LValue: Out << '&'; break;
3070b57cec5SDimitry Andric     case RQ_RValue: Out << "&&"; break;
3080b57cec5SDimitry Andric     }
3090b57cec5SDimitry Andric   }
3100b57cec5SDimitry Andric }
3110b57cec5SDimitry Andric 
3120b57cec5SDimitry Andric void USRGenerator::VisitNamedDecl(const NamedDecl *D) {
3130b57cec5SDimitry Andric   VisitDeclContext(D->getDeclContext());
3140b57cec5SDimitry Andric   Out << "@";
3150b57cec5SDimitry Andric 
3160b57cec5SDimitry Andric   if (EmitDeclName(D)) {
3170b57cec5SDimitry Andric     // The string can be empty if the declaration has no name; e.g., it is
3180b57cec5SDimitry Andric     // the ParmDecl with no name for declaration of a function pointer type,
3190b57cec5SDimitry Andric     // e.g.: void  (*f)(void *);
3200b57cec5SDimitry Andric     // In this case, don't generate a USR.
3210b57cec5SDimitry Andric     IgnoreResults = true;
3220b57cec5SDimitry Andric   }
3230b57cec5SDimitry Andric }
3240b57cec5SDimitry Andric 
3250b57cec5SDimitry Andric void USRGenerator::VisitVarDecl(const VarDecl *D) {
3260b57cec5SDimitry Andric   // VarDecls can be declared 'extern' within a function or method body,
3270b57cec5SDimitry Andric   // but their enclosing DeclContext is the function, not the TU.  We need
3280b57cec5SDimitry Andric   // to check the storage class to correctly generate the USR.
3290b57cec5SDimitry Andric   if (ShouldGenerateLocation(D) && GenLoc(D, /*IncludeOffset=*/isLocal(D)))
3300b57cec5SDimitry Andric     return;
3310b57cec5SDimitry Andric 
3320b57cec5SDimitry Andric   VisitDeclContext(D->getDeclContext());
3330b57cec5SDimitry Andric 
3340b57cec5SDimitry Andric   if (VarTemplateDecl *VarTmpl = D->getDescribedVarTemplate()) {
3350b57cec5SDimitry Andric     Out << "@VT";
3360b57cec5SDimitry Andric     VisitTemplateParameterList(VarTmpl->getTemplateParameters());
3370b57cec5SDimitry Andric   } else if (const VarTemplatePartialSpecializationDecl *PartialSpec
3380b57cec5SDimitry Andric              = dyn_cast<VarTemplatePartialSpecializationDecl>(D)) {
3390b57cec5SDimitry Andric     Out << "@VP";
3400b57cec5SDimitry Andric     VisitTemplateParameterList(PartialSpec->getTemplateParameters());
3410b57cec5SDimitry Andric   }
3420b57cec5SDimitry Andric 
3430b57cec5SDimitry Andric   // Variables always have simple names.
3440b57cec5SDimitry Andric   StringRef s = D->getName();
3450b57cec5SDimitry Andric 
3460b57cec5SDimitry Andric   // The string can be empty if the declaration has no name; e.g., it is
3470b57cec5SDimitry Andric   // the ParmDecl with no name for declaration of a function pointer type, e.g.:
3480b57cec5SDimitry Andric   //    void  (*f)(void *);
3490b57cec5SDimitry Andric   // In this case, don't generate a USR.
3500b57cec5SDimitry Andric   if (s.empty())
3510b57cec5SDimitry Andric     IgnoreResults = true;
3520b57cec5SDimitry Andric   else
3530b57cec5SDimitry Andric     Out << '@' << s;
3540b57cec5SDimitry Andric 
3550b57cec5SDimitry Andric   // For a template specialization, mangle the template arguments.
3560b57cec5SDimitry Andric   if (const VarTemplateSpecializationDecl *Spec
3570b57cec5SDimitry Andric                               = dyn_cast<VarTemplateSpecializationDecl>(D)) {
3580b57cec5SDimitry Andric     const TemplateArgumentList &Args = Spec->getTemplateArgs();
3590b57cec5SDimitry Andric     Out << '>';
3600b57cec5SDimitry Andric     for (unsigned I = 0, N = Args.size(); I != N; ++I) {
3610b57cec5SDimitry Andric       Out << '#';
3620b57cec5SDimitry Andric       VisitTemplateArgument(Args.get(I));
3630b57cec5SDimitry Andric     }
3640b57cec5SDimitry Andric   }
3650b57cec5SDimitry Andric }
3660b57cec5SDimitry Andric 
3670b57cec5SDimitry Andric void USRGenerator::VisitBindingDecl(const BindingDecl *D) {
3680b57cec5SDimitry Andric   if (isLocal(D) && GenLoc(D, /*IncludeOffset=*/true))
3690b57cec5SDimitry Andric     return;
3700b57cec5SDimitry Andric   VisitNamedDecl(D);
3710b57cec5SDimitry Andric }
3720b57cec5SDimitry Andric 
3730b57cec5SDimitry Andric void USRGenerator::VisitNonTypeTemplateParmDecl(
3740b57cec5SDimitry Andric                                         const NonTypeTemplateParmDecl *D) {
3750b57cec5SDimitry Andric   GenLoc(D, /*IncludeOffset=*/true);
3760b57cec5SDimitry Andric }
3770b57cec5SDimitry Andric 
3780b57cec5SDimitry Andric void USRGenerator::VisitTemplateTemplateParmDecl(
3790b57cec5SDimitry Andric                                         const TemplateTemplateParmDecl *D) {
3800b57cec5SDimitry Andric   GenLoc(D, /*IncludeOffset=*/true);
3810b57cec5SDimitry Andric }
3820b57cec5SDimitry Andric 
3830b57cec5SDimitry Andric void USRGenerator::VisitNamespaceDecl(const NamespaceDecl *D) {
3845f757f3fSDimitry Andric   if (IgnoreResults)
3855f757f3fSDimitry Andric     return;
3865f757f3fSDimitry Andric   VisitDeclContext(D->getDeclContext());
3870b57cec5SDimitry Andric   if (D->isAnonymousNamespace()) {
3880b57cec5SDimitry Andric     Out << "@aN";
3890b57cec5SDimitry Andric     return;
3900b57cec5SDimitry Andric   }
3910b57cec5SDimitry Andric   Out << "@N@" << D->getName();
3920b57cec5SDimitry Andric }
3930b57cec5SDimitry Andric 
3940b57cec5SDimitry Andric void USRGenerator::VisitFunctionTemplateDecl(const FunctionTemplateDecl *D) {
3950b57cec5SDimitry Andric   VisitFunctionDecl(D->getTemplatedDecl());
3960b57cec5SDimitry Andric }
3970b57cec5SDimitry Andric 
3980b57cec5SDimitry Andric void USRGenerator::VisitClassTemplateDecl(const ClassTemplateDecl *D) {
3990b57cec5SDimitry Andric   VisitTagDecl(D->getTemplatedDecl());
4000b57cec5SDimitry Andric }
4010b57cec5SDimitry Andric 
4020b57cec5SDimitry Andric void USRGenerator::VisitNamespaceAliasDecl(const NamespaceAliasDecl *D) {
4030b57cec5SDimitry Andric   VisitDeclContext(D->getDeclContext());
4040b57cec5SDimitry Andric   if (!IgnoreResults)
4050b57cec5SDimitry Andric     Out << "@NA@" << D->getName();
4060b57cec5SDimitry Andric }
4070b57cec5SDimitry Andric 
4085ffd83dbSDimitry Andric static const ObjCCategoryDecl *getCategoryContext(const NamedDecl *D) {
4095ffd83dbSDimitry Andric   if (auto *CD = dyn_cast<ObjCCategoryDecl>(D->getDeclContext()))
4105ffd83dbSDimitry Andric     return CD;
4115ffd83dbSDimitry Andric   if (auto *ICD = dyn_cast<ObjCCategoryImplDecl>(D->getDeclContext()))
4125ffd83dbSDimitry Andric     return ICD->getCategoryDecl();
4135ffd83dbSDimitry Andric   return nullptr;
4145ffd83dbSDimitry Andric }
4155ffd83dbSDimitry Andric 
4160b57cec5SDimitry Andric void USRGenerator::VisitObjCMethodDecl(const ObjCMethodDecl *D) {
4170b57cec5SDimitry Andric   const DeclContext *container = D->getDeclContext();
4180b57cec5SDimitry Andric   if (const ObjCProtocolDecl *pd = dyn_cast<ObjCProtocolDecl>(container)) {
4190b57cec5SDimitry Andric     Visit(pd);
4200b57cec5SDimitry Andric   }
4210b57cec5SDimitry Andric   else {
4220b57cec5SDimitry Andric     // The USR for a method declared in a class extension or category is based on
4230b57cec5SDimitry Andric     // the ObjCInterfaceDecl, not the ObjCCategoryDecl.
4240b57cec5SDimitry Andric     const ObjCInterfaceDecl *ID = D->getClassInterface();
4250b57cec5SDimitry Andric     if (!ID) {
4260b57cec5SDimitry Andric       IgnoreResults = true;
4270b57cec5SDimitry Andric       return;
4280b57cec5SDimitry Andric     }
4290b57cec5SDimitry Andric     auto *CD = getCategoryContext(D);
4300b57cec5SDimitry Andric     VisitObjCContainerDecl(ID, CD);
4310b57cec5SDimitry Andric   }
4320b57cec5SDimitry Andric   // Ideally we would use 'GenObjCMethod', but this is such a hot path
4330b57cec5SDimitry Andric   // for Objective-C code that we don't want to use
4340b57cec5SDimitry Andric   // DeclarationName::getAsString().
4350b57cec5SDimitry Andric   Out << (D->isInstanceMethod() ? "(im)" : "(cm)")
4360b57cec5SDimitry Andric       << DeclarationName(D->getSelector());
4370b57cec5SDimitry Andric }
4380b57cec5SDimitry Andric 
4390b57cec5SDimitry Andric void USRGenerator::VisitObjCContainerDecl(const ObjCContainerDecl *D,
4400b57cec5SDimitry Andric                                           const ObjCCategoryDecl *CatD) {
4410b57cec5SDimitry Andric   switch (D->getKind()) {
4420b57cec5SDimitry Andric     default:
4430b57cec5SDimitry Andric       llvm_unreachable("Invalid ObjC container.");
4440b57cec5SDimitry Andric     case Decl::ObjCInterface:
4450b57cec5SDimitry Andric     case Decl::ObjCImplementation:
4460b57cec5SDimitry Andric       GenObjCClass(D->getName(), GetExternalSourceContainer(D),
4470b57cec5SDimitry Andric                    GetExternalSourceContainer(CatD));
4480b57cec5SDimitry Andric       break;
4490b57cec5SDimitry Andric     case Decl::ObjCCategory: {
4500b57cec5SDimitry Andric       const ObjCCategoryDecl *CD = cast<ObjCCategoryDecl>(D);
4510b57cec5SDimitry Andric       const ObjCInterfaceDecl *ID = CD->getClassInterface();
4520b57cec5SDimitry Andric       if (!ID) {
4530b57cec5SDimitry Andric         // Handle invalid code where the @interface might not
4540b57cec5SDimitry Andric         // have been specified.
4550b57cec5SDimitry Andric         // FIXME: We should be able to generate this USR even if the
4560b57cec5SDimitry Andric         // @interface isn't available.
4570b57cec5SDimitry Andric         IgnoreResults = true;
4580b57cec5SDimitry Andric         return;
4590b57cec5SDimitry Andric       }
4600b57cec5SDimitry Andric       // Specially handle class extensions, which are anonymous categories.
4610b57cec5SDimitry Andric       // We want to mangle in the location to uniquely distinguish them.
4620b57cec5SDimitry Andric       if (CD->IsClassExtension()) {
4630b57cec5SDimitry Andric         Out << "objc(ext)" << ID->getName() << '@';
4640b57cec5SDimitry Andric         GenLoc(CD, /*IncludeOffset=*/true);
4650b57cec5SDimitry Andric       }
4660b57cec5SDimitry Andric       else
4670b57cec5SDimitry Andric         GenObjCCategory(ID->getName(), CD->getName(),
4680b57cec5SDimitry Andric                         GetExternalSourceContainer(ID),
4690b57cec5SDimitry Andric                         GetExternalSourceContainer(CD));
4700b57cec5SDimitry Andric 
4710b57cec5SDimitry Andric       break;
4720b57cec5SDimitry Andric     }
4730b57cec5SDimitry Andric     case Decl::ObjCCategoryImpl: {
4740b57cec5SDimitry Andric       const ObjCCategoryImplDecl *CD = cast<ObjCCategoryImplDecl>(D);
4750b57cec5SDimitry Andric       const ObjCInterfaceDecl *ID = CD->getClassInterface();
4760b57cec5SDimitry Andric       if (!ID) {
4770b57cec5SDimitry Andric         // Handle invalid code where the @interface might not
4780b57cec5SDimitry Andric         // have been specified.
4790b57cec5SDimitry Andric         // FIXME: We should be able to generate this USR even if the
4800b57cec5SDimitry Andric         // @interface isn't available.
4810b57cec5SDimitry Andric         IgnoreResults = true;
4820b57cec5SDimitry Andric         return;
4830b57cec5SDimitry Andric       }
4840b57cec5SDimitry Andric       GenObjCCategory(ID->getName(), CD->getName(),
4850b57cec5SDimitry Andric                       GetExternalSourceContainer(ID),
4860b57cec5SDimitry Andric                       GetExternalSourceContainer(CD));
4870b57cec5SDimitry Andric       break;
4880b57cec5SDimitry Andric     }
4890b57cec5SDimitry Andric     case Decl::ObjCProtocol: {
4900b57cec5SDimitry Andric       const ObjCProtocolDecl *PD = cast<ObjCProtocolDecl>(D);
4910b57cec5SDimitry Andric       GenObjCProtocol(PD->getName(), GetExternalSourceContainer(PD));
4920b57cec5SDimitry Andric       break;
4930b57cec5SDimitry Andric     }
4940b57cec5SDimitry Andric   }
4950b57cec5SDimitry Andric }
4960b57cec5SDimitry Andric 
4970b57cec5SDimitry Andric void USRGenerator::VisitObjCPropertyDecl(const ObjCPropertyDecl *D) {
4980b57cec5SDimitry Andric   // The USR for a property declared in a class extension or category is based
4990b57cec5SDimitry Andric   // on the ObjCInterfaceDecl, not the ObjCCategoryDecl.
5000b57cec5SDimitry Andric   if (const ObjCInterfaceDecl *ID = Context->getObjContainingInterface(D))
5015ffd83dbSDimitry Andric     VisitObjCContainerDecl(ID, getCategoryContext(D));
5020b57cec5SDimitry Andric   else
5030b57cec5SDimitry Andric     Visit(cast<Decl>(D->getDeclContext()));
5040b57cec5SDimitry Andric   GenObjCProperty(D->getName(), D->isClassProperty());
5050b57cec5SDimitry Andric }
5060b57cec5SDimitry Andric 
5070b57cec5SDimitry Andric void USRGenerator::VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D) {
5080b57cec5SDimitry Andric   if (ObjCPropertyDecl *PD = D->getPropertyDecl()) {
5090b57cec5SDimitry Andric     VisitObjCPropertyDecl(PD);
5100b57cec5SDimitry Andric     return;
5110b57cec5SDimitry Andric   }
5120b57cec5SDimitry Andric 
5130b57cec5SDimitry Andric   IgnoreResults = true;
5140b57cec5SDimitry Andric }
5150b57cec5SDimitry Andric 
5160b57cec5SDimitry Andric void USRGenerator::VisitTagDecl(const TagDecl *D) {
5170b57cec5SDimitry Andric   // Add the location of the tag decl to handle resolution across
5180b57cec5SDimitry Andric   // translation units.
5190b57cec5SDimitry Andric   if (!isa<EnumDecl>(D) &&
5200b57cec5SDimitry Andric       ShouldGenerateLocation(D) && GenLoc(D, /*IncludeOffset=*/isLocal(D)))
5210b57cec5SDimitry Andric     return;
5220b57cec5SDimitry Andric 
5230b57cec5SDimitry Andric   GenExtSymbolContainer(D);
5240b57cec5SDimitry Andric 
5250b57cec5SDimitry Andric   D = D->getCanonicalDecl();
5260b57cec5SDimitry Andric   VisitDeclContext(D->getDeclContext());
5270b57cec5SDimitry Andric 
5280b57cec5SDimitry Andric   bool AlreadyStarted = false;
5290b57cec5SDimitry Andric   if (const CXXRecordDecl *CXXRecord = dyn_cast<CXXRecordDecl>(D)) {
5300b57cec5SDimitry Andric     if (ClassTemplateDecl *ClassTmpl = CXXRecord->getDescribedClassTemplate()) {
5310b57cec5SDimitry Andric       AlreadyStarted = true;
5320b57cec5SDimitry Andric 
5330b57cec5SDimitry Andric       switch (D->getTagKind()) {
5345f757f3fSDimitry Andric       case TagTypeKind::Interface:
5355f757f3fSDimitry Andric       case TagTypeKind::Class:
5365f757f3fSDimitry Andric       case TagTypeKind::Struct:
5375f757f3fSDimitry Andric         Out << "@ST";
5385f757f3fSDimitry Andric         break;
5395f757f3fSDimitry Andric       case TagTypeKind::Union:
5405f757f3fSDimitry Andric         Out << "@UT";
5415f757f3fSDimitry Andric         break;
5425f757f3fSDimitry Andric       case TagTypeKind::Enum:
5435f757f3fSDimitry Andric         llvm_unreachable("enum template");
5440b57cec5SDimitry Andric       }
5450b57cec5SDimitry Andric       VisitTemplateParameterList(ClassTmpl->getTemplateParameters());
5460b57cec5SDimitry Andric     } else if (const ClassTemplatePartialSpecializationDecl *PartialSpec
5470b57cec5SDimitry Andric                 = dyn_cast<ClassTemplatePartialSpecializationDecl>(CXXRecord)) {
5480b57cec5SDimitry Andric       AlreadyStarted = true;
5490b57cec5SDimitry Andric 
5500b57cec5SDimitry Andric       switch (D->getTagKind()) {
5515f757f3fSDimitry Andric       case TagTypeKind::Interface:
5525f757f3fSDimitry Andric       case TagTypeKind::Class:
5535f757f3fSDimitry Andric       case TagTypeKind::Struct:
5545f757f3fSDimitry Andric         Out << "@SP";
5555f757f3fSDimitry Andric         break;
5565f757f3fSDimitry Andric       case TagTypeKind::Union:
5575f757f3fSDimitry Andric         Out << "@UP";
5585f757f3fSDimitry Andric         break;
5595f757f3fSDimitry Andric       case TagTypeKind::Enum:
5605f757f3fSDimitry Andric         llvm_unreachable("enum partial specialization");
5610b57cec5SDimitry Andric       }
5620b57cec5SDimitry Andric       VisitTemplateParameterList(PartialSpec->getTemplateParameters());
5630b57cec5SDimitry Andric     }
5640b57cec5SDimitry Andric   }
5650b57cec5SDimitry Andric 
5660b57cec5SDimitry Andric   if (!AlreadyStarted) {
5670b57cec5SDimitry Andric     switch (D->getTagKind()) {
5685f757f3fSDimitry Andric     case TagTypeKind::Interface:
5695f757f3fSDimitry Andric     case TagTypeKind::Class:
5705f757f3fSDimitry Andric     case TagTypeKind::Struct:
5715f757f3fSDimitry Andric       Out << "@S";
5725f757f3fSDimitry Andric       break;
5735f757f3fSDimitry Andric     case TagTypeKind::Union:
5745f757f3fSDimitry Andric       Out << "@U";
5755f757f3fSDimitry Andric       break;
5765f757f3fSDimitry Andric     case TagTypeKind::Enum:
5775f757f3fSDimitry Andric       Out << "@E";
5785f757f3fSDimitry Andric       break;
5790b57cec5SDimitry Andric     }
5800b57cec5SDimitry Andric   }
5810b57cec5SDimitry Andric 
5820b57cec5SDimitry Andric   Out << '@';
5830b57cec5SDimitry Andric   assert(Buf.size() > 0);
5840b57cec5SDimitry Andric   const unsigned off = Buf.size() - 1;
5850b57cec5SDimitry Andric 
5860b57cec5SDimitry Andric   if (EmitDeclName(D)) {
5870b57cec5SDimitry Andric     if (const TypedefNameDecl *TD = D->getTypedefNameForAnonDecl()) {
5880b57cec5SDimitry Andric       Buf[off] = 'A';
5890b57cec5SDimitry Andric       Out << '@' << *TD;
59081ad6265SDimitry Andric     } else {
5910b57cec5SDimitry Andric       if (D->isEmbeddedInDeclarator() && !D->isFreeStanding()) {
5920b57cec5SDimitry Andric         printLoc(Out, D->getLocation(), Context->getSourceManager(), true);
5930b57cec5SDimitry Andric       } else {
5940b57cec5SDimitry Andric         Buf[off] = 'a';
5950b57cec5SDimitry Andric         if (auto *ED = dyn_cast<EnumDecl>(D)) {
59681ad6265SDimitry Andric           // Distinguish USRs of anonymous enums by using their first
59781ad6265SDimitry Andric           // enumerator.
5980b57cec5SDimitry Andric           auto enum_range = ED->enumerators();
5990b57cec5SDimitry Andric           if (enum_range.begin() != enum_range.end()) {
6000b57cec5SDimitry Andric             Out << '@' << **enum_range.begin();
6010b57cec5SDimitry Andric           }
6020b57cec5SDimitry Andric         }
6030b57cec5SDimitry Andric       }
6040b57cec5SDimitry Andric     }
6050b57cec5SDimitry Andric   }
6060b57cec5SDimitry Andric 
6070b57cec5SDimitry Andric   // For a class template specialization, mangle the template arguments.
6080b57cec5SDimitry Andric   if (const ClassTemplateSpecializationDecl *Spec
6090b57cec5SDimitry Andric                               = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
6100b57cec5SDimitry Andric     const TemplateArgumentList &Args = Spec->getTemplateArgs();
6110b57cec5SDimitry Andric     Out << '>';
6120b57cec5SDimitry Andric     for (unsigned I = 0, N = Args.size(); I != N; ++I) {
6130b57cec5SDimitry Andric       Out << '#';
6140b57cec5SDimitry Andric       VisitTemplateArgument(Args.get(I));
6150b57cec5SDimitry Andric     }
6160b57cec5SDimitry Andric   }
6170b57cec5SDimitry Andric }
6180b57cec5SDimitry Andric 
6190b57cec5SDimitry Andric void USRGenerator::VisitTypedefDecl(const TypedefDecl *D) {
6200b57cec5SDimitry Andric   if (ShouldGenerateLocation(D) && GenLoc(D, /*IncludeOffset=*/isLocal(D)))
6210b57cec5SDimitry Andric     return;
6220b57cec5SDimitry Andric   const DeclContext *DC = D->getDeclContext();
6230b57cec5SDimitry Andric   if (const NamedDecl *DCN = dyn_cast<NamedDecl>(DC))
6240b57cec5SDimitry Andric     Visit(DCN);
6250b57cec5SDimitry Andric   Out << "@T@";
6260b57cec5SDimitry Andric   Out << D->getName();
6270b57cec5SDimitry Andric }
6280b57cec5SDimitry Andric 
6290b57cec5SDimitry Andric void USRGenerator::VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D) {
6300b57cec5SDimitry Andric   GenLoc(D, /*IncludeOffset=*/true);
6310b57cec5SDimitry Andric }
6320b57cec5SDimitry Andric 
6330b57cec5SDimitry Andric void USRGenerator::GenExtSymbolContainer(const NamedDecl *D) {
6340b57cec5SDimitry Andric   StringRef Container = GetExternalSourceContainer(D);
6350b57cec5SDimitry Andric   if (!Container.empty())
6360b57cec5SDimitry Andric     Out << "@M@" << Container;
6370b57cec5SDimitry Andric }
6380b57cec5SDimitry Andric 
6390b57cec5SDimitry Andric bool USRGenerator::GenLoc(const Decl *D, bool IncludeOffset) {
6400b57cec5SDimitry Andric   if (generatedLoc)
6410b57cec5SDimitry Andric     return IgnoreResults;
6420b57cec5SDimitry Andric   generatedLoc = true;
6430b57cec5SDimitry Andric 
6440b57cec5SDimitry Andric   // Guard against null declarations in invalid code.
6450b57cec5SDimitry Andric   if (!D) {
6460b57cec5SDimitry Andric     IgnoreResults = true;
6470b57cec5SDimitry Andric     return true;
6480b57cec5SDimitry Andric   }
6490b57cec5SDimitry Andric 
6500b57cec5SDimitry Andric   // Use the location of canonical decl.
6510b57cec5SDimitry Andric   D = D->getCanonicalDecl();
6520b57cec5SDimitry Andric 
6530b57cec5SDimitry Andric   IgnoreResults =
6540b57cec5SDimitry Andric       IgnoreResults || printLoc(Out, D->getBeginLoc(),
6550b57cec5SDimitry Andric                                 Context->getSourceManager(), IncludeOffset);
6560b57cec5SDimitry Andric 
6570b57cec5SDimitry Andric   return IgnoreResults;
6580b57cec5SDimitry Andric }
6590b57cec5SDimitry Andric 
6600b57cec5SDimitry Andric static void printQualifier(llvm::raw_ostream &Out, ASTContext &Ctx, NestedNameSpecifier *NNS) {
6610b57cec5SDimitry Andric   // FIXME: Encode the qualifier, don't just print it.
6620b57cec5SDimitry Andric   PrintingPolicy PO(Ctx.getLangOpts());
6630b57cec5SDimitry Andric   PO.SuppressTagKeyword = true;
6640b57cec5SDimitry Andric   PO.SuppressUnwrittenScope = true;
6650b57cec5SDimitry Andric   PO.ConstantArraySizeAsWritten = false;
6660b57cec5SDimitry Andric   PO.AnonymousTagLocations = false;
6670b57cec5SDimitry Andric   NNS->print(Out, PO);
6680b57cec5SDimitry Andric }
6690b57cec5SDimitry Andric 
6700b57cec5SDimitry Andric void USRGenerator::VisitType(QualType T) {
6710b57cec5SDimitry Andric   // This method mangles in USR information for types.  It can possibly
6720b57cec5SDimitry Andric   // just reuse the naming-mangling logic used by codegen, although the
6730b57cec5SDimitry Andric   // requirements for USRs might not be the same.
6740b57cec5SDimitry Andric   ASTContext &Ctx = *Context;
6750b57cec5SDimitry Andric 
6760b57cec5SDimitry Andric   do {
6770b57cec5SDimitry Andric     T = Ctx.getCanonicalType(T);
6780b57cec5SDimitry Andric     Qualifiers Q = T.getQualifiers();
6790b57cec5SDimitry Andric     unsigned qVal = 0;
6800b57cec5SDimitry Andric     if (Q.hasConst())
6810b57cec5SDimitry Andric       qVal |= 0x1;
6820b57cec5SDimitry Andric     if (Q.hasVolatile())
6830b57cec5SDimitry Andric       qVal |= 0x2;
6840b57cec5SDimitry Andric     if (Q.hasRestrict())
6850b57cec5SDimitry Andric       qVal |= 0x4;
6860b57cec5SDimitry Andric     if(qVal)
6870b57cec5SDimitry Andric       Out << ((char) ('0' + qVal));
6880b57cec5SDimitry Andric 
6890b57cec5SDimitry Andric     // Mangle in ObjC GC qualifiers?
6900b57cec5SDimitry Andric 
6910b57cec5SDimitry Andric     if (const PackExpansionType *Expansion = T->getAs<PackExpansionType>()) {
6920b57cec5SDimitry Andric       Out << 'P';
6930b57cec5SDimitry Andric       T = Expansion->getPattern();
6940b57cec5SDimitry Andric     }
6950b57cec5SDimitry Andric 
6960b57cec5SDimitry Andric     if (const BuiltinType *BT = T->getAs<BuiltinType>()) {
6970b57cec5SDimitry Andric       switch (BT->getKind()) {
6980b57cec5SDimitry Andric         case BuiltinType::Void:
699bdd1243dSDimitry Andric           Out << 'v'; break;
7000b57cec5SDimitry Andric         case BuiltinType::Bool:
701bdd1243dSDimitry Andric           Out << 'b'; break;
7020b57cec5SDimitry Andric         case BuiltinType::UChar:
703bdd1243dSDimitry Andric           Out << 'c'; break;
7040b57cec5SDimitry Andric         case BuiltinType::Char8:
705bdd1243dSDimitry Andric           Out << 'u'; break;
7060b57cec5SDimitry Andric         case BuiltinType::Char16:
707bdd1243dSDimitry Andric           Out << 'q'; break;
7080b57cec5SDimitry Andric         case BuiltinType::Char32:
709bdd1243dSDimitry Andric           Out << 'w'; break;
7100b57cec5SDimitry Andric         case BuiltinType::UShort:
711bdd1243dSDimitry Andric           Out << 's'; break;
7120b57cec5SDimitry Andric         case BuiltinType::UInt:
713bdd1243dSDimitry Andric           Out << 'i'; break;
7140b57cec5SDimitry Andric         case BuiltinType::ULong:
715bdd1243dSDimitry Andric           Out << 'l'; break;
7160b57cec5SDimitry Andric         case BuiltinType::ULongLong:
717bdd1243dSDimitry Andric           Out << 'k'; break;
7180b57cec5SDimitry Andric         case BuiltinType::UInt128:
719bdd1243dSDimitry Andric           Out << 'j'; break;
7200b57cec5SDimitry Andric         case BuiltinType::Char_U:
7210b57cec5SDimitry Andric         case BuiltinType::Char_S:
722bdd1243dSDimitry Andric           Out << 'C'; break;
7230b57cec5SDimitry Andric         case BuiltinType::SChar:
724bdd1243dSDimitry Andric           Out << 'r'; break;
7250b57cec5SDimitry Andric         case BuiltinType::WChar_S:
7260b57cec5SDimitry Andric         case BuiltinType::WChar_U:
727bdd1243dSDimitry Andric           Out << 'W'; break;
7280b57cec5SDimitry Andric         case BuiltinType::Short:
729bdd1243dSDimitry Andric           Out << 'S'; break;
7300b57cec5SDimitry Andric         case BuiltinType::Int:
731bdd1243dSDimitry Andric           Out << 'I'; break;
7320b57cec5SDimitry Andric         case BuiltinType::Long:
733bdd1243dSDimitry Andric           Out << 'L'; break;
7340b57cec5SDimitry Andric         case BuiltinType::LongLong:
735bdd1243dSDimitry Andric           Out << 'K'; break;
7360b57cec5SDimitry Andric         case BuiltinType::Int128:
737bdd1243dSDimitry Andric           Out << 'J'; break;
7380b57cec5SDimitry Andric         case BuiltinType::Float16:
7390b57cec5SDimitry Andric         case BuiltinType::Half:
740bdd1243dSDimitry Andric           Out << 'h'; break;
7410b57cec5SDimitry Andric         case BuiltinType::Float:
742bdd1243dSDimitry Andric           Out << 'f'; break;
7430b57cec5SDimitry Andric         case BuiltinType::Double:
744bdd1243dSDimitry Andric           Out << 'd'; break;
7450b57cec5SDimitry Andric         case BuiltinType::LongDouble:
746bdd1243dSDimitry Andric           Out << 'D'; break;
7470b57cec5SDimitry Andric         case BuiltinType::Float128:
748bdd1243dSDimitry Andric           Out << 'Q'; break;
7490b57cec5SDimitry Andric         case BuiltinType::NullPtr:
750bdd1243dSDimitry Andric           Out << 'n'; break;
751bdd1243dSDimitry Andric #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
752bdd1243dSDimitry Andric         case BuiltinType::Id: \
753bdd1243dSDimitry Andric           Out << "@BT@" << #Suffix << "_" << #ImgType; break;
754bdd1243dSDimitry Andric #include "clang/Basic/OpenCLImageTypes.def"
755bdd1243dSDimitry Andric #define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
756bdd1243dSDimitry Andric         case BuiltinType::Id: \
757bdd1243dSDimitry Andric           Out << "@BT@" << #ExtType; break;
758bdd1243dSDimitry Andric #include "clang/Basic/OpenCLExtensionTypes.def"
759bdd1243dSDimitry Andric         case BuiltinType::OCLEvent:
760bdd1243dSDimitry Andric           Out << "@BT@OCLEvent"; break;
761bdd1243dSDimitry Andric         case BuiltinType::OCLClkEvent:
762bdd1243dSDimitry Andric           Out << "@BT@OCLClkEvent"; break;
763bdd1243dSDimitry Andric         case BuiltinType::OCLQueue:
764bdd1243dSDimitry Andric           Out << "@BT@OCLQueue"; break;
765bdd1243dSDimitry Andric         case BuiltinType::OCLReserveID:
766bdd1243dSDimitry Andric           Out << "@BT@OCLReserveID"; break;
767bdd1243dSDimitry Andric         case BuiltinType::OCLSampler:
768bdd1243dSDimitry Andric           Out << "@BT@OCLSampler"; break;
769bdd1243dSDimitry Andric #define SVE_TYPE(Name, Id, SingletonId) \
770bdd1243dSDimitry Andric         case BuiltinType::Id: \
771bdd1243dSDimitry Andric           Out << "@BT@" << Name; break;
772bdd1243dSDimitry Andric #include "clang/Basic/AArch64SVEACLETypes.def"
773bdd1243dSDimitry Andric #define PPC_VECTOR_TYPE(Name, Id, Size) \
774bdd1243dSDimitry Andric         case BuiltinType::Id: \
775bdd1243dSDimitry Andric           Out << "@BT@" << #Name; break;
776bdd1243dSDimitry Andric #include "clang/Basic/PPCTypes.def"
777bdd1243dSDimitry Andric #define RVV_TYPE(Name, Id, SingletonId) \
778bdd1243dSDimitry Andric         case BuiltinType::Id: \
779bdd1243dSDimitry Andric           Out << "@BT@" << Name; break;
780bdd1243dSDimitry Andric #include "clang/Basic/RISCVVTypes.def"
78106c3fb27SDimitry Andric #define WASM_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
78206c3fb27SDimitry Andric #include "clang/Basic/WebAssemblyReferenceTypes.def"
783*0fca6ea1SDimitry Andric #define AMDGPU_TYPE(Name, Id, SingletonId)                                     \
784*0fca6ea1SDimitry Andric   case BuiltinType::Id:                                                        \
785*0fca6ea1SDimitry Andric     Out << "@BT@" << #Name;                                                    \
786*0fca6ea1SDimitry Andric     break;
787*0fca6ea1SDimitry Andric #include "clang/Basic/AMDGPUTypes.def"
788bdd1243dSDimitry Andric         case BuiltinType::ShortAccum:
789bdd1243dSDimitry Andric           Out << "@BT@ShortAccum"; break;
790bdd1243dSDimitry Andric         case BuiltinType::Accum:
791bdd1243dSDimitry Andric           Out << "@BT@Accum"; break;
792bdd1243dSDimitry Andric         case BuiltinType::LongAccum:
793bdd1243dSDimitry Andric           Out << "@BT@LongAccum"; break;
794bdd1243dSDimitry Andric         case BuiltinType::UShortAccum:
795bdd1243dSDimitry Andric           Out << "@BT@UShortAccum"; break;
796bdd1243dSDimitry Andric         case BuiltinType::UAccum:
797bdd1243dSDimitry Andric           Out << "@BT@UAccum"; break;
798bdd1243dSDimitry Andric         case BuiltinType::ULongAccum:
799bdd1243dSDimitry Andric           Out << "@BT@ULongAccum"; break;
800bdd1243dSDimitry Andric         case BuiltinType::ShortFract:
801bdd1243dSDimitry Andric           Out << "@BT@ShortFract"; break;
802bdd1243dSDimitry Andric         case BuiltinType::Fract:
803bdd1243dSDimitry Andric           Out << "@BT@Fract"; break;
804bdd1243dSDimitry Andric         case BuiltinType::LongFract:
805bdd1243dSDimitry Andric           Out << "@BT@LongFract"; break;
806bdd1243dSDimitry Andric         case BuiltinType::UShortFract:
807bdd1243dSDimitry Andric           Out << "@BT@UShortFract"; break;
808bdd1243dSDimitry Andric         case BuiltinType::UFract:
809bdd1243dSDimitry Andric           Out << "@BT@UFract"; break;
810bdd1243dSDimitry Andric         case BuiltinType::ULongFract:
811bdd1243dSDimitry Andric           Out << "@BT@ULongFract"; break;
812bdd1243dSDimitry Andric         case BuiltinType::SatShortAccum:
813bdd1243dSDimitry Andric           Out << "@BT@SatShortAccum"; break;
814bdd1243dSDimitry Andric         case BuiltinType::SatAccum:
815bdd1243dSDimitry Andric           Out << "@BT@SatAccum"; break;
816bdd1243dSDimitry Andric         case BuiltinType::SatLongAccum:
817bdd1243dSDimitry Andric           Out << "@BT@SatLongAccum"; break;
818bdd1243dSDimitry Andric         case BuiltinType::SatUShortAccum:
819bdd1243dSDimitry Andric           Out << "@BT@SatUShortAccum"; break;
820bdd1243dSDimitry Andric         case BuiltinType::SatUAccum:
821bdd1243dSDimitry Andric           Out << "@BT@SatUAccum"; break;
822bdd1243dSDimitry Andric         case BuiltinType::SatULongAccum:
823bdd1243dSDimitry Andric           Out << "@BT@SatULongAccum"; break;
824bdd1243dSDimitry Andric         case BuiltinType::SatShortFract:
825bdd1243dSDimitry Andric           Out << "@BT@SatShortFract"; break;
826bdd1243dSDimitry Andric         case BuiltinType::SatFract:
827bdd1243dSDimitry Andric           Out << "@BT@SatFract"; break;
828bdd1243dSDimitry Andric         case BuiltinType::SatLongFract:
829bdd1243dSDimitry Andric           Out << "@BT@SatLongFract"; break;
830bdd1243dSDimitry Andric         case BuiltinType::SatUShortFract:
831bdd1243dSDimitry Andric           Out << "@BT@SatUShortFract"; break;
832bdd1243dSDimitry Andric         case BuiltinType::SatUFract:
833bdd1243dSDimitry Andric           Out << "@BT@SatUFract"; break;
834bdd1243dSDimitry Andric         case BuiltinType::SatULongFract:
835bdd1243dSDimitry Andric           Out << "@BT@SatULongFract"; break;
836bdd1243dSDimitry Andric         case BuiltinType::BFloat16:
837bdd1243dSDimitry Andric           Out << "@BT@__bf16"; break;
838bdd1243dSDimitry Andric         case BuiltinType::Ibm128:
839bdd1243dSDimitry Andric           Out << "@BT@__ibm128"; break;
840bdd1243dSDimitry Andric         case BuiltinType::ObjCId:
841bdd1243dSDimitry Andric           Out << 'o'; break;
842bdd1243dSDimitry Andric         case BuiltinType::ObjCClass:
843bdd1243dSDimitry Andric           Out << 'O'; break;
844bdd1243dSDimitry Andric         case BuiltinType::ObjCSel:
845bdd1243dSDimitry Andric           Out << 'e'; break;
8460b57cec5SDimitry Andric #define BUILTIN_TYPE(Id, SingletonId)
8470b57cec5SDimitry Andric #define PLACEHOLDER_TYPE(Id, SingletonId) case BuiltinType::Id:
8480b57cec5SDimitry Andric #include "clang/AST/BuiltinTypes.def"
8490b57cec5SDimitry Andric         case BuiltinType::Dependent:
850bdd1243dSDimitry Andric           // If you're adding a new builtin type, please add its name prefixed
851bdd1243dSDimitry Andric           // with "@BT@" to `Out` (see cases above).
8520b57cec5SDimitry Andric           IgnoreResults = true;
853bdd1243dSDimitry Andric           break;
8540b57cec5SDimitry Andric       }
8550b57cec5SDimitry Andric       return;
8560b57cec5SDimitry Andric     }
8570b57cec5SDimitry Andric 
8580b57cec5SDimitry Andric     // If we have already seen this (non-built-in) type, use a substitution
8590b57cec5SDimitry Andric     // encoding.
8600b57cec5SDimitry Andric     llvm::DenseMap<const Type *, unsigned>::iterator Substitution
8610b57cec5SDimitry Andric       = TypeSubstitutions.find(T.getTypePtr());
8620b57cec5SDimitry Andric     if (Substitution != TypeSubstitutions.end()) {
8630b57cec5SDimitry Andric       Out << 'S' << Substitution->second << '_';
8640b57cec5SDimitry Andric       return;
8650b57cec5SDimitry Andric     } else {
8660b57cec5SDimitry Andric       // Record this as a substitution.
8670b57cec5SDimitry Andric       unsigned Number = TypeSubstitutions.size();
8680b57cec5SDimitry Andric       TypeSubstitutions[T.getTypePtr()] = Number;
8690b57cec5SDimitry Andric     }
8700b57cec5SDimitry Andric 
8710b57cec5SDimitry Andric     if (const PointerType *PT = T->getAs<PointerType>()) {
8720b57cec5SDimitry Andric       Out << '*';
8730b57cec5SDimitry Andric       T = PT->getPointeeType();
8740b57cec5SDimitry Andric       continue;
8750b57cec5SDimitry Andric     }
8760b57cec5SDimitry Andric     if (const ObjCObjectPointerType *OPT = T->getAs<ObjCObjectPointerType>()) {
8770b57cec5SDimitry Andric       Out << '*';
8780b57cec5SDimitry Andric       T = OPT->getPointeeType();
8790b57cec5SDimitry Andric       continue;
8800b57cec5SDimitry Andric     }
8810b57cec5SDimitry Andric     if (const RValueReferenceType *RT = T->getAs<RValueReferenceType>()) {
8820b57cec5SDimitry Andric       Out << "&&";
8830b57cec5SDimitry Andric       T = RT->getPointeeType();
8840b57cec5SDimitry Andric       continue;
8850b57cec5SDimitry Andric     }
8860b57cec5SDimitry Andric     if (const ReferenceType *RT = T->getAs<ReferenceType>()) {
8870b57cec5SDimitry Andric       Out << '&';
8880b57cec5SDimitry Andric       T = RT->getPointeeType();
8890b57cec5SDimitry Andric       continue;
8900b57cec5SDimitry Andric     }
8910b57cec5SDimitry Andric     if (const FunctionProtoType *FT = T->getAs<FunctionProtoType>()) {
8920b57cec5SDimitry Andric       Out << 'F';
8930b57cec5SDimitry Andric       VisitType(FT->getReturnType());
8940b57cec5SDimitry Andric       Out << '(';
8950b57cec5SDimitry Andric       for (const auto &I : FT->param_types()) {
8960b57cec5SDimitry Andric         Out << '#';
8970b57cec5SDimitry Andric         VisitType(I);
8980b57cec5SDimitry Andric       }
8990b57cec5SDimitry Andric       Out << ')';
9000b57cec5SDimitry Andric       if (FT->isVariadic())
9010b57cec5SDimitry Andric         Out << '.';
9020b57cec5SDimitry Andric       return;
9030b57cec5SDimitry Andric     }
9040b57cec5SDimitry Andric     if (const BlockPointerType *BT = T->getAs<BlockPointerType>()) {
9050b57cec5SDimitry Andric       Out << 'B';
9060b57cec5SDimitry Andric       T = BT->getPointeeType();
9070b57cec5SDimitry Andric       continue;
9080b57cec5SDimitry Andric     }
9090b57cec5SDimitry Andric     if (const ComplexType *CT = T->getAs<ComplexType>()) {
9100b57cec5SDimitry Andric       Out << '<';
9110b57cec5SDimitry Andric       T = CT->getElementType();
9120b57cec5SDimitry Andric       continue;
9130b57cec5SDimitry Andric     }
9140b57cec5SDimitry Andric     if (const TagType *TT = T->getAs<TagType>()) {
9150b57cec5SDimitry Andric       Out << '$';
9160b57cec5SDimitry Andric       VisitTagDecl(TT->getDecl());
9170b57cec5SDimitry Andric       return;
9180b57cec5SDimitry Andric     }
9190b57cec5SDimitry Andric     if (const ObjCInterfaceType *OIT = T->getAs<ObjCInterfaceType>()) {
9200b57cec5SDimitry Andric       Out << '$';
9210b57cec5SDimitry Andric       VisitObjCInterfaceDecl(OIT->getDecl());
9220b57cec5SDimitry Andric       return;
9230b57cec5SDimitry Andric     }
9240b57cec5SDimitry Andric     if (const ObjCObjectType *OIT = T->getAs<ObjCObjectType>()) {
9250b57cec5SDimitry Andric       Out << 'Q';
9260b57cec5SDimitry Andric       VisitType(OIT->getBaseType());
9270b57cec5SDimitry Andric       for (auto *Prot : OIT->getProtocols())
9280b57cec5SDimitry Andric         VisitObjCProtocolDecl(Prot);
9290b57cec5SDimitry Andric       return;
9300b57cec5SDimitry Andric     }
9310b57cec5SDimitry Andric     if (const TemplateTypeParmType *TTP = T->getAs<TemplateTypeParmType>()) {
9320b57cec5SDimitry Andric       Out << 't' << TTP->getDepth() << '.' << TTP->getIndex();
9330b57cec5SDimitry Andric       return;
9340b57cec5SDimitry Andric     }
9350b57cec5SDimitry Andric     if (const TemplateSpecializationType *Spec
9360b57cec5SDimitry Andric                                     = T->getAs<TemplateSpecializationType>()) {
9370b57cec5SDimitry Andric       Out << '>';
9380b57cec5SDimitry Andric       VisitTemplateName(Spec->getTemplateName());
939bdd1243dSDimitry Andric       Out << Spec->template_arguments().size();
940bdd1243dSDimitry Andric       for (const auto &Arg : Spec->template_arguments())
941bdd1243dSDimitry Andric         VisitTemplateArgument(Arg);
9420b57cec5SDimitry Andric       return;
9430b57cec5SDimitry Andric     }
9440b57cec5SDimitry Andric     if (const DependentNameType *DNT = T->getAs<DependentNameType>()) {
9450b57cec5SDimitry Andric       Out << '^';
9460b57cec5SDimitry Andric       printQualifier(Out, Ctx, DNT->getQualifier());
9470b57cec5SDimitry Andric       Out << ':' << DNT->getIdentifier()->getName();
9480b57cec5SDimitry Andric       return;
9490b57cec5SDimitry Andric     }
9500b57cec5SDimitry Andric     if (const InjectedClassNameType *InjT = T->getAs<InjectedClassNameType>()) {
9510b57cec5SDimitry Andric       T = InjT->getInjectedSpecializationType();
9520b57cec5SDimitry Andric       continue;
9530b57cec5SDimitry Andric     }
9540b57cec5SDimitry Andric     if (const auto *VT = T->getAs<VectorType>()) {
9550b57cec5SDimitry Andric       Out << (T->isExtVectorType() ? ']' : '[');
9560b57cec5SDimitry Andric       Out << VT->getNumElements();
9570b57cec5SDimitry Andric       T = VT->getElementType();
9580b57cec5SDimitry Andric       continue;
9590b57cec5SDimitry Andric     }
9600b57cec5SDimitry Andric     if (const auto *const AT = dyn_cast<ArrayType>(T)) {
9610b57cec5SDimitry Andric       Out << '{';
9620b57cec5SDimitry Andric       switch (AT->getSizeModifier()) {
9635f757f3fSDimitry Andric       case ArraySizeModifier::Static:
9640b57cec5SDimitry Andric         Out << 's';
9650b57cec5SDimitry Andric         break;
9665f757f3fSDimitry Andric       case ArraySizeModifier::Star:
9670b57cec5SDimitry Andric         Out << '*';
9680b57cec5SDimitry Andric         break;
9695f757f3fSDimitry Andric       case ArraySizeModifier::Normal:
9700b57cec5SDimitry Andric         Out << 'n';
9710b57cec5SDimitry Andric         break;
9720b57cec5SDimitry Andric       }
9730b57cec5SDimitry Andric       if (const auto *const CAT = dyn_cast<ConstantArrayType>(T))
9740b57cec5SDimitry Andric         Out << CAT->getSize();
9750b57cec5SDimitry Andric 
9760b57cec5SDimitry Andric       T = AT->getElementType();
9770b57cec5SDimitry Andric       continue;
9780b57cec5SDimitry Andric     }
9790b57cec5SDimitry Andric 
9800b57cec5SDimitry Andric     // Unhandled type.
9810b57cec5SDimitry Andric     Out << ' ';
9820b57cec5SDimitry Andric     break;
9830b57cec5SDimitry Andric   } while (true);
9840b57cec5SDimitry Andric }
9850b57cec5SDimitry Andric 
9860b57cec5SDimitry Andric void USRGenerator::VisitTemplateParameterList(
9870b57cec5SDimitry Andric                                          const TemplateParameterList *Params) {
9880b57cec5SDimitry Andric   if (!Params)
9890b57cec5SDimitry Andric     return;
9900b57cec5SDimitry Andric   Out << '>' << Params->size();
9910b57cec5SDimitry Andric   for (TemplateParameterList::const_iterator P = Params->begin(),
9920b57cec5SDimitry Andric                                           PEnd = Params->end();
9930b57cec5SDimitry Andric        P != PEnd; ++P) {
9940b57cec5SDimitry Andric     Out << '#';
9950b57cec5SDimitry Andric     if (isa<TemplateTypeParmDecl>(*P)) {
9960b57cec5SDimitry Andric       if (cast<TemplateTypeParmDecl>(*P)->isParameterPack())
9970b57cec5SDimitry Andric         Out<< 'p';
9980b57cec5SDimitry Andric       Out << 'T';
9990b57cec5SDimitry Andric       continue;
10000b57cec5SDimitry Andric     }
10010b57cec5SDimitry Andric 
10020b57cec5SDimitry Andric     if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(*P)) {
10030b57cec5SDimitry Andric       if (NTTP->isParameterPack())
10040b57cec5SDimitry Andric         Out << 'p';
10050b57cec5SDimitry Andric       Out << 'N';
10060b57cec5SDimitry Andric       VisitType(NTTP->getType());
10070b57cec5SDimitry Andric       continue;
10080b57cec5SDimitry Andric     }
10090b57cec5SDimitry Andric 
10100b57cec5SDimitry Andric     TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*P);
10110b57cec5SDimitry Andric     if (TTP->isParameterPack())
10120b57cec5SDimitry Andric       Out << 'p';
10130b57cec5SDimitry Andric     Out << 't';
10140b57cec5SDimitry Andric     VisitTemplateParameterList(TTP->getTemplateParameters());
10150b57cec5SDimitry Andric   }
10160b57cec5SDimitry Andric }
10170b57cec5SDimitry Andric 
10180b57cec5SDimitry Andric void USRGenerator::VisitTemplateName(TemplateName Name) {
10190b57cec5SDimitry Andric   if (TemplateDecl *Template = Name.getAsTemplateDecl()) {
10200b57cec5SDimitry Andric     if (TemplateTemplateParmDecl *TTP
10210b57cec5SDimitry Andric                               = dyn_cast<TemplateTemplateParmDecl>(Template)) {
10220b57cec5SDimitry Andric       Out << 't' << TTP->getDepth() << '.' << TTP->getIndex();
10230b57cec5SDimitry Andric       return;
10240b57cec5SDimitry Andric     }
10250b57cec5SDimitry Andric 
10260b57cec5SDimitry Andric     Visit(Template);
10270b57cec5SDimitry Andric     return;
10280b57cec5SDimitry Andric   }
10290b57cec5SDimitry Andric 
10300b57cec5SDimitry Andric   // FIXME: Visit dependent template names.
10310b57cec5SDimitry Andric }
10320b57cec5SDimitry Andric 
10330b57cec5SDimitry Andric void USRGenerator::VisitTemplateArgument(const TemplateArgument &Arg) {
10340b57cec5SDimitry Andric   switch (Arg.getKind()) {
10350b57cec5SDimitry Andric   case TemplateArgument::Null:
10360b57cec5SDimitry Andric     break;
10370b57cec5SDimitry Andric 
10380b57cec5SDimitry Andric   case TemplateArgument::Declaration:
10390b57cec5SDimitry Andric     Visit(Arg.getAsDecl());
10400b57cec5SDimitry Andric     break;
10410b57cec5SDimitry Andric 
10420b57cec5SDimitry Andric   case TemplateArgument::NullPtr:
10430b57cec5SDimitry Andric     break;
10440b57cec5SDimitry Andric 
10450b57cec5SDimitry Andric   case TemplateArgument::TemplateExpansion:
10460b57cec5SDimitry Andric     Out << 'P'; // pack expansion of...
1047bdd1243dSDimitry Andric     [[fallthrough]];
10480b57cec5SDimitry Andric   case TemplateArgument::Template:
10490b57cec5SDimitry Andric     VisitTemplateName(Arg.getAsTemplateOrTemplatePattern());
10500b57cec5SDimitry Andric     break;
10510b57cec5SDimitry Andric 
10520b57cec5SDimitry Andric   case TemplateArgument::Expression:
10530b57cec5SDimitry Andric     // FIXME: Visit expressions.
10540b57cec5SDimitry Andric     break;
10550b57cec5SDimitry Andric 
10560b57cec5SDimitry Andric   case TemplateArgument::Pack:
10570b57cec5SDimitry Andric     Out << 'p' << Arg.pack_size();
10580b57cec5SDimitry Andric     for (const auto &P : Arg.pack_elements())
10590b57cec5SDimitry Andric       VisitTemplateArgument(P);
10600b57cec5SDimitry Andric     break;
10610b57cec5SDimitry Andric 
10620b57cec5SDimitry Andric   case TemplateArgument::Type:
10630b57cec5SDimitry Andric     VisitType(Arg.getAsType());
10640b57cec5SDimitry Andric     break;
10650b57cec5SDimitry Andric 
10660b57cec5SDimitry Andric   case TemplateArgument::Integral:
10670b57cec5SDimitry Andric     Out << 'V';
10680b57cec5SDimitry Andric     VisitType(Arg.getIntegralType());
10690b57cec5SDimitry Andric     Out << Arg.getAsIntegral();
10700b57cec5SDimitry Andric     break;
10717a6dacacSDimitry Andric 
10727a6dacacSDimitry Andric   case TemplateArgument::StructuralValue: {
10737a6dacacSDimitry Andric     Out << 'S';
10747a6dacacSDimitry Andric     VisitType(Arg.getStructuralValueType());
10757a6dacacSDimitry Andric     ODRHash Hash{};
10767a6dacacSDimitry Andric     Hash.AddStructuralValue(Arg.getAsStructuralValue());
10777a6dacacSDimitry Andric     Out << Hash.CalculateHash();
10787a6dacacSDimitry Andric     break;
10797a6dacacSDimitry Andric   }
10800b57cec5SDimitry Andric   }
10810b57cec5SDimitry Andric }
10820b57cec5SDimitry Andric 
10830b57cec5SDimitry Andric void USRGenerator::VisitUnresolvedUsingValueDecl(const UnresolvedUsingValueDecl *D) {
10840b57cec5SDimitry Andric   if (ShouldGenerateLocation(D) && GenLoc(D, /*IncludeOffset=*/isLocal(D)))
10850b57cec5SDimitry Andric     return;
10860b57cec5SDimitry Andric   VisitDeclContext(D->getDeclContext());
10870b57cec5SDimitry Andric   Out << "@UUV@";
10880b57cec5SDimitry Andric   printQualifier(Out, D->getASTContext(), D->getQualifier());
10890b57cec5SDimitry Andric   EmitDeclName(D);
10900b57cec5SDimitry Andric }
10910b57cec5SDimitry Andric 
10920b57cec5SDimitry Andric void USRGenerator::VisitUnresolvedUsingTypenameDecl(const UnresolvedUsingTypenameDecl *D) {
10930b57cec5SDimitry Andric   if (ShouldGenerateLocation(D) && GenLoc(D, /*IncludeOffset=*/isLocal(D)))
10940b57cec5SDimitry Andric     return;
10950b57cec5SDimitry Andric   VisitDeclContext(D->getDeclContext());
10960b57cec5SDimitry Andric   Out << "@UUT@";
10970b57cec5SDimitry Andric   printQualifier(Out, D->getASTContext(), D->getQualifier());
10980b57cec5SDimitry Andric   Out << D->getName(); // Simple name.
10990b57cec5SDimitry Andric }
11000b57cec5SDimitry Andric 
110181ad6265SDimitry Andric void USRGenerator::VisitConceptDecl(const ConceptDecl *D) {
110281ad6265SDimitry Andric   if (ShouldGenerateLocation(D) && GenLoc(D, /*IncludeOffset=*/isLocal(D)))
110381ad6265SDimitry Andric     return;
110481ad6265SDimitry Andric   VisitDeclContext(D->getDeclContext());
110581ad6265SDimitry Andric   Out << "@CT@";
110681ad6265SDimitry Andric   EmitDeclName(D);
110781ad6265SDimitry Andric }
11080b57cec5SDimitry Andric 
1109bdd1243dSDimitry Andric void USRGenerator::VisitMSGuidDecl(const MSGuidDecl *D) {
1110bdd1243dSDimitry Andric   VisitDeclContext(D->getDeclContext());
1111bdd1243dSDimitry Andric   Out << "@MG@";
1112bdd1243dSDimitry Andric   D->NamedDecl::printName(Out);
1113bdd1243dSDimitry Andric }
1114bdd1243dSDimitry Andric 
11150b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
11160b57cec5SDimitry Andric // USR generation functions.
11170b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
11180b57cec5SDimitry Andric 
11190b57cec5SDimitry Andric static void combineClassAndCategoryExtContainers(StringRef ClsSymDefinedIn,
11200b57cec5SDimitry Andric                                                  StringRef CatSymDefinedIn,
11210b57cec5SDimitry Andric                                                  raw_ostream &OS) {
11220b57cec5SDimitry Andric   if (ClsSymDefinedIn.empty() && CatSymDefinedIn.empty())
11230b57cec5SDimitry Andric     return;
11240b57cec5SDimitry Andric   if (CatSymDefinedIn.empty()) {
11250b57cec5SDimitry Andric     OS << "@M@" << ClsSymDefinedIn << '@';
11260b57cec5SDimitry Andric     return;
11270b57cec5SDimitry Andric   }
11280b57cec5SDimitry Andric   OS << "@CM@" << CatSymDefinedIn << '@';
11290b57cec5SDimitry Andric   if (ClsSymDefinedIn != CatSymDefinedIn) {
11300b57cec5SDimitry Andric     OS << ClsSymDefinedIn << '@';
11310b57cec5SDimitry Andric   }
11320b57cec5SDimitry Andric }
11330b57cec5SDimitry Andric 
11340b57cec5SDimitry Andric void clang::index::generateUSRForObjCClass(StringRef Cls, raw_ostream &OS,
11350b57cec5SDimitry Andric                                            StringRef ExtSymDefinedIn,
11360b57cec5SDimitry Andric                                   StringRef CategoryContextExtSymbolDefinedIn) {
11370b57cec5SDimitry Andric   combineClassAndCategoryExtContainers(ExtSymDefinedIn,
11380b57cec5SDimitry Andric                                        CategoryContextExtSymbolDefinedIn, OS);
11390b57cec5SDimitry Andric   OS << "objc(cs)" << Cls;
11400b57cec5SDimitry Andric }
11410b57cec5SDimitry Andric 
11420b57cec5SDimitry Andric void clang::index::generateUSRForObjCCategory(StringRef Cls, StringRef Cat,
11430b57cec5SDimitry Andric                                               raw_ostream &OS,
11440b57cec5SDimitry Andric                                               StringRef ClsSymDefinedIn,
11450b57cec5SDimitry Andric                                               StringRef CatSymDefinedIn) {
11460b57cec5SDimitry Andric   combineClassAndCategoryExtContainers(ClsSymDefinedIn, CatSymDefinedIn, OS);
11470b57cec5SDimitry Andric   OS << "objc(cy)" << Cls << '@' << Cat;
11480b57cec5SDimitry Andric }
11490b57cec5SDimitry Andric 
11500b57cec5SDimitry Andric void clang::index::generateUSRForObjCIvar(StringRef Ivar, raw_ostream &OS) {
11510b57cec5SDimitry Andric   OS << '@' << Ivar;
11520b57cec5SDimitry Andric }
11530b57cec5SDimitry Andric 
11540b57cec5SDimitry Andric void clang::index::generateUSRForObjCMethod(StringRef Sel,
11550b57cec5SDimitry Andric                                             bool IsInstanceMethod,
11560b57cec5SDimitry Andric                                             raw_ostream &OS) {
11570b57cec5SDimitry Andric   OS << (IsInstanceMethod ? "(im)" : "(cm)") << Sel;
11580b57cec5SDimitry Andric }
11590b57cec5SDimitry Andric 
11600b57cec5SDimitry Andric void clang::index::generateUSRForObjCProperty(StringRef Prop, bool isClassProp,
11610b57cec5SDimitry Andric                                               raw_ostream &OS) {
11620b57cec5SDimitry Andric   OS << (isClassProp ? "(cpy)" : "(py)") << Prop;
11630b57cec5SDimitry Andric }
11640b57cec5SDimitry Andric 
11650b57cec5SDimitry Andric void clang::index::generateUSRForObjCProtocol(StringRef Prot, raw_ostream &OS,
11660b57cec5SDimitry Andric                                               StringRef ExtSymDefinedIn) {
11670b57cec5SDimitry Andric   if (!ExtSymDefinedIn.empty())
11680b57cec5SDimitry Andric     OS << "@M@" << ExtSymDefinedIn << '@';
11690b57cec5SDimitry Andric   OS << "objc(pl)" << Prot;
11700b57cec5SDimitry Andric }
11710b57cec5SDimitry Andric 
11720b57cec5SDimitry Andric void clang::index::generateUSRForGlobalEnum(StringRef EnumName, raw_ostream &OS,
11730b57cec5SDimitry Andric                                             StringRef ExtSymDefinedIn) {
11740b57cec5SDimitry Andric   if (!ExtSymDefinedIn.empty())
11750b57cec5SDimitry Andric     OS << "@M@" << ExtSymDefinedIn;
11760b57cec5SDimitry Andric   OS << "@E@" << EnumName;
11770b57cec5SDimitry Andric }
11780b57cec5SDimitry Andric 
11790b57cec5SDimitry Andric void clang::index::generateUSRForEnumConstant(StringRef EnumConstantName,
11800b57cec5SDimitry Andric                                               raw_ostream &OS) {
11810b57cec5SDimitry Andric   OS << '@' << EnumConstantName;
11820b57cec5SDimitry Andric }
11830b57cec5SDimitry Andric 
11840b57cec5SDimitry Andric bool clang::index::generateUSRForDecl(const Decl *D,
11850b57cec5SDimitry Andric                                       SmallVectorImpl<char> &Buf) {
11860b57cec5SDimitry Andric   if (!D)
11870b57cec5SDimitry Andric     return true;
11880b57cec5SDimitry Andric   // We don't ignore decls with invalid source locations. Implicit decls, like
11890b57cec5SDimitry Andric   // C++'s operator new function, can have invalid locations but it is fine to
11900b57cec5SDimitry Andric   // create USRs that can identify them.
11910b57cec5SDimitry Andric 
119206c3fb27SDimitry Andric   // Check if the declaration has explicit external USR specified.
119306c3fb27SDimitry Andric   auto *CD = D->getCanonicalDecl();
119406c3fb27SDimitry Andric   if (auto *ExternalSymAttr = CD->getAttr<ExternalSourceSymbolAttr>()) {
119506c3fb27SDimitry Andric     if (!ExternalSymAttr->getUSR().empty()) {
119606c3fb27SDimitry Andric       llvm::raw_svector_ostream Out(Buf);
119706c3fb27SDimitry Andric       Out << ExternalSymAttr->getUSR();
119806c3fb27SDimitry Andric       return false;
119906c3fb27SDimitry Andric     }
120006c3fb27SDimitry Andric   }
12010b57cec5SDimitry Andric   USRGenerator UG(&D->getASTContext(), Buf);
12020b57cec5SDimitry Andric   UG.Visit(D);
12030b57cec5SDimitry Andric   return UG.ignoreResults();
12040b57cec5SDimitry Andric }
12050b57cec5SDimitry Andric 
12060b57cec5SDimitry Andric bool clang::index::generateUSRForMacro(const MacroDefinitionRecord *MD,
12070b57cec5SDimitry Andric                                        const SourceManager &SM,
12080b57cec5SDimitry Andric                                        SmallVectorImpl<char> &Buf) {
12090b57cec5SDimitry Andric   if (!MD)
12100b57cec5SDimitry Andric     return true;
12110b57cec5SDimitry Andric   return generateUSRForMacro(MD->getName()->getName(), MD->getLocation(),
12120b57cec5SDimitry Andric                              SM, Buf);
12130b57cec5SDimitry Andric 
12140b57cec5SDimitry Andric }
12150b57cec5SDimitry Andric 
12160b57cec5SDimitry Andric bool clang::index::generateUSRForMacro(StringRef MacroName, SourceLocation Loc,
12170b57cec5SDimitry Andric                                        const SourceManager &SM,
12180b57cec5SDimitry Andric                                        SmallVectorImpl<char> &Buf) {
1219fe6060f1SDimitry Andric   if (MacroName.empty())
12200b57cec5SDimitry Andric     return true;
12210b57cec5SDimitry Andric 
12220b57cec5SDimitry Andric   llvm::raw_svector_ostream Out(Buf);
12230b57cec5SDimitry Andric 
12240b57cec5SDimitry Andric   // Assume that system headers are sane.  Don't put source location
12250b57cec5SDimitry Andric   // information into the USR if the macro comes from a system header.
1226fe6060f1SDimitry Andric   bool ShouldGenerateLocation = Loc.isValid() && !SM.isInSystemHeader(Loc);
12270b57cec5SDimitry Andric 
12280b57cec5SDimitry Andric   Out << getUSRSpacePrefix();
12290b57cec5SDimitry Andric   if (ShouldGenerateLocation)
12300b57cec5SDimitry Andric     printLoc(Out, Loc, SM, /*IncludeOffset=*/true);
12310b57cec5SDimitry Andric   Out << "@macro@";
12320b57cec5SDimitry Andric   Out << MacroName;
12330b57cec5SDimitry Andric   return false;
12340b57cec5SDimitry Andric }
12350b57cec5SDimitry Andric 
12360b57cec5SDimitry Andric bool clang::index::generateUSRForType(QualType T, ASTContext &Ctx,
12370b57cec5SDimitry Andric                                       SmallVectorImpl<char> &Buf) {
12380b57cec5SDimitry Andric   if (T.isNull())
12390b57cec5SDimitry Andric     return true;
12400b57cec5SDimitry Andric   T = T.getCanonicalType();
12410b57cec5SDimitry Andric 
12420b57cec5SDimitry Andric   USRGenerator UG(&Ctx, Buf);
12430b57cec5SDimitry Andric   UG.VisitType(T);
12440b57cec5SDimitry Andric   return UG.ignoreResults();
12450b57cec5SDimitry Andric }
12460b57cec5SDimitry Andric 
12470b57cec5SDimitry Andric bool clang::index::generateFullUSRForModule(const Module *Mod,
12480b57cec5SDimitry Andric                                             raw_ostream &OS) {
12490b57cec5SDimitry Andric   if (!Mod->Parent)
12500b57cec5SDimitry Andric     return generateFullUSRForTopLevelModuleName(Mod->Name, OS);
12510b57cec5SDimitry Andric   if (generateFullUSRForModule(Mod->Parent, OS))
12520b57cec5SDimitry Andric     return true;
12530b57cec5SDimitry Andric   return generateUSRFragmentForModule(Mod, OS);
12540b57cec5SDimitry Andric }
12550b57cec5SDimitry Andric 
12560b57cec5SDimitry Andric bool clang::index::generateFullUSRForTopLevelModuleName(StringRef ModName,
12570b57cec5SDimitry Andric                                                         raw_ostream &OS) {
12580b57cec5SDimitry Andric   OS << getUSRSpacePrefix();
12590b57cec5SDimitry Andric   return generateUSRFragmentForModuleName(ModName, OS);
12600b57cec5SDimitry Andric }
12610b57cec5SDimitry Andric 
12620b57cec5SDimitry Andric bool clang::index::generateUSRFragmentForModule(const Module *Mod,
12630b57cec5SDimitry Andric                                                 raw_ostream &OS) {
12640b57cec5SDimitry Andric   return generateUSRFragmentForModuleName(Mod->Name, OS);
12650b57cec5SDimitry Andric }
12660b57cec5SDimitry Andric 
12670b57cec5SDimitry Andric bool clang::index::generateUSRFragmentForModuleName(StringRef ModName,
12680b57cec5SDimitry Andric                                                     raw_ostream &OS) {
12690b57cec5SDimitry Andric   OS << "@M@" << ModName;
12700b57cec5SDimitry Andric   return false;
12710b57cec5SDimitry Andric }
1272