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