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