1 //===- USRGeneration.cpp - Routines for USR generation --------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "clang/Index/USRGeneration.h" 10 #include "clang/AST/ASTContext.h" 11 #include "clang/AST/Attr.h" 12 #include "clang/AST/DeclCXX.h" 13 #include "clang/AST/DeclTemplate.h" 14 #include "clang/AST/DeclVisitor.h" 15 #include "clang/Basic/FileManager.h" 16 #include "clang/Lex/PreprocessingRecord.h" 17 #include "llvm/Support/Path.h" 18 #include "llvm/Support/raw_ostream.h" 19 20 using namespace clang; 21 using namespace clang::index; 22 23 //===----------------------------------------------------------------------===// 24 // USR generation. 25 //===----------------------------------------------------------------------===// 26 27 /// \returns true on error. 28 static bool printLoc(llvm::raw_ostream &OS, SourceLocation Loc, 29 const SourceManager &SM, bool IncludeOffset) { 30 if (Loc.isInvalid()) { 31 return true; 32 } 33 Loc = SM.getExpansionLoc(Loc); 34 const std::pair<FileID, unsigned> &Decomposed = SM.getDecomposedLoc(Loc); 35 OptionalFileEntryRef FE = SM.getFileEntryRefForID(Decomposed.first); 36 if (FE) { 37 OS << llvm::sys::path::filename(FE->getName()); 38 } else { 39 // This case really isn't interesting. 40 return true; 41 } 42 if (IncludeOffset) { 43 // Use the offest into the FileID to represent the location. Using 44 // a line/column can cause us to look back at the original source file, 45 // which is expensive. 46 OS << '@' << Decomposed.second; 47 } 48 return false; 49 } 50 51 static StringRef GetExternalSourceContainer(const NamedDecl *D) { 52 if (!D) 53 return StringRef(); 54 if (auto *attr = D->getExternalSourceSymbolAttr()) { 55 return attr->getDefinedIn(); 56 } 57 return StringRef(); 58 } 59 60 namespace { 61 class USRGenerator : public ConstDeclVisitor<USRGenerator> { 62 SmallVectorImpl<char> &Buf; 63 llvm::raw_svector_ostream Out; 64 bool IgnoreResults; 65 ASTContext *Context; 66 bool generatedLoc; 67 68 llvm::DenseMap<const Type *, unsigned> TypeSubstitutions; 69 70 public: 71 explicit USRGenerator(ASTContext *Ctx, SmallVectorImpl<char> &Buf) 72 : Buf(Buf), 73 Out(Buf), 74 IgnoreResults(false), 75 Context(Ctx), 76 generatedLoc(false) 77 { 78 // Add the USR space prefix. 79 Out << getUSRSpacePrefix(); 80 } 81 82 bool ignoreResults() const { return IgnoreResults; } 83 84 // Visitation methods from generating USRs from AST elements. 85 void VisitDeclContext(const DeclContext *D); 86 void VisitFieldDecl(const FieldDecl *D); 87 void VisitFunctionDecl(const FunctionDecl *D); 88 void VisitNamedDecl(const NamedDecl *D); 89 void VisitNamespaceDecl(const NamespaceDecl *D); 90 void VisitNamespaceAliasDecl(const NamespaceAliasDecl *D); 91 void VisitFunctionTemplateDecl(const FunctionTemplateDecl *D); 92 void VisitClassTemplateDecl(const ClassTemplateDecl *D); 93 void VisitObjCContainerDecl(const ObjCContainerDecl *CD, 94 const ObjCCategoryDecl *CatD = nullptr); 95 void VisitObjCMethodDecl(const ObjCMethodDecl *MD); 96 void VisitObjCPropertyDecl(const ObjCPropertyDecl *D); 97 void VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D); 98 void VisitTagDecl(const TagDecl *D); 99 void VisitTypedefDecl(const TypedefDecl *D); 100 void VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D); 101 void VisitVarDecl(const VarDecl *D); 102 void VisitBindingDecl(const BindingDecl *D); 103 void VisitNonTypeTemplateParmDecl(const NonTypeTemplateParmDecl *D); 104 void VisitTemplateTemplateParmDecl(const TemplateTemplateParmDecl *D); 105 void VisitUnresolvedUsingValueDecl(const UnresolvedUsingValueDecl *D); 106 void VisitUnresolvedUsingTypenameDecl(const UnresolvedUsingTypenameDecl *D); 107 void VisitConceptDecl(const ConceptDecl *D); 108 109 void VisitLinkageSpecDecl(const LinkageSpecDecl *D) { 110 IgnoreResults = true; // No USRs for linkage specs themselves. 111 } 112 113 void VisitUsingDirectiveDecl(const UsingDirectiveDecl *D) { 114 IgnoreResults = true; 115 } 116 117 void VisitUsingDecl(const UsingDecl *D) { 118 VisitDeclContext(D->getDeclContext()); 119 Out << "@UD@"; 120 121 bool EmittedDeclName = !EmitDeclName(D); 122 assert(EmittedDeclName && "EmitDeclName can not fail for UsingDecls"); 123 (void)EmittedDeclName; 124 } 125 126 bool ShouldGenerateLocation(const NamedDecl *D); 127 128 bool isLocal(const NamedDecl *D) { 129 return D->getParentFunctionOrMethod() != nullptr; 130 } 131 132 void GenExtSymbolContainer(const NamedDecl *D); 133 134 /// Generate the string component containing the location of the 135 /// declaration. 136 bool GenLoc(const Decl *D, bool IncludeOffset); 137 138 /// String generation methods used both by the visitation methods 139 /// and from other clients that want to directly generate USRs. These 140 /// methods do not construct complete USRs (which incorporate the parents 141 /// of an AST element), but only the fragments concerning the AST element 142 /// itself. 143 144 /// Generate a USR for an Objective-C class. 145 void GenObjCClass(StringRef cls, StringRef ExtSymDefinedIn, 146 StringRef CategoryContextExtSymbolDefinedIn) { 147 generateUSRForObjCClass(cls, Out, ExtSymDefinedIn, 148 CategoryContextExtSymbolDefinedIn); 149 } 150 151 /// Generate a USR for an Objective-C class category. 152 void GenObjCCategory(StringRef cls, StringRef cat, 153 StringRef clsExt, StringRef catExt) { 154 generateUSRForObjCCategory(cls, cat, Out, clsExt, catExt); 155 } 156 157 /// Generate a USR fragment for an Objective-C property. 158 void GenObjCProperty(StringRef prop, bool isClassProp) { 159 generateUSRForObjCProperty(prop, isClassProp, Out); 160 } 161 162 /// Generate a USR for an Objective-C protocol. 163 void GenObjCProtocol(StringRef prot, StringRef ext) { 164 generateUSRForObjCProtocol(prot, Out, ext); 165 } 166 167 void VisitType(QualType T); 168 void VisitTemplateParameterList(const TemplateParameterList *Params); 169 void VisitTemplateName(TemplateName Name); 170 void VisitTemplateArgument(const TemplateArgument &Arg); 171 172 void VisitMSGuidDecl(const MSGuidDecl *D); 173 174 /// Emit a Decl's name using NamedDecl::printName() and return true if 175 /// the decl had no name. 176 bool EmitDeclName(const NamedDecl *D); 177 }; 178 } // end anonymous namespace 179 180 //===----------------------------------------------------------------------===// 181 // Generating USRs from ASTS. 182 //===----------------------------------------------------------------------===// 183 184 bool USRGenerator::EmitDeclName(const NamedDecl *D) { 185 DeclarationName N = D->getDeclName(); 186 if (N.isEmpty()) 187 return true; 188 Out << N; 189 return false; 190 } 191 192 bool USRGenerator::ShouldGenerateLocation(const NamedDecl *D) { 193 if (D->isExternallyVisible()) 194 return false; 195 if (D->getParentFunctionOrMethod()) 196 return true; 197 SourceLocation Loc = D->getLocation(); 198 if (Loc.isInvalid()) 199 return false; 200 const SourceManager &SM = Context->getSourceManager(); 201 return !SM.isInSystemHeader(Loc); 202 } 203 204 void USRGenerator::VisitDeclContext(const DeclContext *DC) { 205 if (const NamedDecl *D = dyn_cast<NamedDecl>(DC)) 206 Visit(D); 207 else if (isa<LinkageSpecDecl>(DC)) // Linkage specs are transparent in USRs. 208 VisitDeclContext(DC->getParent()); 209 } 210 211 void USRGenerator::VisitFieldDecl(const FieldDecl *D) { 212 // The USR for an ivar declared in a class extension is based on the 213 // ObjCInterfaceDecl, not the ObjCCategoryDecl. 214 if (const ObjCInterfaceDecl *ID = Context->getObjContainingInterface(D)) 215 Visit(ID); 216 else 217 VisitDeclContext(D->getDeclContext()); 218 Out << (isa<ObjCIvarDecl>(D) ? "@" : "@FI@"); 219 if (EmitDeclName(D)) { 220 // Bit fields can be anonymous. 221 IgnoreResults = true; 222 return; 223 } 224 } 225 226 void USRGenerator::VisitFunctionDecl(const FunctionDecl *D) { 227 if (ShouldGenerateLocation(D) && GenLoc(D, /*IncludeOffset=*/isLocal(D))) 228 return; 229 230 if (D->getType().isNull()) { 231 IgnoreResults = true; 232 return; 233 } 234 235 const unsigned StartSize = Buf.size(); 236 VisitDeclContext(D->getDeclContext()); 237 if (Buf.size() == StartSize) 238 GenExtSymbolContainer(D); 239 240 bool IsTemplate = false; 241 if (FunctionTemplateDecl *FunTmpl = D->getDescribedFunctionTemplate()) { 242 IsTemplate = true; 243 Out << "@FT@"; 244 VisitTemplateParameterList(FunTmpl->getTemplateParameters()); 245 } else 246 Out << "@F@"; 247 248 PrintingPolicy Policy(Context->getLangOpts()); 249 // Forward references can have different template argument names. Suppress the 250 // template argument names in constructors to make their USR more stable. 251 Policy.SuppressTemplateArgsInCXXConstructors = true; 252 D->getDeclName().print(Out, Policy); 253 254 ASTContext &Ctx = *Context; 255 if ((!Ctx.getLangOpts().CPlusPlus || D->isExternC()) && 256 !D->hasAttr<OverloadableAttr>()) 257 return; 258 259 if (const TemplateArgumentList * 260 SpecArgs = D->getTemplateSpecializationArgs()) { 261 Out << '<'; 262 for (unsigned I = 0, N = SpecArgs->size(); I != N; ++I) { 263 Out << '#'; 264 VisitTemplateArgument(SpecArgs->get(I)); 265 } 266 Out << '>'; 267 } 268 269 // Mangle in type information for the arguments. 270 for (auto *PD : D->parameters()) { 271 Out << '#'; 272 VisitType(PD->getType()); 273 } 274 if (D->isVariadic()) 275 Out << '.'; 276 if (IsTemplate) { 277 // Function templates can be overloaded by return type, for example: 278 // \code 279 // template <class T> typename T::A foo() {} 280 // template <class T> typename T::B foo() {} 281 // \endcode 282 Out << '#'; 283 VisitType(D->getReturnType()); 284 } 285 Out << '#'; 286 if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) { 287 if (MD->isStatic()) 288 Out << 'S'; 289 // FIXME: OpenCL: Need to consider address spaces 290 if (unsigned quals = MD->getMethodQualifiers().getCVRUQualifiers()) 291 Out << (char)('0' + quals); 292 switch (MD->getRefQualifier()) { 293 case RQ_None: break; 294 case RQ_LValue: Out << '&'; break; 295 case RQ_RValue: Out << "&&"; break; 296 } 297 } 298 } 299 300 void USRGenerator::VisitNamedDecl(const NamedDecl *D) { 301 VisitDeclContext(D->getDeclContext()); 302 Out << "@"; 303 304 if (EmitDeclName(D)) { 305 // The string can be empty if the declaration has no name; e.g., it is 306 // the ParmDecl with no name for declaration of a function pointer type, 307 // e.g.: void (*f)(void *); 308 // In this case, don't generate a USR. 309 IgnoreResults = true; 310 } 311 } 312 313 void USRGenerator::VisitVarDecl(const VarDecl *D) { 314 // VarDecls can be declared 'extern' within a function or method body, 315 // but their enclosing DeclContext is the function, not the TU. We need 316 // to check the storage class to correctly generate the USR. 317 if (ShouldGenerateLocation(D) && GenLoc(D, /*IncludeOffset=*/isLocal(D))) 318 return; 319 320 VisitDeclContext(D->getDeclContext()); 321 322 if (VarTemplateDecl *VarTmpl = D->getDescribedVarTemplate()) { 323 Out << "@VT"; 324 VisitTemplateParameterList(VarTmpl->getTemplateParameters()); 325 } else if (const VarTemplatePartialSpecializationDecl *PartialSpec 326 = dyn_cast<VarTemplatePartialSpecializationDecl>(D)) { 327 Out << "@VP"; 328 VisitTemplateParameterList(PartialSpec->getTemplateParameters()); 329 } 330 331 // Variables always have simple names. 332 StringRef s = D->getName(); 333 334 // The string can be empty if the declaration has no name; e.g., it is 335 // the ParmDecl with no name for declaration of a function pointer type, e.g.: 336 // void (*f)(void *); 337 // In this case, don't generate a USR. 338 if (s.empty()) 339 IgnoreResults = true; 340 else 341 Out << '@' << s; 342 343 // For a template specialization, mangle the template arguments. 344 if (const VarTemplateSpecializationDecl *Spec 345 = dyn_cast<VarTemplateSpecializationDecl>(D)) { 346 const TemplateArgumentList &Args = Spec->getTemplateArgs(); 347 Out << '>'; 348 for (unsigned I = 0, N = Args.size(); I != N; ++I) { 349 Out << '#'; 350 VisitTemplateArgument(Args.get(I)); 351 } 352 } 353 } 354 355 void USRGenerator::VisitBindingDecl(const BindingDecl *D) { 356 if (isLocal(D) && GenLoc(D, /*IncludeOffset=*/true)) 357 return; 358 VisitNamedDecl(D); 359 } 360 361 void USRGenerator::VisitNonTypeTemplateParmDecl( 362 const NonTypeTemplateParmDecl *D) { 363 GenLoc(D, /*IncludeOffset=*/true); 364 } 365 366 void USRGenerator::VisitTemplateTemplateParmDecl( 367 const TemplateTemplateParmDecl *D) { 368 GenLoc(D, /*IncludeOffset=*/true); 369 } 370 371 void USRGenerator::VisitNamespaceDecl(const NamespaceDecl *D) { 372 if (IgnoreResults) 373 return; 374 VisitDeclContext(D->getDeclContext()); 375 if (D->isAnonymousNamespace()) { 376 Out << "@aN"; 377 return; 378 } 379 Out << "@N@" << D->getName(); 380 } 381 382 void USRGenerator::VisitFunctionTemplateDecl(const FunctionTemplateDecl *D) { 383 VisitFunctionDecl(D->getTemplatedDecl()); 384 } 385 386 void USRGenerator::VisitClassTemplateDecl(const ClassTemplateDecl *D) { 387 VisitTagDecl(D->getTemplatedDecl()); 388 } 389 390 void USRGenerator::VisitNamespaceAliasDecl(const NamespaceAliasDecl *D) { 391 VisitDeclContext(D->getDeclContext()); 392 if (!IgnoreResults) 393 Out << "@NA@" << D->getName(); 394 } 395 396 static const ObjCCategoryDecl *getCategoryContext(const NamedDecl *D) { 397 if (auto *CD = dyn_cast<ObjCCategoryDecl>(D->getDeclContext())) 398 return CD; 399 if (auto *ICD = dyn_cast<ObjCCategoryImplDecl>(D->getDeclContext())) 400 return ICD->getCategoryDecl(); 401 return nullptr; 402 } 403 404 void USRGenerator::VisitObjCMethodDecl(const ObjCMethodDecl *D) { 405 const DeclContext *container = D->getDeclContext(); 406 if (const ObjCProtocolDecl *pd = dyn_cast<ObjCProtocolDecl>(container)) { 407 Visit(pd); 408 } 409 else { 410 // The USR for a method declared in a class extension or category is based on 411 // the ObjCInterfaceDecl, not the ObjCCategoryDecl. 412 const ObjCInterfaceDecl *ID = D->getClassInterface(); 413 if (!ID) { 414 IgnoreResults = true; 415 return; 416 } 417 auto *CD = getCategoryContext(D); 418 VisitObjCContainerDecl(ID, CD); 419 } 420 // Ideally we would use 'GenObjCMethod', but this is such a hot path 421 // for Objective-C code that we don't want to use 422 // DeclarationName::getAsString(). 423 Out << (D->isInstanceMethod() ? "(im)" : "(cm)") 424 << DeclarationName(D->getSelector()); 425 } 426 427 void USRGenerator::VisitObjCContainerDecl(const ObjCContainerDecl *D, 428 const ObjCCategoryDecl *CatD) { 429 switch (D->getKind()) { 430 default: 431 llvm_unreachable("Invalid ObjC container."); 432 case Decl::ObjCInterface: 433 case Decl::ObjCImplementation: 434 GenObjCClass(D->getName(), GetExternalSourceContainer(D), 435 GetExternalSourceContainer(CatD)); 436 break; 437 case Decl::ObjCCategory: { 438 const ObjCCategoryDecl *CD = cast<ObjCCategoryDecl>(D); 439 const ObjCInterfaceDecl *ID = CD->getClassInterface(); 440 if (!ID) { 441 // Handle invalid code where the @interface might not 442 // have been specified. 443 // FIXME: We should be able to generate this USR even if the 444 // @interface isn't available. 445 IgnoreResults = true; 446 return; 447 } 448 // Specially handle class extensions, which are anonymous categories. 449 // We want to mangle in the location to uniquely distinguish them. 450 if (CD->IsClassExtension()) { 451 Out << "objc(ext)" << ID->getName() << '@'; 452 GenLoc(CD, /*IncludeOffset=*/true); 453 } 454 else 455 GenObjCCategory(ID->getName(), CD->getName(), 456 GetExternalSourceContainer(ID), 457 GetExternalSourceContainer(CD)); 458 459 break; 460 } 461 case Decl::ObjCCategoryImpl: { 462 const ObjCCategoryImplDecl *CD = cast<ObjCCategoryImplDecl>(D); 463 const ObjCInterfaceDecl *ID = CD->getClassInterface(); 464 if (!ID) { 465 // Handle invalid code where the @interface might not 466 // have been specified. 467 // FIXME: We should be able to generate this USR even if the 468 // @interface isn't available. 469 IgnoreResults = true; 470 return; 471 } 472 GenObjCCategory(ID->getName(), CD->getName(), 473 GetExternalSourceContainer(ID), 474 GetExternalSourceContainer(CD)); 475 break; 476 } 477 case Decl::ObjCProtocol: { 478 const ObjCProtocolDecl *PD = cast<ObjCProtocolDecl>(D); 479 GenObjCProtocol(PD->getName(), GetExternalSourceContainer(PD)); 480 break; 481 } 482 } 483 } 484 485 void USRGenerator::VisitObjCPropertyDecl(const ObjCPropertyDecl *D) { 486 // The USR for a property declared in a class extension or category is based 487 // on the ObjCInterfaceDecl, not the ObjCCategoryDecl. 488 if (const ObjCInterfaceDecl *ID = Context->getObjContainingInterface(D)) 489 VisitObjCContainerDecl(ID, getCategoryContext(D)); 490 else 491 Visit(cast<Decl>(D->getDeclContext())); 492 GenObjCProperty(D->getName(), D->isClassProperty()); 493 } 494 495 void USRGenerator::VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D) { 496 if (ObjCPropertyDecl *PD = D->getPropertyDecl()) { 497 VisitObjCPropertyDecl(PD); 498 return; 499 } 500 501 IgnoreResults = true; 502 } 503 504 void USRGenerator::VisitTagDecl(const TagDecl *D) { 505 // Add the location of the tag decl to handle resolution across 506 // translation units. 507 if (!isa<EnumDecl>(D) && 508 ShouldGenerateLocation(D) && GenLoc(D, /*IncludeOffset=*/isLocal(D))) 509 return; 510 511 GenExtSymbolContainer(D); 512 513 D = D->getCanonicalDecl(); 514 VisitDeclContext(D->getDeclContext()); 515 516 bool AlreadyStarted = false; 517 if (const CXXRecordDecl *CXXRecord = dyn_cast<CXXRecordDecl>(D)) { 518 if (ClassTemplateDecl *ClassTmpl = CXXRecord->getDescribedClassTemplate()) { 519 AlreadyStarted = true; 520 521 switch (D->getTagKind()) { 522 case TagTypeKind::Interface: 523 case TagTypeKind::Class: 524 case TagTypeKind::Struct: 525 Out << "@ST"; 526 break; 527 case TagTypeKind::Union: 528 Out << "@UT"; 529 break; 530 case TagTypeKind::Enum: 531 llvm_unreachable("enum template"); 532 } 533 VisitTemplateParameterList(ClassTmpl->getTemplateParameters()); 534 } else if (const ClassTemplatePartialSpecializationDecl *PartialSpec 535 = dyn_cast<ClassTemplatePartialSpecializationDecl>(CXXRecord)) { 536 AlreadyStarted = true; 537 538 switch (D->getTagKind()) { 539 case TagTypeKind::Interface: 540 case TagTypeKind::Class: 541 case TagTypeKind::Struct: 542 Out << "@SP"; 543 break; 544 case TagTypeKind::Union: 545 Out << "@UP"; 546 break; 547 case TagTypeKind::Enum: 548 llvm_unreachable("enum partial specialization"); 549 } 550 VisitTemplateParameterList(PartialSpec->getTemplateParameters()); 551 } 552 } 553 554 if (!AlreadyStarted) { 555 switch (D->getTagKind()) { 556 case TagTypeKind::Interface: 557 case TagTypeKind::Class: 558 case TagTypeKind::Struct: 559 Out << "@S"; 560 break; 561 case TagTypeKind::Union: 562 Out << "@U"; 563 break; 564 case TagTypeKind::Enum: 565 Out << "@E"; 566 break; 567 } 568 } 569 570 Out << '@'; 571 assert(Buf.size() > 0); 572 const unsigned off = Buf.size() - 1; 573 574 if (EmitDeclName(D)) { 575 if (const TypedefNameDecl *TD = D->getTypedefNameForAnonDecl()) { 576 Buf[off] = 'A'; 577 Out << '@' << *TD; 578 } else { 579 if (D->isEmbeddedInDeclarator() && !D->isFreeStanding()) { 580 printLoc(Out, D->getLocation(), Context->getSourceManager(), true); 581 } else { 582 Buf[off] = 'a'; 583 if (auto *ED = dyn_cast<EnumDecl>(D)) { 584 // Distinguish USRs of anonymous enums by using their first 585 // enumerator. 586 auto enum_range = ED->enumerators(); 587 if (enum_range.begin() != enum_range.end()) { 588 Out << '@' << **enum_range.begin(); 589 } 590 } 591 } 592 } 593 } 594 595 // For a class template specialization, mangle the template arguments. 596 if (const ClassTemplateSpecializationDecl *Spec 597 = dyn_cast<ClassTemplateSpecializationDecl>(D)) { 598 const TemplateArgumentList &Args = Spec->getTemplateArgs(); 599 Out << '>'; 600 for (unsigned I = 0, N = Args.size(); I != N; ++I) { 601 Out << '#'; 602 VisitTemplateArgument(Args.get(I)); 603 } 604 } 605 } 606 607 void USRGenerator::VisitTypedefDecl(const TypedefDecl *D) { 608 if (ShouldGenerateLocation(D) && GenLoc(D, /*IncludeOffset=*/isLocal(D))) 609 return; 610 const DeclContext *DC = D->getDeclContext(); 611 if (const NamedDecl *DCN = dyn_cast<NamedDecl>(DC)) 612 Visit(DCN); 613 Out << "@T@"; 614 Out << D->getName(); 615 } 616 617 void USRGenerator::VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D) { 618 GenLoc(D, /*IncludeOffset=*/true); 619 } 620 621 void USRGenerator::GenExtSymbolContainer(const NamedDecl *D) { 622 StringRef Container = GetExternalSourceContainer(D); 623 if (!Container.empty()) 624 Out << "@M@" << Container; 625 } 626 627 bool USRGenerator::GenLoc(const Decl *D, bool IncludeOffset) { 628 if (generatedLoc) 629 return IgnoreResults; 630 generatedLoc = true; 631 632 // Guard against null declarations in invalid code. 633 if (!D) { 634 IgnoreResults = true; 635 return true; 636 } 637 638 // Use the location of canonical decl. 639 D = D->getCanonicalDecl(); 640 641 IgnoreResults = 642 IgnoreResults || printLoc(Out, D->getBeginLoc(), 643 Context->getSourceManager(), IncludeOffset); 644 645 return IgnoreResults; 646 } 647 648 static void printQualifier(llvm::raw_ostream &Out, ASTContext &Ctx, NestedNameSpecifier *NNS) { 649 // FIXME: Encode the qualifier, don't just print it. 650 PrintingPolicy PO(Ctx.getLangOpts()); 651 PO.SuppressTagKeyword = true; 652 PO.SuppressUnwrittenScope = true; 653 PO.ConstantArraySizeAsWritten = false; 654 PO.AnonymousTagLocations = false; 655 NNS->print(Out, PO); 656 } 657 658 void USRGenerator::VisitType(QualType T) { 659 // This method mangles in USR information for types. It can possibly 660 // just reuse the naming-mangling logic used by codegen, although the 661 // requirements for USRs might not be the same. 662 ASTContext &Ctx = *Context; 663 664 do { 665 T = Ctx.getCanonicalType(T); 666 Qualifiers Q = T.getQualifiers(); 667 unsigned qVal = 0; 668 if (Q.hasConst()) 669 qVal |= 0x1; 670 if (Q.hasVolatile()) 671 qVal |= 0x2; 672 if (Q.hasRestrict()) 673 qVal |= 0x4; 674 if(qVal) 675 Out << ((char) ('0' + qVal)); 676 677 // Mangle in ObjC GC qualifiers? 678 679 if (const PackExpansionType *Expansion = T->getAs<PackExpansionType>()) { 680 Out << 'P'; 681 T = Expansion->getPattern(); 682 } 683 684 if (const BuiltinType *BT = T->getAs<BuiltinType>()) { 685 switch (BT->getKind()) { 686 case BuiltinType::Void: 687 Out << 'v'; break; 688 case BuiltinType::Bool: 689 Out << 'b'; break; 690 case BuiltinType::UChar: 691 Out << 'c'; break; 692 case BuiltinType::Char8: 693 Out << 'u'; break; 694 case BuiltinType::Char16: 695 Out << 'q'; break; 696 case BuiltinType::Char32: 697 Out << 'w'; break; 698 case BuiltinType::UShort: 699 Out << 's'; break; 700 case BuiltinType::UInt: 701 Out << 'i'; break; 702 case BuiltinType::ULong: 703 Out << 'l'; break; 704 case BuiltinType::ULongLong: 705 Out << 'k'; break; 706 case BuiltinType::UInt128: 707 Out << 'j'; break; 708 case BuiltinType::Char_U: 709 case BuiltinType::Char_S: 710 Out << 'C'; break; 711 case BuiltinType::SChar: 712 Out << 'r'; break; 713 case BuiltinType::WChar_S: 714 case BuiltinType::WChar_U: 715 Out << 'W'; break; 716 case BuiltinType::Short: 717 Out << 'S'; break; 718 case BuiltinType::Int: 719 Out << 'I'; break; 720 case BuiltinType::Long: 721 Out << 'L'; break; 722 case BuiltinType::LongLong: 723 Out << 'K'; break; 724 case BuiltinType::Int128: 725 Out << 'J'; break; 726 case BuiltinType::Float16: 727 case BuiltinType::Half: 728 Out << 'h'; break; 729 case BuiltinType::Float: 730 Out << 'f'; break; 731 case BuiltinType::Double: 732 Out << 'd'; break; 733 case BuiltinType::LongDouble: 734 Out << 'D'; break; 735 case BuiltinType::Float128: 736 Out << 'Q'; break; 737 case BuiltinType::NullPtr: 738 Out << 'n'; break; 739 #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \ 740 case BuiltinType::Id: \ 741 Out << "@BT@" << #Suffix << "_" << #ImgType; break; 742 #include "clang/Basic/OpenCLImageTypes.def" 743 #define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \ 744 case BuiltinType::Id: \ 745 Out << "@BT@" << #ExtType; break; 746 #include "clang/Basic/OpenCLExtensionTypes.def" 747 case BuiltinType::OCLEvent: 748 Out << "@BT@OCLEvent"; break; 749 case BuiltinType::OCLClkEvent: 750 Out << "@BT@OCLClkEvent"; break; 751 case BuiltinType::OCLQueue: 752 Out << "@BT@OCLQueue"; break; 753 case BuiltinType::OCLReserveID: 754 Out << "@BT@OCLReserveID"; break; 755 case BuiltinType::OCLSampler: 756 Out << "@BT@OCLSampler"; break; 757 #define SVE_TYPE(Name, Id, SingletonId) \ 758 case BuiltinType::Id: \ 759 Out << "@BT@" << Name; break; 760 #include "clang/Basic/AArch64SVEACLETypes.def" 761 #define PPC_VECTOR_TYPE(Name, Id, Size) \ 762 case BuiltinType::Id: \ 763 Out << "@BT@" << #Name; break; 764 #include "clang/Basic/PPCTypes.def" 765 #define RVV_TYPE(Name, Id, SingletonId) \ 766 case BuiltinType::Id: \ 767 Out << "@BT@" << Name; break; 768 #include "clang/Basic/RISCVVTypes.def" 769 #define WASM_TYPE(Name, Id, SingletonId) case BuiltinType::Id: 770 #include "clang/Basic/WebAssemblyReferenceTypes.def" 771 case BuiltinType::ShortAccum: 772 Out << "@BT@ShortAccum"; break; 773 case BuiltinType::Accum: 774 Out << "@BT@Accum"; break; 775 case BuiltinType::LongAccum: 776 Out << "@BT@LongAccum"; break; 777 case BuiltinType::UShortAccum: 778 Out << "@BT@UShortAccum"; break; 779 case BuiltinType::UAccum: 780 Out << "@BT@UAccum"; break; 781 case BuiltinType::ULongAccum: 782 Out << "@BT@ULongAccum"; break; 783 case BuiltinType::ShortFract: 784 Out << "@BT@ShortFract"; break; 785 case BuiltinType::Fract: 786 Out << "@BT@Fract"; break; 787 case BuiltinType::LongFract: 788 Out << "@BT@LongFract"; break; 789 case BuiltinType::UShortFract: 790 Out << "@BT@UShortFract"; break; 791 case BuiltinType::UFract: 792 Out << "@BT@UFract"; break; 793 case BuiltinType::ULongFract: 794 Out << "@BT@ULongFract"; break; 795 case BuiltinType::SatShortAccum: 796 Out << "@BT@SatShortAccum"; break; 797 case BuiltinType::SatAccum: 798 Out << "@BT@SatAccum"; break; 799 case BuiltinType::SatLongAccum: 800 Out << "@BT@SatLongAccum"; break; 801 case BuiltinType::SatUShortAccum: 802 Out << "@BT@SatUShortAccum"; break; 803 case BuiltinType::SatUAccum: 804 Out << "@BT@SatUAccum"; break; 805 case BuiltinType::SatULongAccum: 806 Out << "@BT@SatULongAccum"; break; 807 case BuiltinType::SatShortFract: 808 Out << "@BT@SatShortFract"; break; 809 case BuiltinType::SatFract: 810 Out << "@BT@SatFract"; break; 811 case BuiltinType::SatLongFract: 812 Out << "@BT@SatLongFract"; break; 813 case BuiltinType::SatUShortFract: 814 Out << "@BT@SatUShortFract"; break; 815 case BuiltinType::SatUFract: 816 Out << "@BT@SatUFract"; break; 817 case BuiltinType::SatULongFract: 818 Out << "@BT@SatULongFract"; break; 819 case BuiltinType::BFloat16: 820 Out << "@BT@__bf16"; break; 821 case BuiltinType::Ibm128: 822 Out << "@BT@__ibm128"; break; 823 case BuiltinType::ObjCId: 824 Out << 'o'; break; 825 case BuiltinType::ObjCClass: 826 Out << 'O'; break; 827 case BuiltinType::ObjCSel: 828 Out << 'e'; break; 829 #define BUILTIN_TYPE(Id, SingletonId) 830 #define PLACEHOLDER_TYPE(Id, SingletonId) case BuiltinType::Id: 831 #include "clang/AST/BuiltinTypes.def" 832 case BuiltinType::Dependent: 833 // If you're adding a new builtin type, please add its name prefixed 834 // with "@BT@" to `Out` (see cases above). 835 IgnoreResults = true; 836 break; 837 } 838 return; 839 } 840 841 // If we have already seen this (non-built-in) type, use a substitution 842 // encoding. 843 llvm::DenseMap<const Type *, unsigned>::iterator Substitution 844 = TypeSubstitutions.find(T.getTypePtr()); 845 if (Substitution != TypeSubstitutions.end()) { 846 Out << 'S' << Substitution->second << '_'; 847 return; 848 } else { 849 // Record this as a substitution. 850 unsigned Number = TypeSubstitutions.size(); 851 TypeSubstitutions[T.getTypePtr()] = Number; 852 } 853 854 if (const PointerType *PT = T->getAs<PointerType>()) { 855 Out << '*'; 856 T = PT->getPointeeType(); 857 continue; 858 } 859 if (const ObjCObjectPointerType *OPT = T->getAs<ObjCObjectPointerType>()) { 860 Out << '*'; 861 T = OPT->getPointeeType(); 862 continue; 863 } 864 if (const RValueReferenceType *RT = T->getAs<RValueReferenceType>()) { 865 Out << "&&"; 866 T = RT->getPointeeType(); 867 continue; 868 } 869 if (const ReferenceType *RT = T->getAs<ReferenceType>()) { 870 Out << '&'; 871 T = RT->getPointeeType(); 872 continue; 873 } 874 if (const FunctionProtoType *FT = T->getAs<FunctionProtoType>()) { 875 Out << 'F'; 876 VisitType(FT->getReturnType()); 877 Out << '('; 878 for (const auto &I : FT->param_types()) { 879 Out << '#'; 880 VisitType(I); 881 } 882 Out << ')'; 883 if (FT->isVariadic()) 884 Out << '.'; 885 return; 886 } 887 if (const BlockPointerType *BT = T->getAs<BlockPointerType>()) { 888 Out << 'B'; 889 T = BT->getPointeeType(); 890 continue; 891 } 892 if (const ComplexType *CT = T->getAs<ComplexType>()) { 893 Out << '<'; 894 T = CT->getElementType(); 895 continue; 896 } 897 if (const TagType *TT = T->getAs<TagType>()) { 898 Out << '$'; 899 VisitTagDecl(TT->getDecl()); 900 return; 901 } 902 if (const ObjCInterfaceType *OIT = T->getAs<ObjCInterfaceType>()) { 903 Out << '$'; 904 VisitObjCInterfaceDecl(OIT->getDecl()); 905 return; 906 } 907 if (const ObjCObjectType *OIT = T->getAs<ObjCObjectType>()) { 908 Out << 'Q'; 909 VisitType(OIT->getBaseType()); 910 for (auto *Prot : OIT->getProtocols()) 911 VisitObjCProtocolDecl(Prot); 912 return; 913 } 914 if (const TemplateTypeParmType *TTP = T->getAs<TemplateTypeParmType>()) { 915 Out << 't' << TTP->getDepth() << '.' << TTP->getIndex(); 916 return; 917 } 918 if (const TemplateSpecializationType *Spec 919 = T->getAs<TemplateSpecializationType>()) { 920 Out << '>'; 921 VisitTemplateName(Spec->getTemplateName()); 922 Out << Spec->template_arguments().size(); 923 for (const auto &Arg : Spec->template_arguments()) 924 VisitTemplateArgument(Arg); 925 return; 926 } 927 if (const DependentNameType *DNT = T->getAs<DependentNameType>()) { 928 Out << '^'; 929 printQualifier(Out, Ctx, DNT->getQualifier()); 930 Out << ':' << DNT->getIdentifier()->getName(); 931 return; 932 } 933 if (const InjectedClassNameType *InjT = T->getAs<InjectedClassNameType>()) { 934 T = InjT->getInjectedSpecializationType(); 935 continue; 936 } 937 if (const auto *VT = T->getAs<VectorType>()) { 938 Out << (T->isExtVectorType() ? ']' : '['); 939 Out << VT->getNumElements(); 940 T = VT->getElementType(); 941 continue; 942 } 943 if (const auto *const AT = dyn_cast<ArrayType>(T)) { 944 Out << '{'; 945 switch (AT->getSizeModifier()) { 946 case ArraySizeModifier::Static: 947 Out << 's'; 948 break; 949 case ArraySizeModifier::Star: 950 Out << '*'; 951 break; 952 case ArraySizeModifier::Normal: 953 Out << 'n'; 954 break; 955 } 956 if (const auto *const CAT = dyn_cast<ConstantArrayType>(T)) 957 Out << CAT->getSize(); 958 959 T = AT->getElementType(); 960 continue; 961 } 962 963 // Unhandled type. 964 Out << ' '; 965 break; 966 } while (true); 967 } 968 969 void USRGenerator::VisitTemplateParameterList( 970 const TemplateParameterList *Params) { 971 if (!Params) 972 return; 973 Out << '>' << Params->size(); 974 for (TemplateParameterList::const_iterator P = Params->begin(), 975 PEnd = Params->end(); 976 P != PEnd; ++P) { 977 Out << '#'; 978 if (isa<TemplateTypeParmDecl>(*P)) { 979 if (cast<TemplateTypeParmDecl>(*P)->isParameterPack()) 980 Out<< 'p'; 981 Out << 'T'; 982 continue; 983 } 984 985 if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(*P)) { 986 if (NTTP->isParameterPack()) 987 Out << 'p'; 988 Out << 'N'; 989 VisitType(NTTP->getType()); 990 continue; 991 } 992 993 TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*P); 994 if (TTP->isParameterPack()) 995 Out << 'p'; 996 Out << 't'; 997 VisitTemplateParameterList(TTP->getTemplateParameters()); 998 } 999 } 1000 1001 void USRGenerator::VisitTemplateName(TemplateName Name) { 1002 if (TemplateDecl *Template = Name.getAsTemplateDecl()) { 1003 if (TemplateTemplateParmDecl *TTP 1004 = dyn_cast<TemplateTemplateParmDecl>(Template)) { 1005 Out << 't' << TTP->getDepth() << '.' << TTP->getIndex(); 1006 return; 1007 } 1008 1009 Visit(Template); 1010 return; 1011 } 1012 1013 // FIXME: Visit dependent template names. 1014 } 1015 1016 void USRGenerator::VisitTemplateArgument(const TemplateArgument &Arg) { 1017 switch (Arg.getKind()) { 1018 case TemplateArgument::Null: 1019 break; 1020 1021 case TemplateArgument::Declaration: 1022 Visit(Arg.getAsDecl()); 1023 break; 1024 1025 case TemplateArgument::NullPtr: 1026 break; 1027 1028 case TemplateArgument::TemplateExpansion: 1029 Out << 'P'; // pack expansion of... 1030 [[fallthrough]]; 1031 case TemplateArgument::Template: 1032 VisitTemplateName(Arg.getAsTemplateOrTemplatePattern()); 1033 break; 1034 1035 case TemplateArgument::Expression: 1036 // FIXME: Visit expressions. 1037 break; 1038 1039 case TemplateArgument::Pack: 1040 Out << 'p' << Arg.pack_size(); 1041 for (const auto &P : Arg.pack_elements()) 1042 VisitTemplateArgument(P); 1043 break; 1044 1045 case TemplateArgument::Type: 1046 VisitType(Arg.getAsType()); 1047 break; 1048 1049 case TemplateArgument::Integral: 1050 Out << 'V'; 1051 VisitType(Arg.getIntegralType()); 1052 Out << Arg.getAsIntegral(); 1053 break; 1054 } 1055 } 1056 1057 void USRGenerator::VisitUnresolvedUsingValueDecl(const UnresolvedUsingValueDecl *D) { 1058 if (ShouldGenerateLocation(D) && GenLoc(D, /*IncludeOffset=*/isLocal(D))) 1059 return; 1060 VisitDeclContext(D->getDeclContext()); 1061 Out << "@UUV@"; 1062 printQualifier(Out, D->getASTContext(), D->getQualifier()); 1063 EmitDeclName(D); 1064 } 1065 1066 void USRGenerator::VisitUnresolvedUsingTypenameDecl(const UnresolvedUsingTypenameDecl *D) { 1067 if (ShouldGenerateLocation(D) && GenLoc(D, /*IncludeOffset=*/isLocal(D))) 1068 return; 1069 VisitDeclContext(D->getDeclContext()); 1070 Out << "@UUT@"; 1071 printQualifier(Out, D->getASTContext(), D->getQualifier()); 1072 Out << D->getName(); // Simple name. 1073 } 1074 1075 void USRGenerator::VisitConceptDecl(const ConceptDecl *D) { 1076 if (ShouldGenerateLocation(D) && GenLoc(D, /*IncludeOffset=*/isLocal(D))) 1077 return; 1078 VisitDeclContext(D->getDeclContext()); 1079 Out << "@CT@"; 1080 EmitDeclName(D); 1081 } 1082 1083 void USRGenerator::VisitMSGuidDecl(const MSGuidDecl *D) { 1084 VisitDeclContext(D->getDeclContext()); 1085 Out << "@MG@"; 1086 D->NamedDecl::printName(Out); 1087 } 1088 1089 //===----------------------------------------------------------------------===// 1090 // USR generation functions. 1091 //===----------------------------------------------------------------------===// 1092 1093 static void combineClassAndCategoryExtContainers(StringRef ClsSymDefinedIn, 1094 StringRef CatSymDefinedIn, 1095 raw_ostream &OS) { 1096 if (ClsSymDefinedIn.empty() && CatSymDefinedIn.empty()) 1097 return; 1098 if (CatSymDefinedIn.empty()) { 1099 OS << "@M@" << ClsSymDefinedIn << '@'; 1100 return; 1101 } 1102 OS << "@CM@" << CatSymDefinedIn << '@'; 1103 if (ClsSymDefinedIn != CatSymDefinedIn) { 1104 OS << ClsSymDefinedIn << '@'; 1105 } 1106 } 1107 1108 void clang::index::generateUSRForObjCClass(StringRef Cls, raw_ostream &OS, 1109 StringRef ExtSymDefinedIn, 1110 StringRef CategoryContextExtSymbolDefinedIn) { 1111 combineClassAndCategoryExtContainers(ExtSymDefinedIn, 1112 CategoryContextExtSymbolDefinedIn, OS); 1113 OS << "objc(cs)" << Cls; 1114 } 1115 1116 void clang::index::generateUSRForObjCCategory(StringRef Cls, StringRef Cat, 1117 raw_ostream &OS, 1118 StringRef ClsSymDefinedIn, 1119 StringRef CatSymDefinedIn) { 1120 combineClassAndCategoryExtContainers(ClsSymDefinedIn, CatSymDefinedIn, OS); 1121 OS << "objc(cy)" << Cls << '@' << Cat; 1122 } 1123 1124 void clang::index::generateUSRForObjCIvar(StringRef Ivar, raw_ostream &OS) { 1125 OS << '@' << Ivar; 1126 } 1127 1128 void clang::index::generateUSRForObjCMethod(StringRef Sel, 1129 bool IsInstanceMethod, 1130 raw_ostream &OS) { 1131 OS << (IsInstanceMethod ? "(im)" : "(cm)") << Sel; 1132 } 1133 1134 void clang::index::generateUSRForObjCProperty(StringRef Prop, bool isClassProp, 1135 raw_ostream &OS) { 1136 OS << (isClassProp ? "(cpy)" : "(py)") << Prop; 1137 } 1138 1139 void clang::index::generateUSRForObjCProtocol(StringRef Prot, raw_ostream &OS, 1140 StringRef ExtSymDefinedIn) { 1141 if (!ExtSymDefinedIn.empty()) 1142 OS << "@M@" << ExtSymDefinedIn << '@'; 1143 OS << "objc(pl)" << Prot; 1144 } 1145 1146 void clang::index::generateUSRForGlobalEnum(StringRef EnumName, raw_ostream &OS, 1147 StringRef ExtSymDefinedIn) { 1148 if (!ExtSymDefinedIn.empty()) 1149 OS << "@M@" << ExtSymDefinedIn; 1150 OS << "@E@" << EnumName; 1151 } 1152 1153 void clang::index::generateUSRForEnumConstant(StringRef EnumConstantName, 1154 raw_ostream &OS) { 1155 OS << '@' << EnumConstantName; 1156 } 1157 1158 bool clang::index::generateUSRForDecl(const Decl *D, 1159 SmallVectorImpl<char> &Buf) { 1160 if (!D) 1161 return true; 1162 // We don't ignore decls with invalid source locations. Implicit decls, like 1163 // C++'s operator new function, can have invalid locations but it is fine to 1164 // create USRs that can identify them. 1165 1166 // Check if the declaration has explicit external USR specified. 1167 auto *CD = D->getCanonicalDecl(); 1168 if (auto *ExternalSymAttr = CD->getAttr<ExternalSourceSymbolAttr>()) { 1169 if (!ExternalSymAttr->getUSR().empty()) { 1170 llvm::raw_svector_ostream Out(Buf); 1171 Out << ExternalSymAttr->getUSR(); 1172 return false; 1173 } 1174 } 1175 USRGenerator UG(&D->getASTContext(), Buf); 1176 UG.Visit(D); 1177 return UG.ignoreResults(); 1178 } 1179 1180 bool clang::index::generateUSRForMacro(const MacroDefinitionRecord *MD, 1181 const SourceManager &SM, 1182 SmallVectorImpl<char> &Buf) { 1183 if (!MD) 1184 return true; 1185 return generateUSRForMacro(MD->getName()->getName(), MD->getLocation(), 1186 SM, Buf); 1187 1188 } 1189 1190 bool clang::index::generateUSRForMacro(StringRef MacroName, SourceLocation Loc, 1191 const SourceManager &SM, 1192 SmallVectorImpl<char> &Buf) { 1193 if (MacroName.empty()) 1194 return true; 1195 1196 llvm::raw_svector_ostream Out(Buf); 1197 1198 // Assume that system headers are sane. Don't put source location 1199 // information into the USR if the macro comes from a system header. 1200 bool ShouldGenerateLocation = Loc.isValid() && !SM.isInSystemHeader(Loc); 1201 1202 Out << getUSRSpacePrefix(); 1203 if (ShouldGenerateLocation) 1204 printLoc(Out, Loc, SM, /*IncludeOffset=*/true); 1205 Out << "@macro@"; 1206 Out << MacroName; 1207 return false; 1208 } 1209 1210 bool clang::index::generateUSRForType(QualType T, ASTContext &Ctx, 1211 SmallVectorImpl<char> &Buf) { 1212 if (T.isNull()) 1213 return true; 1214 T = T.getCanonicalType(); 1215 1216 USRGenerator UG(&Ctx, Buf); 1217 UG.VisitType(T); 1218 return UG.ignoreResults(); 1219 } 1220 1221 bool clang::index::generateFullUSRForModule(const Module *Mod, 1222 raw_ostream &OS) { 1223 if (!Mod->Parent) 1224 return generateFullUSRForTopLevelModuleName(Mod->Name, OS); 1225 if (generateFullUSRForModule(Mod->Parent, OS)) 1226 return true; 1227 return generateUSRFragmentForModule(Mod, OS); 1228 } 1229 1230 bool clang::index::generateFullUSRForTopLevelModuleName(StringRef ModName, 1231 raw_ostream &OS) { 1232 OS << getUSRSpacePrefix(); 1233 return generateUSRFragmentForModuleName(ModName, OS); 1234 } 1235 1236 bool clang::index::generateUSRFragmentForModule(const Module *Mod, 1237 raw_ostream &OS) { 1238 return generateUSRFragmentForModuleName(Mod->Name, OS); 1239 } 1240 1241 bool clang::index::generateUSRFragmentForModuleName(StringRef ModName, 1242 raw_ostream &OS) { 1243 OS << "@M@" << ModName; 1244 return false; 1245 } 1246