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