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