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