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