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