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