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