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