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