Coverage Report

Created: 2023-09-12 09:32

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