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