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