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