Coverage Report

Created: 2022-01-22 13:19

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