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