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