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