1259701Sdim//===- USRGeneration.cpp - Routines for USR generation --------------------===//
2259701Sdim//
3259701Sdim//                     The LLVM Compiler Infrastructure
4259701Sdim//
5259701Sdim// This file is distributed under the University of Illinois Open Source
6259701Sdim// License. See LICENSE.TXT for details.
7259701Sdim//
8259701Sdim//===----------------------------------------------------------------------===//
9259701Sdim
10259701Sdim#include "clang/Index/USRGeneration.h"
11259701Sdim#include "clang/AST/ASTContext.h"
12259701Sdim#include "clang/AST/DeclTemplate.h"
13259701Sdim#include "clang/AST/DeclVisitor.h"
14259701Sdim#include "llvm/ADT/SmallString.h"
15259701Sdim#include "llvm/Support/Path.h"
16259701Sdim#include "llvm/Support/raw_ostream.h"
17259701Sdim
18259701Sdimusing namespace clang;
19259701Sdimusing namespace clang::index;
20259701Sdim
21259701Sdim//===----------------------------------------------------------------------===//
22259701Sdim// USR generation.
23259701Sdim//===----------------------------------------------------------------------===//
24259701Sdim
25259701Sdimnamespace {
26259701Sdimclass USRGenerator : public ConstDeclVisitor<USRGenerator> {
27259701Sdim  SmallVectorImpl<char> &Buf;
28259701Sdim  llvm::raw_svector_ostream Out;
29259701Sdim  bool IgnoreResults;
30259701Sdim  ASTContext *Context;
31259701Sdim  bool generatedLoc;
32259701Sdim
33259701Sdim  llvm::DenseMap<const Type *, unsigned> TypeSubstitutions;
34259701Sdim
35259701Sdimpublic:
36259701Sdim  explicit USRGenerator(ASTContext *Ctx, SmallVectorImpl<char> &Buf)
37259701Sdim  : Buf(Buf),
38259701Sdim    Out(Buf),
39259701Sdim    IgnoreResults(false),
40259701Sdim    Context(Ctx),
41259701Sdim    generatedLoc(false)
42259701Sdim  {
43259701Sdim    // Add the USR space prefix.
44259701Sdim    Out << getUSRSpacePrefix();
45259701Sdim  }
46259701Sdim
47259701Sdim  bool ignoreResults() const { return IgnoreResults; }
48259701Sdim
49259701Sdim  // Visitation methods from generating USRs from AST elements.
50259701Sdim  void VisitDeclContext(const DeclContext *D);
51259701Sdim  void VisitFieldDecl(const FieldDecl *D);
52259701Sdim  void VisitFunctionDecl(const FunctionDecl *D);
53259701Sdim  void VisitNamedDecl(const NamedDecl *D);
54259701Sdim  void VisitNamespaceDecl(const NamespaceDecl *D);
55259701Sdim  void VisitNamespaceAliasDecl(const NamespaceAliasDecl *D);
56259701Sdim  void VisitFunctionTemplateDecl(const FunctionTemplateDecl *D);
57259701Sdim  void VisitClassTemplateDecl(const ClassTemplateDecl *D);
58259701Sdim  void VisitObjCContainerDecl(const ObjCContainerDecl *CD);
59259701Sdim  void VisitObjCMethodDecl(const ObjCMethodDecl *MD);
60259701Sdim  void VisitObjCPropertyDecl(const ObjCPropertyDecl *D);
61259701Sdim  void VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D);
62259701Sdim  void VisitTagDecl(const TagDecl *D);
63259701Sdim  void VisitTypedefDecl(const TypedefDecl *D);
64259701Sdim  void VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D);
65259701Sdim  void VisitVarDecl(const VarDecl *D);
66259701Sdim  void VisitNonTypeTemplateParmDecl(const NonTypeTemplateParmDecl *D);
67259701Sdim  void VisitTemplateTemplateParmDecl(const TemplateTemplateParmDecl *D);
68259701Sdim  void VisitLinkageSpecDecl(const LinkageSpecDecl *D) {
69259701Sdim    IgnoreResults = true;
70259701Sdim  }
71259701Sdim  void VisitUsingDirectiveDecl(const UsingDirectiveDecl *D) {
72259701Sdim    IgnoreResults = true;
73259701Sdim  }
74259701Sdim  void VisitUsingDecl(const UsingDecl *D) {
75259701Sdim    IgnoreResults = true;
76259701Sdim  }
77259701Sdim  void VisitUnresolvedUsingValueDecl(const UnresolvedUsingValueDecl *D) {
78259701Sdim    IgnoreResults = true;
79259701Sdim  }
80259701Sdim  void VisitUnresolvedUsingTypenameDecl(const UnresolvedUsingTypenameDecl *D) {
81259701Sdim    IgnoreResults = true;
82259701Sdim  }
83259701Sdim
84259701Sdim  /// Generate the string component containing the location of the
85259701Sdim  ///  declaration.
86259701Sdim  bool GenLoc(const Decl *D);
87259701Sdim
88259701Sdim  /// String generation methods used both by the visitation methods
89259701Sdim  /// and from other clients that want to directly generate USRs.  These
90259701Sdim  /// methods do not construct complete USRs (which incorporate the parents
91259701Sdim  /// of an AST element), but only the fragments concerning the AST element
92259701Sdim  /// itself.
93259701Sdim
94259701Sdim  /// Generate a USR for an Objective-C class.
95259701Sdim  void GenObjCClass(StringRef cls) {
96259701Sdim    generateUSRForObjCClass(cls, Out);
97259701Sdim  }
98259701Sdim  /// Generate a USR for an Objective-C class category.
99259701Sdim  void GenObjCCategory(StringRef cls, StringRef cat) {
100259701Sdim    generateUSRForObjCCategory(cls, cat, Out);
101259701Sdim  }
102259701Sdim  /// Generate a USR fragment for an Objective-C instance variable.  The
103259701Sdim  /// complete USR can be created by concatenating the USR for the
104259701Sdim  /// encompassing class with this USR fragment.
105259701Sdim  void GenObjCIvar(StringRef ivar) {
106259701Sdim    generateUSRForObjCIvar(ivar, Out);
107259701Sdim  }
108259701Sdim  /// Generate a USR fragment for an Objective-C method.
109259701Sdim  void GenObjCMethod(StringRef sel, bool isInstanceMethod) {
110259701Sdim    generateUSRForObjCMethod(sel, isInstanceMethod, Out);
111259701Sdim  }
112259701Sdim  /// Generate a USR fragment for an Objective-C property.
113259701Sdim  void GenObjCProperty(StringRef prop) {
114259701Sdim    generateUSRForObjCProperty(prop, Out);
115259701Sdim  }
116259701Sdim  /// Generate a USR for an Objective-C protocol.
117259701Sdim  void GenObjCProtocol(StringRef prot) {
118259701Sdim    generateUSRForObjCProtocol(prot, Out);
119259701Sdim  }
120259701Sdim
121259701Sdim  void VisitType(QualType T);
122259701Sdim  void VisitTemplateParameterList(const TemplateParameterList *Params);
123259701Sdim  void VisitTemplateName(TemplateName Name);
124259701Sdim  void VisitTemplateArgument(const TemplateArgument &Arg);
125259701Sdim
126259701Sdim  /// Emit a Decl's name using NamedDecl::printName() and return true if
127259701Sdim  ///  the decl had no name.
128259701Sdim  bool EmitDeclName(const NamedDecl *D);
129259701Sdim};
130259701Sdim
131259701Sdim} // end anonymous namespace
132259701Sdim
133259701Sdim//===----------------------------------------------------------------------===//
134259701Sdim// Generating USRs from ASTS.
135259701Sdim//===----------------------------------------------------------------------===//
136259701Sdim
137259701Sdimbool USRGenerator::EmitDeclName(const NamedDecl *D) {
138259701Sdim  Out.flush();
139259701Sdim  const unsigned startSize = Buf.size();
140259701Sdim  D->printName(Out);
141259701Sdim  Out.flush();
142259701Sdim  const unsigned endSize = Buf.size();
143259701Sdim  return startSize == endSize;
144259701Sdim}
145259701Sdim
146259701Sdimstatic inline bool ShouldGenerateLocation(const NamedDecl *D) {
147259701Sdim  return !D->isExternallyVisible();
148259701Sdim}
149259701Sdim
150259701Sdimvoid USRGenerator::VisitDeclContext(const DeclContext *DC) {
151259701Sdim  if (const NamedDecl *D = dyn_cast<NamedDecl>(DC))
152259701Sdim    Visit(D);
153259701Sdim}
154259701Sdim
155259701Sdimvoid USRGenerator::VisitFieldDecl(const FieldDecl *D) {
156259701Sdim  // The USR for an ivar declared in a class extension is based on the
157259701Sdim  // ObjCInterfaceDecl, not the ObjCCategoryDecl.
158259701Sdim  if (const ObjCInterfaceDecl *ID = Context->getObjContainingInterface(D))
159259701Sdim    Visit(ID);
160259701Sdim  else
161259701Sdim    VisitDeclContext(D->getDeclContext());
162259701Sdim  Out << (isa<ObjCIvarDecl>(D) ? "@" : "@FI@");
163259701Sdim  if (EmitDeclName(D)) {
164259701Sdim    // Bit fields can be anonymous.
165259701Sdim    IgnoreResults = true;
166259701Sdim    return;
167259701Sdim  }
168259701Sdim}
169259701Sdim
170259701Sdimvoid USRGenerator::VisitFunctionDecl(const FunctionDecl *D) {
171259701Sdim  if (ShouldGenerateLocation(D) && GenLoc(D))
172259701Sdim    return;
173259701Sdim
174259701Sdim  VisitDeclContext(D->getDeclContext());
175259701Sdim  if (FunctionTemplateDecl *FunTmpl = D->getDescribedFunctionTemplate()) {
176259701Sdim    Out << "@FT@";
177259701Sdim    VisitTemplateParameterList(FunTmpl->getTemplateParameters());
178259701Sdim  } else
179259701Sdim    Out << "@F@";
180259701Sdim  D->printName(Out);
181259701Sdim
182259701Sdim  ASTContext &Ctx = *Context;
183259701Sdim  if (!Ctx.getLangOpts().CPlusPlus || D->isExternC())
184259701Sdim    return;
185259701Sdim
186259701Sdim  if (const TemplateArgumentList *
187259701Sdim        SpecArgs = D->getTemplateSpecializationArgs()) {
188259701Sdim    Out << '<';
189259701Sdim    for (unsigned I = 0, N = SpecArgs->size(); I != N; ++I) {
190259701Sdim      Out << '#';
191259701Sdim      VisitTemplateArgument(SpecArgs->get(I));
192259701Sdim    }
193259701Sdim    Out << '>';
194259701Sdim  }
195259701Sdim
196259701Sdim  // Mangle in type information for the arguments.
197259701Sdim  for (FunctionDecl::param_const_iterator I = D->param_begin(),
198259701Sdim                                          E = D->param_end();
199259701Sdim       I != E; ++I) {
200259701Sdim    Out << '#';
201259701Sdim    if (ParmVarDecl *PD = *I)
202259701Sdim      VisitType(PD->getType());
203259701Sdim  }
204259701Sdim  if (D->isVariadic())
205259701Sdim    Out << '.';
206259701Sdim  Out << '#';
207259701Sdim  if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {
208259701Sdim    if (MD->isStatic())
209259701Sdim      Out << 'S';
210259701Sdim    if (unsigned quals = MD->getTypeQualifiers())
211259701Sdim      Out << (char)('0' + quals);
212259701Sdim  }
213259701Sdim}
214259701Sdim
215259701Sdimvoid USRGenerator::VisitNamedDecl(const NamedDecl *D) {
216259701Sdim  VisitDeclContext(D->getDeclContext());
217259701Sdim  Out << "@";
218259701Sdim
219259701Sdim  if (EmitDeclName(D)) {
220259701Sdim    // The string can be empty if the declaration has no name; e.g., it is
221259701Sdim    // the ParmDecl with no name for declaration of a function pointer type,
222259701Sdim    // e.g.: void  (*f)(void *);
223259701Sdim    // In this case, don't generate a USR.
224259701Sdim    IgnoreResults = true;
225259701Sdim  }
226259701Sdim}
227259701Sdim
228259701Sdimvoid USRGenerator::VisitVarDecl(const VarDecl *D) {
229259701Sdim  // VarDecls can be declared 'extern' within a function or method body,
230259701Sdim  // but their enclosing DeclContext is the function, not the TU.  We need
231259701Sdim  // to check the storage class to correctly generate the USR.
232259701Sdim  if (ShouldGenerateLocation(D) && GenLoc(D))
233259701Sdim    return;
234259701Sdim
235259701Sdim  VisitDeclContext(D->getDeclContext());
236259701Sdim
237259701Sdim  // Variables always have simple names.
238259701Sdim  StringRef s = D->getName();
239259701Sdim
240259701Sdim  // The string can be empty if the declaration has no name; e.g., it is
241259701Sdim  // the ParmDecl with no name for declaration of a function pointer type, e.g.:
242259701Sdim  //    void  (*f)(void *);
243259701Sdim  // In this case, don't generate a USR.
244259701Sdim  if (s.empty())
245259701Sdim    IgnoreResults = true;
246259701Sdim  else
247259701Sdim    Out << '@' << s;
248259701Sdim}
249259701Sdim
250259701Sdimvoid USRGenerator::VisitNonTypeTemplateParmDecl(
251259701Sdim                                        const NonTypeTemplateParmDecl *D) {
252259701Sdim  GenLoc(D);
253259701Sdim  return;
254259701Sdim}
255259701Sdim
256259701Sdimvoid USRGenerator::VisitTemplateTemplateParmDecl(
257259701Sdim                                        const TemplateTemplateParmDecl *D) {
258259701Sdim  GenLoc(D);
259259701Sdim  return;
260259701Sdim}
261259701Sdim
262259701Sdimvoid USRGenerator::VisitNamespaceDecl(const NamespaceDecl *D) {
263259701Sdim  if (D->isAnonymousNamespace()) {
264259701Sdim    Out << "@aN";
265259701Sdim    return;
266259701Sdim  }
267259701Sdim
268259701Sdim  VisitDeclContext(D->getDeclContext());
269259701Sdim  if (!IgnoreResults)
270259701Sdim    Out << "@N@" << D->getName();
271259701Sdim}
272259701Sdim
273259701Sdimvoid USRGenerator::VisitFunctionTemplateDecl(const FunctionTemplateDecl *D) {
274259701Sdim  VisitFunctionDecl(D->getTemplatedDecl());
275259701Sdim}
276259701Sdim
277259701Sdimvoid USRGenerator::VisitClassTemplateDecl(const ClassTemplateDecl *D) {
278259701Sdim  VisitTagDecl(D->getTemplatedDecl());
279259701Sdim}
280259701Sdim
281259701Sdimvoid USRGenerator::VisitNamespaceAliasDecl(const NamespaceAliasDecl *D) {
282259701Sdim  VisitDeclContext(D->getDeclContext());
283259701Sdim  if (!IgnoreResults)
284259701Sdim    Out << "@NA@" << D->getName();
285259701Sdim}
286259701Sdim
287259701Sdimvoid USRGenerator::VisitObjCMethodDecl(const ObjCMethodDecl *D) {
288259701Sdim  const DeclContext *container = D->getDeclContext();
289259701Sdim  if (const ObjCProtocolDecl *pd = dyn_cast<ObjCProtocolDecl>(container)) {
290259701Sdim    Visit(pd);
291259701Sdim  }
292259701Sdim  else {
293259701Sdim    // The USR for a method declared in a class extension or category is based on
294259701Sdim    // the ObjCInterfaceDecl, not the ObjCCategoryDecl.
295259701Sdim    const ObjCInterfaceDecl *ID = D->getClassInterface();
296259701Sdim    if (!ID) {
297259701Sdim      IgnoreResults = true;
298259701Sdim      return;
299259701Sdim    }
300259701Sdim    Visit(ID);
301259701Sdim  }
302259701Sdim  // Ideally we would use 'GenObjCMethod', but this is such a hot path
303259701Sdim  // for Objective-C code that we don't want to use
304259701Sdim  // DeclarationName::getAsString().
305259701Sdim  Out << (D->isInstanceMethod() ? "(im)" : "(cm)")
306259701Sdim      << DeclarationName(D->getSelector());
307259701Sdim}
308259701Sdim
309259701Sdimvoid USRGenerator::VisitObjCContainerDecl(const ObjCContainerDecl *D) {
310259701Sdim  switch (D->getKind()) {
311259701Sdim    default:
312259701Sdim      llvm_unreachable("Invalid ObjC container.");
313259701Sdim    case Decl::ObjCInterface:
314259701Sdim    case Decl::ObjCImplementation:
315259701Sdim      GenObjCClass(D->getName());
316259701Sdim      break;
317259701Sdim    case Decl::ObjCCategory: {
318259701Sdim      const ObjCCategoryDecl *CD = cast<ObjCCategoryDecl>(D);
319259701Sdim      const ObjCInterfaceDecl *ID = CD->getClassInterface();
320259701Sdim      if (!ID) {
321259701Sdim        // Handle invalid code where the @interface might not
322259701Sdim        // have been specified.
323259701Sdim        // FIXME: We should be able to generate this USR even if the
324259701Sdim        // @interface isn't available.
325259701Sdim        IgnoreResults = true;
326259701Sdim        return;
327259701Sdim      }
328259701Sdim      // Specially handle class extensions, which are anonymous categories.
329259701Sdim      // We want to mangle in the location to uniquely distinguish them.
330259701Sdim      if (CD->IsClassExtension()) {
331259701Sdim        Out << "objc(ext)" << ID->getName() << '@';
332259701Sdim        GenLoc(CD);
333259701Sdim      }
334259701Sdim      else
335259701Sdim        GenObjCCategory(ID->getName(), CD->getName());
336259701Sdim
337259701Sdim      break;
338259701Sdim    }
339259701Sdim    case Decl::ObjCCategoryImpl: {
340259701Sdim      const ObjCCategoryImplDecl *CD = cast<ObjCCategoryImplDecl>(D);
341259701Sdim      const ObjCInterfaceDecl *ID = CD->getClassInterface();
342259701Sdim      if (!ID) {
343259701Sdim        // Handle invalid code where the @interface might not
344259701Sdim        // have been specified.
345259701Sdim        // FIXME: We should be able to generate this USR even if the
346259701Sdim        // @interface isn't available.
347259701Sdim        IgnoreResults = true;
348259701Sdim        return;
349259701Sdim      }
350259701Sdim      GenObjCCategory(ID->getName(), CD->getName());
351259701Sdim      break;
352259701Sdim    }
353259701Sdim    case Decl::ObjCProtocol:
354259701Sdim      GenObjCProtocol(cast<ObjCProtocolDecl>(D)->getName());
355259701Sdim      break;
356259701Sdim  }
357259701Sdim}
358259701Sdim
359259701Sdimvoid USRGenerator::VisitObjCPropertyDecl(const ObjCPropertyDecl *D) {
360259701Sdim  // The USR for a property declared in a class extension or category is based
361259701Sdim  // on the ObjCInterfaceDecl, not the ObjCCategoryDecl.
362259701Sdim  if (const ObjCInterfaceDecl *ID = Context->getObjContainingInterface(D))
363259701Sdim    Visit(ID);
364259701Sdim  else
365259701Sdim    Visit(cast<Decl>(D->getDeclContext()));
366259701Sdim  GenObjCProperty(D->getName());
367259701Sdim}
368259701Sdim
369259701Sdimvoid USRGenerator::VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D) {
370259701Sdim  if (ObjCPropertyDecl *PD = D->getPropertyDecl()) {
371259701Sdim    VisitObjCPropertyDecl(PD);
372259701Sdim    return;
373259701Sdim  }
374259701Sdim
375259701Sdim  IgnoreResults = true;
376259701Sdim}
377259701Sdim
378259701Sdimvoid USRGenerator::VisitTagDecl(const TagDecl *D) {
379259701Sdim  // Add the location of the tag decl to handle resolution across
380259701Sdim  // translation units.
381259701Sdim  if (ShouldGenerateLocation(D) && GenLoc(D))
382259701Sdim    return;
383259701Sdim
384259701Sdim  D = D->getCanonicalDecl();
385259701Sdim  VisitDeclContext(D->getDeclContext());
386259701Sdim
387259701Sdim  bool AlreadyStarted = false;
388259701Sdim  if (const CXXRecordDecl *CXXRecord = dyn_cast<CXXRecordDecl>(D)) {
389259701Sdim    if (ClassTemplateDecl *ClassTmpl = CXXRecord->getDescribedClassTemplate()) {
390259701Sdim      AlreadyStarted = true;
391259701Sdim
392259701Sdim      switch (D->getTagKind()) {
393259701Sdim      case TTK_Interface:
394259701Sdim      case TTK_Struct: Out << "@ST"; break;
395259701Sdim      case TTK_Class:  Out << "@CT"; break;
396259701Sdim      case TTK_Union:  Out << "@UT"; break;
397259701Sdim      case TTK_Enum: llvm_unreachable("enum template");
398259701Sdim      }
399259701Sdim      VisitTemplateParameterList(ClassTmpl->getTemplateParameters());
400259701Sdim    } else if (const ClassTemplatePartialSpecializationDecl *PartialSpec
401259701Sdim                = dyn_cast<ClassTemplatePartialSpecializationDecl>(CXXRecord)) {
402259701Sdim      AlreadyStarted = true;
403259701Sdim
404259701Sdim      switch (D->getTagKind()) {
405259701Sdim      case TTK_Interface:
406259701Sdim      case TTK_Struct: Out << "@SP"; break;
407259701Sdim      case TTK_Class:  Out << "@CP"; break;
408259701Sdim      case TTK_Union:  Out << "@UP"; break;
409259701Sdim      case TTK_Enum: llvm_unreachable("enum partial specialization");
410259701Sdim      }
411259701Sdim      VisitTemplateParameterList(PartialSpec->getTemplateParameters());
412259701Sdim    }
413259701Sdim  }
414259701Sdim
415259701Sdim  if (!AlreadyStarted) {
416259701Sdim    switch (D->getTagKind()) {
417259701Sdim      case TTK_Interface:
418259701Sdim      case TTK_Struct: Out << "@S"; break;
419259701Sdim      case TTK_Class:  Out << "@C"; break;
420259701Sdim      case TTK_Union:  Out << "@U"; break;
421259701Sdim      case TTK_Enum:   Out << "@E"; break;
422259701Sdim    }
423259701Sdim  }
424259701Sdim
425259701Sdim  Out << '@';
426259701Sdim  Out.flush();
427259701Sdim  assert(Buf.size() > 0);
428259701Sdim  const unsigned off = Buf.size() - 1;
429259701Sdim
430259701Sdim  if (EmitDeclName(D)) {
431259701Sdim    if (const TypedefNameDecl *TD = D->getTypedefNameForAnonDecl()) {
432259701Sdim      Buf[off] = 'A';
433259701Sdim      Out << '@' << *TD;
434259701Sdim    }
435259701Sdim    else
436259701Sdim      Buf[off] = 'a';
437259701Sdim  }
438259701Sdim
439259701Sdim  // For a class template specialization, mangle the template arguments.
440259701Sdim  if (const ClassTemplateSpecializationDecl *Spec
441259701Sdim                              = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
442259701Sdim    const TemplateArgumentList &Args = Spec->getTemplateInstantiationArgs();
443259701Sdim    Out << '>';
444259701Sdim    for (unsigned I = 0, N = Args.size(); I != N; ++I) {
445259701Sdim      Out << '#';
446259701Sdim      VisitTemplateArgument(Args.get(I));
447259701Sdim    }
448259701Sdim  }
449259701Sdim}
450259701Sdim
451259701Sdimvoid USRGenerator::VisitTypedefDecl(const TypedefDecl *D) {
452259701Sdim  if (ShouldGenerateLocation(D) && GenLoc(D))
453259701Sdim    return;
454259701Sdim  const DeclContext *DC = D->getDeclContext();
455259701Sdim  if (const NamedDecl *DCN = dyn_cast<NamedDecl>(DC))
456259701Sdim    Visit(DCN);
457259701Sdim  Out << "@T@";
458259701Sdim  Out << D->getName();
459259701Sdim}
460259701Sdim
461259701Sdimvoid USRGenerator::VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D) {
462259701Sdim  GenLoc(D);
463259701Sdim  return;
464259701Sdim}
465259701Sdim
466259701Sdimbool USRGenerator::GenLoc(const Decl *D) {
467259701Sdim  if (generatedLoc)
468259701Sdim    return IgnoreResults;
469259701Sdim  generatedLoc = true;
470259701Sdim
471259701Sdim  // Guard against null declarations in invalid code.
472259701Sdim  if (!D) {
473259701Sdim    IgnoreResults = true;
474259701Sdim    return true;
475259701Sdim  }
476259701Sdim
477259701Sdim  // Use the location of canonical decl.
478259701Sdim  D = D->getCanonicalDecl();
479259701Sdim
480259701Sdim  const SourceManager &SM = Context->getSourceManager();
481259701Sdim  SourceLocation L = D->getLocStart();
482259701Sdim  if (L.isInvalid()) {
483259701Sdim    IgnoreResults = true;
484259701Sdim    return true;
485259701Sdim  }
486259701Sdim  L = SM.getExpansionLoc(L);
487259701Sdim  const std::pair<FileID, unsigned> &Decomposed = SM.getDecomposedLoc(L);
488259701Sdim  const FileEntry *FE = SM.getFileEntryForID(Decomposed.first);
489259701Sdim  if (FE) {
490259701Sdim    Out << llvm::sys::path::filename(FE->getName());
491259701Sdim  }
492259701Sdim  else {
493259701Sdim    // This case really isn't interesting.
494259701Sdim    IgnoreResults = true;
495259701Sdim    return true;
496259701Sdim  }
497259701Sdim  // Use the offest into the FileID to represent the location.  Using
498259701Sdim  // a line/column can cause us to look back at the original source file,
499259701Sdim  // which is expensive.
500259701Sdim  Out << '@' << Decomposed.second;
501259701Sdim  return IgnoreResults;
502259701Sdim}
503259701Sdim
504259701Sdimvoid USRGenerator::VisitType(QualType T) {
505259701Sdim  // This method mangles in USR information for types.  It can possibly
506259701Sdim  // just reuse the naming-mangling logic used by codegen, although the
507259701Sdim  // requirements for USRs might not be the same.
508259701Sdim  ASTContext &Ctx = *Context;
509259701Sdim
510259701Sdim  do {
511259701Sdim    T = Ctx.getCanonicalType(T);
512259701Sdim    Qualifiers Q = T.getQualifiers();
513259701Sdim    unsigned qVal = 0;
514259701Sdim    if (Q.hasConst())
515259701Sdim      qVal |= 0x1;
516259701Sdim    if (Q.hasVolatile())
517259701Sdim      qVal |= 0x2;
518259701Sdim    if (Q.hasRestrict())
519259701Sdim      qVal |= 0x4;
520259701Sdim    if(qVal)
521259701Sdim      Out << ((char) ('0' + qVal));
522259701Sdim
523259701Sdim    // Mangle in ObjC GC qualifiers?
524259701Sdim
525259701Sdim    if (const PackExpansionType *Expansion = T->getAs<PackExpansionType>()) {
526259701Sdim      Out << 'P';
527259701Sdim      T = Expansion->getPattern();
528259701Sdim    }
529259701Sdim
530259701Sdim    if (const BuiltinType *BT = T->getAs<BuiltinType>()) {
531259701Sdim      unsigned char c = '\0';
532259701Sdim      switch (BT->getKind()) {
533259701Sdim        case BuiltinType::Void:
534259701Sdim          c = 'v'; break;
535259701Sdim        case BuiltinType::Bool:
536259701Sdim          c = 'b'; break;
537259701Sdim        case BuiltinType::Char_U:
538259701Sdim        case BuiltinType::UChar:
539259701Sdim          c = 'c'; break;
540259701Sdim        case BuiltinType::Char16:
541259701Sdim          c = 'q'; break;
542259701Sdim        case BuiltinType::Char32:
543259701Sdim          c = 'w'; break;
544259701Sdim        case BuiltinType::UShort:
545259701Sdim          c = 's'; break;
546259701Sdim        case BuiltinType::UInt:
547259701Sdim          c = 'i'; break;
548259701Sdim        case BuiltinType::ULong:
549259701Sdim          c = 'l'; break;
550259701Sdim        case BuiltinType::ULongLong:
551259701Sdim          c = 'k'; break;
552259701Sdim        case BuiltinType::UInt128:
553259701Sdim          c = 'j'; break;
554259701Sdim        case BuiltinType::Char_S:
555259701Sdim        case BuiltinType::SChar:
556259701Sdim          c = 'C'; break;
557259701Sdim        case BuiltinType::WChar_S:
558259701Sdim        case BuiltinType::WChar_U:
559259701Sdim          c = 'W'; break;
560259701Sdim        case BuiltinType::Short:
561259701Sdim          c = 'S'; break;
562259701Sdim        case BuiltinType::Int:
563259701Sdim          c = 'I'; break;
564259701Sdim        case BuiltinType::Long:
565259701Sdim          c = 'L'; break;
566259701Sdim        case BuiltinType::LongLong:
567259701Sdim          c = 'K'; break;
568259701Sdim        case BuiltinType::Int128:
569259701Sdim          c = 'J'; break;
570259701Sdim        case BuiltinType::Half:
571259701Sdim          c = 'h'; break;
572259701Sdim        case BuiltinType::Float:
573259701Sdim          c = 'f'; break;
574259701Sdim        case BuiltinType::Double:
575259701Sdim          c = 'd'; break;
576259701Sdim        case BuiltinType::LongDouble:
577259701Sdim          c = 'D'; break;
578259701Sdim        case BuiltinType::NullPtr:
579259701Sdim          c = 'n'; break;
580259701Sdim#define BUILTIN_TYPE(Id, SingletonId)
581259701Sdim#define PLACEHOLDER_TYPE(Id, SingletonId) case BuiltinType::Id:
582259701Sdim#include "clang/AST/BuiltinTypes.def"
583259701Sdim        case BuiltinType::Dependent:
584259701Sdim        case BuiltinType::OCLImage1d:
585259701Sdim        case BuiltinType::OCLImage1dArray:
586259701Sdim        case BuiltinType::OCLImage1dBuffer:
587259701Sdim        case BuiltinType::OCLImage2d:
588259701Sdim        case BuiltinType::OCLImage2dArray:
589259701Sdim        case BuiltinType::OCLImage3d:
590259701Sdim        case BuiltinType::OCLEvent:
591259701Sdim        case BuiltinType::OCLSampler:
592259701Sdim          IgnoreResults = true;
593259701Sdim          return;
594259701Sdim        case BuiltinType::ObjCId:
595259701Sdim          c = 'o'; break;
596259701Sdim        case BuiltinType::ObjCClass:
597259701Sdim          c = 'O'; break;
598259701Sdim        case BuiltinType::ObjCSel:
599259701Sdim          c = 'e'; break;
600259701Sdim      }
601259701Sdim      Out << c;
602259701Sdim      return;
603259701Sdim    }
604259701Sdim
605259701Sdim    // If we have already seen this (non-built-in) type, use a substitution
606259701Sdim    // encoding.
607259701Sdim    llvm::DenseMap<const Type *, unsigned>::iterator Substitution
608259701Sdim      = TypeSubstitutions.find(T.getTypePtr());
609259701Sdim    if (Substitution != TypeSubstitutions.end()) {
610259701Sdim      Out << 'S' << Substitution->second << '_';
611259701Sdim      return;
612259701Sdim    } else {
613259701Sdim      // Record this as a substitution.
614259701Sdim      unsigned Number = TypeSubstitutions.size();
615259701Sdim      TypeSubstitutions[T.getTypePtr()] = Number;
616259701Sdim    }
617259701Sdim
618259701Sdim    if (const PointerType *PT = T->getAs<PointerType>()) {
619259701Sdim      Out << '*';
620259701Sdim      T = PT->getPointeeType();
621259701Sdim      continue;
622259701Sdim    }
623259701Sdim    if (const ReferenceType *RT = T->getAs<ReferenceType>()) {
624259701Sdim      Out << '&';
625259701Sdim      T = RT->getPointeeType();
626259701Sdim      continue;
627259701Sdim    }
628259701Sdim    if (const FunctionProtoType *FT = T->getAs<FunctionProtoType>()) {
629259701Sdim      Out << 'F';
630259701Sdim      VisitType(FT->getResultType());
631259701Sdim      for (FunctionProtoType::arg_type_iterator
632259701Sdim            I = FT->arg_type_begin(), E = FT->arg_type_end(); I!=E; ++I) {
633259701Sdim        VisitType(*I);
634259701Sdim      }
635259701Sdim      if (FT->isVariadic())
636259701Sdim        Out << '.';
637259701Sdim      return;
638259701Sdim    }
639259701Sdim    if (const BlockPointerType *BT = T->getAs<BlockPointerType>()) {
640259701Sdim      Out << 'B';
641259701Sdim      T = BT->getPointeeType();
642259701Sdim      continue;
643259701Sdim    }
644259701Sdim    if (const ComplexType *CT = T->getAs<ComplexType>()) {
645259701Sdim      Out << '<';
646259701Sdim      T = CT->getElementType();
647259701Sdim      continue;
648259701Sdim    }
649259701Sdim    if (const TagType *TT = T->getAs<TagType>()) {
650259701Sdim      Out << '$';
651259701Sdim      VisitTagDecl(TT->getDecl());
652259701Sdim      return;
653259701Sdim    }
654259701Sdim    if (const TemplateTypeParmType *TTP = T->getAs<TemplateTypeParmType>()) {
655259701Sdim      Out << 't' << TTP->getDepth() << '.' << TTP->getIndex();
656259701Sdim      return;
657259701Sdim    }
658259701Sdim    if (const TemplateSpecializationType *Spec
659259701Sdim                                    = T->getAs<TemplateSpecializationType>()) {
660259701Sdim      Out << '>';
661259701Sdim      VisitTemplateName(Spec->getTemplateName());
662259701Sdim      Out << Spec->getNumArgs();
663259701Sdim      for (unsigned I = 0, N = Spec->getNumArgs(); I != N; ++I)
664259701Sdim        VisitTemplateArgument(Spec->getArg(I));
665259701Sdim      return;
666259701Sdim    }
667259701Sdim
668259701Sdim    // Unhandled type.
669259701Sdim    Out << ' ';
670259701Sdim    break;
671259701Sdim  } while (true);
672259701Sdim}
673259701Sdim
674259701Sdimvoid USRGenerator::VisitTemplateParameterList(
675259701Sdim                                         const TemplateParameterList *Params) {
676259701Sdim  if (!Params)
677259701Sdim    return;
678259701Sdim  Out << '>' << Params->size();
679259701Sdim  for (TemplateParameterList::const_iterator P = Params->begin(),
680259701Sdim                                          PEnd = Params->end();
681259701Sdim       P != PEnd; ++P) {
682259701Sdim    Out << '#';
683259701Sdim    if (isa<TemplateTypeParmDecl>(*P)) {
684259701Sdim      if (cast<TemplateTypeParmDecl>(*P)->isParameterPack())
685259701Sdim        Out<< 'p';
686259701Sdim      Out << 'T';
687259701Sdim      continue;
688259701Sdim    }
689259701Sdim
690259701Sdim    if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(*P)) {
691259701Sdim      if (NTTP->isParameterPack())
692259701Sdim        Out << 'p';
693259701Sdim      Out << 'N';
694259701Sdim      VisitType(NTTP->getType());
695259701Sdim      continue;
696259701Sdim    }
697259701Sdim
698259701Sdim    TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*P);
699259701Sdim    if (TTP->isParameterPack())
700259701Sdim      Out << 'p';
701259701Sdim    Out << 't';
702259701Sdim    VisitTemplateParameterList(TTP->getTemplateParameters());
703259701Sdim  }
704259701Sdim}
705259701Sdim
706259701Sdimvoid USRGenerator::VisitTemplateName(TemplateName Name) {
707259701Sdim  if (TemplateDecl *Template = Name.getAsTemplateDecl()) {
708259701Sdim    if (TemplateTemplateParmDecl *TTP
709259701Sdim                              = dyn_cast<TemplateTemplateParmDecl>(Template)) {
710259701Sdim      Out << 't' << TTP->getDepth() << '.' << TTP->getIndex();
711259701Sdim      return;
712259701Sdim    }
713259701Sdim
714259701Sdim    Visit(Template);
715259701Sdim    return;
716259701Sdim  }
717259701Sdim
718259701Sdim  // FIXME: Visit dependent template names.
719259701Sdim}
720259701Sdim
721259701Sdimvoid USRGenerator::VisitTemplateArgument(const TemplateArgument &Arg) {
722259701Sdim  switch (Arg.getKind()) {
723259701Sdim  case TemplateArgument::Null:
724259701Sdim    break;
725259701Sdim
726259701Sdim  case TemplateArgument::Declaration:
727259701Sdim    Visit(Arg.getAsDecl());
728259701Sdim    break;
729259701Sdim
730259701Sdim  case TemplateArgument::NullPtr:
731259701Sdim    break;
732259701Sdim
733259701Sdim  case TemplateArgument::TemplateExpansion:
734259701Sdim    Out << 'P'; // pack expansion of...
735259701Sdim    // Fall through
736259701Sdim  case TemplateArgument::Template:
737259701Sdim    VisitTemplateName(Arg.getAsTemplateOrTemplatePattern());
738259701Sdim    break;
739259701Sdim
740259701Sdim  case TemplateArgument::Expression:
741259701Sdim    // FIXME: Visit expressions.
742259701Sdim    break;
743259701Sdim
744259701Sdim  case TemplateArgument::Pack:
745259701Sdim    Out << 'p' << Arg.pack_size();
746259701Sdim    for (TemplateArgument::pack_iterator P = Arg.pack_begin(), PEnd = Arg.pack_end();
747259701Sdim         P != PEnd; ++P)
748259701Sdim      VisitTemplateArgument(*P);
749259701Sdim    break;
750259701Sdim
751259701Sdim  case TemplateArgument::Type:
752259701Sdim    VisitType(Arg.getAsType());
753259701Sdim    break;
754259701Sdim
755259701Sdim  case TemplateArgument::Integral:
756259701Sdim    Out << 'V';
757259701Sdim    VisitType(Arg.getIntegralType());
758259701Sdim    Out << Arg.getAsIntegral();
759259701Sdim    break;
760259701Sdim  }
761259701Sdim}
762259701Sdim
763259701Sdim//===----------------------------------------------------------------------===//
764259701Sdim// USR generation functions.
765259701Sdim//===----------------------------------------------------------------------===//
766259701Sdim
767259701Sdimvoid clang::index::generateUSRForObjCClass(StringRef Cls, raw_ostream &OS) {
768259701Sdim  OS << "objc(cs)" << Cls;
769259701Sdim}
770259701Sdim
771259701Sdimvoid clang::index::generateUSRForObjCCategory(StringRef Cls, StringRef Cat,
772259701Sdim                                              raw_ostream &OS) {
773259701Sdim  OS << "objc(cy)" << Cls << '@' << Cat;
774259701Sdim}
775259701Sdim
776259701Sdimvoid clang::index::generateUSRForObjCIvar(StringRef Ivar, raw_ostream &OS) {
777259701Sdim  OS << '@' << Ivar;
778259701Sdim}
779259701Sdim
780259701Sdimvoid clang::index::generateUSRForObjCMethod(StringRef Sel,
781259701Sdim                                            bool IsInstanceMethod,
782259701Sdim                                            raw_ostream &OS) {
783259701Sdim  OS << (IsInstanceMethod ? "(im)" : "(cm)") << Sel;
784259701Sdim}
785259701Sdim
786259701Sdimvoid clang::index::generateUSRForObjCProperty(StringRef Prop, raw_ostream &OS) {
787259701Sdim  OS << "(py)" << Prop;
788259701Sdim}
789259701Sdim
790259701Sdimvoid clang::index::generateUSRForObjCProtocol(StringRef Prot, raw_ostream &OS) {
791259701Sdim  OS << "objc(pl)" << Prot;
792259701Sdim}
793259701Sdim
794259701Sdimbool clang::index::generateUSRForDecl(const Decl *D,
795259701Sdim                                      SmallVectorImpl<char> &Buf) {
796259701Sdim  // Don't generate USRs for things with invalid locations.
797259701Sdim  if (!D || D->getLocStart().isInvalid())
798259701Sdim    return true;
799259701Sdim
800259701Sdim  USRGenerator UG(&D->getASTContext(), Buf);
801259701Sdim  UG.Visit(D);
802259701Sdim  return UG.ignoreResults();
803259701Sdim}
804