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

source code of clang/lib/Index/USRGeneration.cpp