1259701Sdim//===- USRGeneration.cpp - Routines for USR generation --------------------===// 2259701Sdim// 3259701Sdim// The LLVM Compiler Infrastructure 4259701Sdim// 5259701Sdim// This file is distributed under the University of Illinois Open Source 6259701Sdim// License. See LICENSE.TXT for details. 7259701Sdim// 8259701Sdim//===----------------------------------------------------------------------===// 9259701Sdim 10259701Sdim#include "clang/Index/USRGeneration.h" 11259701Sdim#include "clang/AST/ASTContext.h" 12259701Sdim#include "clang/AST/DeclTemplate.h" 13259701Sdim#include "clang/AST/DeclVisitor.h" 14276479Sdim#include "clang/Lex/PreprocessingRecord.h" 15259701Sdim#include "llvm/ADT/SmallString.h" 16259701Sdim#include "llvm/Support/Path.h" 17259701Sdim#include "llvm/Support/raw_ostream.h" 18259701Sdim 19259701Sdimusing namespace clang; 20259701Sdimusing namespace clang::index; 21259701Sdim 22259701Sdim//===----------------------------------------------------------------------===// 23259701Sdim// USR generation. 24259701Sdim//===----------------------------------------------------------------------===// 25259701Sdim 26276479Sdim/// \returns true on error. 27276479Sdimstatic bool printLoc(llvm::raw_ostream &OS, SourceLocation Loc, 28276479Sdim const SourceManager &SM, bool IncludeOffset) { 29276479Sdim if (Loc.isInvalid()) { 30276479Sdim return true; 31276479Sdim } 32276479Sdim Loc = SM.getExpansionLoc(Loc); 33276479Sdim const std::pair<FileID, unsigned> &Decomposed = SM.getDecomposedLoc(Loc); 34276479Sdim const FileEntry *FE = SM.getFileEntryForID(Decomposed.first); 35276479Sdim if (FE) { 36276479Sdim OS << llvm::sys::path::filename(FE->getName()); 37276479Sdim } else { 38276479Sdim // This case really isn't interesting. 39276479Sdim return true; 40276479Sdim } 41276479Sdim if (IncludeOffset) { 42276479Sdim // Use the offest into the FileID to represent the location. Using 43276479Sdim // a line/column can cause us to look back at the original source file, 44276479Sdim // which is expensive. 45276479Sdim OS << '@' << Decomposed.second; 46276479Sdim } 47276479Sdim return false; 48276479Sdim} 49276479Sdim 50259701Sdimnamespace { 51259701Sdimclass USRGenerator : public ConstDeclVisitor<USRGenerator> { 52259701Sdim SmallVectorImpl<char> &Buf; 53259701Sdim llvm::raw_svector_ostream Out; 54259701Sdim bool IgnoreResults; 55259701Sdim ASTContext *Context; 56259701Sdim bool generatedLoc; 57259701Sdim 58259701Sdim llvm::DenseMap<const Type *, unsigned> TypeSubstitutions; 59259701Sdim 60259701Sdimpublic: 61259701Sdim explicit USRGenerator(ASTContext *Ctx, SmallVectorImpl<char> &Buf) 62259701Sdim : Buf(Buf), 63259701Sdim Out(Buf), 64259701Sdim IgnoreResults(false), 65259701Sdim Context(Ctx), 66259701Sdim generatedLoc(false) 67259701Sdim { 68259701Sdim // Add the USR space prefix. 69259701Sdim Out << getUSRSpacePrefix(); 70259701Sdim } 71259701Sdim 72259701Sdim bool ignoreResults() const { return IgnoreResults; } 73259701Sdim 74259701Sdim // Visitation methods from generating USRs from AST elements. 75259701Sdim void VisitDeclContext(const DeclContext *D); 76259701Sdim void VisitFieldDecl(const FieldDecl *D); 77259701Sdim void VisitFunctionDecl(const FunctionDecl *D); 78259701Sdim void VisitNamedDecl(const NamedDecl *D); 79259701Sdim void VisitNamespaceDecl(const NamespaceDecl *D); 80259701Sdim void VisitNamespaceAliasDecl(const NamespaceAliasDecl *D); 81259701Sdim void VisitFunctionTemplateDecl(const FunctionTemplateDecl *D); 82259701Sdim void VisitClassTemplateDecl(const ClassTemplateDecl *D); 83259701Sdim void VisitObjCContainerDecl(const ObjCContainerDecl *CD); 84259701Sdim void VisitObjCMethodDecl(const ObjCMethodDecl *MD); 85259701Sdim void VisitObjCPropertyDecl(const ObjCPropertyDecl *D); 86259701Sdim void VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D); 87259701Sdim void VisitTagDecl(const TagDecl *D); 88259701Sdim void VisitTypedefDecl(const TypedefDecl *D); 89259701Sdim void VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D); 90259701Sdim void VisitVarDecl(const VarDecl *D); 91259701Sdim void VisitNonTypeTemplateParmDecl(const NonTypeTemplateParmDecl *D); 92259701Sdim void VisitTemplateTemplateParmDecl(const TemplateTemplateParmDecl *D); 93259701Sdim void VisitLinkageSpecDecl(const LinkageSpecDecl *D) { 94259701Sdim IgnoreResults = true; 95259701Sdim } 96259701Sdim void VisitUsingDirectiveDecl(const UsingDirectiveDecl *D) { 97259701Sdim IgnoreResults = true; 98259701Sdim } 99259701Sdim void VisitUsingDecl(const UsingDecl *D) { 100259701Sdim IgnoreResults = true; 101259701Sdim } 102259701Sdim void VisitUnresolvedUsingValueDecl(const UnresolvedUsingValueDecl *D) { 103259701Sdim IgnoreResults = true; 104259701Sdim } 105259701Sdim void VisitUnresolvedUsingTypenameDecl(const UnresolvedUsingTypenameDecl *D) { 106259701Sdim IgnoreResults = true; 107259701Sdim } 108276479Sdim 109276479Sdim bool ShouldGenerateLocation(const NamedDecl *D); 110276479Sdim 111276479Sdim bool isLocal(const NamedDecl *D) { 112276479Sdim return D->getParentFunctionOrMethod() != nullptr; 113276479Sdim } 114276479Sdim 115259701Sdim /// Generate the string component containing the location of the 116259701Sdim /// declaration. 117276479Sdim bool GenLoc(const Decl *D, bool IncludeOffset); 118259701Sdim 119259701Sdim /// String generation methods used both by the visitation methods 120259701Sdim /// and from other clients that want to directly generate USRs. These 121259701Sdim /// methods do not construct complete USRs (which incorporate the parents 122259701Sdim /// of an AST element), but only the fragments concerning the AST element 123259701Sdim /// itself. 124259701Sdim 125259701Sdim /// Generate a USR for an Objective-C class. 126259701Sdim void GenObjCClass(StringRef cls) { 127259701Sdim generateUSRForObjCClass(cls, Out); 128259701Sdim } 129259701Sdim /// Generate a USR for an Objective-C class category. 130259701Sdim void GenObjCCategory(StringRef cls, StringRef cat) { 131259701Sdim generateUSRForObjCCategory(cls, cat, Out); 132259701Sdim } 133259701Sdim /// Generate a USR fragment for an Objective-C property. 134259701Sdim void GenObjCProperty(StringRef prop) { 135259701Sdim generateUSRForObjCProperty(prop, Out); 136259701Sdim } 137259701Sdim /// Generate a USR for an Objective-C protocol. 138259701Sdim void GenObjCProtocol(StringRef prot) { 139259701Sdim generateUSRForObjCProtocol(prot, Out); 140259701Sdim } 141259701Sdim 142259701Sdim void VisitType(QualType T); 143259701Sdim void VisitTemplateParameterList(const TemplateParameterList *Params); 144259701Sdim void VisitTemplateName(TemplateName Name); 145259701Sdim void VisitTemplateArgument(const TemplateArgument &Arg); 146259701Sdim 147259701Sdim /// Emit a Decl's name using NamedDecl::printName() and return true if 148259701Sdim /// the decl had no name. 149259701Sdim bool EmitDeclName(const NamedDecl *D); 150259701Sdim}; 151259701Sdim 152259701Sdim} // end anonymous namespace 153259701Sdim 154259701Sdim//===----------------------------------------------------------------------===// 155259701Sdim// Generating USRs from ASTS. 156259701Sdim//===----------------------------------------------------------------------===// 157259701Sdim 158259701Sdimbool USRGenerator::EmitDeclName(const NamedDecl *D) { 159259701Sdim const unsigned startSize = Buf.size(); 160259701Sdim D->printName(Out); 161259701Sdim const unsigned endSize = Buf.size(); 162259701Sdim return startSize == endSize; 163259701Sdim} 164259701Sdim 165276479Sdimbool USRGenerator::ShouldGenerateLocation(const NamedDecl *D) { 166276479Sdim if (D->isExternallyVisible()) 167276479Sdim return false; 168276479Sdim if (D->getParentFunctionOrMethod()) 169276479Sdim return true; 170276479Sdim const SourceManager &SM = Context->getSourceManager(); 171276479Sdim return !SM.isInSystemHeader(D->getLocation()); 172259701Sdim} 173259701Sdim 174259701Sdimvoid USRGenerator::VisitDeclContext(const DeclContext *DC) { 175259701Sdim if (const NamedDecl *D = dyn_cast<NamedDecl>(DC)) 176259701Sdim Visit(D); 177259701Sdim} 178259701Sdim 179259701Sdimvoid USRGenerator::VisitFieldDecl(const FieldDecl *D) { 180259701Sdim // The USR for an ivar declared in a class extension is based on the 181259701Sdim // ObjCInterfaceDecl, not the ObjCCategoryDecl. 182259701Sdim if (const ObjCInterfaceDecl *ID = Context->getObjContainingInterface(D)) 183259701Sdim Visit(ID); 184259701Sdim else 185259701Sdim VisitDeclContext(D->getDeclContext()); 186259701Sdim Out << (isa<ObjCIvarDecl>(D) ? "@" : "@FI@"); 187259701Sdim if (EmitDeclName(D)) { 188259701Sdim // Bit fields can be anonymous. 189259701Sdim IgnoreResults = true; 190259701Sdim return; 191259701Sdim } 192259701Sdim} 193259701Sdim 194259701Sdimvoid USRGenerator::VisitFunctionDecl(const FunctionDecl *D) { 195276479Sdim if (ShouldGenerateLocation(D) && GenLoc(D, /*IncludeOffset=*/isLocal(D))) 196259701Sdim return; 197259701Sdim 198259701Sdim VisitDeclContext(D->getDeclContext()); 199280031Sdim bool IsTemplate = false; 200259701Sdim if (FunctionTemplateDecl *FunTmpl = D->getDescribedFunctionTemplate()) { 201280031Sdim IsTemplate = true; 202259701Sdim Out << "@FT@"; 203259701Sdim VisitTemplateParameterList(FunTmpl->getTemplateParameters()); 204259701Sdim } else 205259701Sdim Out << "@F@"; 206259701Sdim D->printName(Out); 207259701Sdim 208259701Sdim ASTContext &Ctx = *Context; 209259701Sdim if (!Ctx.getLangOpts().CPlusPlus || D->isExternC()) 210259701Sdim return; 211259701Sdim 212259701Sdim if (const TemplateArgumentList * 213259701Sdim SpecArgs = D->getTemplateSpecializationArgs()) { 214259701Sdim Out << '<'; 215259701Sdim for (unsigned I = 0, N = SpecArgs->size(); I != N; ++I) { 216259701Sdim Out << '#'; 217259701Sdim VisitTemplateArgument(SpecArgs->get(I)); 218259701Sdim } 219259701Sdim Out << '>'; 220259701Sdim } 221259701Sdim 222259701Sdim // Mangle in type information for the arguments. 223276479Sdim for (auto PD : D->params()) { 224259701Sdim Out << '#'; 225276479Sdim VisitType(PD->getType()); 226259701Sdim } 227259701Sdim if (D->isVariadic()) 228259701Sdim Out << '.'; 229280031Sdim if (IsTemplate) { 230280031Sdim // Function templates can be overloaded by return type, for example: 231280031Sdim // \code 232280031Sdim // template <class T> typename T::A foo() {} 233280031Sdim // template <class T> typename T::B foo() {} 234280031Sdim // \endcode 235280031Sdim Out << '#'; 236280031Sdim VisitType(D->getReturnType()); 237280031Sdim } 238259701Sdim Out << '#'; 239259701Sdim if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) { 240259701Sdim if (MD->isStatic()) 241259701Sdim Out << 'S'; 242259701Sdim if (unsigned quals = MD->getTypeQualifiers()) 243259701Sdim Out << (char)('0' + quals); 244280031Sdim switch (MD->getRefQualifier()) { 245280031Sdim case RQ_None: break; 246280031Sdim case RQ_LValue: Out << '&'; break; 247280031Sdim case RQ_RValue: Out << "&&"; break; 248280031Sdim } 249259701Sdim } 250259701Sdim} 251259701Sdim 252259701Sdimvoid USRGenerator::VisitNamedDecl(const NamedDecl *D) { 253259701Sdim VisitDeclContext(D->getDeclContext()); 254259701Sdim Out << "@"; 255259701Sdim 256259701Sdim if (EmitDeclName(D)) { 257259701Sdim // The string can be empty if the declaration has no name; e.g., it is 258259701Sdim // the ParmDecl with no name for declaration of a function pointer type, 259259701Sdim // e.g.: void (*f)(void *); 260259701Sdim // In this case, don't generate a USR. 261259701Sdim IgnoreResults = true; 262259701Sdim } 263259701Sdim} 264259701Sdim 265259701Sdimvoid USRGenerator::VisitVarDecl(const VarDecl *D) { 266259701Sdim // VarDecls can be declared 'extern' within a function or method body, 267259701Sdim // but their enclosing DeclContext is the function, not the TU. We need 268259701Sdim // to check the storage class to correctly generate the USR. 269276479Sdim if (ShouldGenerateLocation(D) && GenLoc(D, /*IncludeOffset=*/isLocal(D))) 270259701Sdim return; 271259701Sdim 272259701Sdim VisitDeclContext(D->getDeclContext()); 273259701Sdim 274259701Sdim // Variables always have simple names. 275259701Sdim StringRef s = D->getName(); 276259701Sdim 277259701Sdim // The string can be empty if the declaration has no name; e.g., it is 278259701Sdim // the ParmDecl with no name for declaration of a function pointer type, e.g.: 279259701Sdim // void (*f)(void *); 280259701Sdim // In this case, don't generate a USR. 281259701Sdim if (s.empty()) 282259701Sdim IgnoreResults = true; 283259701Sdim else 284259701Sdim Out << '@' << s; 285259701Sdim} 286259701Sdim 287259701Sdimvoid USRGenerator::VisitNonTypeTemplateParmDecl( 288259701Sdim const NonTypeTemplateParmDecl *D) { 289276479Sdim GenLoc(D, /*IncludeOffset=*/true); 290259701Sdim return; 291259701Sdim} 292259701Sdim 293259701Sdimvoid USRGenerator::VisitTemplateTemplateParmDecl( 294259701Sdim const TemplateTemplateParmDecl *D) { 295276479Sdim GenLoc(D, /*IncludeOffset=*/true); 296259701Sdim return; 297259701Sdim} 298259701Sdim 299259701Sdimvoid USRGenerator::VisitNamespaceDecl(const NamespaceDecl *D) { 300259701Sdim if (D->isAnonymousNamespace()) { 301259701Sdim Out << "@aN"; 302259701Sdim return; 303259701Sdim } 304259701Sdim 305259701Sdim VisitDeclContext(D->getDeclContext()); 306259701Sdim if (!IgnoreResults) 307259701Sdim Out << "@N@" << D->getName(); 308259701Sdim} 309259701Sdim 310259701Sdimvoid USRGenerator::VisitFunctionTemplateDecl(const FunctionTemplateDecl *D) { 311259701Sdim VisitFunctionDecl(D->getTemplatedDecl()); 312259701Sdim} 313259701Sdim 314259701Sdimvoid USRGenerator::VisitClassTemplateDecl(const ClassTemplateDecl *D) { 315259701Sdim VisitTagDecl(D->getTemplatedDecl()); 316259701Sdim} 317259701Sdim 318259701Sdimvoid USRGenerator::VisitNamespaceAliasDecl(const NamespaceAliasDecl *D) { 319259701Sdim VisitDeclContext(D->getDeclContext()); 320259701Sdim if (!IgnoreResults) 321259701Sdim Out << "@NA@" << D->getName(); 322259701Sdim} 323259701Sdim 324259701Sdimvoid USRGenerator::VisitObjCMethodDecl(const ObjCMethodDecl *D) { 325259701Sdim const DeclContext *container = D->getDeclContext(); 326259701Sdim if (const ObjCProtocolDecl *pd = dyn_cast<ObjCProtocolDecl>(container)) { 327259701Sdim Visit(pd); 328259701Sdim } 329259701Sdim else { 330259701Sdim // The USR for a method declared in a class extension or category is based on 331259701Sdim // the ObjCInterfaceDecl, not the ObjCCategoryDecl. 332259701Sdim const ObjCInterfaceDecl *ID = D->getClassInterface(); 333259701Sdim if (!ID) { 334259701Sdim IgnoreResults = true; 335259701Sdim return; 336259701Sdim } 337259701Sdim Visit(ID); 338259701Sdim } 339259701Sdim // Ideally we would use 'GenObjCMethod', but this is such a hot path 340259701Sdim // for Objective-C code that we don't want to use 341259701Sdim // DeclarationName::getAsString(). 342259701Sdim Out << (D->isInstanceMethod() ? "(im)" : "(cm)") 343259701Sdim << DeclarationName(D->getSelector()); 344259701Sdim} 345259701Sdim 346259701Sdimvoid USRGenerator::VisitObjCContainerDecl(const ObjCContainerDecl *D) { 347259701Sdim switch (D->getKind()) { 348259701Sdim default: 349259701Sdim llvm_unreachable("Invalid ObjC container."); 350259701Sdim case Decl::ObjCInterface: 351259701Sdim case Decl::ObjCImplementation: 352259701Sdim GenObjCClass(D->getName()); 353259701Sdim break; 354259701Sdim case Decl::ObjCCategory: { 355259701Sdim const ObjCCategoryDecl *CD = cast<ObjCCategoryDecl>(D); 356259701Sdim const ObjCInterfaceDecl *ID = CD->getClassInterface(); 357259701Sdim if (!ID) { 358259701Sdim // Handle invalid code where the @interface might not 359259701Sdim // have been specified. 360259701Sdim // FIXME: We should be able to generate this USR even if the 361259701Sdim // @interface isn't available. 362259701Sdim IgnoreResults = true; 363259701Sdim return; 364259701Sdim } 365259701Sdim // Specially handle class extensions, which are anonymous categories. 366259701Sdim // We want to mangle in the location to uniquely distinguish them. 367259701Sdim if (CD->IsClassExtension()) { 368259701Sdim Out << "objc(ext)" << ID->getName() << '@'; 369276479Sdim GenLoc(CD, /*IncludeOffset=*/true); 370259701Sdim } 371259701Sdim else 372259701Sdim GenObjCCategory(ID->getName(), CD->getName()); 373259701Sdim 374259701Sdim break; 375259701Sdim } 376259701Sdim case Decl::ObjCCategoryImpl: { 377259701Sdim const ObjCCategoryImplDecl *CD = cast<ObjCCategoryImplDecl>(D); 378259701Sdim const ObjCInterfaceDecl *ID = CD->getClassInterface(); 379259701Sdim if (!ID) { 380259701Sdim // Handle invalid code where the @interface might not 381259701Sdim // have been specified. 382259701Sdim // FIXME: We should be able to generate this USR even if the 383259701Sdim // @interface isn't available. 384259701Sdim IgnoreResults = true; 385259701Sdim return; 386259701Sdim } 387259701Sdim GenObjCCategory(ID->getName(), CD->getName()); 388259701Sdim break; 389259701Sdim } 390259701Sdim case Decl::ObjCProtocol: 391259701Sdim GenObjCProtocol(cast<ObjCProtocolDecl>(D)->getName()); 392259701Sdim break; 393259701Sdim } 394259701Sdim} 395259701Sdim 396259701Sdimvoid USRGenerator::VisitObjCPropertyDecl(const ObjCPropertyDecl *D) { 397259701Sdim // The USR for a property declared in a class extension or category is based 398259701Sdim // on the ObjCInterfaceDecl, not the ObjCCategoryDecl. 399259701Sdim if (const ObjCInterfaceDecl *ID = Context->getObjContainingInterface(D)) 400259701Sdim Visit(ID); 401259701Sdim else 402259701Sdim Visit(cast<Decl>(D->getDeclContext())); 403259701Sdim GenObjCProperty(D->getName()); 404259701Sdim} 405259701Sdim 406259701Sdimvoid USRGenerator::VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D) { 407259701Sdim if (ObjCPropertyDecl *PD = D->getPropertyDecl()) { 408259701Sdim VisitObjCPropertyDecl(PD); 409259701Sdim return; 410259701Sdim } 411259701Sdim 412259701Sdim IgnoreResults = true; 413259701Sdim} 414259701Sdim 415259701Sdimvoid USRGenerator::VisitTagDecl(const TagDecl *D) { 416259701Sdim // Add the location of the tag decl to handle resolution across 417259701Sdim // translation units. 418276479Sdim if (ShouldGenerateLocation(D) && GenLoc(D, /*IncludeOffset=*/isLocal(D))) 419259701Sdim return; 420259701Sdim 421259701Sdim D = D->getCanonicalDecl(); 422259701Sdim VisitDeclContext(D->getDeclContext()); 423259701Sdim 424259701Sdim bool AlreadyStarted = false; 425259701Sdim if (const CXXRecordDecl *CXXRecord = dyn_cast<CXXRecordDecl>(D)) { 426259701Sdim if (ClassTemplateDecl *ClassTmpl = CXXRecord->getDescribedClassTemplate()) { 427259701Sdim AlreadyStarted = true; 428259701Sdim 429259701Sdim switch (D->getTagKind()) { 430259701Sdim case TTK_Interface: 431280031Sdim case TTK_Class: 432259701Sdim case TTK_Struct: Out << "@ST"; break; 433259701Sdim case TTK_Union: Out << "@UT"; break; 434259701Sdim case TTK_Enum: llvm_unreachable("enum template"); 435259701Sdim } 436259701Sdim VisitTemplateParameterList(ClassTmpl->getTemplateParameters()); 437259701Sdim } else if (const ClassTemplatePartialSpecializationDecl *PartialSpec 438259701Sdim = dyn_cast<ClassTemplatePartialSpecializationDecl>(CXXRecord)) { 439259701Sdim AlreadyStarted = true; 440259701Sdim 441259701Sdim switch (D->getTagKind()) { 442259701Sdim case TTK_Interface: 443280031Sdim case TTK_Class: 444259701Sdim case TTK_Struct: Out << "@SP"; break; 445259701Sdim case TTK_Union: Out << "@UP"; break; 446259701Sdim case TTK_Enum: llvm_unreachable("enum partial specialization"); 447259701Sdim } 448259701Sdim VisitTemplateParameterList(PartialSpec->getTemplateParameters()); 449259701Sdim } 450259701Sdim } 451259701Sdim 452259701Sdim if (!AlreadyStarted) { 453259701Sdim switch (D->getTagKind()) { 454259701Sdim case TTK_Interface: 455280031Sdim case TTK_Class: 456259701Sdim case TTK_Struct: Out << "@S"; break; 457259701Sdim case TTK_Union: Out << "@U"; break; 458259701Sdim case TTK_Enum: Out << "@E"; break; 459259701Sdim } 460259701Sdim } 461259701Sdim 462259701Sdim Out << '@'; 463259701Sdim assert(Buf.size() > 0); 464259701Sdim const unsigned off = Buf.size() - 1; 465259701Sdim 466259701Sdim if (EmitDeclName(D)) { 467259701Sdim if (const TypedefNameDecl *TD = D->getTypedefNameForAnonDecl()) { 468259701Sdim Buf[off] = 'A'; 469259701Sdim Out << '@' << *TD; 470259701Sdim } 471280031Sdim else { 472280031Sdim if (D->isEmbeddedInDeclarator() && !D->isFreeStanding()) { 473280031Sdim printLoc(Out, D->getLocation(), Context->getSourceManager(), true); 474280031Sdim } else 475259701Sdim Buf[off] = 'a'; 476259701Sdim } 477280031Sdim } 478259701Sdim 479259701Sdim // For a class template specialization, mangle the template arguments. 480259701Sdim if (const ClassTemplateSpecializationDecl *Spec 481259701Sdim = dyn_cast<ClassTemplateSpecializationDecl>(D)) { 482259701Sdim const TemplateArgumentList &Args = Spec->getTemplateInstantiationArgs(); 483259701Sdim Out << '>'; 484259701Sdim for (unsigned I = 0, N = Args.size(); I != N; ++I) { 485259701Sdim Out << '#'; 486259701Sdim VisitTemplateArgument(Args.get(I)); 487259701Sdim } 488259701Sdim } 489259701Sdim} 490259701Sdim 491259701Sdimvoid USRGenerator::VisitTypedefDecl(const TypedefDecl *D) { 492276479Sdim if (ShouldGenerateLocation(D) && GenLoc(D, /*IncludeOffset=*/isLocal(D))) 493259701Sdim return; 494259701Sdim const DeclContext *DC = D->getDeclContext(); 495259701Sdim if (const NamedDecl *DCN = dyn_cast<NamedDecl>(DC)) 496259701Sdim Visit(DCN); 497259701Sdim Out << "@T@"; 498259701Sdim Out << D->getName(); 499259701Sdim} 500259701Sdim 501259701Sdimvoid USRGenerator::VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D) { 502276479Sdim GenLoc(D, /*IncludeOffset=*/true); 503259701Sdim return; 504259701Sdim} 505259701Sdim 506276479Sdimbool USRGenerator::GenLoc(const Decl *D, bool IncludeOffset) { 507259701Sdim if (generatedLoc) 508259701Sdim return IgnoreResults; 509259701Sdim generatedLoc = true; 510276479Sdim 511259701Sdim // Guard against null declarations in invalid code. 512259701Sdim if (!D) { 513259701Sdim IgnoreResults = true; 514259701Sdim return true; 515259701Sdim } 516259701Sdim 517259701Sdim // Use the location of canonical decl. 518259701Sdim D = D->getCanonicalDecl(); 519259701Sdim 520276479Sdim IgnoreResults = 521276479Sdim IgnoreResults || printLoc(Out, D->getLocStart(), 522276479Sdim Context->getSourceManager(), IncludeOffset); 523276479Sdim 524259701Sdim return IgnoreResults; 525259701Sdim} 526259701Sdim 527259701Sdimvoid USRGenerator::VisitType(QualType T) { 528259701Sdim // This method mangles in USR information for types. It can possibly 529259701Sdim // just reuse the naming-mangling logic used by codegen, although the 530259701Sdim // requirements for USRs might not be the same. 531259701Sdim ASTContext &Ctx = *Context; 532259701Sdim 533259701Sdim do { 534259701Sdim T = Ctx.getCanonicalType(T); 535259701Sdim Qualifiers Q = T.getQualifiers(); 536259701Sdim unsigned qVal = 0; 537259701Sdim if (Q.hasConst()) 538259701Sdim qVal |= 0x1; 539259701Sdim if (Q.hasVolatile()) 540259701Sdim qVal |= 0x2; 541259701Sdim if (Q.hasRestrict()) 542259701Sdim qVal |= 0x4; 543259701Sdim if(qVal) 544259701Sdim Out << ((char) ('0' + qVal)); 545259701Sdim 546259701Sdim // Mangle in ObjC GC qualifiers? 547259701Sdim 548259701Sdim if (const PackExpansionType *Expansion = T->getAs<PackExpansionType>()) { 549259701Sdim Out << 'P'; 550259701Sdim T = Expansion->getPattern(); 551259701Sdim } 552259701Sdim 553259701Sdim if (const BuiltinType *BT = T->getAs<BuiltinType>()) { 554259701Sdim unsigned char c = '\0'; 555259701Sdim switch (BT->getKind()) { 556259701Sdim case BuiltinType::Void: 557259701Sdim c = 'v'; break; 558259701Sdim case BuiltinType::Bool: 559259701Sdim c = 'b'; break; 560259701Sdim case BuiltinType::UChar: 561259701Sdim c = 'c'; break; 562259701Sdim case BuiltinType::Char16: 563259701Sdim c = 'q'; break; 564259701Sdim case BuiltinType::Char32: 565259701Sdim c = 'w'; break; 566259701Sdim case BuiltinType::UShort: 567259701Sdim c = 's'; break; 568259701Sdim case BuiltinType::UInt: 569259701Sdim c = 'i'; break; 570259701Sdim case BuiltinType::ULong: 571259701Sdim c = 'l'; break; 572259701Sdim case BuiltinType::ULongLong: 573259701Sdim c = 'k'; break; 574259701Sdim case BuiltinType::UInt128: 575259701Sdim c = 'j'; break; 576280031Sdim case BuiltinType::Char_U: 577259701Sdim case BuiltinType::Char_S: 578280031Sdim c = 'C'; break; 579259701Sdim case BuiltinType::SChar: 580280031Sdim c = 'r'; break; 581259701Sdim case BuiltinType::WChar_S: 582259701Sdim case BuiltinType::WChar_U: 583259701Sdim c = 'W'; break; 584259701Sdim case BuiltinType::Short: 585259701Sdim c = 'S'; break; 586259701Sdim case BuiltinType::Int: 587259701Sdim c = 'I'; break; 588259701Sdim case BuiltinType::Long: 589259701Sdim c = 'L'; break; 590259701Sdim case BuiltinType::LongLong: 591259701Sdim c = 'K'; break; 592259701Sdim case BuiltinType::Int128: 593259701Sdim c = 'J'; break; 594259701Sdim case BuiltinType::Half: 595259701Sdim c = 'h'; break; 596259701Sdim case BuiltinType::Float: 597259701Sdim c = 'f'; break; 598259701Sdim case BuiltinType::Double: 599259701Sdim c = 'd'; break; 600259701Sdim case BuiltinType::LongDouble: 601259701Sdim c = 'D'; break; 602259701Sdim case BuiltinType::NullPtr: 603259701Sdim c = 'n'; break; 604259701Sdim#define BUILTIN_TYPE(Id, SingletonId) 605259701Sdim#define PLACEHOLDER_TYPE(Id, SingletonId) case BuiltinType::Id: 606259701Sdim#include "clang/AST/BuiltinTypes.def" 607259701Sdim case BuiltinType::Dependent: 608259701Sdim case BuiltinType::OCLImage1d: 609259701Sdim case BuiltinType::OCLImage1dArray: 610259701Sdim case BuiltinType::OCLImage1dBuffer: 611259701Sdim case BuiltinType::OCLImage2d: 612259701Sdim case BuiltinType::OCLImage2dArray: 613296417Sdim case BuiltinType::OCLImage2dDepth: 614296417Sdim case BuiltinType::OCLImage2dArrayDepth: 615296417Sdim case BuiltinType::OCLImage2dMSAA: 616296417Sdim case BuiltinType::OCLImage2dArrayMSAA: 617296417Sdim case BuiltinType::OCLImage2dMSAADepth: 618296417Sdim case BuiltinType::OCLImage2dArrayMSAADepth: 619259701Sdim case BuiltinType::OCLImage3d: 620259701Sdim case BuiltinType::OCLEvent: 621296417Sdim case BuiltinType::OCLClkEvent: 622296417Sdim case BuiltinType::OCLQueue: 623296417Sdim case BuiltinType::OCLNDRange: 624296417Sdim case BuiltinType::OCLReserveID: 625259701Sdim case BuiltinType::OCLSampler: 626259701Sdim IgnoreResults = true; 627259701Sdim return; 628259701Sdim case BuiltinType::ObjCId: 629259701Sdim c = 'o'; break; 630259701Sdim case BuiltinType::ObjCClass: 631259701Sdim c = 'O'; break; 632259701Sdim case BuiltinType::ObjCSel: 633259701Sdim c = 'e'; break; 634259701Sdim } 635259701Sdim Out << c; 636259701Sdim return; 637259701Sdim } 638259701Sdim 639259701Sdim // If we have already seen this (non-built-in) type, use a substitution 640259701Sdim // encoding. 641259701Sdim llvm::DenseMap<const Type *, unsigned>::iterator Substitution 642259701Sdim = TypeSubstitutions.find(T.getTypePtr()); 643259701Sdim if (Substitution != TypeSubstitutions.end()) { 644259701Sdim Out << 'S' << Substitution->second << '_'; 645259701Sdim return; 646259701Sdim } else { 647259701Sdim // Record this as a substitution. 648259701Sdim unsigned Number = TypeSubstitutions.size(); 649259701Sdim TypeSubstitutions[T.getTypePtr()] = Number; 650259701Sdim } 651259701Sdim 652259701Sdim if (const PointerType *PT = T->getAs<PointerType>()) { 653259701Sdim Out << '*'; 654259701Sdim T = PT->getPointeeType(); 655259701Sdim continue; 656259701Sdim } 657280031Sdim if (const RValueReferenceType *RT = T->getAs<RValueReferenceType>()) { 658280031Sdim Out << "&&"; 659280031Sdim T = RT->getPointeeType(); 660280031Sdim continue; 661280031Sdim } 662259701Sdim if (const ReferenceType *RT = T->getAs<ReferenceType>()) { 663259701Sdim Out << '&'; 664259701Sdim T = RT->getPointeeType(); 665259701Sdim continue; 666259701Sdim } 667259701Sdim if (const FunctionProtoType *FT = T->getAs<FunctionProtoType>()) { 668259701Sdim Out << 'F'; 669276479Sdim VisitType(FT->getReturnType()); 670276479Sdim for (const auto &I : FT->param_types()) 671276479Sdim VisitType(I); 672259701Sdim if (FT->isVariadic()) 673259701Sdim Out << '.'; 674259701Sdim return; 675259701Sdim } 676259701Sdim if (const BlockPointerType *BT = T->getAs<BlockPointerType>()) { 677259701Sdim Out << 'B'; 678259701Sdim T = BT->getPointeeType(); 679259701Sdim continue; 680259701Sdim } 681259701Sdim if (const ComplexType *CT = T->getAs<ComplexType>()) { 682259701Sdim Out << '<'; 683259701Sdim T = CT->getElementType(); 684259701Sdim continue; 685259701Sdim } 686259701Sdim if (const TagType *TT = T->getAs<TagType>()) { 687259701Sdim Out << '$'; 688259701Sdim VisitTagDecl(TT->getDecl()); 689259701Sdim return; 690259701Sdim } 691259701Sdim if (const TemplateTypeParmType *TTP = T->getAs<TemplateTypeParmType>()) { 692259701Sdim Out << 't' << TTP->getDepth() << '.' << TTP->getIndex(); 693259701Sdim return; 694259701Sdim } 695259701Sdim if (const TemplateSpecializationType *Spec 696259701Sdim = T->getAs<TemplateSpecializationType>()) { 697259701Sdim Out << '>'; 698259701Sdim VisitTemplateName(Spec->getTemplateName()); 699259701Sdim Out << Spec->getNumArgs(); 700259701Sdim for (unsigned I = 0, N = Spec->getNumArgs(); I != N; ++I) 701259701Sdim VisitTemplateArgument(Spec->getArg(I)); 702259701Sdim return; 703259701Sdim } 704280031Sdim if (const DependentNameType *DNT = T->getAs<DependentNameType>()) { 705280031Sdim Out << '^'; 706280031Sdim // FIXME: Encode the qualifier, don't just print it. 707280031Sdim PrintingPolicy PO(Ctx.getLangOpts()); 708280031Sdim PO.SuppressTagKeyword = true; 709280031Sdim PO.SuppressUnwrittenScope = true; 710280031Sdim PO.ConstantArraySizeAsWritten = false; 711280031Sdim PO.AnonymousTagLocations = false; 712280031Sdim DNT->getQualifier()->print(Out, PO); 713280031Sdim Out << ':' << DNT->getIdentifier()->getName(); 714280031Sdim return; 715280031Sdim } 716280031Sdim if (const InjectedClassNameType *InjT = T->getAs<InjectedClassNameType>()) { 717280031Sdim T = InjT->getInjectedSpecializationType(); 718280031Sdim continue; 719280031Sdim } 720259701Sdim 721259701Sdim // Unhandled type. 722259701Sdim Out << ' '; 723259701Sdim break; 724259701Sdim } while (true); 725259701Sdim} 726259701Sdim 727259701Sdimvoid USRGenerator::VisitTemplateParameterList( 728259701Sdim const TemplateParameterList *Params) { 729259701Sdim if (!Params) 730259701Sdim return; 731259701Sdim Out << '>' << Params->size(); 732259701Sdim for (TemplateParameterList::const_iterator P = Params->begin(), 733259701Sdim PEnd = Params->end(); 734259701Sdim P != PEnd; ++P) { 735259701Sdim Out << '#'; 736259701Sdim if (isa<TemplateTypeParmDecl>(*P)) { 737259701Sdim if (cast<TemplateTypeParmDecl>(*P)->isParameterPack()) 738259701Sdim Out<< 'p'; 739259701Sdim Out << 'T'; 740259701Sdim continue; 741259701Sdim } 742259701Sdim 743259701Sdim if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(*P)) { 744259701Sdim if (NTTP->isParameterPack()) 745259701Sdim Out << 'p'; 746259701Sdim Out << 'N'; 747259701Sdim VisitType(NTTP->getType()); 748259701Sdim continue; 749259701Sdim } 750259701Sdim 751259701Sdim TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*P); 752259701Sdim if (TTP->isParameterPack()) 753259701Sdim Out << 'p'; 754259701Sdim Out << 't'; 755259701Sdim VisitTemplateParameterList(TTP->getTemplateParameters()); 756259701Sdim } 757259701Sdim} 758259701Sdim 759259701Sdimvoid USRGenerator::VisitTemplateName(TemplateName Name) { 760259701Sdim if (TemplateDecl *Template = Name.getAsTemplateDecl()) { 761259701Sdim if (TemplateTemplateParmDecl *TTP 762259701Sdim = dyn_cast<TemplateTemplateParmDecl>(Template)) { 763259701Sdim Out << 't' << TTP->getDepth() << '.' << TTP->getIndex(); 764259701Sdim return; 765259701Sdim } 766259701Sdim 767259701Sdim Visit(Template); 768259701Sdim return; 769259701Sdim } 770259701Sdim 771259701Sdim // FIXME: Visit dependent template names. 772259701Sdim} 773259701Sdim 774259701Sdimvoid USRGenerator::VisitTemplateArgument(const TemplateArgument &Arg) { 775259701Sdim switch (Arg.getKind()) { 776259701Sdim case TemplateArgument::Null: 777259701Sdim break; 778259701Sdim 779259701Sdim case TemplateArgument::Declaration: 780259701Sdim Visit(Arg.getAsDecl()); 781259701Sdim break; 782259701Sdim 783259701Sdim case TemplateArgument::NullPtr: 784259701Sdim break; 785259701Sdim 786259701Sdim case TemplateArgument::TemplateExpansion: 787259701Sdim Out << 'P'; // pack expansion of... 788259701Sdim // Fall through 789259701Sdim case TemplateArgument::Template: 790259701Sdim VisitTemplateName(Arg.getAsTemplateOrTemplatePattern()); 791259701Sdim break; 792259701Sdim 793259701Sdim case TemplateArgument::Expression: 794259701Sdim // FIXME: Visit expressions. 795259701Sdim break; 796259701Sdim 797259701Sdim case TemplateArgument::Pack: 798259701Sdim Out << 'p' << Arg.pack_size(); 799276479Sdim for (const auto &P : Arg.pack_elements()) 800276479Sdim VisitTemplateArgument(P); 801259701Sdim break; 802259701Sdim 803259701Sdim case TemplateArgument::Type: 804259701Sdim VisitType(Arg.getAsType()); 805259701Sdim break; 806259701Sdim 807259701Sdim case TemplateArgument::Integral: 808259701Sdim Out << 'V'; 809259701Sdim VisitType(Arg.getIntegralType()); 810259701Sdim Out << Arg.getAsIntegral(); 811259701Sdim break; 812259701Sdim } 813259701Sdim} 814259701Sdim 815259701Sdim//===----------------------------------------------------------------------===// 816259701Sdim// USR generation functions. 817259701Sdim//===----------------------------------------------------------------------===// 818259701Sdim 819259701Sdimvoid clang::index::generateUSRForObjCClass(StringRef Cls, raw_ostream &OS) { 820259701Sdim OS << "objc(cs)" << Cls; 821259701Sdim} 822259701Sdim 823259701Sdimvoid clang::index::generateUSRForObjCCategory(StringRef Cls, StringRef Cat, 824259701Sdim raw_ostream &OS) { 825259701Sdim OS << "objc(cy)" << Cls << '@' << Cat; 826259701Sdim} 827259701Sdim 828259701Sdimvoid clang::index::generateUSRForObjCIvar(StringRef Ivar, raw_ostream &OS) { 829259701Sdim OS << '@' << Ivar; 830259701Sdim} 831259701Sdim 832259701Sdimvoid clang::index::generateUSRForObjCMethod(StringRef Sel, 833259701Sdim bool IsInstanceMethod, 834259701Sdim raw_ostream &OS) { 835259701Sdim OS << (IsInstanceMethod ? "(im)" : "(cm)") << Sel; 836259701Sdim} 837259701Sdim 838259701Sdimvoid clang::index::generateUSRForObjCProperty(StringRef Prop, raw_ostream &OS) { 839259701Sdim OS << "(py)" << Prop; 840259701Sdim} 841259701Sdim 842259701Sdimvoid clang::index::generateUSRForObjCProtocol(StringRef Prot, raw_ostream &OS) { 843259701Sdim OS << "objc(pl)" << Prot; 844259701Sdim} 845259701Sdim 846259701Sdimbool clang::index::generateUSRForDecl(const Decl *D, 847259701Sdim SmallVectorImpl<char> &Buf) { 848259701Sdim // Don't generate USRs for things with invalid locations. 849259701Sdim if (!D || D->getLocStart().isInvalid()) 850259701Sdim return true; 851259701Sdim 852259701Sdim USRGenerator UG(&D->getASTContext(), Buf); 853259701Sdim UG.Visit(D); 854259701Sdim return UG.ignoreResults(); 855259701Sdim} 856276479Sdim 857288943Sdimbool clang::index::generateUSRForMacro(const MacroDefinitionRecord *MD, 858276479Sdim const SourceManager &SM, 859276479Sdim SmallVectorImpl<char> &Buf) { 860276479Sdim // Don't generate USRs for things with invalid locations. 861276479Sdim if (!MD || MD->getLocation().isInvalid()) 862276479Sdim return true; 863276479Sdim 864276479Sdim llvm::raw_svector_ostream Out(Buf); 865276479Sdim 866276479Sdim // Assume that system headers are sane. Don't put source location 867276479Sdim // information into the USR if the macro comes from a system header. 868276479Sdim SourceLocation Loc = MD->getLocation(); 869276479Sdim bool ShouldGenerateLocation = !SM.isInSystemHeader(Loc); 870276479Sdim 871276479Sdim Out << getUSRSpacePrefix(); 872276479Sdim if (ShouldGenerateLocation) 873276479Sdim printLoc(Out, Loc, SM, /*IncludeOffset=*/true); 874276479Sdim Out << "@macro@"; 875276479Sdim Out << MD->getName()->getName(); 876276479Sdim return false; 877276479Sdim} 878276479Sdim 879