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