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