CIndexUSRs.cpp revision cbd66f00cfe5c4412f8efd6e66b0bb6bae956f7c
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::raw_ostream &Out; 32 bool IgnoreResults; 33 ASTUnit *AU; 34 bool generatedLoc; 35public: 36 USRGenerator(ASTUnit *au, llvm::raw_ostream &out) 37 : Out(out), IgnoreResults(false), AU(au), generatedLoc(false) {} 38 39 bool ignoreResults() const { return IgnoreResults; } 40 41 // Visitation methods from generating USRs from AST elements. 42 void VisitDeclContext(DeclContext *D); 43 void VisitFieldDecl(FieldDecl *D); 44 void VisitFunctionDecl(FunctionDecl *D); 45 void VisitNamedDecl(NamedDecl *D); 46 void VisitNamespaceDecl(NamespaceDecl *D); 47 void VisitObjCClassDecl(ObjCClassDecl *CD); 48 void VisitObjCContainerDecl(ObjCContainerDecl *CD); 49 void VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *P); 50 void VisitObjCMethodDecl(ObjCMethodDecl *MD); 51 void VisitObjCPropertyDecl(ObjCPropertyDecl *D); 52 void VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D); 53 void VisitTagDecl(TagDecl *D); 54 void VisitTypedefDecl(TypedefDecl *D); 55 void VisitVarDecl(VarDecl *D); 56 57 /// Generate the string component containing the location of the 58 /// declaration. 59 bool GenLoc(const Decl *D); 60 61 /// String generation methods used both by the visitation methods 62 /// and from other clients that want to directly generate USRs. These 63 /// methods do not construct complete USRs (which incorporate the parents 64 /// of an AST element), but only the fragments concerning the AST element 65 /// itself. 66 67 /// Generate a USR fragment for a named declaration. This does 68 /// not include the USR component for the parent. 69 void GenNamedDecl(llvm::StringRef name); 70 71 /// Generate a USR for an Objective-C class. 72 void GenObjCClass(llvm::StringRef cls); 73 /// Generate a USR for an Objective-C class category. 74 void GenObjCCategory(llvm::StringRef cls, llvm::StringRef cat); 75 /// Generate a USR fragment for an Objective-C instance variable. The 76 /// complete USR can be created by concatenating the USR for the 77 /// encompassing class with this USR fragment. 78 void GenObjCIvar(llvm::StringRef ivar); 79 /// Generate a USR fragment for an Objective-C method. 80 void GenObjCMethod(llvm::StringRef sel, bool isInstanceMethod); 81 /// Generate a USR fragment for an Objective-C property. 82 void GenObjCProperty(llvm::StringRef prop); 83 /// Generate a USR for an Objective-C protocol. 84 void GenObjCProtocol(llvm::StringRef prot); 85}; 86 87class StringUSRGenerator { 88private: 89 llvm::SmallString<1024> StrBuf; 90 llvm::raw_svector_ostream Out; 91 USRGenerator UG; 92public: 93 StringUSRGenerator(const CXCursor *C = 0) 94 : Out(StrBuf), UG(C ? cxcursor::getCursorASTUnit(*C) : 0, Out) { 95 // Add the USR space prefix. 96 Out << "c:"; 97 } 98 99 llvm::StringRef str() { 100 return Out.str(); 101 } 102 103 USRGenerator* operator->() { return &UG; } 104 105 template <typename T> 106 llvm::raw_svector_ostream &operator<<(const T &x) { 107 Out << x; 108 return Out; 109 } 110}; 111 112} // end anonymous namespace 113 114//===----------------------------------------------------------------------===// 115// Generating USRs from ASTS. 116//===----------------------------------------------------------------------===// 117 118static bool InAnonymousNamespace(const Decl *D) { 119 if (const NamespaceDecl *ND = dyn_cast<NamespaceDecl>(D->getDeclContext())) 120 return ND->isAnonymousNamespace(); 121 return false; 122} 123 124static inline bool ShouldGenerateLocation(const NamedDecl *D) { 125 return D->getLinkage() != ExternalLinkage && !InAnonymousNamespace(D); 126} 127 128void USRGenerator::VisitDeclContext(DeclContext *DC) { 129 if (NamedDecl *D = dyn_cast<NamedDecl>(DC)) 130 Visit(D); 131} 132 133void USRGenerator::VisitFieldDecl(FieldDecl *D) { 134 const std::string &s = D->getNameAsString(); 135 if (s.empty()) { 136 // Bit fields can be anonymous. 137 IgnoreResults = true; 138 return; 139 } 140 VisitDeclContext(D->getDeclContext()); 141 Out << (isa<ObjCIvarDecl>(D) ? "@" : "@FI@") << s; 142} 143 144void USRGenerator::VisitFunctionDecl(FunctionDecl *D) { 145 if (ShouldGenerateLocation(D) && GenLoc(D)) 146 return; 147 148 VisitDeclContext(D->getDeclContext()); 149 Out << "@F@" << D->getNameAsString(); 150} 151 152void USRGenerator::VisitNamedDecl(NamedDecl *D) { 153 VisitDeclContext(D->getDeclContext()); 154 const std::string &s = D->getNameAsString(); 155 // The string can be empty if the declaration has no name; e.g., it is 156 // the ParmDecl with no name for declaration of a function pointer type, e.g.: 157 // void (*f)(void *); 158 // In this case, don't generate a USR. 159 if (s.empty()) 160 IgnoreResults = true; 161 else 162 GenNamedDecl(s); 163} 164 165void USRGenerator::VisitVarDecl(VarDecl *D) { 166 // VarDecls can be declared 'extern' within a function or method body, 167 // but their enclosing DeclContext is the function, not the TU. We need 168 // to check the storage class to correctly generate the USR. 169 if (ShouldGenerateLocation(D) && GenLoc(D)) 170 return; 171 172 VisitDeclContext(D->getDeclContext()); 173 174 // Variables always have simple names. 175 llvm::StringRef s = D->getName(); 176 177 // The string can be empty if the declaration has no name; e.g., it is 178 // the ParmDecl with no name for declaration of a function pointer type, e.g.: 179 // void (*f)(void *); 180 // In this case, don't generate a USR. 181 if (s.empty()) 182 IgnoreResults = true; 183 else 184 GenNamedDecl(s); 185} 186 187void USRGenerator::VisitNamespaceDecl(NamespaceDecl *D) { 188 if (D->isAnonymousNamespace()) { 189 Out << "@aN"; 190 return; 191 } 192 193 VisitDeclContext(D->getDeclContext()); 194 if (!IgnoreResults) 195 Out << "@N@" << D->getName(); 196} 197 198void USRGenerator::VisitObjCMethodDecl(ObjCMethodDecl *D) { 199 Visit(cast<Decl>(D->getDeclContext())); 200 GenObjCMethod(DeclarationName(D->getSelector()).getAsString(), 201 D->isInstanceMethod()); 202} 203 204void USRGenerator::VisitObjCClassDecl(ObjCClassDecl *D) { 205 // FIXME: @class declarations can refer to multiple classes. We need 206 // to be able to traverse these. 207 IgnoreResults = true; 208} 209 210void USRGenerator::VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *D) { 211 // FIXME: @protocol declarations can refer to multiple protocols. We need 212 // to be able to traverse these. 213 IgnoreResults = true; 214} 215 216void USRGenerator::VisitObjCContainerDecl(ObjCContainerDecl *D) { 217 switch (D->getKind()) { 218 default: 219 assert(false && "Invalid ObjC container."); 220 case Decl::ObjCInterface: 221 case Decl::ObjCImplementation: 222 GenObjCClass(D->getName()); 223 break; 224 case Decl::ObjCCategory: { 225 ObjCCategoryDecl *CD = cast<ObjCCategoryDecl>(D); 226 ObjCInterfaceDecl *ID = CD->getClassInterface(); 227 if (!ID) { 228 // Handle invalid code where the @interface might not 229 // have been specified. 230 // FIXME: We should be able to generate this USR even if the 231 // @interface isn't available. 232 IgnoreResults = true; 233 return; 234 } 235 GenObjCCategory(ID->getName(), CD->getName()); 236 break; 237 } 238 case Decl::ObjCCategoryImpl: { 239 ObjCCategoryImplDecl *CD = cast<ObjCCategoryImplDecl>(D); 240 ObjCInterfaceDecl *ID = CD->getClassInterface(); 241 if (!ID) { 242 // Handle invalid code where the @interface might not 243 // have been specified. 244 // FIXME: We should be able to generate this USR even if the 245 // @interface isn't available. 246 IgnoreResults = true; 247 return; 248 } 249 GenObjCCategory(ID->getName(), CD->getName()); 250 break; 251 } 252 case Decl::ObjCProtocol: 253 GenObjCProtocol(cast<ObjCProtocolDecl>(D)->getName()); 254 break; 255 } 256} 257 258void USRGenerator::VisitObjCPropertyDecl(ObjCPropertyDecl *D) { 259 Visit(cast<Decl>(D->getDeclContext())); 260 GenObjCProperty(D->getName()); 261} 262 263void USRGenerator::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) { 264 if (ObjCPropertyDecl *PD = D->getPropertyDecl()) { 265 VisitObjCPropertyDecl(PD); 266 return; 267 } 268 269 IgnoreResults = true; 270} 271 272void USRGenerator::VisitTagDecl(TagDecl *D) { 273 // Add the location of the tag decl to handle resolution across 274 // translation units. 275 if (ShouldGenerateLocation(D) && GenLoc(D)) 276 return; 277 278 D = D->getCanonicalDecl(); 279 VisitDeclContext(D->getDeclContext()); 280 281 switch (D->getTagKind()) { 282 case TagDecl::TK_struct: Out << "@S"; break; 283 case TagDecl::TK_class: Out << "@C"; break; 284 case TagDecl::TK_union: Out << "@U"; break; 285 case TagDecl::TK_enum: Out << "@E"; break; 286 } 287 288 const std::string &s = D->getNameAsString(); 289 const TypedefDecl *TD = 0; 290 if (s.empty()) { 291 TD = D->getTypedefForAnonDecl(); 292 Out << (TD ? 'A' : 'a'); 293 } 294 295 if (s.empty()) { 296 if (TD) 297 Out << '@' << TD; 298 } 299 else 300 Out << '@' << s; 301} 302 303void USRGenerator::VisitTypedefDecl(TypedefDecl *D) { 304 if (ShouldGenerateLocation(D) && GenLoc(D)) 305 return; 306 DeclContext *DC = D->getDeclContext(); 307 if (NamedDecl *DCN = dyn_cast<NamedDecl>(DC)) 308 Visit(DCN); 309 Out << "@T@"; 310 Out << D->getName(); 311} 312 313bool USRGenerator::GenLoc(const Decl *D) { 314 if (generatedLoc) 315 return IgnoreResults; 316 generatedLoc = true; 317 318 const SourceManager &SM = AU->getSourceManager(); 319 SourceLocation L = D->getLocStart(); 320 if (L.isInvalid()) { 321 IgnoreResults = true; 322 return true; 323 } 324 L = SM.getInstantiationLoc(L); 325 const std::pair<FileID, unsigned> &Decomposed = SM.getDecomposedLoc(L); 326 const FileEntry *FE = SM.getFileEntryForID(Decomposed.first); 327 if (FE) { 328 llvm::sys::Path P(FE->getName()); 329 Out << P.getLast(); 330 } 331 else { 332 // This case really isn't interesting. 333 IgnoreResults = true; 334 return true; 335 } 336 Out << '@' 337 << SM.getLineNumber(Decomposed.first, Decomposed.second) << ':' 338 << SM.getColumnNumber(Decomposed.first, Decomposed.second); 339 340 return IgnoreResults; 341} 342 343//===----------------------------------------------------------------------===// 344// General purpose USR generation methods. 345//===----------------------------------------------------------------------===// 346 347void USRGenerator::GenNamedDecl(llvm::StringRef name) { 348 Out << "@" << name; 349} 350 351void USRGenerator::GenObjCClass(llvm::StringRef cls) { 352 Out << "objc(cs)" << cls; 353} 354 355void USRGenerator::GenObjCCategory(llvm::StringRef cls, llvm::StringRef cat) { 356 Out << "objc(cy)" << cls << '@' << cat; 357} 358 359void USRGenerator::GenObjCIvar(llvm::StringRef ivar) { 360 GenNamedDecl(ivar); 361} 362 363void USRGenerator::GenObjCMethod(llvm::StringRef meth, bool isInstanceMethod) { 364 Out << (isInstanceMethod ? "(im)" : "(cm)") << meth; 365} 366 367void USRGenerator::GenObjCProperty(llvm::StringRef prop) { 368 Out << "(py)" << prop; 369} 370 371void USRGenerator::GenObjCProtocol(llvm::StringRef prot) { 372 Out << "objc(pl)" << prot; 373} 374 375//===----------------------------------------------------------------------===// 376// API hooks. 377//===----------------------------------------------------------------------===// 378 379static inline llvm::StringRef extractUSRSuffix(llvm::StringRef s) { 380 return s.startswith("c:") ? s.substr(2) : ""; 381} 382 383static CXString getDeclCursorUSR(const CXCursor &C) { 384 Decl *D = cxcursor::getCursorDecl(C); 385 386 // Don't generate USRs for things with invalid locations. 387 if (!D || D->getLocStart().isInvalid()) 388 return createCXString(""); 389 390 // Check if the cursor has 'NoLinkage'. 391 if (const NamedDecl *ND = dyn_cast<NamedDecl>(D)) 392 switch (ND->getLinkage()) { 393 case ExternalLinkage: 394 // Generate USRs for all entities with external linkage. 395 break; 396 case NoLinkage: 397 case UniqueExternalLinkage: 398 // We allow enums, typedefs, and structs that have no linkage to 399 // have USRs that are anchored to the file they were defined in 400 // (e.g., the header). This is a little gross, but in principal 401 // enums/anonymous structs/etc. defined in a common header file 402 // are referred to across multiple translation units. 403 if (isa<TagDecl>(ND) || isa<TypedefDecl>(ND) || 404 isa<EnumConstantDecl>(ND) || isa<FieldDecl>(ND) || 405 isa<VarDecl>(ND) || isa<NamespaceDecl>(ND)) 406 break; 407 // Fall-through. 408 case InternalLinkage: 409 if (isa<FunctionDecl>(ND)) 410 break; 411 } 412 413 StringUSRGenerator SUG(&C); 414 SUG->Visit(D); 415 416 if (SUG->ignoreResults()) 417 return createCXString(""); 418 419 // For development testing. 420 // assert(SUG.str().size() > 2); 421 422 // Return a copy of the string that must be disposed by the caller. 423 return createCXString(SUG.str(), true); 424} 425 426extern "C" { 427 428CXString clang_getCursorUSR(CXCursor C) { 429 const CXCursorKind &K = clang_getCursorKind(C); 430 431 if (clang_isDeclaration(K)) 432 return getDeclCursorUSR(C); 433 434 if (K == CXCursor_MacroDefinition) { 435 StringUSRGenerator SUG(&C); 436 SUG << "macro@" 437 << cxcursor::getCursorMacroDefinition(C)->getName()->getNameStart(); 438 return createCXString(SUG.str(), true); 439 } 440 441 return createCXString(""); 442} 443 444CXString clang_constructUSR_ObjCIvar(const char *name, CXString classUSR) { 445 StringUSRGenerator SUG; 446 SUG << extractUSRSuffix(clang_getCString(classUSR)); 447 SUG->GenObjCIvar(name); 448 return createCXString(SUG.str(), true); 449} 450 451CXString clang_constructUSR_ObjCMethod(const char *name, 452 unsigned isInstanceMethod, 453 CXString classUSR) { 454 StringUSRGenerator SUG; 455 SUG << extractUSRSuffix(clang_getCString(classUSR)); 456 SUG->GenObjCMethod(name, isInstanceMethod); 457 return createCXString(SUG.str(), true); 458} 459 460CXString clang_constructUSR_ObjCClass(const char *name) { 461 StringUSRGenerator SUG; 462 SUG->GenObjCClass(name); 463 return createCXString(SUG.str(), true); 464} 465 466CXString clang_constructUSR_ObjCProtocol(const char *name) { 467 StringUSRGenerator SUG; 468 SUG->GenObjCProtocol(name); 469 return createCXString(SUG.str(), true); 470} 471 472CXString clang_constructUSR_ObjCCategory(const char *class_name, 473 const char *category_name) { 474 StringUSRGenerator SUG; 475 SUG->GenObjCCategory(class_name, category_name); 476 return createCXString(SUG.str(), true); 477} 478 479CXString clang_constructUSR_ObjCProperty(const char *property, 480 CXString classUSR) { 481 StringUSRGenerator SUG; 482 SUG << extractUSRSuffix(clang_getCString(classUSR)); 483 SUG->GenObjCProperty(property); 484 return createCXString(SUG.str(), true); 485} 486 487} // end extern "C" 488