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