1//===- USRGeneration.cpp - Routines for USR generation --------------------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9 10#include "clang/Index/USRGeneration.h" 11#include "clang/AST/ASTContext.h" 12#include "clang/AST/DeclTemplate.h" 13#include "clang/AST/DeclVisitor.h" 14#include "clang/Lex/PreprocessingRecord.h" 15#include "llvm/ADT/SmallString.h" 16#include "llvm/Support/Path.h" 17#include "llvm/Support/raw_ostream.h" 18 19using namespace clang; 20using namespace clang::index; 21 22//===----------------------------------------------------------------------===// 23// USR generation. 24//===----------------------------------------------------------------------===// 25 26/// \returns true on error. 27static bool printLoc(llvm::raw_ostream &OS, SourceLocation Loc, 28 const SourceManager &SM, bool IncludeOffset) { 29 if (Loc.isInvalid()) { 30 return true; 31 } 32 Loc = SM.getExpansionLoc(Loc); 33 const std::pair<FileID, unsigned> &Decomposed = SM.getDecomposedLoc(Loc); 34 const FileEntry *FE = SM.getFileEntryForID(Decomposed.first); 35 if (FE) { 36 OS << llvm::sys::path::filename(FE->getName()); 37 } else { 38 // This case really isn't interesting. 39 return true; 40 } 41 if (IncludeOffset) { 42 // Use the offest into the FileID to represent the location. Using 43 // a line/column can cause us to look back at the original source file, 44 // which is expensive. 45 OS << '@' << Decomposed.second; 46 } 47 return false; 48} 49 50namespace { 51class USRGenerator : public ConstDeclVisitor<USRGenerator> { 52 SmallVectorImpl<char> &Buf; 53 llvm::raw_svector_ostream Out; 54 bool IgnoreResults; 55 ASTContext *Context; 56 bool generatedLoc; 57 58 llvm::DenseMap<const Type *, unsigned> TypeSubstitutions; 59 60public: 61 explicit USRGenerator(ASTContext *Ctx, SmallVectorImpl<char> &Buf) 62 : Buf(Buf), 63 Out(Buf), 64 IgnoreResults(false), 65 Context(Ctx), 66 generatedLoc(false) 67 { 68 // Add the USR space prefix. 69 Out << getUSRSpacePrefix(); 70 } 71 72 bool ignoreResults() const { return IgnoreResults; } 73 74 // Visitation methods from generating USRs from AST elements. 75 void VisitDeclContext(const DeclContext *D); 76 void VisitFieldDecl(const FieldDecl *D); 77 void VisitFunctionDecl(const FunctionDecl *D); 78 void VisitNamedDecl(const NamedDecl *D); 79 void VisitNamespaceDecl(const NamespaceDecl *D); 80 void VisitNamespaceAliasDecl(const NamespaceAliasDecl *D); 81 void VisitFunctionTemplateDecl(const FunctionTemplateDecl *D); 82 void VisitClassTemplateDecl(const ClassTemplateDecl *D); 83 void VisitObjCContainerDecl(const ObjCContainerDecl *CD); 84 void VisitObjCMethodDecl(const ObjCMethodDecl *MD); 85 void VisitObjCPropertyDecl(const ObjCPropertyDecl *D); 86 void VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D); 87 void VisitTagDecl(const TagDecl *D); 88 void VisitTypedefDecl(const TypedefDecl *D); 89 void VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D); 90 void VisitVarDecl(const VarDecl *D); 91 void VisitNonTypeTemplateParmDecl(const NonTypeTemplateParmDecl *D); 92 void VisitTemplateTemplateParmDecl(const TemplateTemplateParmDecl *D); 93 void VisitLinkageSpecDecl(const LinkageSpecDecl *D) { 94 IgnoreResults = true; 95 } 96 void VisitUsingDirectiveDecl(const UsingDirectiveDecl *D) { 97 IgnoreResults = true; 98 } 99 void VisitUsingDecl(const UsingDecl *D) { 100 IgnoreResults = true; 101 } 102 void VisitUnresolvedUsingValueDecl(const UnresolvedUsingValueDecl *D) { 103 IgnoreResults = true; 104 } 105 void VisitUnresolvedUsingTypenameDecl(const UnresolvedUsingTypenameDecl *D) { 106 IgnoreResults = true; 107 } 108 109 bool ShouldGenerateLocation(const NamedDecl *D); 110 111 bool isLocal(const NamedDecl *D) { 112 return D->getParentFunctionOrMethod() != nullptr; 113 } 114 115 /// Generate the string component containing the location of the 116 /// declaration. 117 bool GenLoc(const Decl *D, bool IncludeOffset); 118 119 /// String generation methods used both by the visitation methods 120 /// and from other clients that want to directly generate USRs. These 121 /// methods do not construct complete USRs (which incorporate the parents 122 /// of an AST element), but only the fragments concerning the AST element 123 /// itself. 124 125 /// Generate a USR for an Objective-C class. 126 void GenObjCClass(StringRef cls) { 127 generateUSRForObjCClass(cls, Out); 128 } 129 /// Generate a USR for an Objective-C class category. 130 void GenObjCCategory(StringRef cls, StringRef cat) { 131 generateUSRForObjCCategory(cls, cat, Out); 132 } 133 /// Generate a USR fragment for an Objective-C property. 134 void GenObjCProperty(StringRef prop) { 135 generateUSRForObjCProperty(prop, Out); 136 } 137 /// Generate a USR for an Objective-C protocol. 138 void GenObjCProtocol(StringRef prot) { 139 generateUSRForObjCProtocol(prot, Out); 140 } 141 142 void VisitType(QualType T); 143 void VisitTemplateParameterList(const TemplateParameterList *Params); 144 void VisitTemplateName(TemplateName Name); 145 void VisitTemplateArgument(const TemplateArgument &Arg); 146 147 /// Emit a Decl's name using NamedDecl::printName() and return true if 148 /// the decl had no name. 149 bool EmitDeclName(const NamedDecl *D); 150}; 151 152} // end anonymous namespace 153 154//===----------------------------------------------------------------------===// 155// Generating USRs from ASTS. 156//===----------------------------------------------------------------------===// 157 158bool USRGenerator::EmitDeclName(const NamedDecl *D) { 159 Out.flush(); 160 const unsigned startSize = Buf.size(); 161 D->printName(Out); 162 Out.flush(); 163 const unsigned endSize = Buf.size(); 164 return startSize == endSize; 165} 166 167bool USRGenerator::ShouldGenerateLocation(const NamedDecl *D) { 168 if (D->isExternallyVisible()) 169 return false; 170 if (D->getParentFunctionOrMethod()) 171 return true; 172 const SourceManager &SM = Context->getSourceManager(); 173 return !SM.isInSystemHeader(D->getLocation()); 174} 175 176void USRGenerator::VisitDeclContext(const DeclContext *DC) { 177 if (const NamedDecl *D = dyn_cast<NamedDecl>(DC)) 178 Visit(D); 179} 180 181void USRGenerator::VisitFieldDecl(const FieldDecl *D) { 182 // The USR for an ivar declared in a class extension is based on the 183 // ObjCInterfaceDecl, not the ObjCCategoryDecl. 184 if (const ObjCInterfaceDecl *ID = Context->getObjContainingInterface(D)) 185 Visit(ID); 186 else 187 VisitDeclContext(D->getDeclContext()); 188 Out << (isa<ObjCIvarDecl>(D) ? "@" : "@FI@"); 189 if (EmitDeclName(D)) { 190 // Bit fields can be anonymous. 191 IgnoreResults = true; 192 return; 193 } 194} 195 196void USRGenerator::VisitFunctionDecl(const FunctionDecl *D) { 197 if (ShouldGenerateLocation(D) && GenLoc(D, /*IncludeOffset=*/isLocal(D))) 198 return; 199 200 VisitDeclContext(D->getDeclContext()); 201 bool IsTemplate = false; 202 if (FunctionTemplateDecl *FunTmpl = D->getDescribedFunctionTemplate()) { 203 IsTemplate = true; 204 Out << "@FT@"; 205 VisitTemplateParameterList(FunTmpl->getTemplateParameters()); 206 } else 207 Out << "@F@"; 208 D->printName(Out); 209 210 ASTContext &Ctx = *Context; 211 if (!Ctx.getLangOpts().CPlusPlus || D->isExternC()) 212 return; 213 214 if (const TemplateArgumentList * 215 SpecArgs = D->getTemplateSpecializationArgs()) { 216 Out << '<'; 217 for (unsigned I = 0, N = SpecArgs->size(); I != N; ++I) { 218 Out << '#'; 219 VisitTemplateArgument(SpecArgs->get(I)); 220 } 221 Out << '>'; 222 } 223 224 // Mangle in type information for the arguments. 225 for (auto PD : D->params()) { 226 Out << '#'; 227 VisitType(PD->getType()); 228 } 229 if (D->isVariadic()) 230 Out << '.'; 231 if (IsTemplate) { 232 // Function templates can be overloaded by return type, for example: 233 // \code 234 // template <class T> typename T::A foo() {} 235 // template <class T> typename T::B foo() {} 236 // \endcode 237 Out << '#'; 238 VisitType(D->getReturnType()); 239 } 240 Out << '#'; 241 if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) { 242 if (MD->isStatic()) 243 Out << 'S'; 244 if (unsigned quals = MD->getTypeQualifiers()) 245 Out << (char)('0' + quals); 246 switch (MD->getRefQualifier()) { 247 case RQ_None: break; 248 case RQ_LValue: Out << '&'; break; 249 case RQ_RValue: Out << "&&"; break; 250 } 251 } 252} 253 254void USRGenerator::VisitNamedDecl(const NamedDecl *D) { 255 VisitDeclContext(D->getDeclContext()); 256 Out << "@"; 257 258 if (EmitDeclName(D)) { 259 // The string can be empty if the declaration has no name; e.g., it is 260 // the ParmDecl with no name for declaration of a function pointer type, 261 // e.g.: void (*f)(void *); 262 // In this case, don't generate a USR. 263 IgnoreResults = true; 264 } 265} 266 267void USRGenerator::VisitVarDecl(const VarDecl *D) { 268 // VarDecls can be declared 'extern' within a function or method body, 269 // but their enclosing DeclContext is the function, not the TU. We need 270 // to check the storage class to correctly generate the USR. 271 if (ShouldGenerateLocation(D) && GenLoc(D, /*IncludeOffset=*/isLocal(D))) 272 return; 273 274 VisitDeclContext(D->getDeclContext()); 275 276 // Variables always have simple names. 277 StringRef s = D->getName(); 278 279 // The string can be empty if the declaration has no name; e.g., it is 280 // the ParmDecl with no name for declaration of a function pointer type, e.g.: 281 // void (*f)(void *); 282 // In this case, don't generate a USR. 283 if (s.empty()) 284 IgnoreResults = true; 285 else 286 Out << '@' << s; 287} 288 289void USRGenerator::VisitNonTypeTemplateParmDecl( 290 const NonTypeTemplateParmDecl *D) { 291 GenLoc(D, /*IncludeOffset=*/true); 292 return; 293} 294 295void USRGenerator::VisitTemplateTemplateParmDecl( 296 const TemplateTemplateParmDecl *D) { 297 GenLoc(D, /*IncludeOffset=*/true); 298 return; 299} 300 301void USRGenerator::VisitNamespaceDecl(const NamespaceDecl *D) { 302 if (D->isAnonymousNamespace()) { 303 Out << "@aN"; 304 return; 305 } 306 307 VisitDeclContext(D->getDeclContext()); 308 if (!IgnoreResults) 309 Out << "@N@" << D->getName(); 310} 311 312void USRGenerator::VisitFunctionTemplateDecl(const FunctionTemplateDecl *D) { 313 VisitFunctionDecl(D->getTemplatedDecl()); 314} 315 316void USRGenerator::VisitClassTemplateDecl(const ClassTemplateDecl *D) { 317 VisitTagDecl(D->getTemplatedDecl()); 318} 319 320void USRGenerator::VisitNamespaceAliasDecl(const NamespaceAliasDecl *D) { 321 VisitDeclContext(D->getDeclContext()); 322 if (!IgnoreResults) 323 Out << "@NA@" << D->getName(); 324} 325 326void USRGenerator::VisitObjCMethodDecl(const ObjCMethodDecl *D) { 327 const DeclContext *container = D->getDeclContext(); 328 if (const ObjCProtocolDecl *pd = dyn_cast<ObjCProtocolDecl>(container)) { 329 Visit(pd); 330 } 331 else { 332 // The USR for a method declared in a class extension or category is based on 333 // the ObjCInterfaceDecl, not the ObjCCategoryDecl. 334 const ObjCInterfaceDecl *ID = D->getClassInterface(); 335 if (!ID) { 336 IgnoreResults = true; 337 return; 338 } 339 Visit(ID); 340 } 341 // Ideally we would use 'GenObjCMethod', but this is such a hot path 342 // for Objective-C code that we don't want to use 343 // DeclarationName::getAsString(). 344 Out << (D->isInstanceMethod() ? "(im)" : "(cm)") 345 << DeclarationName(D->getSelector()); 346} 347 348void USRGenerator::VisitObjCContainerDecl(const ObjCContainerDecl *D) { 349 switch (D->getKind()) { 350 default: 351 llvm_unreachable("Invalid ObjC container."); 352 case Decl::ObjCInterface: 353 case Decl::ObjCImplementation: 354 GenObjCClass(D->getName()); 355 break; 356 case Decl::ObjCCategory: { 357 const ObjCCategoryDecl *CD = cast<ObjCCategoryDecl>(D); 358 const ObjCInterfaceDecl *ID = CD->getClassInterface(); 359 if (!ID) { 360 // Handle invalid code where the @interface might not 361 // have been specified. 362 // FIXME: We should be able to generate this USR even if the 363 // @interface isn't available. 364 IgnoreResults = true; 365 return; 366 } 367 // Specially handle class extensions, which are anonymous categories. 368 // We want to mangle in the location to uniquely distinguish them. 369 if (CD->IsClassExtension()) { 370 Out << "objc(ext)" << ID->getName() << '@'; 371 GenLoc(CD, /*IncludeOffset=*/true); 372 } 373 else 374 GenObjCCategory(ID->getName(), CD->getName()); 375 376 break; 377 } 378 case Decl::ObjCCategoryImpl: { 379 const ObjCCategoryImplDecl *CD = cast<ObjCCategoryImplDecl>(D); 380 const ObjCInterfaceDecl *ID = CD->getClassInterface(); 381 if (!ID) { 382 // Handle invalid code where the @interface might not 383 // have been specified. 384 // FIXME: We should be able to generate this USR even if the 385 // @interface isn't available. 386 IgnoreResults = true; 387 return; 388 } 389 GenObjCCategory(ID->getName(), CD->getName()); 390 break; 391 } 392 case Decl::ObjCProtocol: 393 GenObjCProtocol(cast<ObjCProtocolDecl>(D)->getName()); 394 break; 395 } 396} 397 398void USRGenerator::VisitObjCPropertyDecl(const ObjCPropertyDecl *D) { 399 // The USR for a property declared in a class extension or category is based 400 // on the ObjCInterfaceDecl, not the ObjCCategoryDecl. 401 if (const ObjCInterfaceDecl *ID = Context->getObjContainingInterface(D)) 402 Visit(ID); 403 else 404 Visit(cast<Decl>(D->getDeclContext())); 405 GenObjCProperty(D->getName()); 406} 407 408void USRGenerator::VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D) { 409 if (ObjCPropertyDecl *PD = D->getPropertyDecl()) { 410 VisitObjCPropertyDecl(PD); 411 return; 412 } 413 414 IgnoreResults = true; 415} 416 417void USRGenerator::VisitTagDecl(const TagDecl *D) { 418 // Add the location of the tag decl to handle resolution across 419 // translation units. 420 if (ShouldGenerateLocation(D) && GenLoc(D, /*IncludeOffset=*/isLocal(D))) 421 return; 422 423 D = D->getCanonicalDecl(); 424 VisitDeclContext(D->getDeclContext()); 425 426 bool AlreadyStarted = false; 427 if (const CXXRecordDecl *CXXRecord = dyn_cast<CXXRecordDecl>(D)) { 428 if (ClassTemplateDecl *ClassTmpl = CXXRecord->getDescribedClassTemplate()) { 429 AlreadyStarted = true; 430 431 switch (D->getTagKind()) { 432 case TTK_Interface: 433 case TTK_Class: 434 case TTK_Struct: Out << "@ST"; break; 435 case TTK_Union: Out << "@UT"; break; 436 case TTK_Enum: llvm_unreachable("enum template"); 437 } 438 VisitTemplateParameterList(ClassTmpl->getTemplateParameters()); 439 } else if (const ClassTemplatePartialSpecializationDecl *PartialSpec 440 = dyn_cast<ClassTemplatePartialSpecializationDecl>(CXXRecord)) { 441 AlreadyStarted = true; 442 443 switch (D->getTagKind()) { 444 case TTK_Interface: 445 case TTK_Class: 446 case TTK_Struct: Out << "@SP"; break; 447 case TTK_Union: Out << "@UP"; break; 448 case TTK_Enum: llvm_unreachable("enum partial specialization"); 449 } 450 VisitTemplateParameterList(PartialSpec->getTemplateParameters()); 451 } 452 } 453 454 if (!AlreadyStarted) { 455 switch (D->getTagKind()) { 456 case TTK_Interface: 457 case TTK_Class: 458 case TTK_Struct: Out << "@S"; break; 459 case TTK_Union: Out << "@U"; break; 460 case TTK_Enum: Out << "@E"; break; 461 } 462 } 463 464 Out << '@'; 465 Out.flush(); 466 assert(Buf.size() > 0); 467 const unsigned off = Buf.size() - 1; 468 469 if (EmitDeclName(D)) { 470 if (const TypedefNameDecl *TD = D->getTypedefNameForAnonDecl()) { 471 Buf[off] = 'A'; 472 Out << '@' << *TD; 473 } 474 else { 475 if (D->isEmbeddedInDeclarator() && !D->isFreeStanding()) { 476 printLoc(Out, D->getLocation(), Context->getSourceManager(), true); 477 } else 478 Buf[off] = 'a'; 479 } 480 } 481 482 // For a class template specialization, mangle the template arguments. 483 if (const ClassTemplateSpecializationDecl *Spec 484 = dyn_cast<ClassTemplateSpecializationDecl>(D)) { 485 const TemplateArgumentList &Args = Spec->getTemplateInstantiationArgs(); 486 Out << '>'; 487 for (unsigned I = 0, N = Args.size(); I != N; ++I) { 488 Out << '#'; 489 VisitTemplateArgument(Args.get(I)); 490 } 491 } 492} 493 494void USRGenerator::VisitTypedefDecl(const TypedefDecl *D) { 495 if (ShouldGenerateLocation(D) && GenLoc(D, /*IncludeOffset=*/isLocal(D))) 496 return; 497 const DeclContext *DC = D->getDeclContext(); 498 if (const NamedDecl *DCN = dyn_cast<NamedDecl>(DC)) 499 Visit(DCN); 500 Out << "@T@"; 501 Out << D->getName(); 502} 503 504void USRGenerator::VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D) { 505 GenLoc(D, /*IncludeOffset=*/true); 506 return; 507} 508 509bool USRGenerator::GenLoc(const Decl *D, bool IncludeOffset) { 510 if (generatedLoc) 511 return IgnoreResults; 512 generatedLoc = true; 513 514 // Guard against null declarations in invalid code. 515 if (!D) { 516 IgnoreResults = true; 517 return true; 518 } 519 520 // Use the location of canonical decl. 521 D = D->getCanonicalDecl(); 522 523 IgnoreResults = 524 IgnoreResults || printLoc(Out, D->getLocStart(), 525 Context->getSourceManager(), IncludeOffset); 526 527 return IgnoreResults; 528} 529 530void USRGenerator::VisitType(QualType T) { 531 // This method mangles in USR information for types. It can possibly 532 // just reuse the naming-mangling logic used by codegen, although the 533 // requirements for USRs might not be the same. 534 ASTContext &Ctx = *Context; 535 536 do { 537 T = Ctx.getCanonicalType(T); 538 Qualifiers Q = T.getQualifiers(); 539 unsigned qVal = 0; 540 if (Q.hasConst()) 541 qVal |= 0x1; 542 if (Q.hasVolatile()) 543 qVal |= 0x2; 544 if (Q.hasRestrict()) 545 qVal |= 0x4; 546 if(qVal) 547 Out << ((char) ('0' + qVal)); 548 549 // Mangle in ObjC GC qualifiers? 550 551 if (const PackExpansionType *Expansion = T->getAs<PackExpansionType>()) { 552 Out << 'P'; 553 T = Expansion->getPattern(); 554 } 555 556 if (const BuiltinType *BT = T->getAs<BuiltinType>()) { 557 unsigned char c = '\0'; 558 switch (BT->getKind()) { 559 case BuiltinType::Void: 560 c = 'v'; break; 561 case BuiltinType::Bool: 562 c = 'b'; break; 563 case BuiltinType::UChar: 564 c = 'c'; break; 565 case BuiltinType::Char16: 566 c = 'q'; break; 567 case BuiltinType::Char32: 568 c = 'w'; break; 569 case BuiltinType::UShort: 570 c = 's'; break; 571 case BuiltinType::UInt: 572 c = 'i'; break; 573 case BuiltinType::ULong: 574 c = 'l'; break; 575 case BuiltinType::ULongLong: 576 c = 'k'; break; 577 case BuiltinType::UInt128: 578 c = 'j'; break; 579 case BuiltinType::Char_U: 580 case BuiltinType::Char_S: 581 c = 'C'; break; 582 case BuiltinType::SChar: 583 c = 'r'; break; 584 case BuiltinType::WChar_S: 585 case BuiltinType::WChar_U: 586 c = 'W'; break; 587 case BuiltinType::Short: 588 c = 'S'; break; 589 case BuiltinType::Int: 590 c = 'I'; break; 591 case BuiltinType::Long: 592 c = 'L'; break; 593 case BuiltinType::LongLong: 594 c = 'K'; break; 595 case BuiltinType::Int128: 596 c = 'J'; break; 597 case BuiltinType::Half: 598 c = 'h'; break; 599 case BuiltinType::Float: 600 c = 'f'; break; 601 case BuiltinType::Double: 602 c = 'd'; break; 603 case BuiltinType::LongDouble: 604 c = 'D'; break; 605 case BuiltinType::NullPtr: 606 c = 'n'; break; 607#define BUILTIN_TYPE(Id, SingletonId) 608#define PLACEHOLDER_TYPE(Id, SingletonId) case BuiltinType::Id: 609#include "clang/AST/BuiltinTypes.def" 610 case BuiltinType::Dependent: 611 case BuiltinType::OCLImage1d: 612 case BuiltinType::OCLImage1dArray: 613 case BuiltinType::OCLImage1dBuffer: 614 case BuiltinType::OCLImage2d: 615 case BuiltinType::OCLImage2dArray: 616 case BuiltinType::OCLImage3d: 617 case BuiltinType::OCLEvent: 618 case BuiltinType::OCLSampler: 619 IgnoreResults = true; 620 return; 621 case BuiltinType::ObjCId: 622 c = 'o'; break; 623 case BuiltinType::ObjCClass: 624 c = 'O'; break; 625 case BuiltinType::ObjCSel: 626 c = 'e'; break; 627 } 628 Out << c; 629 return; 630 } 631 632 // If we have already seen this (non-built-in) type, use a substitution 633 // encoding. 634 llvm::DenseMap<const Type *, unsigned>::iterator Substitution 635 = TypeSubstitutions.find(T.getTypePtr()); 636 if (Substitution != TypeSubstitutions.end()) { 637 Out << 'S' << Substitution->second << '_'; 638 return; 639 } else { 640 // Record this as a substitution. 641 unsigned Number = TypeSubstitutions.size(); 642 TypeSubstitutions[T.getTypePtr()] = Number; 643 } 644 645 if (const PointerType *PT = T->getAs<PointerType>()) { 646 Out << '*'; 647 T = PT->getPointeeType(); 648 continue; 649 } 650 if (const RValueReferenceType *RT = T->getAs<RValueReferenceType>()) { 651 Out << "&&"; 652 T = RT->getPointeeType(); 653 continue; 654 } 655 if (const ReferenceType *RT = T->getAs<ReferenceType>()) { 656 Out << '&'; 657 T = RT->getPointeeType(); 658 continue; 659 } 660 if (const FunctionProtoType *FT = T->getAs<FunctionProtoType>()) { 661 Out << 'F'; 662 VisitType(FT->getReturnType()); 663 for (const auto &I : FT->param_types()) 664 VisitType(I); 665 if (FT->isVariadic()) 666 Out << '.'; 667 return; 668 } 669 if (const BlockPointerType *BT = T->getAs<BlockPointerType>()) { 670 Out << 'B'; 671 T = BT->getPointeeType(); 672 continue; 673 } 674 if (const ComplexType *CT = T->getAs<ComplexType>()) { 675 Out << '<'; 676 T = CT->getElementType(); 677 continue; 678 } 679 if (const TagType *TT = T->getAs<TagType>()) { 680 Out << '$'; 681 VisitTagDecl(TT->getDecl()); 682 return; 683 } 684 if (const TemplateTypeParmType *TTP = T->getAs<TemplateTypeParmType>()) { 685 Out << 't' << TTP->getDepth() << '.' << TTP->getIndex(); 686 return; 687 } 688 if (const TemplateSpecializationType *Spec 689 = T->getAs<TemplateSpecializationType>()) { 690 Out << '>'; 691 VisitTemplateName(Spec->getTemplateName()); 692 Out << Spec->getNumArgs(); 693 for (unsigned I = 0, N = Spec->getNumArgs(); I != N; ++I) 694 VisitTemplateArgument(Spec->getArg(I)); 695 return; 696 } 697 if (const DependentNameType *DNT = T->getAs<DependentNameType>()) { 698 Out << '^'; 699 // FIXME: Encode the qualifier, don't just print it. 700 PrintingPolicy PO(Ctx.getLangOpts()); 701 PO.SuppressTagKeyword = true; 702 PO.SuppressUnwrittenScope = true; 703 PO.ConstantArraySizeAsWritten = false; 704 PO.AnonymousTagLocations = false; 705 DNT->getQualifier()->print(Out, PO); 706 Out << ':' << DNT->getIdentifier()->getName(); 707 return; 708 } 709 if (const InjectedClassNameType *InjT = T->getAs<InjectedClassNameType>()) { 710 T = InjT->getInjectedSpecializationType(); 711 continue; 712 } 713 714 // Unhandled type. 715 Out << ' '; 716 break; 717 } while (true); 718} 719 720void USRGenerator::VisitTemplateParameterList( 721 const TemplateParameterList *Params) { 722 if (!Params) 723 return; 724 Out << '>' << Params->size(); 725 for (TemplateParameterList::const_iterator P = Params->begin(), 726 PEnd = Params->end(); 727 P != PEnd; ++P) { 728 Out << '#'; 729 if (isa<TemplateTypeParmDecl>(*P)) { 730 if (cast<TemplateTypeParmDecl>(*P)->isParameterPack()) 731 Out<< 'p'; 732 Out << 'T'; 733 continue; 734 } 735 736 if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(*P)) { 737 if (NTTP->isParameterPack()) 738 Out << 'p'; 739 Out << 'N'; 740 VisitType(NTTP->getType()); 741 continue; 742 } 743 744 TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*P); 745 if (TTP->isParameterPack()) 746 Out << 'p'; 747 Out << 't'; 748 VisitTemplateParameterList(TTP->getTemplateParameters()); 749 } 750} 751 752void USRGenerator::VisitTemplateName(TemplateName Name) { 753 if (TemplateDecl *Template = Name.getAsTemplateDecl()) { 754 if (TemplateTemplateParmDecl *TTP 755 = dyn_cast<TemplateTemplateParmDecl>(Template)) { 756 Out << 't' << TTP->getDepth() << '.' << TTP->getIndex(); 757 return; 758 } 759 760 Visit(Template); 761 return; 762 } 763 764 // FIXME: Visit dependent template names. 765} 766 767void USRGenerator::VisitTemplateArgument(const TemplateArgument &Arg) { 768 switch (Arg.getKind()) { 769 case TemplateArgument::Null: 770 break; 771 772 case TemplateArgument::Declaration: 773 Visit(Arg.getAsDecl()); 774 break; 775 776 case TemplateArgument::NullPtr: 777 break; 778 779 case TemplateArgument::TemplateExpansion: 780 Out << 'P'; // pack expansion of... 781 // Fall through 782 case TemplateArgument::Template: 783 VisitTemplateName(Arg.getAsTemplateOrTemplatePattern()); 784 break; 785 786 case TemplateArgument::Expression: 787 // FIXME: Visit expressions. 788 break; 789 790 case TemplateArgument::Pack: 791 Out << 'p' << Arg.pack_size(); 792 for (const auto &P : Arg.pack_elements()) 793 VisitTemplateArgument(P); 794 break; 795 796 case TemplateArgument::Type: 797 VisitType(Arg.getAsType()); 798 break; 799 800 case TemplateArgument::Integral: 801 Out << 'V'; 802 VisitType(Arg.getIntegralType()); 803 Out << Arg.getAsIntegral(); 804 break; 805 } 806} 807 808//===----------------------------------------------------------------------===// 809// USR generation functions. 810//===----------------------------------------------------------------------===// 811 812void clang::index::generateUSRForObjCClass(StringRef Cls, raw_ostream &OS) { 813 OS << "objc(cs)" << Cls; 814} 815 816void clang::index::generateUSRForObjCCategory(StringRef Cls, StringRef Cat, 817 raw_ostream &OS) { 818 OS << "objc(cy)" << Cls << '@' << Cat; 819} 820 821void clang::index::generateUSRForObjCIvar(StringRef Ivar, raw_ostream &OS) { 822 OS << '@' << Ivar; 823} 824 825void clang::index::generateUSRForObjCMethod(StringRef Sel, 826 bool IsInstanceMethod, 827 raw_ostream &OS) { 828 OS << (IsInstanceMethod ? "(im)" : "(cm)") << Sel; 829} 830 831void clang::index::generateUSRForObjCProperty(StringRef Prop, raw_ostream &OS) { 832 OS << "(py)" << Prop; 833} 834 835void clang::index::generateUSRForObjCProtocol(StringRef Prot, raw_ostream &OS) { 836 OS << "objc(pl)" << Prot; 837} 838 839bool clang::index::generateUSRForDecl(const Decl *D, 840 SmallVectorImpl<char> &Buf) { 841 // Don't generate USRs for things with invalid locations. 842 if (!D || D->getLocStart().isInvalid()) 843 return true; 844 845 USRGenerator UG(&D->getASTContext(), Buf); 846 UG.Visit(D); 847 return UG.ignoreResults(); 848} 849 850bool clang::index::generateUSRForMacro(const MacroDefinition *MD, 851 const SourceManager &SM, 852 SmallVectorImpl<char> &Buf) { 853 // Don't generate USRs for things with invalid locations. 854 if (!MD || MD->getLocation().isInvalid()) 855 return true; 856 857 llvm::raw_svector_ostream Out(Buf); 858 859 // Assume that system headers are sane. Don't put source location 860 // information into the USR if the macro comes from a system header. 861 SourceLocation Loc = MD->getLocation(); 862 bool ShouldGenerateLocation = !SM.isInSystemHeader(Loc); 863 864 Out << getUSRSpacePrefix(); 865 if (ShouldGenerateLocation) 866 printLoc(Out, Loc, SM, /*IncludeOffset=*/true); 867 Out << "@macro@"; 868 Out << MD->getName()->getName(); 869 return false; 870} 871 872