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