annotate clang/lib/Index/USRGeneration.cpp @ 152:e8a9b4f4d755

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