Path: blob/main/contrib/llvm-project/clang/lib/Index/USRGeneration.cpp
35233 views
//===- USRGeneration.cpp - Routines for USR generation --------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "clang/Index/USRGeneration.h"9#include "clang/AST/ASTContext.h"10#include "clang/AST/Attr.h"11#include "clang/AST/DeclCXX.h"12#include "clang/AST/DeclTemplate.h"13#include "clang/AST/DeclVisitor.h"14#include "clang/AST/ODRHash.h"15#include "clang/Basic/FileManager.h"16#include "clang/Lex/PreprocessingRecord.h"17#include "llvm/Support/Path.h"18#include "llvm/Support/raw_ostream.h"1920using namespace clang;21using namespace clang::index;2223//===----------------------------------------------------------------------===//24// USR generation.25//===----------------------------------------------------------------------===//2627/// \returns true on error.28static bool printLoc(llvm::raw_ostream &OS, SourceLocation Loc,29const SourceManager &SM, bool IncludeOffset) {30if (Loc.isInvalid()) {31return true;32}33Loc = SM.getExpansionLoc(Loc);34const std::pair<FileID, unsigned> &Decomposed = SM.getDecomposedLoc(Loc);35OptionalFileEntryRef FE = SM.getFileEntryRefForID(Decomposed.first);36if (FE) {37OS << llvm::sys::path::filename(FE->getName());38} else {39// This case really isn't interesting.40return true;41}42if (IncludeOffset) {43// Use the offest into the FileID to represent the location. Using44// a line/column can cause us to look back at the original source file,45// which is expensive.46OS << '@' << Decomposed.second;47}48return false;49}5051static StringRef GetExternalSourceContainer(const NamedDecl *D) {52if (!D)53return StringRef();54if (auto *attr = D->getExternalSourceSymbolAttr()) {55return attr->getDefinedIn();56}57return StringRef();58}5960namespace {61class USRGenerator : public ConstDeclVisitor<USRGenerator> {62SmallVectorImpl<char> &Buf;63llvm::raw_svector_ostream Out;64bool IgnoreResults;65ASTContext *Context;66bool generatedLoc;6768llvm::DenseMap<const Type *, unsigned> TypeSubstitutions;6970public:71explicit USRGenerator(ASTContext *Ctx, SmallVectorImpl<char> &Buf)72: Buf(Buf),73Out(Buf),74IgnoreResults(false),75Context(Ctx),76generatedLoc(false)77{78// Add the USR space prefix.79Out << getUSRSpacePrefix();80}8182bool ignoreResults() const { return IgnoreResults; }8384// Visitation methods from generating USRs from AST elements.85void VisitDeclContext(const DeclContext *D);86void VisitFieldDecl(const FieldDecl *D);87void VisitFunctionDecl(const FunctionDecl *D);88void VisitNamedDecl(const NamedDecl *D);89void VisitNamespaceDecl(const NamespaceDecl *D);90void VisitNamespaceAliasDecl(const NamespaceAliasDecl *D);91void VisitFunctionTemplateDecl(const FunctionTemplateDecl *D);92void VisitClassTemplateDecl(const ClassTemplateDecl *D);93void VisitObjCContainerDecl(const ObjCContainerDecl *CD,94const ObjCCategoryDecl *CatD = nullptr);95void VisitObjCMethodDecl(const ObjCMethodDecl *MD);96void VisitObjCPropertyDecl(const ObjCPropertyDecl *D);97void VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D);98void VisitTagDecl(const TagDecl *D);99void VisitTypedefDecl(const TypedefDecl *D);100void VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D);101void VisitVarDecl(const VarDecl *D);102void VisitBindingDecl(const BindingDecl *D);103void VisitNonTypeTemplateParmDecl(const NonTypeTemplateParmDecl *D);104void VisitTemplateTemplateParmDecl(const TemplateTemplateParmDecl *D);105void VisitUnresolvedUsingValueDecl(const UnresolvedUsingValueDecl *D);106void VisitUnresolvedUsingTypenameDecl(const UnresolvedUsingTypenameDecl *D);107void VisitConceptDecl(const ConceptDecl *D);108109void VisitLinkageSpecDecl(const LinkageSpecDecl *D) {110IgnoreResults = true; // No USRs for linkage specs themselves.111}112113void VisitUsingDirectiveDecl(const UsingDirectiveDecl *D) {114IgnoreResults = true;115}116117void VisitUsingDecl(const UsingDecl *D) {118VisitDeclContext(D->getDeclContext());119Out << "@UD@";120121bool EmittedDeclName = !EmitDeclName(D);122assert(EmittedDeclName && "EmitDeclName can not fail for UsingDecls");123(void)EmittedDeclName;124}125126bool ShouldGenerateLocation(const NamedDecl *D);127128bool isLocal(const NamedDecl *D) {129return D->getParentFunctionOrMethod() != nullptr;130}131132void GenExtSymbolContainer(const NamedDecl *D);133134/// Generate the string component containing the location of the135/// declaration.136bool GenLoc(const Decl *D, bool IncludeOffset);137138/// String generation methods used both by the visitation methods139/// and from other clients that want to directly generate USRs. These140/// methods do not construct complete USRs (which incorporate the parents141/// of an AST element), but only the fragments concerning the AST element142/// itself.143144/// Generate a USR for an Objective-C class.145void GenObjCClass(StringRef cls, StringRef ExtSymDefinedIn,146StringRef CategoryContextExtSymbolDefinedIn) {147generateUSRForObjCClass(cls, Out, ExtSymDefinedIn,148CategoryContextExtSymbolDefinedIn);149}150151/// Generate a USR for an Objective-C class category.152void GenObjCCategory(StringRef cls, StringRef cat,153StringRef clsExt, StringRef catExt) {154generateUSRForObjCCategory(cls, cat, Out, clsExt, catExt);155}156157/// Generate a USR fragment for an Objective-C property.158void GenObjCProperty(StringRef prop, bool isClassProp) {159generateUSRForObjCProperty(prop, isClassProp, Out);160}161162/// Generate a USR for an Objective-C protocol.163void GenObjCProtocol(StringRef prot, StringRef ext) {164generateUSRForObjCProtocol(prot, Out, ext);165}166167void VisitType(QualType T);168void VisitTemplateParameterList(const TemplateParameterList *Params);169void VisitTemplateName(TemplateName Name);170void VisitTemplateArgument(const TemplateArgument &Arg);171172void VisitMSGuidDecl(const MSGuidDecl *D);173174/// Emit a Decl's name using NamedDecl::printName() and return true if175/// the decl had no name.176bool EmitDeclName(const NamedDecl *D);177};178} // end anonymous namespace179180//===----------------------------------------------------------------------===//181// Generating USRs from ASTS.182//===----------------------------------------------------------------------===//183184bool USRGenerator::EmitDeclName(const NamedDecl *D) {185DeclarationName N = D->getDeclName();186if (N.isEmpty())187return true;188Out << N;189return false;190}191192bool USRGenerator::ShouldGenerateLocation(const NamedDecl *D) {193if (D->isExternallyVisible())194return false;195if (D->getParentFunctionOrMethod())196return true;197SourceLocation Loc = D->getLocation();198if (Loc.isInvalid())199return false;200const SourceManager &SM = Context->getSourceManager();201return !SM.isInSystemHeader(Loc);202}203204void USRGenerator::VisitDeclContext(const DeclContext *DC) {205if (const NamedDecl *D = dyn_cast<NamedDecl>(DC))206Visit(D);207else if (isa<LinkageSpecDecl>(DC)) // Linkage specs are transparent in USRs.208VisitDeclContext(DC->getParent());209}210211void USRGenerator::VisitFieldDecl(const FieldDecl *D) {212// The USR for an ivar declared in a class extension is based on the213// ObjCInterfaceDecl, not the ObjCCategoryDecl.214if (const ObjCInterfaceDecl *ID = Context->getObjContainingInterface(D))215Visit(ID);216else217VisitDeclContext(D->getDeclContext());218Out << (isa<ObjCIvarDecl>(D) ? "@" : "@FI@");219if (EmitDeclName(D)) {220// Bit fields can be anonymous.221IgnoreResults = true;222return;223}224}225226void USRGenerator::VisitFunctionDecl(const FunctionDecl *D) {227if (ShouldGenerateLocation(D) && GenLoc(D, /*IncludeOffset=*/isLocal(D)))228return;229230if (D->getType().isNull()) {231IgnoreResults = true;232return;233}234235const unsigned StartSize = Buf.size();236VisitDeclContext(D->getDeclContext());237if (Buf.size() == StartSize)238GenExtSymbolContainer(D);239240bool IsTemplate = false;241if (FunctionTemplateDecl *FunTmpl = D->getDescribedFunctionTemplate()) {242IsTemplate = true;243Out << "@FT@";244VisitTemplateParameterList(FunTmpl->getTemplateParameters());245} else246Out << "@F@";247248PrintingPolicy Policy(Context->getLangOpts());249// Forward references can have different template argument names. Suppress the250// template argument names in constructors to make their USR more stable.251Policy.SuppressTemplateArgsInCXXConstructors = true;252D->getDeclName().print(Out, Policy);253254ASTContext &Ctx = *Context;255if ((!Ctx.getLangOpts().CPlusPlus || D->isExternC()) &&256!D->hasAttr<OverloadableAttr>())257return;258259if (D->isFunctionTemplateSpecialization()) {260Out << '<';261if (const TemplateArgumentList *SpecArgs =262D->getTemplateSpecializationArgs()) {263for (const auto &Arg : SpecArgs->asArray()) {264Out << '#';265VisitTemplateArgument(Arg);266}267} else if (const ASTTemplateArgumentListInfo *SpecArgsWritten =268D->getTemplateSpecializationArgsAsWritten()) {269for (const auto &ArgLoc : SpecArgsWritten->arguments()) {270Out << '#';271VisitTemplateArgument(ArgLoc.getArgument());272}273}274Out << '>';275}276277QualType CanonicalType = D->getType().getCanonicalType();278// Mangle in type information for the arguments.279if (const auto *FPT = CanonicalType->getAs<FunctionProtoType>()) {280for (QualType PT : FPT->param_types()) {281Out << '#';282VisitType(PT);283}284}285if (D->isVariadic())286Out << '.';287if (IsTemplate) {288// Function templates can be overloaded by return type, for example:289// \code290// template <class T> typename T::A foo() {}291// template <class T> typename T::B foo() {}292// \endcode293Out << '#';294VisitType(D->getReturnType());295}296Out << '#';297if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {298if (MD->isStatic())299Out << 'S';300// FIXME: OpenCL: Need to consider address spaces301if (unsigned quals = MD->getMethodQualifiers().getCVRUQualifiers())302Out << (char)('0' + quals);303switch (MD->getRefQualifier()) {304case RQ_None: break;305case RQ_LValue: Out << '&'; break;306case RQ_RValue: Out << "&&"; break;307}308}309}310311void USRGenerator::VisitNamedDecl(const NamedDecl *D) {312VisitDeclContext(D->getDeclContext());313Out << "@";314315if (EmitDeclName(D)) {316// The string can be empty if the declaration has no name; e.g., it is317// the ParmDecl with no name for declaration of a function pointer type,318// e.g.: void (*f)(void *);319// In this case, don't generate a USR.320IgnoreResults = true;321}322}323324void USRGenerator::VisitVarDecl(const VarDecl *D) {325// VarDecls can be declared 'extern' within a function or method body,326// but their enclosing DeclContext is the function, not the TU. We need327// to check the storage class to correctly generate the USR.328if (ShouldGenerateLocation(D) && GenLoc(D, /*IncludeOffset=*/isLocal(D)))329return;330331VisitDeclContext(D->getDeclContext());332333if (VarTemplateDecl *VarTmpl = D->getDescribedVarTemplate()) {334Out << "@VT";335VisitTemplateParameterList(VarTmpl->getTemplateParameters());336} else if (const VarTemplatePartialSpecializationDecl *PartialSpec337= dyn_cast<VarTemplatePartialSpecializationDecl>(D)) {338Out << "@VP";339VisitTemplateParameterList(PartialSpec->getTemplateParameters());340}341342// Variables always have simple names.343StringRef s = D->getName();344345// The string can be empty if the declaration has no name; e.g., it is346// the ParmDecl with no name for declaration of a function pointer type, e.g.:347// void (*f)(void *);348// In this case, don't generate a USR.349if (s.empty())350IgnoreResults = true;351else352Out << '@' << s;353354// For a template specialization, mangle the template arguments.355if (const VarTemplateSpecializationDecl *Spec356= dyn_cast<VarTemplateSpecializationDecl>(D)) {357const TemplateArgumentList &Args = Spec->getTemplateArgs();358Out << '>';359for (unsigned I = 0, N = Args.size(); I != N; ++I) {360Out << '#';361VisitTemplateArgument(Args.get(I));362}363}364}365366void USRGenerator::VisitBindingDecl(const BindingDecl *D) {367if (isLocal(D) && GenLoc(D, /*IncludeOffset=*/true))368return;369VisitNamedDecl(D);370}371372void USRGenerator::VisitNonTypeTemplateParmDecl(373const NonTypeTemplateParmDecl *D) {374GenLoc(D, /*IncludeOffset=*/true);375}376377void USRGenerator::VisitTemplateTemplateParmDecl(378const TemplateTemplateParmDecl *D) {379GenLoc(D, /*IncludeOffset=*/true);380}381382void USRGenerator::VisitNamespaceDecl(const NamespaceDecl *D) {383if (IgnoreResults)384return;385VisitDeclContext(D->getDeclContext());386if (D->isAnonymousNamespace()) {387Out << "@aN";388return;389}390Out << "@N@" << D->getName();391}392393void USRGenerator::VisitFunctionTemplateDecl(const FunctionTemplateDecl *D) {394VisitFunctionDecl(D->getTemplatedDecl());395}396397void USRGenerator::VisitClassTemplateDecl(const ClassTemplateDecl *D) {398VisitTagDecl(D->getTemplatedDecl());399}400401void USRGenerator::VisitNamespaceAliasDecl(const NamespaceAliasDecl *D) {402VisitDeclContext(D->getDeclContext());403if (!IgnoreResults)404Out << "@NA@" << D->getName();405}406407static const ObjCCategoryDecl *getCategoryContext(const NamedDecl *D) {408if (auto *CD = dyn_cast<ObjCCategoryDecl>(D->getDeclContext()))409return CD;410if (auto *ICD = dyn_cast<ObjCCategoryImplDecl>(D->getDeclContext()))411return ICD->getCategoryDecl();412return nullptr;413}414415void USRGenerator::VisitObjCMethodDecl(const ObjCMethodDecl *D) {416const DeclContext *container = D->getDeclContext();417if (const ObjCProtocolDecl *pd = dyn_cast<ObjCProtocolDecl>(container)) {418Visit(pd);419}420else {421// The USR for a method declared in a class extension or category is based on422// the ObjCInterfaceDecl, not the ObjCCategoryDecl.423const ObjCInterfaceDecl *ID = D->getClassInterface();424if (!ID) {425IgnoreResults = true;426return;427}428auto *CD = getCategoryContext(D);429VisitObjCContainerDecl(ID, CD);430}431// Ideally we would use 'GenObjCMethod', but this is such a hot path432// for Objective-C code that we don't want to use433// DeclarationName::getAsString().434Out << (D->isInstanceMethod() ? "(im)" : "(cm)")435<< DeclarationName(D->getSelector());436}437438void USRGenerator::VisitObjCContainerDecl(const ObjCContainerDecl *D,439const ObjCCategoryDecl *CatD) {440switch (D->getKind()) {441default:442llvm_unreachable("Invalid ObjC container.");443case Decl::ObjCInterface:444case Decl::ObjCImplementation:445GenObjCClass(D->getName(), GetExternalSourceContainer(D),446GetExternalSourceContainer(CatD));447break;448case Decl::ObjCCategory: {449const ObjCCategoryDecl *CD = cast<ObjCCategoryDecl>(D);450const ObjCInterfaceDecl *ID = CD->getClassInterface();451if (!ID) {452// Handle invalid code where the @interface might not453// have been specified.454// FIXME: We should be able to generate this USR even if the455// @interface isn't available.456IgnoreResults = true;457return;458}459// Specially handle class extensions, which are anonymous categories.460// We want to mangle in the location to uniquely distinguish them.461if (CD->IsClassExtension()) {462Out << "objc(ext)" << ID->getName() << '@';463GenLoc(CD, /*IncludeOffset=*/true);464}465else466GenObjCCategory(ID->getName(), CD->getName(),467GetExternalSourceContainer(ID),468GetExternalSourceContainer(CD));469470break;471}472case Decl::ObjCCategoryImpl: {473const ObjCCategoryImplDecl *CD = cast<ObjCCategoryImplDecl>(D);474const ObjCInterfaceDecl *ID = CD->getClassInterface();475if (!ID) {476// Handle invalid code where the @interface might not477// have been specified.478// FIXME: We should be able to generate this USR even if the479// @interface isn't available.480IgnoreResults = true;481return;482}483GenObjCCategory(ID->getName(), CD->getName(),484GetExternalSourceContainer(ID),485GetExternalSourceContainer(CD));486break;487}488case Decl::ObjCProtocol: {489const ObjCProtocolDecl *PD = cast<ObjCProtocolDecl>(D);490GenObjCProtocol(PD->getName(), GetExternalSourceContainer(PD));491break;492}493}494}495496void USRGenerator::VisitObjCPropertyDecl(const ObjCPropertyDecl *D) {497// The USR for a property declared in a class extension or category is based498// on the ObjCInterfaceDecl, not the ObjCCategoryDecl.499if (const ObjCInterfaceDecl *ID = Context->getObjContainingInterface(D))500VisitObjCContainerDecl(ID, getCategoryContext(D));501else502Visit(cast<Decl>(D->getDeclContext()));503GenObjCProperty(D->getName(), D->isClassProperty());504}505506void USRGenerator::VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D) {507if (ObjCPropertyDecl *PD = D->getPropertyDecl()) {508VisitObjCPropertyDecl(PD);509return;510}511512IgnoreResults = true;513}514515void USRGenerator::VisitTagDecl(const TagDecl *D) {516// Add the location of the tag decl to handle resolution across517// translation units.518if (!isa<EnumDecl>(D) &&519ShouldGenerateLocation(D) && GenLoc(D, /*IncludeOffset=*/isLocal(D)))520return;521522GenExtSymbolContainer(D);523524D = D->getCanonicalDecl();525VisitDeclContext(D->getDeclContext());526527bool AlreadyStarted = false;528if (const CXXRecordDecl *CXXRecord = dyn_cast<CXXRecordDecl>(D)) {529if (ClassTemplateDecl *ClassTmpl = CXXRecord->getDescribedClassTemplate()) {530AlreadyStarted = true;531532switch (D->getTagKind()) {533case TagTypeKind::Interface:534case TagTypeKind::Class:535case TagTypeKind::Struct:536Out << "@ST";537break;538case TagTypeKind::Union:539Out << "@UT";540break;541case TagTypeKind::Enum:542llvm_unreachable("enum template");543}544VisitTemplateParameterList(ClassTmpl->getTemplateParameters());545} else if (const ClassTemplatePartialSpecializationDecl *PartialSpec546= dyn_cast<ClassTemplatePartialSpecializationDecl>(CXXRecord)) {547AlreadyStarted = true;548549switch (D->getTagKind()) {550case TagTypeKind::Interface:551case TagTypeKind::Class:552case TagTypeKind::Struct:553Out << "@SP";554break;555case TagTypeKind::Union:556Out << "@UP";557break;558case TagTypeKind::Enum:559llvm_unreachable("enum partial specialization");560}561VisitTemplateParameterList(PartialSpec->getTemplateParameters());562}563}564565if (!AlreadyStarted) {566switch (D->getTagKind()) {567case TagTypeKind::Interface:568case TagTypeKind::Class:569case TagTypeKind::Struct:570Out << "@S";571break;572case TagTypeKind::Union:573Out << "@U";574break;575case TagTypeKind::Enum:576Out << "@E";577break;578}579}580581Out << '@';582assert(Buf.size() > 0);583const unsigned off = Buf.size() - 1;584585if (EmitDeclName(D)) {586if (const TypedefNameDecl *TD = D->getTypedefNameForAnonDecl()) {587Buf[off] = 'A';588Out << '@' << *TD;589} else {590if (D->isEmbeddedInDeclarator() && !D->isFreeStanding()) {591printLoc(Out, D->getLocation(), Context->getSourceManager(), true);592} else {593Buf[off] = 'a';594if (auto *ED = dyn_cast<EnumDecl>(D)) {595// Distinguish USRs of anonymous enums by using their first596// enumerator.597auto enum_range = ED->enumerators();598if (enum_range.begin() != enum_range.end()) {599Out << '@' << **enum_range.begin();600}601}602}603}604}605606// For a class template specialization, mangle the template arguments.607if (const ClassTemplateSpecializationDecl *Spec608= dyn_cast<ClassTemplateSpecializationDecl>(D)) {609const TemplateArgumentList &Args = Spec->getTemplateArgs();610Out << '>';611for (unsigned I = 0, N = Args.size(); I != N; ++I) {612Out << '#';613VisitTemplateArgument(Args.get(I));614}615}616}617618void USRGenerator::VisitTypedefDecl(const TypedefDecl *D) {619if (ShouldGenerateLocation(D) && GenLoc(D, /*IncludeOffset=*/isLocal(D)))620return;621const DeclContext *DC = D->getDeclContext();622if (const NamedDecl *DCN = dyn_cast<NamedDecl>(DC))623Visit(DCN);624Out << "@T@";625Out << D->getName();626}627628void USRGenerator::VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D) {629GenLoc(D, /*IncludeOffset=*/true);630}631632void USRGenerator::GenExtSymbolContainer(const NamedDecl *D) {633StringRef Container = GetExternalSourceContainer(D);634if (!Container.empty())635Out << "@M@" << Container;636}637638bool USRGenerator::GenLoc(const Decl *D, bool IncludeOffset) {639if (generatedLoc)640return IgnoreResults;641generatedLoc = true;642643// Guard against null declarations in invalid code.644if (!D) {645IgnoreResults = true;646return true;647}648649// Use the location of canonical decl.650D = D->getCanonicalDecl();651652IgnoreResults =653IgnoreResults || printLoc(Out, D->getBeginLoc(),654Context->getSourceManager(), IncludeOffset);655656return IgnoreResults;657}658659static void printQualifier(llvm::raw_ostream &Out, ASTContext &Ctx, NestedNameSpecifier *NNS) {660// FIXME: Encode the qualifier, don't just print it.661PrintingPolicy PO(Ctx.getLangOpts());662PO.SuppressTagKeyword = true;663PO.SuppressUnwrittenScope = true;664PO.ConstantArraySizeAsWritten = false;665PO.AnonymousTagLocations = false;666NNS->print(Out, PO);667}668669void USRGenerator::VisitType(QualType T) {670// This method mangles in USR information for types. It can possibly671// just reuse the naming-mangling logic used by codegen, although the672// requirements for USRs might not be the same.673ASTContext &Ctx = *Context;674675do {676T = Ctx.getCanonicalType(T);677Qualifiers Q = T.getQualifiers();678unsigned qVal = 0;679if (Q.hasConst())680qVal |= 0x1;681if (Q.hasVolatile())682qVal |= 0x2;683if (Q.hasRestrict())684qVal |= 0x4;685if(qVal)686Out << ((char) ('0' + qVal));687688// Mangle in ObjC GC qualifiers?689690if (const PackExpansionType *Expansion = T->getAs<PackExpansionType>()) {691Out << 'P';692T = Expansion->getPattern();693}694695if (const BuiltinType *BT = T->getAs<BuiltinType>()) {696switch (BT->getKind()) {697case BuiltinType::Void:698Out << 'v'; break;699case BuiltinType::Bool:700Out << 'b'; break;701case BuiltinType::UChar:702Out << 'c'; break;703case BuiltinType::Char8:704Out << 'u'; break;705case BuiltinType::Char16:706Out << 'q'; break;707case BuiltinType::Char32:708Out << 'w'; break;709case BuiltinType::UShort:710Out << 's'; break;711case BuiltinType::UInt:712Out << 'i'; break;713case BuiltinType::ULong:714Out << 'l'; break;715case BuiltinType::ULongLong:716Out << 'k'; break;717case BuiltinType::UInt128:718Out << 'j'; break;719case BuiltinType::Char_U:720case BuiltinType::Char_S:721Out << 'C'; break;722case BuiltinType::SChar:723Out << 'r'; break;724case BuiltinType::WChar_S:725case BuiltinType::WChar_U:726Out << 'W'; break;727case BuiltinType::Short:728Out << 'S'; break;729case BuiltinType::Int:730Out << 'I'; break;731case BuiltinType::Long:732Out << 'L'; break;733case BuiltinType::LongLong:734Out << 'K'; break;735case BuiltinType::Int128:736Out << 'J'; break;737case BuiltinType::Float16:738case BuiltinType::Half:739Out << 'h'; break;740case BuiltinType::Float:741Out << 'f'; break;742case BuiltinType::Double:743Out << 'd'; break;744case BuiltinType::LongDouble:745Out << 'D'; break;746case BuiltinType::Float128:747Out << 'Q'; break;748case BuiltinType::NullPtr:749Out << 'n'; break;750#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \751case BuiltinType::Id: \752Out << "@BT@" << #Suffix << "_" << #ImgType; break;753#include "clang/Basic/OpenCLImageTypes.def"754#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \755case BuiltinType::Id: \756Out << "@BT@" << #ExtType; break;757#include "clang/Basic/OpenCLExtensionTypes.def"758case BuiltinType::OCLEvent:759Out << "@BT@OCLEvent"; break;760case BuiltinType::OCLClkEvent:761Out << "@BT@OCLClkEvent"; break;762case BuiltinType::OCLQueue:763Out << "@BT@OCLQueue"; break;764case BuiltinType::OCLReserveID:765Out << "@BT@OCLReserveID"; break;766case BuiltinType::OCLSampler:767Out << "@BT@OCLSampler"; break;768#define SVE_TYPE(Name, Id, SingletonId) \769case BuiltinType::Id: \770Out << "@BT@" << Name; break;771#include "clang/Basic/AArch64SVEACLETypes.def"772#define PPC_VECTOR_TYPE(Name, Id, Size) \773case BuiltinType::Id: \774Out << "@BT@" << #Name; break;775#include "clang/Basic/PPCTypes.def"776#define RVV_TYPE(Name, Id, SingletonId) \777case BuiltinType::Id: \778Out << "@BT@" << Name; break;779#include "clang/Basic/RISCVVTypes.def"780#define WASM_TYPE(Name, Id, SingletonId) case BuiltinType::Id:781#include "clang/Basic/WebAssemblyReferenceTypes.def"782#define AMDGPU_TYPE(Name, Id, SingletonId) \783case BuiltinType::Id: \784Out << "@BT@" << #Name; \785break;786#include "clang/Basic/AMDGPUTypes.def"787case BuiltinType::ShortAccum:788Out << "@BT@ShortAccum"; break;789case BuiltinType::Accum:790Out << "@BT@Accum"; break;791case BuiltinType::LongAccum:792Out << "@BT@LongAccum"; break;793case BuiltinType::UShortAccum:794Out << "@BT@UShortAccum"; break;795case BuiltinType::UAccum:796Out << "@BT@UAccum"; break;797case BuiltinType::ULongAccum:798Out << "@BT@ULongAccum"; break;799case BuiltinType::ShortFract:800Out << "@BT@ShortFract"; break;801case BuiltinType::Fract:802Out << "@BT@Fract"; break;803case BuiltinType::LongFract:804Out << "@BT@LongFract"; break;805case BuiltinType::UShortFract:806Out << "@BT@UShortFract"; break;807case BuiltinType::UFract:808Out << "@BT@UFract"; break;809case BuiltinType::ULongFract:810Out << "@BT@ULongFract"; break;811case BuiltinType::SatShortAccum:812Out << "@BT@SatShortAccum"; break;813case BuiltinType::SatAccum:814Out << "@BT@SatAccum"; break;815case BuiltinType::SatLongAccum:816Out << "@BT@SatLongAccum"; break;817case BuiltinType::SatUShortAccum:818Out << "@BT@SatUShortAccum"; break;819case BuiltinType::SatUAccum:820Out << "@BT@SatUAccum"; break;821case BuiltinType::SatULongAccum:822Out << "@BT@SatULongAccum"; break;823case BuiltinType::SatShortFract:824Out << "@BT@SatShortFract"; break;825case BuiltinType::SatFract:826Out << "@BT@SatFract"; break;827case BuiltinType::SatLongFract:828Out << "@BT@SatLongFract"; break;829case BuiltinType::SatUShortFract:830Out << "@BT@SatUShortFract"; break;831case BuiltinType::SatUFract:832Out << "@BT@SatUFract"; break;833case BuiltinType::SatULongFract:834Out << "@BT@SatULongFract"; break;835case BuiltinType::BFloat16:836Out << "@BT@__bf16"; break;837case BuiltinType::Ibm128:838Out << "@BT@__ibm128"; break;839case BuiltinType::ObjCId:840Out << 'o'; break;841case BuiltinType::ObjCClass:842Out << 'O'; break;843case BuiltinType::ObjCSel:844Out << 'e'; break;845#define BUILTIN_TYPE(Id, SingletonId)846#define PLACEHOLDER_TYPE(Id, SingletonId) case BuiltinType::Id:847#include "clang/AST/BuiltinTypes.def"848case BuiltinType::Dependent:849// If you're adding a new builtin type, please add its name prefixed850// with "@BT@" to `Out` (see cases above).851IgnoreResults = true;852break;853}854return;855}856857// If we have already seen this (non-built-in) type, use a substitution858// encoding.859llvm::DenseMap<const Type *, unsigned>::iterator Substitution860= TypeSubstitutions.find(T.getTypePtr());861if (Substitution != TypeSubstitutions.end()) {862Out << 'S' << Substitution->second << '_';863return;864} else {865// Record this as a substitution.866unsigned Number = TypeSubstitutions.size();867TypeSubstitutions[T.getTypePtr()] = Number;868}869870if (const PointerType *PT = T->getAs<PointerType>()) {871Out << '*';872T = PT->getPointeeType();873continue;874}875if (const ObjCObjectPointerType *OPT = T->getAs<ObjCObjectPointerType>()) {876Out << '*';877T = OPT->getPointeeType();878continue;879}880if (const RValueReferenceType *RT = T->getAs<RValueReferenceType>()) {881Out << "&&";882T = RT->getPointeeType();883continue;884}885if (const ReferenceType *RT = T->getAs<ReferenceType>()) {886Out << '&';887T = RT->getPointeeType();888continue;889}890if (const FunctionProtoType *FT = T->getAs<FunctionProtoType>()) {891Out << 'F';892VisitType(FT->getReturnType());893Out << '(';894for (const auto &I : FT->param_types()) {895Out << '#';896VisitType(I);897}898Out << ')';899if (FT->isVariadic())900Out << '.';901return;902}903if (const BlockPointerType *BT = T->getAs<BlockPointerType>()) {904Out << 'B';905T = BT->getPointeeType();906continue;907}908if (const ComplexType *CT = T->getAs<ComplexType>()) {909Out << '<';910T = CT->getElementType();911continue;912}913if (const TagType *TT = T->getAs<TagType>()) {914Out << '$';915VisitTagDecl(TT->getDecl());916return;917}918if (const ObjCInterfaceType *OIT = T->getAs<ObjCInterfaceType>()) {919Out << '$';920VisitObjCInterfaceDecl(OIT->getDecl());921return;922}923if (const ObjCObjectType *OIT = T->getAs<ObjCObjectType>()) {924Out << 'Q';925VisitType(OIT->getBaseType());926for (auto *Prot : OIT->getProtocols())927VisitObjCProtocolDecl(Prot);928return;929}930if (const TemplateTypeParmType *TTP = T->getAs<TemplateTypeParmType>()) {931Out << 't' << TTP->getDepth() << '.' << TTP->getIndex();932return;933}934if (const TemplateSpecializationType *Spec935= T->getAs<TemplateSpecializationType>()) {936Out << '>';937VisitTemplateName(Spec->getTemplateName());938Out << Spec->template_arguments().size();939for (const auto &Arg : Spec->template_arguments())940VisitTemplateArgument(Arg);941return;942}943if (const DependentNameType *DNT = T->getAs<DependentNameType>()) {944Out << '^';945printQualifier(Out, Ctx, DNT->getQualifier());946Out << ':' << DNT->getIdentifier()->getName();947return;948}949if (const InjectedClassNameType *InjT = T->getAs<InjectedClassNameType>()) {950T = InjT->getInjectedSpecializationType();951continue;952}953if (const auto *VT = T->getAs<VectorType>()) {954Out << (T->isExtVectorType() ? ']' : '[');955Out << VT->getNumElements();956T = VT->getElementType();957continue;958}959if (const auto *const AT = dyn_cast<ArrayType>(T)) {960Out << '{';961switch (AT->getSizeModifier()) {962case ArraySizeModifier::Static:963Out << 's';964break;965case ArraySizeModifier::Star:966Out << '*';967break;968case ArraySizeModifier::Normal:969Out << 'n';970break;971}972if (const auto *const CAT = dyn_cast<ConstantArrayType>(T))973Out << CAT->getSize();974975T = AT->getElementType();976continue;977}978979// Unhandled type.980Out << ' ';981break;982} while (true);983}984985void USRGenerator::VisitTemplateParameterList(986const TemplateParameterList *Params) {987if (!Params)988return;989Out << '>' << Params->size();990for (TemplateParameterList::const_iterator P = Params->begin(),991PEnd = Params->end();992P != PEnd; ++P) {993Out << '#';994if (isa<TemplateTypeParmDecl>(*P)) {995if (cast<TemplateTypeParmDecl>(*P)->isParameterPack())996Out<< 'p';997Out << 'T';998continue;999}10001001if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(*P)) {1002if (NTTP->isParameterPack())1003Out << 'p';1004Out << 'N';1005VisitType(NTTP->getType());1006continue;1007}10081009TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*P);1010if (TTP->isParameterPack())1011Out << 'p';1012Out << 't';1013VisitTemplateParameterList(TTP->getTemplateParameters());1014}1015}10161017void USRGenerator::VisitTemplateName(TemplateName Name) {1018if (TemplateDecl *Template = Name.getAsTemplateDecl()) {1019if (TemplateTemplateParmDecl *TTP1020= dyn_cast<TemplateTemplateParmDecl>(Template)) {1021Out << 't' << TTP->getDepth() << '.' << TTP->getIndex();1022return;1023}10241025Visit(Template);1026return;1027}10281029// FIXME: Visit dependent template names.1030}10311032void USRGenerator::VisitTemplateArgument(const TemplateArgument &Arg) {1033switch (Arg.getKind()) {1034case TemplateArgument::Null:1035break;10361037case TemplateArgument::Declaration:1038Visit(Arg.getAsDecl());1039break;10401041case TemplateArgument::NullPtr:1042break;10431044case TemplateArgument::TemplateExpansion:1045Out << 'P'; // pack expansion of...1046[[fallthrough]];1047case TemplateArgument::Template:1048VisitTemplateName(Arg.getAsTemplateOrTemplatePattern());1049break;10501051case TemplateArgument::Expression:1052// FIXME: Visit expressions.1053break;10541055case TemplateArgument::Pack:1056Out << 'p' << Arg.pack_size();1057for (const auto &P : Arg.pack_elements())1058VisitTemplateArgument(P);1059break;10601061case TemplateArgument::Type:1062VisitType(Arg.getAsType());1063break;10641065case TemplateArgument::Integral:1066Out << 'V';1067VisitType(Arg.getIntegralType());1068Out << Arg.getAsIntegral();1069break;10701071case TemplateArgument::StructuralValue: {1072Out << 'S';1073VisitType(Arg.getStructuralValueType());1074ODRHash Hash{};1075Hash.AddStructuralValue(Arg.getAsStructuralValue());1076Out << Hash.CalculateHash();1077break;1078}1079}1080}10811082void USRGenerator::VisitUnresolvedUsingValueDecl(const UnresolvedUsingValueDecl *D) {1083if (ShouldGenerateLocation(D) && GenLoc(D, /*IncludeOffset=*/isLocal(D)))1084return;1085VisitDeclContext(D->getDeclContext());1086Out << "@UUV@";1087printQualifier(Out, D->getASTContext(), D->getQualifier());1088EmitDeclName(D);1089}10901091void USRGenerator::VisitUnresolvedUsingTypenameDecl(const UnresolvedUsingTypenameDecl *D) {1092if (ShouldGenerateLocation(D) && GenLoc(D, /*IncludeOffset=*/isLocal(D)))1093return;1094VisitDeclContext(D->getDeclContext());1095Out << "@UUT@";1096printQualifier(Out, D->getASTContext(), D->getQualifier());1097Out << D->getName(); // Simple name.1098}10991100void USRGenerator::VisitConceptDecl(const ConceptDecl *D) {1101if (ShouldGenerateLocation(D) && GenLoc(D, /*IncludeOffset=*/isLocal(D)))1102return;1103VisitDeclContext(D->getDeclContext());1104Out << "@CT@";1105EmitDeclName(D);1106}11071108void USRGenerator::VisitMSGuidDecl(const MSGuidDecl *D) {1109VisitDeclContext(D->getDeclContext());1110Out << "@MG@";1111D->NamedDecl::printName(Out);1112}11131114//===----------------------------------------------------------------------===//1115// USR generation functions.1116//===----------------------------------------------------------------------===//11171118static void combineClassAndCategoryExtContainers(StringRef ClsSymDefinedIn,1119StringRef CatSymDefinedIn,1120raw_ostream &OS) {1121if (ClsSymDefinedIn.empty() && CatSymDefinedIn.empty())1122return;1123if (CatSymDefinedIn.empty()) {1124OS << "@M@" << ClsSymDefinedIn << '@';1125return;1126}1127OS << "@CM@" << CatSymDefinedIn << '@';1128if (ClsSymDefinedIn != CatSymDefinedIn) {1129OS << ClsSymDefinedIn << '@';1130}1131}11321133void clang::index::generateUSRForObjCClass(StringRef Cls, raw_ostream &OS,1134StringRef ExtSymDefinedIn,1135StringRef CategoryContextExtSymbolDefinedIn) {1136combineClassAndCategoryExtContainers(ExtSymDefinedIn,1137CategoryContextExtSymbolDefinedIn, OS);1138OS << "objc(cs)" << Cls;1139}11401141void clang::index::generateUSRForObjCCategory(StringRef Cls, StringRef Cat,1142raw_ostream &OS,1143StringRef ClsSymDefinedIn,1144StringRef CatSymDefinedIn) {1145combineClassAndCategoryExtContainers(ClsSymDefinedIn, CatSymDefinedIn, OS);1146OS << "objc(cy)" << Cls << '@' << Cat;1147}11481149void clang::index::generateUSRForObjCIvar(StringRef Ivar, raw_ostream &OS) {1150OS << '@' << Ivar;1151}11521153void clang::index::generateUSRForObjCMethod(StringRef Sel,1154bool IsInstanceMethod,1155raw_ostream &OS) {1156OS << (IsInstanceMethod ? "(im)" : "(cm)") << Sel;1157}11581159void clang::index::generateUSRForObjCProperty(StringRef Prop, bool isClassProp,1160raw_ostream &OS) {1161OS << (isClassProp ? "(cpy)" : "(py)") << Prop;1162}11631164void clang::index::generateUSRForObjCProtocol(StringRef Prot, raw_ostream &OS,1165StringRef ExtSymDefinedIn) {1166if (!ExtSymDefinedIn.empty())1167OS << "@M@" << ExtSymDefinedIn << '@';1168OS << "objc(pl)" << Prot;1169}11701171void clang::index::generateUSRForGlobalEnum(StringRef EnumName, raw_ostream &OS,1172StringRef ExtSymDefinedIn) {1173if (!ExtSymDefinedIn.empty())1174OS << "@M@" << ExtSymDefinedIn;1175OS << "@E@" << EnumName;1176}11771178void clang::index::generateUSRForEnumConstant(StringRef EnumConstantName,1179raw_ostream &OS) {1180OS << '@' << EnumConstantName;1181}11821183bool clang::index::generateUSRForDecl(const Decl *D,1184SmallVectorImpl<char> &Buf) {1185if (!D)1186return true;1187// We don't ignore decls with invalid source locations. Implicit decls, like1188// C++'s operator new function, can have invalid locations but it is fine to1189// create USRs that can identify them.11901191// Check if the declaration has explicit external USR specified.1192auto *CD = D->getCanonicalDecl();1193if (auto *ExternalSymAttr = CD->getAttr<ExternalSourceSymbolAttr>()) {1194if (!ExternalSymAttr->getUSR().empty()) {1195llvm::raw_svector_ostream Out(Buf);1196Out << ExternalSymAttr->getUSR();1197return false;1198}1199}1200USRGenerator UG(&D->getASTContext(), Buf);1201UG.Visit(D);1202return UG.ignoreResults();1203}12041205bool clang::index::generateUSRForMacro(const MacroDefinitionRecord *MD,1206const SourceManager &SM,1207SmallVectorImpl<char> &Buf) {1208if (!MD)1209return true;1210return generateUSRForMacro(MD->getName()->getName(), MD->getLocation(),1211SM, Buf);12121213}12141215bool clang::index::generateUSRForMacro(StringRef MacroName, SourceLocation Loc,1216const SourceManager &SM,1217SmallVectorImpl<char> &Buf) {1218if (MacroName.empty())1219return true;12201221llvm::raw_svector_ostream Out(Buf);12221223// Assume that system headers are sane. Don't put source location1224// information into the USR if the macro comes from a system header.1225bool ShouldGenerateLocation = Loc.isValid() && !SM.isInSystemHeader(Loc);12261227Out << getUSRSpacePrefix();1228if (ShouldGenerateLocation)1229printLoc(Out, Loc, SM, /*IncludeOffset=*/true);1230Out << "@macro@";1231Out << MacroName;1232return false;1233}12341235bool clang::index::generateUSRForType(QualType T, ASTContext &Ctx,1236SmallVectorImpl<char> &Buf) {1237if (T.isNull())1238return true;1239T = T.getCanonicalType();12401241USRGenerator UG(&Ctx, Buf);1242UG.VisitType(T);1243return UG.ignoreResults();1244}12451246bool clang::index::generateFullUSRForModule(const Module *Mod,1247raw_ostream &OS) {1248if (!Mod->Parent)1249return generateFullUSRForTopLevelModuleName(Mod->Name, OS);1250if (generateFullUSRForModule(Mod->Parent, OS))1251return true;1252return generateUSRFragmentForModule(Mod, OS);1253}12541255bool clang::index::generateFullUSRForTopLevelModuleName(StringRef ModName,1256raw_ostream &OS) {1257OS << getUSRSpacePrefix();1258return generateUSRFragmentForModuleName(ModName, OS);1259}12601261bool clang::index::generateUSRFragmentForModule(const Module *Mod,1262raw_ostream &OS) {1263return generateUSRFragmentForModuleName(Mod->Name, OS);1264}12651266bool clang::index::generateUSRFragmentForModuleName(StringRef ModName,1267raw_ostream &OS) {1268OS << "@M@" << ModName;1269return false;1270}127112721273