xref: /minix3/external/bsd/llvm/dist/clang/lib/Index/USRGeneration.cpp (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1f4a2713aSLionel Sambuc //===- USRGeneration.cpp - Routines for USR generation --------------------===//
2f4a2713aSLionel Sambuc //
3f4a2713aSLionel Sambuc //                     The LLVM Compiler Infrastructure
4f4a2713aSLionel Sambuc //
5f4a2713aSLionel Sambuc // This file is distributed under the University of Illinois Open Source
6f4a2713aSLionel Sambuc // License. See LICENSE.TXT for details.
7f4a2713aSLionel Sambuc //
8f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
9f4a2713aSLionel Sambuc 
10f4a2713aSLionel Sambuc #include "clang/Index/USRGeneration.h"
11f4a2713aSLionel Sambuc #include "clang/AST/ASTContext.h"
12f4a2713aSLionel Sambuc #include "clang/AST/DeclTemplate.h"
13f4a2713aSLionel Sambuc #include "clang/AST/DeclVisitor.h"
14*0a6a1f1dSLionel Sambuc #include "clang/Lex/PreprocessingRecord.h"
15f4a2713aSLionel Sambuc #include "llvm/ADT/SmallString.h"
16f4a2713aSLionel Sambuc #include "llvm/Support/Path.h"
17f4a2713aSLionel Sambuc #include "llvm/Support/raw_ostream.h"
18f4a2713aSLionel Sambuc 
19f4a2713aSLionel Sambuc using namespace clang;
20f4a2713aSLionel Sambuc using namespace clang::index;
21f4a2713aSLionel Sambuc 
22f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
23f4a2713aSLionel Sambuc // USR generation.
24f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
25f4a2713aSLionel Sambuc 
26*0a6a1f1dSLionel Sambuc /// \returns true on error.
printLoc(llvm::raw_ostream & OS,SourceLocation Loc,const SourceManager & SM,bool IncludeOffset)27*0a6a1f1dSLionel Sambuc static bool printLoc(llvm::raw_ostream &OS, SourceLocation Loc,
28*0a6a1f1dSLionel Sambuc                      const SourceManager &SM, bool IncludeOffset) {
29*0a6a1f1dSLionel Sambuc   if (Loc.isInvalid()) {
30*0a6a1f1dSLionel Sambuc     return true;
31*0a6a1f1dSLionel Sambuc   }
32*0a6a1f1dSLionel Sambuc   Loc = SM.getExpansionLoc(Loc);
33*0a6a1f1dSLionel Sambuc   const std::pair<FileID, unsigned> &Decomposed = SM.getDecomposedLoc(Loc);
34*0a6a1f1dSLionel Sambuc   const FileEntry *FE = SM.getFileEntryForID(Decomposed.first);
35*0a6a1f1dSLionel Sambuc   if (FE) {
36*0a6a1f1dSLionel Sambuc     OS << llvm::sys::path::filename(FE->getName());
37*0a6a1f1dSLionel Sambuc   } else {
38*0a6a1f1dSLionel Sambuc     // This case really isn't interesting.
39*0a6a1f1dSLionel Sambuc     return true;
40*0a6a1f1dSLionel Sambuc   }
41*0a6a1f1dSLionel Sambuc   if (IncludeOffset) {
42*0a6a1f1dSLionel Sambuc     // Use the offest into the FileID to represent the location.  Using
43*0a6a1f1dSLionel Sambuc     // a line/column can cause us to look back at the original source file,
44*0a6a1f1dSLionel Sambuc     // which is expensive.
45*0a6a1f1dSLionel Sambuc     OS << '@' << Decomposed.second;
46*0a6a1f1dSLionel Sambuc   }
47*0a6a1f1dSLionel Sambuc   return false;
48*0a6a1f1dSLionel Sambuc }
49*0a6a1f1dSLionel Sambuc 
50f4a2713aSLionel Sambuc namespace {
51f4a2713aSLionel Sambuc class USRGenerator : public ConstDeclVisitor<USRGenerator> {
52f4a2713aSLionel Sambuc   SmallVectorImpl<char> &Buf;
53f4a2713aSLionel Sambuc   llvm::raw_svector_ostream Out;
54f4a2713aSLionel Sambuc   bool IgnoreResults;
55f4a2713aSLionel Sambuc   ASTContext *Context;
56f4a2713aSLionel Sambuc   bool generatedLoc;
57f4a2713aSLionel Sambuc 
58f4a2713aSLionel Sambuc   llvm::DenseMap<const Type *, unsigned> TypeSubstitutions;
59f4a2713aSLionel Sambuc 
60f4a2713aSLionel Sambuc public:
USRGenerator(ASTContext * Ctx,SmallVectorImpl<char> & Buf)61f4a2713aSLionel Sambuc   explicit USRGenerator(ASTContext *Ctx, SmallVectorImpl<char> &Buf)
62f4a2713aSLionel Sambuc   : Buf(Buf),
63f4a2713aSLionel Sambuc     Out(Buf),
64f4a2713aSLionel Sambuc     IgnoreResults(false),
65f4a2713aSLionel Sambuc     Context(Ctx),
66f4a2713aSLionel Sambuc     generatedLoc(false)
67f4a2713aSLionel Sambuc   {
68f4a2713aSLionel Sambuc     // Add the USR space prefix.
69f4a2713aSLionel Sambuc     Out << getUSRSpacePrefix();
70f4a2713aSLionel Sambuc   }
71f4a2713aSLionel Sambuc 
ignoreResults() const72f4a2713aSLionel Sambuc   bool ignoreResults() const { return IgnoreResults; }
73f4a2713aSLionel Sambuc 
74f4a2713aSLionel Sambuc   // Visitation methods from generating USRs from AST elements.
75f4a2713aSLionel Sambuc   void VisitDeclContext(const DeclContext *D);
76f4a2713aSLionel Sambuc   void VisitFieldDecl(const FieldDecl *D);
77f4a2713aSLionel Sambuc   void VisitFunctionDecl(const FunctionDecl *D);
78f4a2713aSLionel Sambuc   void VisitNamedDecl(const NamedDecl *D);
79f4a2713aSLionel Sambuc   void VisitNamespaceDecl(const NamespaceDecl *D);
80f4a2713aSLionel Sambuc   void VisitNamespaceAliasDecl(const NamespaceAliasDecl *D);
81f4a2713aSLionel Sambuc   void VisitFunctionTemplateDecl(const FunctionTemplateDecl *D);
82f4a2713aSLionel Sambuc   void VisitClassTemplateDecl(const ClassTemplateDecl *D);
83f4a2713aSLionel Sambuc   void VisitObjCContainerDecl(const ObjCContainerDecl *CD);
84f4a2713aSLionel Sambuc   void VisitObjCMethodDecl(const ObjCMethodDecl *MD);
85f4a2713aSLionel Sambuc   void VisitObjCPropertyDecl(const ObjCPropertyDecl *D);
86f4a2713aSLionel Sambuc   void VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D);
87f4a2713aSLionel Sambuc   void VisitTagDecl(const TagDecl *D);
88f4a2713aSLionel Sambuc   void VisitTypedefDecl(const TypedefDecl *D);
89f4a2713aSLionel Sambuc   void VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D);
90f4a2713aSLionel Sambuc   void VisitVarDecl(const VarDecl *D);
91f4a2713aSLionel Sambuc   void VisitNonTypeTemplateParmDecl(const NonTypeTemplateParmDecl *D);
92f4a2713aSLionel Sambuc   void VisitTemplateTemplateParmDecl(const TemplateTemplateParmDecl *D);
VisitLinkageSpecDecl(const LinkageSpecDecl * D)93f4a2713aSLionel Sambuc   void VisitLinkageSpecDecl(const LinkageSpecDecl *D) {
94f4a2713aSLionel Sambuc     IgnoreResults = true;
95f4a2713aSLionel Sambuc   }
VisitUsingDirectiveDecl(const UsingDirectiveDecl * D)96f4a2713aSLionel Sambuc   void VisitUsingDirectiveDecl(const UsingDirectiveDecl *D) {
97f4a2713aSLionel Sambuc     IgnoreResults = true;
98f4a2713aSLionel Sambuc   }
VisitUsingDecl(const UsingDecl * D)99f4a2713aSLionel Sambuc   void VisitUsingDecl(const UsingDecl *D) {
100f4a2713aSLionel Sambuc     IgnoreResults = true;
101f4a2713aSLionel Sambuc   }
VisitUnresolvedUsingValueDecl(const UnresolvedUsingValueDecl * D)102f4a2713aSLionel Sambuc   void VisitUnresolvedUsingValueDecl(const UnresolvedUsingValueDecl *D) {
103f4a2713aSLionel Sambuc     IgnoreResults = true;
104f4a2713aSLionel Sambuc   }
VisitUnresolvedUsingTypenameDecl(const UnresolvedUsingTypenameDecl * D)105f4a2713aSLionel Sambuc   void VisitUnresolvedUsingTypenameDecl(const UnresolvedUsingTypenameDecl *D) {
106f4a2713aSLionel Sambuc     IgnoreResults = true;
107f4a2713aSLionel Sambuc   }
108f4a2713aSLionel Sambuc 
109*0a6a1f1dSLionel Sambuc   bool ShouldGenerateLocation(const NamedDecl *D);
110*0a6a1f1dSLionel Sambuc 
isLocal(const NamedDecl * D)111*0a6a1f1dSLionel Sambuc   bool isLocal(const NamedDecl *D) {
112*0a6a1f1dSLionel Sambuc     return D->getParentFunctionOrMethod() != nullptr;
113*0a6a1f1dSLionel Sambuc   }
114*0a6a1f1dSLionel Sambuc 
115f4a2713aSLionel Sambuc   /// Generate the string component containing the location of the
116f4a2713aSLionel Sambuc   ///  declaration.
117*0a6a1f1dSLionel Sambuc   bool GenLoc(const Decl *D, bool IncludeOffset);
118f4a2713aSLionel Sambuc 
119f4a2713aSLionel Sambuc   /// String generation methods used both by the visitation methods
120f4a2713aSLionel Sambuc   /// and from other clients that want to directly generate USRs.  These
121f4a2713aSLionel Sambuc   /// methods do not construct complete USRs (which incorporate the parents
122f4a2713aSLionel Sambuc   /// of an AST element), but only the fragments concerning the AST element
123f4a2713aSLionel Sambuc   /// itself.
124f4a2713aSLionel Sambuc 
125f4a2713aSLionel Sambuc   /// Generate a USR for an Objective-C class.
GenObjCClass(StringRef cls)126f4a2713aSLionel Sambuc   void GenObjCClass(StringRef cls) {
127f4a2713aSLionel Sambuc     generateUSRForObjCClass(cls, Out);
128f4a2713aSLionel Sambuc   }
129f4a2713aSLionel Sambuc   /// Generate a USR for an Objective-C class category.
GenObjCCategory(StringRef cls,StringRef cat)130f4a2713aSLionel Sambuc   void GenObjCCategory(StringRef cls, StringRef cat) {
131f4a2713aSLionel Sambuc     generateUSRForObjCCategory(cls, cat, Out);
132f4a2713aSLionel Sambuc   }
133f4a2713aSLionel Sambuc   /// Generate a USR fragment for an Objective-C property.
GenObjCProperty(StringRef prop)134f4a2713aSLionel Sambuc   void GenObjCProperty(StringRef prop) {
135f4a2713aSLionel Sambuc     generateUSRForObjCProperty(prop, Out);
136f4a2713aSLionel Sambuc   }
137f4a2713aSLionel Sambuc   /// Generate a USR for an Objective-C protocol.
GenObjCProtocol(StringRef prot)138f4a2713aSLionel Sambuc   void GenObjCProtocol(StringRef prot) {
139f4a2713aSLionel Sambuc     generateUSRForObjCProtocol(prot, Out);
140f4a2713aSLionel Sambuc   }
141f4a2713aSLionel Sambuc 
142f4a2713aSLionel Sambuc   void VisitType(QualType T);
143f4a2713aSLionel Sambuc   void VisitTemplateParameterList(const TemplateParameterList *Params);
144f4a2713aSLionel Sambuc   void VisitTemplateName(TemplateName Name);
145f4a2713aSLionel Sambuc   void VisitTemplateArgument(const TemplateArgument &Arg);
146f4a2713aSLionel Sambuc 
147f4a2713aSLionel Sambuc   /// Emit a Decl's name using NamedDecl::printName() and return true if
148f4a2713aSLionel Sambuc   ///  the decl had no name.
149f4a2713aSLionel Sambuc   bool EmitDeclName(const NamedDecl *D);
150f4a2713aSLionel Sambuc };
151f4a2713aSLionel Sambuc 
152f4a2713aSLionel Sambuc } // end anonymous namespace
153f4a2713aSLionel Sambuc 
154f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
155f4a2713aSLionel Sambuc // Generating USRs from ASTS.
156f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
157f4a2713aSLionel Sambuc 
EmitDeclName(const NamedDecl * D)158f4a2713aSLionel Sambuc bool USRGenerator::EmitDeclName(const NamedDecl *D) {
159f4a2713aSLionel Sambuc   Out.flush();
160f4a2713aSLionel Sambuc   const unsigned startSize = Buf.size();
161f4a2713aSLionel Sambuc   D->printName(Out);
162f4a2713aSLionel Sambuc   Out.flush();
163f4a2713aSLionel Sambuc   const unsigned endSize = Buf.size();
164f4a2713aSLionel Sambuc   return startSize == endSize;
165f4a2713aSLionel Sambuc }
166f4a2713aSLionel Sambuc 
ShouldGenerateLocation(const NamedDecl * D)167*0a6a1f1dSLionel Sambuc bool USRGenerator::ShouldGenerateLocation(const NamedDecl *D) {
168*0a6a1f1dSLionel Sambuc   if (D->isExternallyVisible())
169*0a6a1f1dSLionel Sambuc     return false;
170*0a6a1f1dSLionel Sambuc   if (D->getParentFunctionOrMethod())
171*0a6a1f1dSLionel Sambuc     return true;
172*0a6a1f1dSLionel Sambuc   const SourceManager &SM = Context->getSourceManager();
173*0a6a1f1dSLionel Sambuc   return !SM.isInSystemHeader(D->getLocation());
174f4a2713aSLionel Sambuc }
175f4a2713aSLionel Sambuc 
VisitDeclContext(const DeclContext * DC)176f4a2713aSLionel Sambuc void USRGenerator::VisitDeclContext(const DeclContext *DC) {
177f4a2713aSLionel Sambuc   if (const NamedDecl *D = dyn_cast<NamedDecl>(DC))
178f4a2713aSLionel Sambuc     Visit(D);
179f4a2713aSLionel Sambuc }
180f4a2713aSLionel Sambuc 
VisitFieldDecl(const FieldDecl * D)181f4a2713aSLionel Sambuc void USRGenerator::VisitFieldDecl(const FieldDecl *D) {
182f4a2713aSLionel Sambuc   // The USR for an ivar declared in a class extension is based on the
183f4a2713aSLionel Sambuc   // ObjCInterfaceDecl, not the ObjCCategoryDecl.
184f4a2713aSLionel Sambuc   if (const ObjCInterfaceDecl *ID = Context->getObjContainingInterface(D))
185f4a2713aSLionel Sambuc     Visit(ID);
186f4a2713aSLionel Sambuc   else
187f4a2713aSLionel Sambuc     VisitDeclContext(D->getDeclContext());
188f4a2713aSLionel Sambuc   Out << (isa<ObjCIvarDecl>(D) ? "@" : "@FI@");
189f4a2713aSLionel Sambuc   if (EmitDeclName(D)) {
190f4a2713aSLionel Sambuc     // Bit fields can be anonymous.
191f4a2713aSLionel Sambuc     IgnoreResults = true;
192f4a2713aSLionel Sambuc     return;
193f4a2713aSLionel Sambuc   }
194f4a2713aSLionel Sambuc }
195f4a2713aSLionel Sambuc 
VisitFunctionDecl(const FunctionDecl * D)196f4a2713aSLionel Sambuc void USRGenerator::VisitFunctionDecl(const FunctionDecl *D) {
197*0a6a1f1dSLionel Sambuc   if (ShouldGenerateLocation(D) && GenLoc(D, /*IncludeOffset=*/isLocal(D)))
198f4a2713aSLionel Sambuc     return;
199f4a2713aSLionel Sambuc 
200f4a2713aSLionel Sambuc   VisitDeclContext(D->getDeclContext());
201*0a6a1f1dSLionel Sambuc   bool IsTemplate = false;
202f4a2713aSLionel Sambuc   if (FunctionTemplateDecl *FunTmpl = D->getDescribedFunctionTemplate()) {
203*0a6a1f1dSLionel Sambuc     IsTemplate = true;
204f4a2713aSLionel Sambuc     Out << "@FT@";
205f4a2713aSLionel Sambuc     VisitTemplateParameterList(FunTmpl->getTemplateParameters());
206f4a2713aSLionel Sambuc   } else
207f4a2713aSLionel Sambuc     Out << "@F@";
208f4a2713aSLionel Sambuc   D->printName(Out);
209f4a2713aSLionel Sambuc 
210f4a2713aSLionel Sambuc   ASTContext &Ctx = *Context;
211f4a2713aSLionel Sambuc   if (!Ctx.getLangOpts().CPlusPlus || D->isExternC())
212f4a2713aSLionel Sambuc     return;
213f4a2713aSLionel Sambuc 
214f4a2713aSLionel Sambuc   if (const TemplateArgumentList *
215f4a2713aSLionel Sambuc         SpecArgs = D->getTemplateSpecializationArgs()) {
216f4a2713aSLionel Sambuc     Out << '<';
217f4a2713aSLionel Sambuc     for (unsigned I = 0, N = SpecArgs->size(); I != N; ++I) {
218f4a2713aSLionel Sambuc       Out << '#';
219f4a2713aSLionel Sambuc       VisitTemplateArgument(SpecArgs->get(I));
220f4a2713aSLionel Sambuc     }
221f4a2713aSLionel Sambuc     Out << '>';
222f4a2713aSLionel Sambuc   }
223f4a2713aSLionel Sambuc 
224f4a2713aSLionel Sambuc   // Mangle in type information for the arguments.
225*0a6a1f1dSLionel Sambuc   for (auto PD : D->params()) {
226f4a2713aSLionel Sambuc     Out << '#';
227f4a2713aSLionel Sambuc     VisitType(PD->getType());
228f4a2713aSLionel Sambuc   }
229f4a2713aSLionel Sambuc   if (D->isVariadic())
230f4a2713aSLionel Sambuc     Out << '.';
231*0a6a1f1dSLionel Sambuc   if (IsTemplate) {
232*0a6a1f1dSLionel Sambuc     // Function templates can be overloaded by return type, for example:
233*0a6a1f1dSLionel Sambuc     // \code
234*0a6a1f1dSLionel Sambuc     //   template <class T> typename T::A foo() {}
235*0a6a1f1dSLionel Sambuc     //   template <class T> typename T::B foo() {}
236*0a6a1f1dSLionel Sambuc     // \endcode
237*0a6a1f1dSLionel Sambuc     Out << '#';
238*0a6a1f1dSLionel Sambuc     VisitType(D->getReturnType());
239*0a6a1f1dSLionel Sambuc   }
240f4a2713aSLionel Sambuc   Out << '#';
241f4a2713aSLionel Sambuc   if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {
242f4a2713aSLionel Sambuc     if (MD->isStatic())
243f4a2713aSLionel Sambuc       Out << 'S';
244f4a2713aSLionel Sambuc     if (unsigned quals = MD->getTypeQualifiers())
245f4a2713aSLionel Sambuc       Out << (char)('0' + quals);
246*0a6a1f1dSLionel Sambuc     switch (MD->getRefQualifier()) {
247*0a6a1f1dSLionel Sambuc     case RQ_None: break;
248*0a6a1f1dSLionel Sambuc     case RQ_LValue: Out << '&'; break;
249*0a6a1f1dSLionel Sambuc     case RQ_RValue: Out << "&&"; break;
250*0a6a1f1dSLionel Sambuc     }
251f4a2713aSLionel Sambuc   }
252f4a2713aSLionel Sambuc }
253f4a2713aSLionel Sambuc 
VisitNamedDecl(const NamedDecl * D)254f4a2713aSLionel Sambuc void USRGenerator::VisitNamedDecl(const NamedDecl *D) {
255f4a2713aSLionel Sambuc   VisitDeclContext(D->getDeclContext());
256f4a2713aSLionel Sambuc   Out << "@";
257f4a2713aSLionel Sambuc 
258f4a2713aSLionel Sambuc   if (EmitDeclName(D)) {
259f4a2713aSLionel Sambuc     // The string can be empty if the declaration has no name; e.g., it is
260f4a2713aSLionel Sambuc     // the ParmDecl with no name for declaration of a function pointer type,
261f4a2713aSLionel Sambuc     // e.g.: void  (*f)(void *);
262f4a2713aSLionel Sambuc     // In this case, don't generate a USR.
263f4a2713aSLionel Sambuc     IgnoreResults = true;
264f4a2713aSLionel Sambuc   }
265f4a2713aSLionel Sambuc }
266f4a2713aSLionel Sambuc 
VisitVarDecl(const VarDecl * D)267f4a2713aSLionel Sambuc void USRGenerator::VisitVarDecl(const VarDecl *D) {
268f4a2713aSLionel Sambuc   // VarDecls can be declared 'extern' within a function or method body,
269f4a2713aSLionel Sambuc   // but their enclosing DeclContext is the function, not the TU.  We need
270f4a2713aSLionel Sambuc   // to check the storage class to correctly generate the USR.
271*0a6a1f1dSLionel Sambuc   if (ShouldGenerateLocation(D) && GenLoc(D, /*IncludeOffset=*/isLocal(D)))
272f4a2713aSLionel Sambuc     return;
273f4a2713aSLionel Sambuc 
274f4a2713aSLionel Sambuc   VisitDeclContext(D->getDeclContext());
275f4a2713aSLionel Sambuc 
276f4a2713aSLionel Sambuc   // Variables always have simple names.
277f4a2713aSLionel Sambuc   StringRef s = D->getName();
278f4a2713aSLionel Sambuc 
279f4a2713aSLionel Sambuc   // The string can be empty if the declaration has no name; e.g., it is
280f4a2713aSLionel Sambuc   // the ParmDecl with no name for declaration of a function pointer type, e.g.:
281f4a2713aSLionel Sambuc   //    void  (*f)(void *);
282f4a2713aSLionel Sambuc   // In this case, don't generate a USR.
283f4a2713aSLionel Sambuc   if (s.empty())
284f4a2713aSLionel Sambuc     IgnoreResults = true;
285f4a2713aSLionel Sambuc   else
286f4a2713aSLionel Sambuc     Out << '@' << s;
287f4a2713aSLionel Sambuc }
288f4a2713aSLionel Sambuc 
VisitNonTypeTemplateParmDecl(const NonTypeTemplateParmDecl * D)289f4a2713aSLionel Sambuc void USRGenerator::VisitNonTypeTemplateParmDecl(
290f4a2713aSLionel Sambuc                                         const NonTypeTemplateParmDecl *D) {
291*0a6a1f1dSLionel Sambuc   GenLoc(D, /*IncludeOffset=*/true);
292f4a2713aSLionel Sambuc   return;
293f4a2713aSLionel Sambuc }
294f4a2713aSLionel Sambuc 
VisitTemplateTemplateParmDecl(const TemplateTemplateParmDecl * D)295f4a2713aSLionel Sambuc void USRGenerator::VisitTemplateTemplateParmDecl(
296f4a2713aSLionel Sambuc                                         const TemplateTemplateParmDecl *D) {
297*0a6a1f1dSLionel Sambuc   GenLoc(D, /*IncludeOffset=*/true);
298f4a2713aSLionel Sambuc   return;
299f4a2713aSLionel Sambuc }
300f4a2713aSLionel Sambuc 
VisitNamespaceDecl(const NamespaceDecl * D)301f4a2713aSLionel Sambuc void USRGenerator::VisitNamespaceDecl(const NamespaceDecl *D) {
302f4a2713aSLionel Sambuc   if (D->isAnonymousNamespace()) {
303f4a2713aSLionel Sambuc     Out << "@aN";
304f4a2713aSLionel Sambuc     return;
305f4a2713aSLionel Sambuc   }
306f4a2713aSLionel Sambuc 
307f4a2713aSLionel Sambuc   VisitDeclContext(D->getDeclContext());
308f4a2713aSLionel Sambuc   if (!IgnoreResults)
309f4a2713aSLionel Sambuc     Out << "@N@" << D->getName();
310f4a2713aSLionel Sambuc }
311f4a2713aSLionel Sambuc 
VisitFunctionTemplateDecl(const FunctionTemplateDecl * D)312f4a2713aSLionel Sambuc void USRGenerator::VisitFunctionTemplateDecl(const FunctionTemplateDecl *D) {
313f4a2713aSLionel Sambuc   VisitFunctionDecl(D->getTemplatedDecl());
314f4a2713aSLionel Sambuc }
315f4a2713aSLionel Sambuc 
VisitClassTemplateDecl(const ClassTemplateDecl * D)316f4a2713aSLionel Sambuc void USRGenerator::VisitClassTemplateDecl(const ClassTemplateDecl *D) {
317f4a2713aSLionel Sambuc   VisitTagDecl(D->getTemplatedDecl());
318f4a2713aSLionel Sambuc }
319f4a2713aSLionel Sambuc 
VisitNamespaceAliasDecl(const NamespaceAliasDecl * D)320f4a2713aSLionel Sambuc void USRGenerator::VisitNamespaceAliasDecl(const NamespaceAliasDecl *D) {
321f4a2713aSLionel Sambuc   VisitDeclContext(D->getDeclContext());
322f4a2713aSLionel Sambuc   if (!IgnoreResults)
323f4a2713aSLionel Sambuc     Out << "@NA@" << D->getName();
324f4a2713aSLionel Sambuc }
325f4a2713aSLionel Sambuc 
VisitObjCMethodDecl(const ObjCMethodDecl * D)326f4a2713aSLionel Sambuc void USRGenerator::VisitObjCMethodDecl(const ObjCMethodDecl *D) {
327f4a2713aSLionel Sambuc   const DeclContext *container = D->getDeclContext();
328f4a2713aSLionel Sambuc   if (const ObjCProtocolDecl *pd = dyn_cast<ObjCProtocolDecl>(container)) {
329f4a2713aSLionel Sambuc     Visit(pd);
330f4a2713aSLionel Sambuc   }
331f4a2713aSLionel Sambuc   else {
332f4a2713aSLionel Sambuc     // The USR for a method declared in a class extension or category is based on
333f4a2713aSLionel Sambuc     // the ObjCInterfaceDecl, not the ObjCCategoryDecl.
334f4a2713aSLionel Sambuc     const ObjCInterfaceDecl *ID = D->getClassInterface();
335f4a2713aSLionel Sambuc     if (!ID) {
336f4a2713aSLionel Sambuc       IgnoreResults = true;
337f4a2713aSLionel Sambuc       return;
338f4a2713aSLionel Sambuc     }
339f4a2713aSLionel Sambuc     Visit(ID);
340f4a2713aSLionel Sambuc   }
341f4a2713aSLionel Sambuc   // Ideally we would use 'GenObjCMethod', but this is such a hot path
342f4a2713aSLionel Sambuc   // for Objective-C code that we don't want to use
343f4a2713aSLionel Sambuc   // DeclarationName::getAsString().
344f4a2713aSLionel Sambuc   Out << (D->isInstanceMethod() ? "(im)" : "(cm)")
345f4a2713aSLionel Sambuc       << DeclarationName(D->getSelector());
346f4a2713aSLionel Sambuc }
347f4a2713aSLionel Sambuc 
VisitObjCContainerDecl(const ObjCContainerDecl * D)348f4a2713aSLionel Sambuc void USRGenerator::VisitObjCContainerDecl(const ObjCContainerDecl *D) {
349f4a2713aSLionel Sambuc   switch (D->getKind()) {
350f4a2713aSLionel Sambuc     default:
351f4a2713aSLionel Sambuc       llvm_unreachable("Invalid ObjC container.");
352f4a2713aSLionel Sambuc     case Decl::ObjCInterface:
353f4a2713aSLionel Sambuc     case Decl::ObjCImplementation:
354f4a2713aSLionel Sambuc       GenObjCClass(D->getName());
355f4a2713aSLionel Sambuc       break;
356f4a2713aSLionel Sambuc     case Decl::ObjCCategory: {
357f4a2713aSLionel Sambuc       const ObjCCategoryDecl *CD = cast<ObjCCategoryDecl>(D);
358f4a2713aSLionel Sambuc       const ObjCInterfaceDecl *ID = CD->getClassInterface();
359f4a2713aSLionel Sambuc       if (!ID) {
360f4a2713aSLionel Sambuc         // Handle invalid code where the @interface might not
361f4a2713aSLionel Sambuc         // have been specified.
362f4a2713aSLionel Sambuc         // FIXME: We should be able to generate this USR even if the
363f4a2713aSLionel Sambuc         // @interface isn't available.
364f4a2713aSLionel Sambuc         IgnoreResults = true;
365f4a2713aSLionel Sambuc         return;
366f4a2713aSLionel Sambuc       }
367f4a2713aSLionel Sambuc       // Specially handle class extensions, which are anonymous categories.
368f4a2713aSLionel Sambuc       // We want to mangle in the location to uniquely distinguish them.
369f4a2713aSLionel Sambuc       if (CD->IsClassExtension()) {
370f4a2713aSLionel Sambuc         Out << "objc(ext)" << ID->getName() << '@';
371*0a6a1f1dSLionel Sambuc         GenLoc(CD, /*IncludeOffset=*/true);
372f4a2713aSLionel Sambuc       }
373f4a2713aSLionel Sambuc       else
374f4a2713aSLionel Sambuc         GenObjCCategory(ID->getName(), CD->getName());
375f4a2713aSLionel Sambuc 
376f4a2713aSLionel Sambuc       break;
377f4a2713aSLionel Sambuc     }
378f4a2713aSLionel Sambuc     case Decl::ObjCCategoryImpl: {
379f4a2713aSLionel Sambuc       const ObjCCategoryImplDecl *CD = cast<ObjCCategoryImplDecl>(D);
380f4a2713aSLionel Sambuc       const ObjCInterfaceDecl *ID = CD->getClassInterface();
381f4a2713aSLionel Sambuc       if (!ID) {
382f4a2713aSLionel Sambuc         // Handle invalid code where the @interface might not
383f4a2713aSLionel Sambuc         // have been specified.
384f4a2713aSLionel Sambuc         // FIXME: We should be able to generate this USR even if the
385f4a2713aSLionel Sambuc         // @interface isn't available.
386f4a2713aSLionel Sambuc         IgnoreResults = true;
387f4a2713aSLionel Sambuc         return;
388f4a2713aSLionel Sambuc       }
389f4a2713aSLionel Sambuc       GenObjCCategory(ID->getName(), CD->getName());
390f4a2713aSLionel Sambuc       break;
391f4a2713aSLionel Sambuc     }
392f4a2713aSLionel Sambuc     case Decl::ObjCProtocol:
393f4a2713aSLionel Sambuc       GenObjCProtocol(cast<ObjCProtocolDecl>(D)->getName());
394f4a2713aSLionel Sambuc       break;
395f4a2713aSLionel Sambuc   }
396f4a2713aSLionel Sambuc }
397f4a2713aSLionel Sambuc 
VisitObjCPropertyDecl(const ObjCPropertyDecl * D)398f4a2713aSLionel Sambuc void USRGenerator::VisitObjCPropertyDecl(const ObjCPropertyDecl *D) {
399f4a2713aSLionel Sambuc   // The USR for a property declared in a class extension or category is based
400f4a2713aSLionel Sambuc   // on the ObjCInterfaceDecl, not the ObjCCategoryDecl.
401f4a2713aSLionel Sambuc   if (const ObjCInterfaceDecl *ID = Context->getObjContainingInterface(D))
402f4a2713aSLionel Sambuc     Visit(ID);
403f4a2713aSLionel Sambuc   else
404f4a2713aSLionel Sambuc     Visit(cast<Decl>(D->getDeclContext()));
405f4a2713aSLionel Sambuc   GenObjCProperty(D->getName());
406f4a2713aSLionel Sambuc }
407f4a2713aSLionel Sambuc 
VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl * D)408f4a2713aSLionel Sambuc void USRGenerator::VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D) {
409f4a2713aSLionel Sambuc   if (ObjCPropertyDecl *PD = D->getPropertyDecl()) {
410f4a2713aSLionel Sambuc     VisitObjCPropertyDecl(PD);
411f4a2713aSLionel Sambuc     return;
412f4a2713aSLionel Sambuc   }
413f4a2713aSLionel Sambuc 
414f4a2713aSLionel Sambuc   IgnoreResults = true;
415f4a2713aSLionel Sambuc }
416f4a2713aSLionel Sambuc 
VisitTagDecl(const TagDecl * D)417f4a2713aSLionel Sambuc void USRGenerator::VisitTagDecl(const TagDecl *D) {
418f4a2713aSLionel Sambuc   // Add the location of the tag decl to handle resolution across
419f4a2713aSLionel Sambuc   // translation units.
420*0a6a1f1dSLionel Sambuc   if (ShouldGenerateLocation(D) && GenLoc(D, /*IncludeOffset=*/isLocal(D)))
421f4a2713aSLionel Sambuc     return;
422f4a2713aSLionel Sambuc 
423f4a2713aSLionel Sambuc   D = D->getCanonicalDecl();
424f4a2713aSLionel Sambuc   VisitDeclContext(D->getDeclContext());
425f4a2713aSLionel Sambuc 
426f4a2713aSLionel Sambuc   bool AlreadyStarted = false;
427f4a2713aSLionel Sambuc   if (const CXXRecordDecl *CXXRecord = dyn_cast<CXXRecordDecl>(D)) {
428f4a2713aSLionel Sambuc     if (ClassTemplateDecl *ClassTmpl = CXXRecord->getDescribedClassTemplate()) {
429f4a2713aSLionel Sambuc       AlreadyStarted = true;
430f4a2713aSLionel Sambuc 
431f4a2713aSLionel Sambuc       switch (D->getTagKind()) {
432f4a2713aSLionel Sambuc       case TTK_Interface:
433*0a6a1f1dSLionel Sambuc       case TTK_Class:
434f4a2713aSLionel Sambuc       case TTK_Struct: Out << "@ST"; break;
435f4a2713aSLionel Sambuc       case TTK_Union:  Out << "@UT"; break;
436f4a2713aSLionel Sambuc       case TTK_Enum: llvm_unreachable("enum template");
437f4a2713aSLionel Sambuc       }
438f4a2713aSLionel Sambuc       VisitTemplateParameterList(ClassTmpl->getTemplateParameters());
439f4a2713aSLionel Sambuc     } else if (const ClassTemplatePartialSpecializationDecl *PartialSpec
440f4a2713aSLionel Sambuc                 = dyn_cast<ClassTemplatePartialSpecializationDecl>(CXXRecord)) {
441f4a2713aSLionel Sambuc       AlreadyStarted = true;
442f4a2713aSLionel Sambuc 
443f4a2713aSLionel Sambuc       switch (D->getTagKind()) {
444f4a2713aSLionel Sambuc       case TTK_Interface:
445*0a6a1f1dSLionel Sambuc       case TTK_Class:
446f4a2713aSLionel Sambuc       case TTK_Struct: Out << "@SP"; break;
447f4a2713aSLionel Sambuc       case TTK_Union:  Out << "@UP"; break;
448f4a2713aSLionel Sambuc       case TTK_Enum: llvm_unreachable("enum partial specialization");
449f4a2713aSLionel Sambuc       }
450f4a2713aSLionel Sambuc       VisitTemplateParameterList(PartialSpec->getTemplateParameters());
451f4a2713aSLionel Sambuc     }
452f4a2713aSLionel Sambuc   }
453f4a2713aSLionel Sambuc 
454f4a2713aSLionel Sambuc   if (!AlreadyStarted) {
455f4a2713aSLionel Sambuc     switch (D->getTagKind()) {
456f4a2713aSLionel Sambuc       case TTK_Interface:
457*0a6a1f1dSLionel Sambuc       case TTK_Class:
458f4a2713aSLionel Sambuc       case TTK_Struct: Out << "@S"; break;
459f4a2713aSLionel Sambuc       case TTK_Union:  Out << "@U"; break;
460f4a2713aSLionel Sambuc       case TTK_Enum:   Out << "@E"; break;
461f4a2713aSLionel Sambuc     }
462f4a2713aSLionel Sambuc   }
463f4a2713aSLionel Sambuc 
464f4a2713aSLionel Sambuc   Out << '@';
465f4a2713aSLionel Sambuc   Out.flush();
466f4a2713aSLionel Sambuc   assert(Buf.size() > 0);
467f4a2713aSLionel Sambuc   const unsigned off = Buf.size() - 1;
468f4a2713aSLionel Sambuc 
469f4a2713aSLionel Sambuc   if (EmitDeclName(D)) {
470f4a2713aSLionel Sambuc     if (const TypedefNameDecl *TD = D->getTypedefNameForAnonDecl()) {
471f4a2713aSLionel Sambuc       Buf[off] = 'A';
472f4a2713aSLionel Sambuc       Out << '@' << *TD;
473f4a2713aSLionel Sambuc     }
474*0a6a1f1dSLionel Sambuc   else {
475*0a6a1f1dSLionel Sambuc     if (D->isEmbeddedInDeclarator() && !D->isFreeStanding()) {
476*0a6a1f1dSLionel Sambuc       printLoc(Out, D->getLocation(), Context->getSourceManager(), true);
477*0a6a1f1dSLionel Sambuc     } else
478f4a2713aSLionel Sambuc       Buf[off] = 'a';
479f4a2713aSLionel Sambuc   }
480*0a6a1f1dSLionel Sambuc   }
481f4a2713aSLionel Sambuc 
482f4a2713aSLionel Sambuc   // For a class template specialization, mangle the template arguments.
483f4a2713aSLionel Sambuc   if (const ClassTemplateSpecializationDecl *Spec
484f4a2713aSLionel Sambuc                               = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
485f4a2713aSLionel Sambuc     const TemplateArgumentList &Args = Spec->getTemplateInstantiationArgs();
486f4a2713aSLionel Sambuc     Out << '>';
487f4a2713aSLionel Sambuc     for (unsigned I = 0, N = Args.size(); I != N; ++I) {
488f4a2713aSLionel Sambuc       Out << '#';
489f4a2713aSLionel Sambuc       VisitTemplateArgument(Args.get(I));
490f4a2713aSLionel Sambuc     }
491f4a2713aSLionel Sambuc   }
492f4a2713aSLionel Sambuc }
493f4a2713aSLionel Sambuc 
VisitTypedefDecl(const TypedefDecl * D)494f4a2713aSLionel Sambuc void USRGenerator::VisitTypedefDecl(const TypedefDecl *D) {
495*0a6a1f1dSLionel Sambuc   if (ShouldGenerateLocation(D) && GenLoc(D, /*IncludeOffset=*/isLocal(D)))
496f4a2713aSLionel Sambuc     return;
497f4a2713aSLionel Sambuc   const DeclContext *DC = D->getDeclContext();
498f4a2713aSLionel Sambuc   if (const NamedDecl *DCN = dyn_cast<NamedDecl>(DC))
499f4a2713aSLionel Sambuc     Visit(DCN);
500f4a2713aSLionel Sambuc   Out << "@T@";
501f4a2713aSLionel Sambuc   Out << D->getName();
502f4a2713aSLionel Sambuc }
503f4a2713aSLionel Sambuc 
VisitTemplateTypeParmDecl(const TemplateTypeParmDecl * D)504f4a2713aSLionel Sambuc void USRGenerator::VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D) {
505*0a6a1f1dSLionel Sambuc   GenLoc(D, /*IncludeOffset=*/true);
506f4a2713aSLionel Sambuc   return;
507f4a2713aSLionel Sambuc }
508f4a2713aSLionel Sambuc 
GenLoc(const Decl * D,bool IncludeOffset)509*0a6a1f1dSLionel Sambuc bool USRGenerator::GenLoc(const Decl *D, bool IncludeOffset) {
510f4a2713aSLionel Sambuc   if (generatedLoc)
511f4a2713aSLionel Sambuc     return IgnoreResults;
512f4a2713aSLionel Sambuc   generatedLoc = true;
513f4a2713aSLionel Sambuc 
514f4a2713aSLionel Sambuc   // Guard against null declarations in invalid code.
515f4a2713aSLionel Sambuc   if (!D) {
516f4a2713aSLionel Sambuc     IgnoreResults = true;
517f4a2713aSLionel Sambuc     return true;
518f4a2713aSLionel Sambuc   }
519f4a2713aSLionel Sambuc 
520f4a2713aSLionel Sambuc   // Use the location of canonical decl.
521f4a2713aSLionel Sambuc   D = D->getCanonicalDecl();
522f4a2713aSLionel Sambuc 
523*0a6a1f1dSLionel Sambuc   IgnoreResults =
524*0a6a1f1dSLionel Sambuc       IgnoreResults || printLoc(Out, D->getLocStart(),
525*0a6a1f1dSLionel Sambuc                                 Context->getSourceManager(), IncludeOffset);
526*0a6a1f1dSLionel Sambuc 
527f4a2713aSLionel Sambuc   return IgnoreResults;
528f4a2713aSLionel Sambuc }
529f4a2713aSLionel Sambuc 
VisitType(QualType T)530f4a2713aSLionel Sambuc void USRGenerator::VisitType(QualType T) {
531f4a2713aSLionel Sambuc   // This method mangles in USR information for types.  It can possibly
532f4a2713aSLionel Sambuc   // just reuse the naming-mangling logic used by codegen, although the
533f4a2713aSLionel Sambuc   // requirements for USRs might not be the same.
534f4a2713aSLionel Sambuc   ASTContext &Ctx = *Context;
535f4a2713aSLionel Sambuc 
536f4a2713aSLionel Sambuc   do {
537f4a2713aSLionel Sambuc     T = Ctx.getCanonicalType(T);
538f4a2713aSLionel Sambuc     Qualifiers Q = T.getQualifiers();
539f4a2713aSLionel Sambuc     unsigned qVal = 0;
540f4a2713aSLionel Sambuc     if (Q.hasConst())
541f4a2713aSLionel Sambuc       qVal |= 0x1;
542f4a2713aSLionel Sambuc     if (Q.hasVolatile())
543f4a2713aSLionel Sambuc       qVal |= 0x2;
544f4a2713aSLionel Sambuc     if (Q.hasRestrict())
545f4a2713aSLionel Sambuc       qVal |= 0x4;
546f4a2713aSLionel Sambuc     if(qVal)
547f4a2713aSLionel Sambuc       Out << ((char) ('0' + qVal));
548f4a2713aSLionel Sambuc 
549f4a2713aSLionel Sambuc     // Mangle in ObjC GC qualifiers?
550f4a2713aSLionel Sambuc 
551f4a2713aSLionel Sambuc     if (const PackExpansionType *Expansion = T->getAs<PackExpansionType>()) {
552f4a2713aSLionel Sambuc       Out << 'P';
553f4a2713aSLionel Sambuc       T = Expansion->getPattern();
554f4a2713aSLionel Sambuc     }
555f4a2713aSLionel Sambuc 
556f4a2713aSLionel Sambuc     if (const BuiltinType *BT = T->getAs<BuiltinType>()) {
557f4a2713aSLionel Sambuc       unsigned char c = '\0';
558f4a2713aSLionel Sambuc       switch (BT->getKind()) {
559f4a2713aSLionel Sambuc         case BuiltinType::Void:
560f4a2713aSLionel Sambuc           c = 'v'; break;
561f4a2713aSLionel Sambuc         case BuiltinType::Bool:
562f4a2713aSLionel Sambuc           c = 'b'; break;
563f4a2713aSLionel Sambuc         case BuiltinType::UChar:
564f4a2713aSLionel Sambuc           c = 'c'; break;
565f4a2713aSLionel Sambuc         case BuiltinType::Char16:
566f4a2713aSLionel Sambuc           c = 'q'; break;
567f4a2713aSLionel Sambuc         case BuiltinType::Char32:
568f4a2713aSLionel Sambuc           c = 'w'; break;
569f4a2713aSLionel Sambuc         case BuiltinType::UShort:
570f4a2713aSLionel Sambuc           c = 's'; break;
571f4a2713aSLionel Sambuc         case BuiltinType::UInt:
572f4a2713aSLionel Sambuc           c = 'i'; break;
573f4a2713aSLionel Sambuc         case BuiltinType::ULong:
574f4a2713aSLionel Sambuc           c = 'l'; break;
575f4a2713aSLionel Sambuc         case BuiltinType::ULongLong:
576f4a2713aSLionel Sambuc           c = 'k'; break;
577f4a2713aSLionel Sambuc         case BuiltinType::UInt128:
578f4a2713aSLionel Sambuc           c = 'j'; break;
579*0a6a1f1dSLionel Sambuc         case BuiltinType::Char_U:
580f4a2713aSLionel Sambuc         case BuiltinType::Char_S:
581f4a2713aSLionel Sambuc           c = 'C'; break;
582*0a6a1f1dSLionel Sambuc         case BuiltinType::SChar:
583*0a6a1f1dSLionel Sambuc           c = 'r'; break;
584f4a2713aSLionel Sambuc         case BuiltinType::WChar_S:
585f4a2713aSLionel Sambuc         case BuiltinType::WChar_U:
586f4a2713aSLionel Sambuc           c = 'W'; break;
587f4a2713aSLionel Sambuc         case BuiltinType::Short:
588f4a2713aSLionel Sambuc           c = 'S'; break;
589f4a2713aSLionel Sambuc         case BuiltinType::Int:
590f4a2713aSLionel Sambuc           c = 'I'; break;
591f4a2713aSLionel Sambuc         case BuiltinType::Long:
592f4a2713aSLionel Sambuc           c = 'L'; break;
593f4a2713aSLionel Sambuc         case BuiltinType::LongLong:
594f4a2713aSLionel Sambuc           c = 'K'; break;
595f4a2713aSLionel Sambuc         case BuiltinType::Int128:
596f4a2713aSLionel Sambuc           c = 'J'; break;
597f4a2713aSLionel Sambuc         case BuiltinType::Half:
598f4a2713aSLionel Sambuc           c = 'h'; break;
599f4a2713aSLionel Sambuc         case BuiltinType::Float:
600f4a2713aSLionel Sambuc           c = 'f'; break;
601f4a2713aSLionel Sambuc         case BuiltinType::Double:
602f4a2713aSLionel Sambuc           c = 'd'; break;
603f4a2713aSLionel Sambuc         case BuiltinType::LongDouble:
604f4a2713aSLionel Sambuc           c = 'D'; break;
605f4a2713aSLionel Sambuc         case BuiltinType::NullPtr:
606f4a2713aSLionel Sambuc           c = 'n'; break;
607f4a2713aSLionel Sambuc #define BUILTIN_TYPE(Id, SingletonId)
608f4a2713aSLionel Sambuc #define PLACEHOLDER_TYPE(Id, SingletonId) case BuiltinType::Id:
609f4a2713aSLionel Sambuc #include "clang/AST/BuiltinTypes.def"
610f4a2713aSLionel Sambuc         case BuiltinType::Dependent:
611f4a2713aSLionel Sambuc         case BuiltinType::OCLImage1d:
612f4a2713aSLionel Sambuc         case BuiltinType::OCLImage1dArray:
613f4a2713aSLionel Sambuc         case BuiltinType::OCLImage1dBuffer:
614f4a2713aSLionel Sambuc         case BuiltinType::OCLImage2d:
615f4a2713aSLionel Sambuc         case BuiltinType::OCLImage2dArray:
616f4a2713aSLionel Sambuc         case BuiltinType::OCLImage3d:
617f4a2713aSLionel Sambuc         case BuiltinType::OCLEvent:
618f4a2713aSLionel Sambuc         case BuiltinType::OCLSampler:
619f4a2713aSLionel Sambuc           IgnoreResults = true;
620f4a2713aSLionel Sambuc           return;
621f4a2713aSLionel Sambuc         case BuiltinType::ObjCId:
622f4a2713aSLionel Sambuc           c = 'o'; break;
623f4a2713aSLionel Sambuc         case BuiltinType::ObjCClass:
624f4a2713aSLionel Sambuc           c = 'O'; break;
625f4a2713aSLionel Sambuc         case BuiltinType::ObjCSel:
626f4a2713aSLionel Sambuc           c = 'e'; break;
627f4a2713aSLionel Sambuc       }
628f4a2713aSLionel Sambuc       Out << c;
629f4a2713aSLionel Sambuc       return;
630f4a2713aSLionel Sambuc     }
631f4a2713aSLionel Sambuc 
632f4a2713aSLionel Sambuc     // If we have already seen this (non-built-in) type, use a substitution
633f4a2713aSLionel Sambuc     // encoding.
634f4a2713aSLionel Sambuc     llvm::DenseMap<const Type *, unsigned>::iterator Substitution
635f4a2713aSLionel Sambuc       = TypeSubstitutions.find(T.getTypePtr());
636f4a2713aSLionel Sambuc     if (Substitution != TypeSubstitutions.end()) {
637f4a2713aSLionel Sambuc       Out << 'S' << Substitution->second << '_';
638f4a2713aSLionel Sambuc       return;
639f4a2713aSLionel Sambuc     } else {
640f4a2713aSLionel Sambuc       // Record this as a substitution.
641f4a2713aSLionel Sambuc       unsigned Number = TypeSubstitutions.size();
642f4a2713aSLionel Sambuc       TypeSubstitutions[T.getTypePtr()] = Number;
643f4a2713aSLionel Sambuc     }
644f4a2713aSLionel Sambuc 
645f4a2713aSLionel Sambuc     if (const PointerType *PT = T->getAs<PointerType>()) {
646f4a2713aSLionel Sambuc       Out << '*';
647f4a2713aSLionel Sambuc       T = PT->getPointeeType();
648f4a2713aSLionel Sambuc       continue;
649f4a2713aSLionel Sambuc     }
650*0a6a1f1dSLionel Sambuc     if (const RValueReferenceType *RT = T->getAs<RValueReferenceType>()) {
651*0a6a1f1dSLionel Sambuc       Out << "&&";
652*0a6a1f1dSLionel Sambuc       T = RT->getPointeeType();
653*0a6a1f1dSLionel Sambuc       continue;
654*0a6a1f1dSLionel Sambuc     }
655f4a2713aSLionel Sambuc     if (const ReferenceType *RT = T->getAs<ReferenceType>()) {
656f4a2713aSLionel Sambuc       Out << '&';
657f4a2713aSLionel Sambuc       T = RT->getPointeeType();
658f4a2713aSLionel Sambuc       continue;
659f4a2713aSLionel Sambuc     }
660f4a2713aSLionel Sambuc     if (const FunctionProtoType *FT = T->getAs<FunctionProtoType>()) {
661f4a2713aSLionel Sambuc       Out << 'F';
662*0a6a1f1dSLionel Sambuc       VisitType(FT->getReturnType());
663*0a6a1f1dSLionel Sambuc       for (const auto &I : FT->param_types())
664*0a6a1f1dSLionel Sambuc         VisitType(I);
665f4a2713aSLionel Sambuc       if (FT->isVariadic())
666f4a2713aSLionel Sambuc         Out << '.';
667f4a2713aSLionel Sambuc       return;
668f4a2713aSLionel Sambuc     }
669f4a2713aSLionel Sambuc     if (const BlockPointerType *BT = T->getAs<BlockPointerType>()) {
670f4a2713aSLionel Sambuc       Out << 'B';
671f4a2713aSLionel Sambuc       T = BT->getPointeeType();
672f4a2713aSLionel Sambuc       continue;
673f4a2713aSLionel Sambuc     }
674f4a2713aSLionel Sambuc     if (const ComplexType *CT = T->getAs<ComplexType>()) {
675f4a2713aSLionel Sambuc       Out << '<';
676f4a2713aSLionel Sambuc       T = CT->getElementType();
677f4a2713aSLionel Sambuc       continue;
678f4a2713aSLionel Sambuc     }
679f4a2713aSLionel Sambuc     if (const TagType *TT = T->getAs<TagType>()) {
680f4a2713aSLionel Sambuc       Out << '$';
681f4a2713aSLionel Sambuc       VisitTagDecl(TT->getDecl());
682f4a2713aSLionel Sambuc       return;
683f4a2713aSLionel Sambuc     }
684f4a2713aSLionel Sambuc     if (const TemplateTypeParmType *TTP = T->getAs<TemplateTypeParmType>()) {
685f4a2713aSLionel Sambuc       Out << 't' << TTP->getDepth() << '.' << TTP->getIndex();
686f4a2713aSLionel Sambuc       return;
687f4a2713aSLionel Sambuc     }
688f4a2713aSLionel Sambuc     if (const TemplateSpecializationType *Spec
689f4a2713aSLionel Sambuc                                     = T->getAs<TemplateSpecializationType>()) {
690f4a2713aSLionel Sambuc       Out << '>';
691f4a2713aSLionel Sambuc       VisitTemplateName(Spec->getTemplateName());
692f4a2713aSLionel Sambuc       Out << Spec->getNumArgs();
693f4a2713aSLionel Sambuc       for (unsigned I = 0, N = Spec->getNumArgs(); I != N; ++I)
694f4a2713aSLionel Sambuc         VisitTemplateArgument(Spec->getArg(I));
695f4a2713aSLionel Sambuc       return;
696f4a2713aSLionel Sambuc     }
697*0a6a1f1dSLionel Sambuc     if (const DependentNameType *DNT = T->getAs<DependentNameType>()) {
698*0a6a1f1dSLionel Sambuc       Out << '^';
699*0a6a1f1dSLionel Sambuc       // FIXME: Encode the qualifier, don't just print it.
700*0a6a1f1dSLionel Sambuc       PrintingPolicy PO(Ctx.getLangOpts());
701*0a6a1f1dSLionel Sambuc       PO.SuppressTagKeyword = true;
702*0a6a1f1dSLionel Sambuc       PO.SuppressUnwrittenScope = true;
703*0a6a1f1dSLionel Sambuc       PO.ConstantArraySizeAsWritten = false;
704*0a6a1f1dSLionel Sambuc       PO.AnonymousTagLocations = false;
705*0a6a1f1dSLionel Sambuc       DNT->getQualifier()->print(Out, PO);
706*0a6a1f1dSLionel Sambuc       Out << ':' << DNT->getIdentifier()->getName();
707*0a6a1f1dSLionel Sambuc       return;
708*0a6a1f1dSLionel Sambuc     }
709*0a6a1f1dSLionel Sambuc     if (const InjectedClassNameType *InjT = T->getAs<InjectedClassNameType>()) {
710*0a6a1f1dSLionel Sambuc       T = InjT->getInjectedSpecializationType();
711*0a6a1f1dSLionel Sambuc       continue;
712*0a6a1f1dSLionel Sambuc     }
713f4a2713aSLionel Sambuc 
714f4a2713aSLionel Sambuc     // Unhandled type.
715f4a2713aSLionel Sambuc     Out << ' ';
716f4a2713aSLionel Sambuc     break;
717f4a2713aSLionel Sambuc   } while (true);
718f4a2713aSLionel Sambuc }
719f4a2713aSLionel Sambuc 
VisitTemplateParameterList(const TemplateParameterList * Params)720f4a2713aSLionel Sambuc void USRGenerator::VisitTemplateParameterList(
721f4a2713aSLionel Sambuc                                          const TemplateParameterList *Params) {
722f4a2713aSLionel Sambuc   if (!Params)
723f4a2713aSLionel Sambuc     return;
724f4a2713aSLionel Sambuc   Out << '>' << Params->size();
725f4a2713aSLionel Sambuc   for (TemplateParameterList::const_iterator P = Params->begin(),
726f4a2713aSLionel Sambuc                                           PEnd = Params->end();
727f4a2713aSLionel Sambuc        P != PEnd; ++P) {
728f4a2713aSLionel Sambuc     Out << '#';
729f4a2713aSLionel Sambuc     if (isa<TemplateTypeParmDecl>(*P)) {
730f4a2713aSLionel Sambuc       if (cast<TemplateTypeParmDecl>(*P)->isParameterPack())
731f4a2713aSLionel Sambuc         Out<< 'p';
732f4a2713aSLionel Sambuc       Out << 'T';
733f4a2713aSLionel Sambuc       continue;
734f4a2713aSLionel Sambuc     }
735f4a2713aSLionel Sambuc 
736f4a2713aSLionel Sambuc     if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(*P)) {
737f4a2713aSLionel Sambuc       if (NTTP->isParameterPack())
738f4a2713aSLionel Sambuc         Out << 'p';
739f4a2713aSLionel Sambuc       Out << 'N';
740f4a2713aSLionel Sambuc       VisitType(NTTP->getType());
741f4a2713aSLionel Sambuc       continue;
742f4a2713aSLionel Sambuc     }
743f4a2713aSLionel Sambuc 
744f4a2713aSLionel Sambuc     TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*P);
745f4a2713aSLionel Sambuc     if (TTP->isParameterPack())
746f4a2713aSLionel Sambuc       Out << 'p';
747f4a2713aSLionel Sambuc     Out << 't';
748f4a2713aSLionel Sambuc     VisitTemplateParameterList(TTP->getTemplateParameters());
749f4a2713aSLionel Sambuc   }
750f4a2713aSLionel Sambuc }
751f4a2713aSLionel Sambuc 
VisitTemplateName(TemplateName Name)752f4a2713aSLionel Sambuc void USRGenerator::VisitTemplateName(TemplateName Name) {
753f4a2713aSLionel Sambuc   if (TemplateDecl *Template = Name.getAsTemplateDecl()) {
754f4a2713aSLionel Sambuc     if (TemplateTemplateParmDecl *TTP
755f4a2713aSLionel Sambuc                               = dyn_cast<TemplateTemplateParmDecl>(Template)) {
756f4a2713aSLionel Sambuc       Out << 't' << TTP->getDepth() << '.' << TTP->getIndex();
757f4a2713aSLionel Sambuc       return;
758f4a2713aSLionel Sambuc     }
759f4a2713aSLionel Sambuc 
760f4a2713aSLionel Sambuc     Visit(Template);
761f4a2713aSLionel Sambuc     return;
762f4a2713aSLionel Sambuc   }
763f4a2713aSLionel Sambuc 
764f4a2713aSLionel Sambuc   // FIXME: Visit dependent template names.
765f4a2713aSLionel Sambuc }
766f4a2713aSLionel Sambuc 
VisitTemplateArgument(const TemplateArgument & Arg)767f4a2713aSLionel Sambuc void USRGenerator::VisitTemplateArgument(const TemplateArgument &Arg) {
768f4a2713aSLionel Sambuc   switch (Arg.getKind()) {
769f4a2713aSLionel Sambuc   case TemplateArgument::Null:
770f4a2713aSLionel Sambuc     break;
771f4a2713aSLionel Sambuc 
772f4a2713aSLionel Sambuc   case TemplateArgument::Declaration:
773f4a2713aSLionel Sambuc     Visit(Arg.getAsDecl());
774f4a2713aSLionel Sambuc     break;
775f4a2713aSLionel Sambuc 
776f4a2713aSLionel Sambuc   case TemplateArgument::NullPtr:
777f4a2713aSLionel Sambuc     break;
778f4a2713aSLionel Sambuc 
779f4a2713aSLionel Sambuc   case TemplateArgument::TemplateExpansion:
780f4a2713aSLionel Sambuc     Out << 'P'; // pack expansion of...
781f4a2713aSLionel Sambuc     // Fall through
782f4a2713aSLionel Sambuc   case TemplateArgument::Template:
783f4a2713aSLionel Sambuc     VisitTemplateName(Arg.getAsTemplateOrTemplatePattern());
784f4a2713aSLionel Sambuc     break;
785f4a2713aSLionel Sambuc 
786f4a2713aSLionel Sambuc   case TemplateArgument::Expression:
787f4a2713aSLionel Sambuc     // FIXME: Visit expressions.
788f4a2713aSLionel Sambuc     break;
789f4a2713aSLionel Sambuc 
790f4a2713aSLionel Sambuc   case TemplateArgument::Pack:
791f4a2713aSLionel Sambuc     Out << 'p' << Arg.pack_size();
792*0a6a1f1dSLionel Sambuc     for (const auto &P : Arg.pack_elements())
793*0a6a1f1dSLionel Sambuc       VisitTemplateArgument(P);
794f4a2713aSLionel Sambuc     break;
795f4a2713aSLionel Sambuc 
796f4a2713aSLionel Sambuc   case TemplateArgument::Type:
797f4a2713aSLionel Sambuc     VisitType(Arg.getAsType());
798f4a2713aSLionel Sambuc     break;
799f4a2713aSLionel Sambuc 
800f4a2713aSLionel Sambuc   case TemplateArgument::Integral:
801f4a2713aSLionel Sambuc     Out << 'V';
802f4a2713aSLionel Sambuc     VisitType(Arg.getIntegralType());
803f4a2713aSLionel Sambuc     Out << Arg.getAsIntegral();
804f4a2713aSLionel Sambuc     break;
805f4a2713aSLionel Sambuc   }
806f4a2713aSLionel Sambuc }
807f4a2713aSLionel Sambuc 
808f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
809f4a2713aSLionel Sambuc // USR generation functions.
810f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
811f4a2713aSLionel Sambuc 
generateUSRForObjCClass(StringRef Cls,raw_ostream & OS)812f4a2713aSLionel Sambuc void clang::index::generateUSRForObjCClass(StringRef Cls, raw_ostream &OS) {
813f4a2713aSLionel Sambuc   OS << "objc(cs)" << Cls;
814f4a2713aSLionel Sambuc }
815f4a2713aSLionel Sambuc 
generateUSRForObjCCategory(StringRef Cls,StringRef Cat,raw_ostream & OS)816f4a2713aSLionel Sambuc void clang::index::generateUSRForObjCCategory(StringRef Cls, StringRef Cat,
817f4a2713aSLionel Sambuc                                               raw_ostream &OS) {
818f4a2713aSLionel Sambuc   OS << "objc(cy)" << Cls << '@' << Cat;
819f4a2713aSLionel Sambuc }
820f4a2713aSLionel Sambuc 
generateUSRForObjCIvar(StringRef Ivar,raw_ostream & OS)821f4a2713aSLionel Sambuc void clang::index::generateUSRForObjCIvar(StringRef Ivar, raw_ostream &OS) {
822f4a2713aSLionel Sambuc   OS << '@' << Ivar;
823f4a2713aSLionel Sambuc }
824f4a2713aSLionel Sambuc 
generateUSRForObjCMethod(StringRef Sel,bool IsInstanceMethod,raw_ostream & OS)825f4a2713aSLionel Sambuc void clang::index::generateUSRForObjCMethod(StringRef Sel,
826f4a2713aSLionel Sambuc                                             bool IsInstanceMethod,
827f4a2713aSLionel Sambuc                                             raw_ostream &OS) {
828f4a2713aSLionel Sambuc   OS << (IsInstanceMethod ? "(im)" : "(cm)") << Sel;
829f4a2713aSLionel Sambuc }
830f4a2713aSLionel Sambuc 
generateUSRForObjCProperty(StringRef Prop,raw_ostream & OS)831f4a2713aSLionel Sambuc void clang::index::generateUSRForObjCProperty(StringRef Prop, raw_ostream &OS) {
832f4a2713aSLionel Sambuc   OS << "(py)" << Prop;
833f4a2713aSLionel Sambuc }
834f4a2713aSLionel Sambuc 
generateUSRForObjCProtocol(StringRef Prot,raw_ostream & OS)835f4a2713aSLionel Sambuc void clang::index::generateUSRForObjCProtocol(StringRef Prot, raw_ostream &OS) {
836f4a2713aSLionel Sambuc   OS << "objc(pl)" << Prot;
837f4a2713aSLionel Sambuc }
838f4a2713aSLionel Sambuc 
generateUSRForDecl(const Decl * D,SmallVectorImpl<char> & Buf)839f4a2713aSLionel Sambuc bool clang::index::generateUSRForDecl(const Decl *D,
840f4a2713aSLionel Sambuc                                       SmallVectorImpl<char> &Buf) {
841f4a2713aSLionel Sambuc   // Don't generate USRs for things with invalid locations.
842f4a2713aSLionel Sambuc   if (!D || D->getLocStart().isInvalid())
843f4a2713aSLionel Sambuc     return true;
844f4a2713aSLionel Sambuc 
845f4a2713aSLionel Sambuc   USRGenerator UG(&D->getASTContext(), Buf);
846f4a2713aSLionel Sambuc   UG.Visit(D);
847f4a2713aSLionel Sambuc   return UG.ignoreResults();
848f4a2713aSLionel Sambuc }
849*0a6a1f1dSLionel Sambuc 
generateUSRForMacro(const MacroDefinition * MD,const SourceManager & SM,SmallVectorImpl<char> & Buf)850*0a6a1f1dSLionel Sambuc bool clang::index::generateUSRForMacro(const MacroDefinition *MD,
851*0a6a1f1dSLionel Sambuc                                        const SourceManager &SM,
852*0a6a1f1dSLionel Sambuc                                        SmallVectorImpl<char> &Buf) {
853*0a6a1f1dSLionel Sambuc   // Don't generate USRs for things with invalid locations.
854*0a6a1f1dSLionel Sambuc   if (!MD || MD->getLocation().isInvalid())
855*0a6a1f1dSLionel Sambuc     return true;
856*0a6a1f1dSLionel Sambuc 
857*0a6a1f1dSLionel Sambuc   llvm::raw_svector_ostream Out(Buf);
858*0a6a1f1dSLionel Sambuc 
859*0a6a1f1dSLionel Sambuc   // Assume that system headers are sane.  Don't put source location
860*0a6a1f1dSLionel Sambuc   // information into the USR if the macro comes from a system header.
861*0a6a1f1dSLionel Sambuc   SourceLocation Loc = MD->getLocation();
862*0a6a1f1dSLionel Sambuc   bool ShouldGenerateLocation = !SM.isInSystemHeader(Loc);
863*0a6a1f1dSLionel Sambuc 
864*0a6a1f1dSLionel Sambuc   Out << getUSRSpacePrefix();
865*0a6a1f1dSLionel Sambuc   if (ShouldGenerateLocation)
866*0a6a1f1dSLionel Sambuc     printLoc(Out, Loc, SM, /*IncludeOffset=*/true);
867*0a6a1f1dSLionel Sambuc   Out << "@macro@";
868*0a6a1f1dSLionel Sambuc   Out << MD->getName()->getName();
869*0a6a1f1dSLionel Sambuc   return false;
870*0a6a1f1dSLionel Sambuc }
871*0a6a1f1dSLionel Sambuc 
872