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" 14259701Sdim#include "llvm/ADT/SmallString.h" 15259701Sdim#include "llvm/Support/Path.h" 16259701Sdim#include "llvm/Support/raw_ostream.h" 17259701Sdim 18259701Sdimusing namespace clang; 19259701Sdimusing namespace clang::index; 20259701Sdim 21259701Sdim//===----------------------------------------------------------------------===// 22259701Sdim// USR generation. 23259701Sdim//===----------------------------------------------------------------------===// 24259701Sdim 25259701Sdimnamespace { 26259701Sdimclass USRGenerator : public ConstDeclVisitor<USRGenerator> { 27259701Sdim SmallVectorImpl<char> &Buf; 28259701Sdim llvm::raw_svector_ostream Out; 29259701Sdim bool IgnoreResults; 30259701Sdim ASTContext *Context; 31259701Sdim bool generatedLoc; 32259701Sdim 33259701Sdim llvm::DenseMap<const Type *, unsigned> TypeSubstitutions; 34259701Sdim 35259701Sdimpublic: 36259701Sdim explicit USRGenerator(ASTContext *Ctx, SmallVectorImpl<char> &Buf) 37259701Sdim : Buf(Buf), 38259701Sdim Out(Buf), 39259701Sdim IgnoreResults(false), 40259701Sdim Context(Ctx), 41259701Sdim generatedLoc(false) 42259701Sdim { 43259701Sdim // Add the USR space prefix. 44259701Sdim Out << getUSRSpacePrefix(); 45259701Sdim } 46259701Sdim 47259701Sdim bool ignoreResults() const { return IgnoreResults; } 48259701Sdim 49259701Sdim // Visitation methods from generating USRs from AST elements. 50259701Sdim void VisitDeclContext(const DeclContext *D); 51259701Sdim void VisitFieldDecl(const FieldDecl *D); 52259701Sdim void VisitFunctionDecl(const FunctionDecl *D); 53259701Sdim void VisitNamedDecl(const NamedDecl *D); 54259701Sdim void VisitNamespaceDecl(const NamespaceDecl *D); 55259701Sdim void VisitNamespaceAliasDecl(const NamespaceAliasDecl *D); 56259701Sdim void VisitFunctionTemplateDecl(const FunctionTemplateDecl *D); 57259701Sdim void VisitClassTemplateDecl(const ClassTemplateDecl *D); 58259701Sdim void VisitObjCContainerDecl(const ObjCContainerDecl *CD); 59259701Sdim void VisitObjCMethodDecl(const ObjCMethodDecl *MD); 60259701Sdim void VisitObjCPropertyDecl(const ObjCPropertyDecl *D); 61259701Sdim void VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D); 62259701Sdim void VisitTagDecl(const TagDecl *D); 63259701Sdim void VisitTypedefDecl(const TypedefDecl *D); 64259701Sdim void VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D); 65259701Sdim void VisitVarDecl(const VarDecl *D); 66259701Sdim void VisitNonTypeTemplateParmDecl(const NonTypeTemplateParmDecl *D); 67259701Sdim void VisitTemplateTemplateParmDecl(const TemplateTemplateParmDecl *D); 68259701Sdim void VisitLinkageSpecDecl(const LinkageSpecDecl *D) { 69259701Sdim IgnoreResults = true; 70259701Sdim } 71259701Sdim void VisitUsingDirectiveDecl(const UsingDirectiveDecl *D) { 72259701Sdim IgnoreResults = true; 73259701Sdim } 74259701Sdim void VisitUsingDecl(const UsingDecl *D) { 75259701Sdim IgnoreResults = true; 76259701Sdim } 77259701Sdim void VisitUnresolvedUsingValueDecl(const UnresolvedUsingValueDecl *D) { 78259701Sdim IgnoreResults = true; 79259701Sdim } 80259701Sdim void VisitUnresolvedUsingTypenameDecl(const UnresolvedUsingTypenameDecl *D) { 81259701Sdim IgnoreResults = true; 82259701Sdim } 83259701Sdim 84259701Sdim /// Generate the string component containing the location of the 85259701Sdim /// declaration. 86259701Sdim bool GenLoc(const Decl *D); 87259701Sdim 88259701Sdim /// String generation methods used both by the visitation methods 89259701Sdim /// and from other clients that want to directly generate USRs. These 90259701Sdim /// methods do not construct complete USRs (which incorporate the parents 91259701Sdim /// of an AST element), but only the fragments concerning the AST element 92259701Sdim /// itself. 93259701Sdim 94259701Sdim /// Generate a USR for an Objective-C class. 95259701Sdim void GenObjCClass(StringRef cls) { 96259701Sdim generateUSRForObjCClass(cls, Out); 97259701Sdim } 98259701Sdim /// Generate a USR for an Objective-C class category. 99259701Sdim void GenObjCCategory(StringRef cls, StringRef cat) { 100259701Sdim generateUSRForObjCCategory(cls, cat, Out); 101259701Sdim } 102259701Sdim /// Generate a USR fragment for an Objective-C instance variable. The 103259701Sdim /// complete USR can be created by concatenating the USR for the 104259701Sdim /// encompassing class with this USR fragment. 105259701Sdim void GenObjCIvar(StringRef ivar) { 106259701Sdim generateUSRForObjCIvar(ivar, Out); 107259701Sdim } 108259701Sdim /// Generate a USR fragment for an Objective-C method. 109259701Sdim void GenObjCMethod(StringRef sel, bool isInstanceMethod) { 110259701Sdim generateUSRForObjCMethod(sel, isInstanceMethod, Out); 111259701Sdim } 112259701Sdim /// Generate a USR fragment for an Objective-C property. 113259701Sdim void GenObjCProperty(StringRef prop) { 114259701Sdim generateUSRForObjCProperty(prop, Out); 115259701Sdim } 116259701Sdim /// Generate a USR for an Objective-C protocol. 117259701Sdim void GenObjCProtocol(StringRef prot) { 118259701Sdim generateUSRForObjCProtocol(prot, Out); 119259701Sdim } 120259701Sdim 121259701Sdim void VisitType(QualType T); 122259701Sdim void VisitTemplateParameterList(const TemplateParameterList *Params); 123259701Sdim void VisitTemplateName(TemplateName Name); 124259701Sdim void VisitTemplateArgument(const TemplateArgument &Arg); 125259701Sdim 126259701Sdim /// Emit a Decl's name using NamedDecl::printName() and return true if 127259701Sdim /// the decl had no name. 128259701Sdim bool EmitDeclName(const NamedDecl *D); 129259701Sdim}; 130259701Sdim 131259701Sdim} // end anonymous namespace 132259701Sdim 133259701Sdim//===----------------------------------------------------------------------===// 134259701Sdim// Generating USRs from ASTS. 135259701Sdim//===----------------------------------------------------------------------===// 136259701Sdim 137259701Sdimbool USRGenerator::EmitDeclName(const NamedDecl *D) { 138259701Sdim Out.flush(); 139259701Sdim const unsigned startSize = Buf.size(); 140259701Sdim D->printName(Out); 141259701Sdim Out.flush(); 142259701Sdim const unsigned endSize = Buf.size(); 143259701Sdim return startSize == endSize; 144259701Sdim} 145259701Sdim 146259701Sdimstatic inline bool ShouldGenerateLocation(const NamedDecl *D) { 147259701Sdim return !D->isExternallyVisible(); 148259701Sdim} 149259701Sdim 150259701Sdimvoid USRGenerator::VisitDeclContext(const DeclContext *DC) { 151259701Sdim if (const NamedDecl *D = dyn_cast<NamedDecl>(DC)) 152259701Sdim Visit(D); 153259701Sdim} 154259701Sdim 155259701Sdimvoid USRGenerator::VisitFieldDecl(const FieldDecl *D) { 156259701Sdim // The USR for an ivar declared in a class extension is based on the 157259701Sdim // ObjCInterfaceDecl, not the ObjCCategoryDecl. 158259701Sdim if (const ObjCInterfaceDecl *ID = Context->getObjContainingInterface(D)) 159259701Sdim Visit(ID); 160259701Sdim else 161259701Sdim VisitDeclContext(D->getDeclContext()); 162259701Sdim Out << (isa<ObjCIvarDecl>(D) ? "@" : "@FI@"); 163259701Sdim if (EmitDeclName(D)) { 164259701Sdim // Bit fields can be anonymous. 165259701Sdim IgnoreResults = true; 166259701Sdim return; 167259701Sdim } 168259701Sdim} 169259701Sdim 170259701Sdimvoid USRGenerator::VisitFunctionDecl(const FunctionDecl *D) { 171259701Sdim if (ShouldGenerateLocation(D) && GenLoc(D)) 172259701Sdim return; 173259701Sdim 174259701Sdim VisitDeclContext(D->getDeclContext()); 175259701Sdim if (FunctionTemplateDecl *FunTmpl = D->getDescribedFunctionTemplate()) { 176259701Sdim Out << "@FT@"; 177259701Sdim VisitTemplateParameterList(FunTmpl->getTemplateParameters()); 178259701Sdim } else 179259701Sdim Out << "@F@"; 180259701Sdim D->printName(Out); 181259701Sdim 182259701Sdim ASTContext &Ctx = *Context; 183259701Sdim if (!Ctx.getLangOpts().CPlusPlus || D->isExternC()) 184259701Sdim return; 185259701Sdim 186259701Sdim if (const TemplateArgumentList * 187259701Sdim SpecArgs = D->getTemplateSpecializationArgs()) { 188259701Sdim Out << '<'; 189259701Sdim for (unsigned I = 0, N = SpecArgs->size(); I != N; ++I) { 190259701Sdim Out << '#'; 191259701Sdim VisitTemplateArgument(SpecArgs->get(I)); 192259701Sdim } 193259701Sdim Out << '>'; 194259701Sdim } 195259701Sdim 196259701Sdim // Mangle in type information for the arguments. 197259701Sdim for (FunctionDecl::param_const_iterator I = D->param_begin(), 198259701Sdim E = D->param_end(); 199259701Sdim I != E; ++I) { 200259701Sdim Out << '#'; 201259701Sdim if (ParmVarDecl *PD = *I) 202259701Sdim VisitType(PD->getType()); 203259701Sdim } 204259701Sdim if (D->isVariadic()) 205259701Sdim Out << '.'; 206259701Sdim Out << '#'; 207259701Sdim if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) { 208259701Sdim if (MD->isStatic()) 209259701Sdim Out << 'S'; 210259701Sdim if (unsigned quals = MD->getTypeQualifiers()) 211259701Sdim Out << (char)('0' + quals); 212259701Sdim } 213259701Sdim} 214259701Sdim 215259701Sdimvoid USRGenerator::VisitNamedDecl(const NamedDecl *D) { 216259701Sdim VisitDeclContext(D->getDeclContext()); 217259701Sdim Out << "@"; 218259701Sdim 219259701Sdim if (EmitDeclName(D)) { 220259701Sdim // The string can be empty if the declaration has no name; e.g., it is 221259701Sdim // the ParmDecl with no name for declaration of a function pointer type, 222259701Sdim // e.g.: void (*f)(void *); 223259701Sdim // In this case, don't generate a USR. 224259701Sdim IgnoreResults = true; 225259701Sdim } 226259701Sdim} 227259701Sdim 228259701Sdimvoid USRGenerator::VisitVarDecl(const VarDecl *D) { 229259701Sdim // VarDecls can be declared 'extern' within a function or method body, 230259701Sdim // but their enclosing DeclContext is the function, not the TU. We need 231259701Sdim // to check the storage class to correctly generate the USR. 232259701Sdim if (ShouldGenerateLocation(D) && GenLoc(D)) 233259701Sdim return; 234259701Sdim 235259701Sdim VisitDeclContext(D->getDeclContext()); 236259701Sdim 237259701Sdim // Variables always have simple names. 238259701Sdim StringRef s = D->getName(); 239259701Sdim 240259701Sdim // The string can be empty if the declaration has no name; e.g., it is 241259701Sdim // the ParmDecl with no name for declaration of a function pointer type, e.g.: 242259701Sdim // void (*f)(void *); 243259701Sdim // In this case, don't generate a USR. 244259701Sdim if (s.empty()) 245259701Sdim IgnoreResults = true; 246259701Sdim else 247259701Sdim Out << '@' << s; 248259701Sdim} 249259701Sdim 250259701Sdimvoid USRGenerator::VisitNonTypeTemplateParmDecl( 251259701Sdim const NonTypeTemplateParmDecl *D) { 252259701Sdim GenLoc(D); 253259701Sdim return; 254259701Sdim} 255259701Sdim 256259701Sdimvoid USRGenerator::VisitTemplateTemplateParmDecl( 257259701Sdim const TemplateTemplateParmDecl *D) { 258259701Sdim GenLoc(D); 259259701Sdim return; 260259701Sdim} 261259701Sdim 262259701Sdimvoid USRGenerator::VisitNamespaceDecl(const NamespaceDecl *D) { 263259701Sdim if (D->isAnonymousNamespace()) { 264259701Sdim Out << "@aN"; 265259701Sdim return; 266259701Sdim } 267259701Sdim 268259701Sdim VisitDeclContext(D->getDeclContext()); 269259701Sdim if (!IgnoreResults) 270259701Sdim Out << "@N@" << D->getName(); 271259701Sdim} 272259701Sdim 273259701Sdimvoid USRGenerator::VisitFunctionTemplateDecl(const FunctionTemplateDecl *D) { 274259701Sdim VisitFunctionDecl(D->getTemplatedDecl()); 275259701Sdim} 276259701Sdim 277259701Sdimvoid USRGenerator::VisitClassTemplateDecl(const ClassTemplateDecl *D) { 278259701Sdim VisitTagDecl(D->getTemplatedDecl()); 279259701Sdim} 280259701Sdim 281259701Sdimvoid USRGenerator::VisitNamespaceAliasDecl(const NamespaceAliasDecl *D) { 282259701Sdim VisitDeclContext(D->getDeclContext()); 283259701Sdim if (!IgnoreResults) 284259701Sdim Out << "@NA@" << D->getName(); 285259701Sdim} 286259701Sdim 287259701Sdimvoid USRGenerator::VisitObjCMethodDecl(const ObjCMethodDecl *D) { 288259701Sdim const DeclContext *container = D->getDeclContext(); 289259701Sdim if (const ObjCProtocolDecl *pd = dyn_cast<ObjCProtocolDecl>(container)) { 290259701Sdim Visit(pd); 291259701Sdim } 292259701Sdim else { 293259701Sdim // The USR for a method declared in a class extension or category is based on 294259701Sdim // the ObjCInterfaceDecl, not the ObjCCategoryDecl. 295259701Sdim const ObjCInterfaceDecl *ID = D->getClassInterface(); 296259701Sdim if (!ID) { 297259701Sdim IgnoreResults = true; 298259701Sdim return; 299259701Sdim } 300259701Sdim Visit(ID); 301259701Sdim } 302259701Sdim // Ideally we would use 'GenObjCMethod', but this is such a hot path 303259701Sdim // for Objective-C code that we don't want to use 304259701Sdim // DeclarationName::getAsString(). 305259701Sdim Out << (D->isInstanceMethod() ? "(im)" : "(cm)") 306259701Sdim << DeclarationName(D->getSelector()); 307259701Sdim} 308259701Sdim 309259701Sdimvoid USRGenerator::VisitObjCContainerDecl(const ObjCContainerDecl *D) { 310259701Sdim switch (D->getKind()) { 311259701Sdim default: 312259701Sdim llvm_unreachable("Invalid ObjC container."); 313259701Sdim case Decl::ObjCInterface: 314259701Sdim case Decl::ObjCImplementation: 315259701Sdim GenObjCClass(D->getName()); 316259701Sdim break; 317259701Sdim case Decl::ObjCCategory: { 318259701Sdim const ObjCCategoryDecl *CD = cast<ObjCCategoryDecl>(D); 319259701Sdim const ObjCInterfaceDecl *ID = CD->getClassInterface(); 320259701Sdim if (!ID) { 321259701Sdim // Handle invalid code where the @interface might not 322259701Sdim // have been specified. 323259701Sdim // FIXME: We should be able to generate this USR even if the 324259701Sdim // @interface isn't available. 325259701Sdim IgnoreResults = true; 326259701Sdim return; 327259701Sdim } 328259701Sdim // Specially handle class extensions, which are anonymous categories. 329259701Sdim // We want to mangle in the location to uniquely distinguish them. 330259701Sdim if (CD->IsClassExtension()) { 331259701Sdim Out << "objc(ext)" << ID->getName() << '@'; 332259701Sdim GenLoc(CD); 333259701Sdim } 334259701Sdim else 335259701Sdim GenObjCCategory(ID->getName(), CD->getName()); 336259701Sdim 337259701Sdim break; 338259701Sdim } 339259701Sdim case Decl::ObjCCategoryImpl: { 340259701Sdim const ObjCCategoryImplDecl *CD = cast<ObjCCategoryImplDecl>(D); 341259701Sdim const ObjCInterfaceDecl *ID = CD->getClassInterface(); 342259701Sdim if (!ID) { 343259701Sdim // Handle invalid code where the @interface might not 344259701Sdim // have been specified. 345259701Sdim // FIXME: We should be able to generate this USR even if the 346259701Sdim // @interface isn't available. 347259701Sdim IgnoreResults = true; 348259701Sdim return; 349259701Sdim } 350259701Sdim GenObjCCategory(ID->getName(), CD->getName()); 351259701Sdim break; 352259701Sdim } 353259701Sdim case Decl::ObjCProtocol: 354259701Sdim GenObjCProtocol(cast<ObjCProtocolDecl>(D)->getName()); 355259701Sdim break; 356259701Sdim } 357259701Sdim} 358259701Sdim 359259701Sdimvoid USRGenerator::VisitObjCPropertyDecl(const ObjCPropertyDecl *D) { 360259701Sdim // The USR for a property declared in a class extension or category is based 361259701Sdim // on the ObjCInterfaceDecl, not the ObjCCategoryDecl. 362259701Sdim if (const ObjCInterfaceDecl *ID = Context->getObjContainingInterface(D)) 363259701Sdim Visit(ID); 364259701Sdim else 365259701Sdim Visit(cast<Decl>(D->getDeclContext())); 366259701Sdim GenObjCProperty(D->getName()); 367259701Sdim} 368259701Sdim 369259701Sdimvoid USRGenerator::VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D) { 370259701Sdim if (ObjCPropertyDecl *PD = D->getPropertyDecl()) { 371259701Sdim VisitObjCPropertyDecl(PD); 372259701Sdim return; 373259701Sdim } 374259701Sdim 375259701Sdim IgnoreResults = true; 376259701Sdim} 377259701Sdim 378259701Sdimvoid USRGenerator::VisitTagDecl(const TagDecl *D) { 379259701Sdim // Add the location of the tag decl to handle resolution across 380259701Sdim // translation units. 381259701Sdim if (ShouldGenerateLocation(D) && GenLoc(D)) 382259701Sdim return; 383259701Sdim 384259701Sdim D = D->getCanonicalDecl(); 385259701Sdim VisitDeclContext(D->getDeclContext()); 386259701Sdim 387259701Sdim bool AlreadyStarted = false; 388259701Sdim if (const CXXRecordDecl *CXXRecord = dyn_cast<CXXRecordDecl>(D)) { 389259701Sdim if (ClassTemplateDecl *ClassTmpl = CXXRecord->getDescribedClassTemplate()) { 390259701Sdim AlreadyStarted = true; 391259701Sdim 392259701Sdim switch (D->getTagKind()) { 393259701Sdim case TTK_Interface: 394259701Sdim case TTK_Struct: Out << "@ST"; break; 395259701Sdim case TTK_Class: Out << "@CT"; break; 396259701Sdim case TTK_Union: Out << "@UT"; break; 397259701Sdim case TTK_Enum: llvm_unreachable("enum template"); 398259701Sdim } 399259701Sdim VisitTemplateParameterList(ClassTmpl->getTemplateParameters()); 400259701Sdim } else if (const ClassTemplatePartialSpecializationDecl *PartialSpec 401259701Sdim = dyn_cast<ClassTemplatePartialSpecializationDecl>(CXXRecord)) { 402259701Sdim AlreadyStarted = true; 403259701Sdim 404259701Sdim switch (D->getTagKind()) { 405259701Sdim case TTK_Interface: 406259701Sdim case TTK_Struct: Out << "@SP"; break; 407259701Sdim case TTK_Class: Out << "@CP"; break; 408259701Sdim case TTK_Union: Out << "@UP"; break; 409259701Sdim case TTK_Enum: llvm_unreachable("enum partial specialization"); 410259701Sdim } 411259701Sdim VisitTemplateParameterList(PartialSpec->getTemplateParameters()); 412259701Sdim } 413259701Sdim } 414259701Sdim 415259701Sdim if (!AlreadyStarted) { 416259701Sdim switch (D->getTagKind()) { 417259701Sdim case TTK_Interface: 418259701Sdim case TTK_Struct: Out << "@S"; break; 419259701Sdim case TTK_Class: Out << "@C"; break; 420259701Sdim case TTK_Union: Out << "@U"; break; 421259701Sdim case TTK_Enum: Out << "@E"; break; 422259701Sdim } 423259701Sdim } 424259701Sdim 425259701Sdim Out << '@'; 426259701Sdim Out.flush(); 427259701Sdim assert(Buf.size() > 0); 428259701Sdim const unsigned off = Buf.size() - 1; 429259701Sdim 430259701Sdim if (EmitDeclName(D)) { 431259701Sdim if (const TypedefNameDecl *TD = D->getTypedefNameForAnonDecl()) { 432259701Sdim Buf[off] = 'A'; 433259701Sdim Out << '@' << *TD; 434259701Sdim } 435259701Sdim else 436259701Sdim Buf[off] = 'a'; 437259701Sdim } 438259701Sdim 439259701Sdim // For a class template specialization, mangle the template arguments. 440259701Sdim if (const ClassTemplateSpecializationDecl *Spec 441259701Sdim = dyn_cast<ClassTemplateSpecializationDecl>(D)) { 442259701Sdim const TemplateArgumentList &Args = Spec->getTemplateInstantiationArgs(); 443259701Sdim Out << '>'; 444259701Sdim for (unsigned I = 0, N = Args.size(); I != N; ++I) { 445259701Sdim Out << '#'; 446259701Sdim VisitTemplateArgument(Args.get(I)); 447259701Sdim } 448259701Sdim } 449259701Sdim} 450259701Sdim 451259701Sdimvoid USRGenerator::VisitTypedefDecl(const TypedefDecl *D) { 452259701Sdim if (ShouldGenerateLocation(D) && GenLoc(D)) 453259701Sdim return; 454259701Sdim const DeclContext *DC = D->getDeclContext(); 455259701Sdim if (const NamedDecl *DCN = dyn_cast<NamedDecl>(DC)) 456259701Sdim Visit(DCN); 457259701Sdim Out << "@T@"; 458259701Sdim Out << D->getName(); 459259701Sdim} 460259701Sdim 461259701Sdimvoid USRGenerator::VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D) { 462259701Sdim GenLoc(D); 463259701Sdim return; 464259701Sdim} 465259701Sdim 466259701Sdimbool USRGenerator::GenLoc(const Decl *D) { 467259701Sdim if (generatedLoc) 468259701Sdim return IgnoreResults; 469259701Sdim generatedLoc = true; 470259701Sdim 471259701Sdim // Guard against null declarations in invalid code. 472259701Sdim if (!D) { 473259701Sdim IgnoreResults = true; 474259701Sdim return true; 475259701Sdim } 476259701Sdim 477259701Sdim // Use the location of canonical decl. 478259701Sdim D = D->getCanonicalDecl(); 479259701Sdim 480259701Sdim const SourceManager &SM = Context->getSourceManager(); 481259701Sdim SourceLocation L = D->getLocStart(); 482259701Sdim if (L.isInvalid()) { 483259701Sdim IgnoreResults = true; 484259701Sdim return true; 485259701Sdim } 486259701Sdim L = SM.getExpansionLoc(L); 487259701Sdim const std::pair<FileID, unsigned> &Decomposed = SM.getDecomposedLoc(L); 488259701Sdim const FileEntry *FE = SM.getFileEntryForID(Decomposed.first); 489259701Sdim if (FE) { 490259701Sdim Out << llvm::sys::path::filename(FE->getName()); 491259701Sdim } 492259701Sdim else { 493259701Sdim // This case really isn't interesting. 494259701Sdim IgnoreResults = true; 495259701Sdim return true; 496259701Sdim } 497259701Sdim // Use the offest into the FileID to represent the location. Using 498259701Sdim // a line/column can cause us to look back at the original source file, 499259701Sdim // which is expensive. 500259701Sdim Out << '@' << Decomposed.second; 501259701Sdim return IgnoreResults; 502259701Sdim} 503259701Sdim 504259701Sdimvoid USRGenerator::VisitType(QualType T) { 505259701Sdim // This method mangles in USR information for types. It can possibly 506259701Sdim // just reuse the naming-mangling logic used by codegen, although the 507259701Sdim // requirements for USRs might not be the same. 508259701Sdim ASTContext &Ctx = *Context; 509259701Sdim 510259701Sdim do { 511259701Sdim T = Ctx.getCanonicalType(T); 512259701Sdim Qualifiers Q = T.getQualifiers(); 513259701Sdim unsigned qVal = 0; 514259701Sdim if (Q.hasConst()) 515259701Sdim qVal |= 0x1; 516259701Sdim if (Q.hasVolatile()) 517259701Sdim qVal |= 0x2; 518259701Sdim if (Q.hasRestrict()) 519259701Sdim qVal |= 0x4; 520259701Sdim if(qVal) 521259701Sdim Out << ((char) ('0' + qVal)); 522259701Sdim 523259701Sdim // Mangle in ObjC GC qualifiers? 524259701Sdim 525259701Sdim if (const PackExpansionType *Expansion = T->getAs<PackExpansionType>()) { 526259701Sdim Out << 'P'; 527259701Sdim T = Expansion->getPattern(); 528259701Sdim } 529259701Sdim 530259701Sdim if (const BuiltinType *BT = T->getAs<BuiltinType>()) { 531259701Sdim unsigned char c = '\0'; 532259701Sdim switch (BT->getKind()) { 533259701Sdim case BuiltinType::Void: 534259701Sdim c = 'v'; break; 535259701Sdim case BuiltinType::Bool: 536259701Sdim c = 'b'; break; 537259701Sdim case BuiltinType::Char_U: 538259701Sdim case BuiltinType::UChar: 539259701Sdim c = 'c'; break; 540259701Sdim case BuiltinType::Char16: 541259701Sdim c = 'q'; break; 542259701Sdim case BuiltinType::Char32: 543259701Sdim c = 'w'; break; 544259701Sdim case BuiltinType::UShort: 545259701Sdim c = 's'; break; 546259701Sdim case BuiltinType::UInt: 547259701Sdim c = 'i'; break; 548259701Sdim case BuiltinType::ULong: 549259701Sdim c = 'l'; break; 550259701Sdim case BuiltinType::ULongLong: 551259701Sdim c = 'k'; break; 552259701Sdim case BuiltinType::UInt128: 553259701Sdim c = 'j'; break; 554259701Sdim case BuiltinType::Char_S: 555259701Sdim case BuiltinType::SChar: 556259701Sdim c = 'C'; break; 557259701Sdim case BuiltinType::WChar_S: 558259701Sdim case BuiltinType::WChar_U: 559259701Sdim c = 'W'; break; 560259701Sdim case BuiltinType::Short: 561259701Sdim c = 'S'; break; 562259701Sdim case BuiltinType::Int: 563259701Sdim c = 'I'; break; 564259701Sdim case BuiltinType::Long: 565259701Sdim c = 'L'; break; 566259701Sdim case BuiltinType::LongLong: 567259701Sdim c = 'K'; break; 568259701Sdim case BuiltinType::Int128: 569259701Sdim c = 'J'; break; 570259701Sdim case BuiltinType::Half: 571259701Sdim c = 'h'; break; 572259701Sdim case BuiltinType::Float: 573259701Sdim c = 'f'; break; 574259701Sdim case BuiltinType::Double: 575259701Sdim c = 'd'; break; 576259701Sdim case BuiltinType::LongDouble: 577259701Sdim c = 'D'; break; 578259701Sdim case BuiltinType::NullPtr: 579259701Sdim c = 'n'; break; 580259701Sdim#define BUILTIN_TYPE(Id, SingletonId) 581259701Sdim#define PLACEHOLDER_TYPE(Id, SingletonId) case BuiltinType::Id: 582259701Sdim#include "clang/AST/BuiltinTypes.def" 583259701Sdim case BuiltinType::Dependent: 584259701Sdim case BuiltinType::OCLImage1d: 585259701Sdim case BuiltinType::OCLImage1dArray: 586259701Sdim case BuiltinType::OCLImage1dBuffer: 587259701Sdim case BuiltinType::OCLImage2d: 588259701Sdim case BuiltinType::OCLImage2dArray: 589259701Sdim case BuiltinType::OCLImage3d: 590259701Sdim case BuiltinType::OCLEvent: 591259701Sdim case BuiltinType::OCLSampler: 592259701Sdim IgnoreResults = true; 593259701Sdim return; 594259701Sdim case BuiltinType::ObjCId: 595259701Sdim c = 'o'; break; 596259701Sdim case BuiltinType::ObjCClass: 597259701Sdim c = 'O'; break; 598259701Sdim case BuiltinType::ObjCSel: 599259701Sdim c = 'e'; break; 600259701Sdim } 601259701Sdim Out << c; 602259701Sdim return; 603259701Sdim } 604259701Sdim 605259701Sdim // If we have already seen this (non-built-in) type, use a substitution 606259701Sdim // encoding. 607259701Sdim llvm::DenseMap<const Type *, unsigned>::iterator Substitution 608259701Sdim = TypeSubstitutions.find(T.getTypePtr()); 609259701Sdim if (Substitution != TypeSubstitutions.end()) { 610259701Sdim Out << 'S' << Substitution->second << '_'; 611259701Sdim return; 612259701Sdim } else { 613259701Sdim // Record this as a substitution. 614259701Sdim unsigned Number = TypeSubstitutions.size(); 615259701Sdim TypeSubstitutions[T.getTypePtr()] = Number; 616259701Sdim } 617259701Sdim 618259701Sdim if (const PointerType *PT = T->getAs<PointerType>()) { 619259701Sdim Out << '*'; 620259701Sdim T = PT->getPointeeType(); 621259701Sdim continue; 622259701Sdim } 623259701Sdim if (const ReferenceType *RT = T->getAs<ReferenceType>()) { 624259701Sdim Out << '&'; 625259701Sdim T = RT->getPointeeType(); 626259701Sdim continue; 627259701Sdim } 628259701Sdim if (const FunctionProtoType *FT = T->getAs<FunctionProtoType>()) { 629259701Sdim Out << 'F'; 630259701Sdim VisitType(FT->getResultType()); 631259701Sdim for (FunctionProtoType::arg_type_iterator 632259701Sdim I = FT->arg_type_begin(), E = FT->arg_type_end(); I!=E; ++I) { 633259701Sdim VisitType(*I); 634259701Sdim } 635259701Sdim if (FT->isVariadic()) 636259701Sdim Out << '.'; 637259701Sdim return; 638259701Sdim } 639259701Sdim if (const BlockPointerType *BT = T->getAs<BlockPointerType>()) { 640259701Sdim Out << 'B'; 641259701Sdim T = BT->getPointeeType(); 642259701Sdim continue; 643259701Sdim } 644259701Sdim if (const ComplexType *CT = T->getAs<ComplexType>()) { 645259701Sdim Out << '<'; 646259701Sdim T = CT->getElementType(); 647259701Sdim continue; 648259701Sdim } 649259701Sdim if (const TagType *TT = T->getAs<TagType>()) { 650259701Sdim Out << '$'; 651259701Sdim VisitTagDecl(TT->getDecl()); 652259701Sdim return; 653259701Sdim } 654259701Sdim if (const TemplateTypeParmType *TTP = T->getAs<TemplateTypeParmType>()) { 655259701Sdim Out << 't' << TTP->getDepth() << '.' << TTP->getIndex(); 656259701Sdim return; 657259701Sdim } 658259701Sdim if (const TemplateSpecializationType *Spec 659259701Sdim = T->getAs<TemplateSpecializationType>()) { 660259701Sdim Out << '>'; 661259701Sdim VisitTemplateName(Spec->getTemplateName()); 662259701Sdim Out << Spec->getNumArgs(); 663259701Sdim for (unsigned I = 0, N = Spec->getNumArgs(); I != N; ++I) 664259701Sdim VisitTemplateArgument(Spec->getArg(I)); 665259701Sdim return; 666259701Sdim } 667259701Sdim 668259701Sdim // Unhandled type. 669259701Sdim Out << ' '; 670259701Sdim break; 671259701Sdim } while (true); 672259701Sdim} 673259701Sdim 674259701Sdimvoid USRGenerator::VisitTemplateParameterList( 675259701Sdim const TemplateParameterList *Params) { 676259701Sdim if (!Params) 677259701Sdim return; 678259701Sdim Out << '>' << Params->size(); 679259701Sdim for (TemplateParameterList::const_iterator P = Params->begin(), 680259701Sdim PEnd = Params->end(); 681259701Sdim P != PEnd; ++P) { 682259701Sdim Out << '#'; 683259701Sdim if (isa<TemplateTypeParmDecl>(*P)) { 684259701Sdim if (cast<TemplateTypeParmDecl>(*P)->isParameterPack()) 685259701Sdim Out<< 'p'; 686259701Sdim Out << 'T'; 687259701Sdim continue; 688259701Sdim } 689259701Sdim 690259701Sdim if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(*P)) { 691259701Sdim if (NTTP->isParameterPack()) 692259701Sdim Out << 'p'; 693259701Sdim Out << 'N'; 694259701Sdim VisitType(NTTP->getType()); 695259701Sdim continue; 696259701Sdim } 697259701Sdim 698259701Sdim TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*P); 699259701Sdim if (TTP->isParameterPack()) 700259701Sdim Out << 'p'; 701259701Sdim Out << 't'; 702259701Sdim VisitTemplateParameterList(TTP->getTemplateParameters()); 703259701Sdim } 704259701Sdim} 705259701Sdim 706259701Sdimvoid USRGenerator::VisitTemplateName(TemplateName Name) { 707259701Sdim if (TemplateDecl *Template = Name.getAsTemplateDecl()) { 708259701Sdim if (TemplateTemplateParmDecl *TTP 709259701Sdim = dyn_cast<TemplateTemplateParmDecl>(Template)) { 710259701Sdim Out << 't' << TTP->getDepth() << '.' << TTP->getIndex(); 711259701Sdim return; 712259701Sdim } 713259701Sdim 714259701Sdim Visit(Template); 715259701Sdim return; 716259701Sdim } 717259701Sdim 718259701Sdim // FIXME: Visit dependent template names. 719259701Sdim} 720259701Sdim 721259701Sdimvoid USRGenerator::VisitTemplateArgument(const TemplateArgument &Arg) { 722259701Sdim switch (Arg.getKind()) { 723259701Sdim case TemplateArgument::Null: 724259701Sdim break; 725259701Sdim 726259701Sdim case TemplateArgument::Declaration: 727259701Sdim Visit(Arg.getAsDecl()); 728259701Sdim break; 729259701Sdim 730259701Sdim case TemplateArgument::NullPtr: 731259701Sdim break; 732259701Sdim 733259701Sdim case TemplateArgument::TemplateExpansion: 734259701Sdim Out << 'P'; // pack expansion of... 735259701Sdim // Fall through 736259701Sdim case TemplateArgument::Template: 737259701Sdim VisitTemplateName(Arg.getAsTemplateOrTemplatePattern()); 738259701Sdim break; 739259701Sdim 740259701Sdim case TemplateArgument::Expression: 741259701Sdim // FIXME: Visit expressions. 742259701Sdim break; 743259701Sdim 744259701Sdim case TemplateArgument::Pack: 745259701Sdim Out << 'p' << Arg.pack_size(); 746259701Sdim for (TemplateArgument::pack_iterator P = Arg.pack_begin(), PEnd = Arg.pack_end(); 747259701Sdim P != PEnd; ++P) 748259701Sdim VisitTemplateArgument(*P); 749259701Sdim break; 750259701Sdim 751259701Sdim case TemplateArgument::Type: 752259701Sdim VisitType(Arg.getAsType()); 753259701Sdim break; 754259701Sdim 755259701Sdim case TemplateArgument::Integral: 756259701Sdim Out << 'V'; 757259701Sdim VisitType(Arg.getIntegralType()); 758259701Sdim Out << Arg.getAsIntegral(); 759259701Sdim break; 760259701Sdim } 761259701Sdim} 762259701Sdim 763259701Sdim//===----------------------------------------------------------------------===// 764259701Sdim// USR generation functions. 765259701Sdim//===----------------------------------------------------------------------===// 766259701Sdim 767259701Sdimvoid clang::index::generateUSRForObjCClass(StringRef Cls, raw_ostream &OS) { 768259701Sdim OS << "objc(cs)" << Cls; 769259701Sdim} 770259701Sdim 771259701Sdimvoid clang::index::generateUSRForObjCCategory(StringRef Cls, StringRef Cat, 772259701Sdim raw_ostream &OS) { 773259701Sdim OS << "objc(cy)" << Cls << '@' << Cat; 774259701Sdim} 775259701Sdim 776259701Sdimvoid clang::index::generateUSRForObjCIvar(StringRef Ivar, raw_ostream &OS) { 777259701Sdim OS << '@' << Ivar; 778259701Sdim} 779259701Sdim 780259701Sdimvoid clang::index::generateUSRForObjCMethod(StringRef Sel, 781259701Sdim bool IsInstanceMethod, 782259701Sdim raw_ostream &OS) { 783259701Sdim OS << (IsInstanceMethod ? "(im)" : "(cm)") << Sel; 784259701Sdim} 785259701Sdim 786259701Sdimvoid clang::index::generateUSRForObjCProperty(StringRef Prop, raw_ostream &OS) { 787259701Sdim OS << "(py)" << Prop; 788259701Sdim} 789259701Sdim 790259701Sdimvoid clang::index::generateUSRForObjCProtocol(StringRef Prot, raw_ostream &OS) { 791259701Sdim OS << "objc(pl)" << Prot; 792259701Sdim} 793259701Sdim 794259701Sdimbool clang::index::generateUSRForDecl(const Decl *D, 795259701Sdim SmallVectorImpl<char> &Buf) { 796259701Sdim // Don't generate USRs for things with invalid locations. 797259701Sdim if (!D || D->getLocStart().isInvalid()) 798259701Sdim return true; 799259701Sdim 800259701Sdim USRGenerator UG(&D->getASTContext(), Buf); 801259701Sdim UG.Visit(D); 802259701Sdim return UG.ignoreResults(); 803259701Sdim} 804