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

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