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