clang 23.0.0git
USRGeneration.cpp
Go to the documentation of this file.
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
11#include "clang/AST/Attr.h"
12#include "clang/AST/DeclCXX.h"
15#include "clang/AST/ODRHash.h"
17#include "llvm/Support/Path.h"
18#include "llvm/Support/raw_ostream.h"
19
20using namespace clang;
21using namespace clang::index;
22
23//===----------------------------------------------------------------------===//
24// USR generation.
25//===----------------------------------------------------------------------===//
26
27/// Print only the offset part of \p Loc
28/// \returns true on error.
29static bool printLocOffset(llvm::raw_ostream &OS, SourceLocation Loc,
30 const SourceManager &SM) {
31 if (Loc.isInvalid())
32 return true;
33 if (SM.getExpansionLoc(Loc) == SM.getSpellingLoc(Loc)) {
34 // Use the offest into the FileID to represent the location. Using
35 // a line/column can cause us to look back at the original source file,
36 // which is expensive.
37 OS << '@' << SM.getDecomposedLoc(Loc).second;
38 return false;
39 }
40 // In case expansion and spelling locations differ, we need both of them to
41 // make the USR distinguishable:
42 OS << '@' << SM.getDecomposedLoc(SM.getExpansionLoc(Loc)).second;
43 OS << '@' << SM.getDecomposedLoc(SM.getSpellingLoc(Loc)).second;
44 return false;
45}
46
47/// Print \p Loc including both the file and offset, if \p IncludeOffset is
48/// true. Print only the file of \p Loc otherwise.
49/// \returns true on error.
50static bool printLoc(llvm::raw_ostream &OS, SourceLocation Loc,
51 const SourceManager &SM, bool IncludeOffset) {
52 if (Loc.isInvalid()) {
53 return true;
54 }
55 Loc = SM.getExpansionLoc(Loc);
56 const FileIDAndOffset &Decomposed = SM.getDecomposedLoc(Loc);
57 OptionalFileEntryRef FE = SM.getFileEntryRefForID(Decomposed.first);
58 if (FE) {
59 OS << llvm::sys::path::filename(FE->getName());
60 } else {
61 // This case really isn't interesting.
62 return true;
63 }
64 if (IncludeOffset) {
65 // Use the offest into the FileID to represent the location. Using
66 // a line/column can cause us to look back at the original source file,
67 // which is expensive.
68 printLocOffset(OS, Loc, SM);
69 }
70 return false;
71}
72
73static StringRef GetExternalSourceContainer(const NamedDecl *D) {
74 if (!D)
75 return StringRef();
76 if (auto *attr = D->getExternalSourceSymbolAttr()) {
77 return attr->getDefinedIn();
78 }
79 return StringRef();
80}
81
82namespace {
83class USRGenerator : public ConstDeclVisitor<USRGenerator> {
84 SmallVectorImpl<char> &Buf;
85 llvm::raw_svector_ostream Out;
86 ASTContext *Context;
87 const LangOptions &LangOpts;
88 bool IgnoreResults = false;
89 // The flag below ensures that, when a source location needs to be printed,
90 // the filename is printed at most once during the recursive visit. The
91 // offset part may be printed multiple times, since sub-decls along the
92 // visit may each need a distinct location to disambiguate them.
93 bool GeneratedFilename = false;
94
95 llvm::DenseMap<const Type *, unsigned> TypeSubstitutions;
96
97public:
98 USRGenerator(ASTContext *Ctx, SmallVectorImpl<char> &Buf,
99 const LangOptions &LangOpts)
100 : Buf(Buf), Out(Buf), Context(Ctx), LangOpts(LangOpts) {
101 // Add the USR space prefix.
102 Out << getUSRSpacePrefix();
103 }
104
105 bool ignoreResults() const { return IgnoreResults; }
106
107 // Visitation methods from generating USRs from AST elements.
108 void VisitDeclContext(const DeclContext *D);
109 void VisitFieldDecl(const FieldDecl *D);
110 void VisitFunctionDecl(const FunctionDecl *D);
111 void VisitNamedDecl(const NamedDecl *D);
112 void VisitNamespaceDecl(const NamespaceDecl *D);
113 void VisitNamespaceAliasDecl(const NamespaceAliasDecl *D);
114 void VisitFunctionTemplateDecl(const FunctionTemplateDecl *D);
115 void VisitClassTemplateDecl(const ClassTemplateDecl *D);
116 void VisitObjCContainerDecl(const ObjCContainerDecl *CD,
117 const ObjCCategoryDecl *CatD = nullptr);
118 void VisitObjCMethodDecl(const ObjCMethodDecl *MD);
119 void VisitObjCPropertyDecl(const ObjCPropertyDecl *D);
120 void VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D);
121 void VisitTagDecl(const TagDecl *D);
122 void VisitTypedefDecl(const TypedefDecl *D);
123 void VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D);
124 void VisitVarDecl(const VarDecl *D);
125 void VisitBindingDecl(const BindingDecl *D);
126 void VisitNonTypeTemplateParmDecl(const NonTypeTemplateParmDecl *D);
127 void VisitTemplateTemplateParmDecl(const TemplateTemplateParmDecl *D);
128 void VisitUnresolvedUsingValueDecl(const UnresolvedUsingValueDecl *D);
129 void VisitUnresolvedUsingTypenameDecl(const UnresolvedUsingTypenameDecl *D);
130 void VisitConceptDecl(const ConceptDecl *D);
131
132 void VisitLinkageSpecDecl(const LinkageSpecDecl *D) {
133 IgnoreResults = true; // No USRs for linkage specs themselves.
134 }
135
136 void VisitUsingDirectiveDecl(const UsingDirectiveDecl *D) {
137 IgnoreResults = true;
138 }
139
140 void VisitUsingDecl(const UsingDecl *D) {
141 VisitDeclContext(D->getDeclContext());
142 Out << "@UD@";
143
144 bool EmittedDeclName = !EmitDeclName(D);
145 assert(EmittedDeclName && "EmitDeclName can not fail for UsingDecls");
146 (void)EmittedDeclName;
147 }
148
149 bool ShouldGenerateLocation(const NamedDecl *D);
150
151 bool isLocal(const NamedDecl *D) {
152 return D->getParentFunctionOrMethod() != nullptr;
153 }
154
155 void GenExtSymbolContainer(const NamedDecl *D);
156
157 /// Generate the string component containing the location of the
158 /// declaration.
159 bool GenLoc(const Decl *D, bool IncludeOffset);
160
161 /// String generation methods used both by the visitation methods
162 /// and from other clients that want to directly generate USRs. These
163 /// methods do not construct complete USRs (which incorporate the parents
164 /// of an AST element), but only the fragments concerning the AST element
165 /// itself.
166
167 /// Generate a USR for an Objective-C class.
168 void GenObjCClass(StringRef cls, StringRef ExtSymDefinedIn,
169 StringRef CategoryContextExtSymbolDefinedIn) {
170 generateUSRForObjCClass(cls, Out, ExtSymDefinedIn,
171 CategoryContextExtSymbolDefinedIn);
172 }
173
174 /// Generate a USR for an Objective-C class category.
175 void GenObjCCategory(StringRef cls, StringRef cat, StringRef clsExt,
176 StringRef catExt) {
177 generateUSRForObjCCategory(cls, cat, Out, clsExt, catExt);
178 }
179
180 /// Generate a USR fragment for an Objective-C property.
181 void GenObjCProperty(StringRef prop, bool isClassProp) {
182 generateUSRForObjCProperty(prop, isClassProp, Out);
183 }
184
185 /// Generate a USR for an Objective-C protocol.
186 void GenObjCProtocol(StringRef prot, StringRef ext) {
187 generateUSRForObjCProtocol(prot, Out, ext);
188 }
189
190 void VisitType(QualType T);
191 void VisitTemplateParameterList(const TemplateParameterList *Params);
192 void VisitTemplateName(TemplateName Name);
193 void VisitTemplateArgument(const TemplateArgument &Arg);
194
195 void VisitMSGuidDecl(const MSGuidDecl *D);
196
197 /// Emit a Decl's name using NamedDecl::printName() and return true if
198 /// the decl had no name.
199 bool EmitDeclName(const NamedDecl *D);
200};
201} // end anonymous namespace
202
203//===----------------------------------------------------------------------===//
204// Generating USRs from ASTS.
205//===----------------------------------------------------------------------===//
206
207bool USRGenerator::EmitDeclName(const NamedDecl *D) {
208 DeclarationName N = D->getDeclName();
209 if (N.isEmpty())
210 return true;
211 Out << N;
212 return false;
213}
214
215bool USRGenerator::ShouldGenerateLocation(const NamedDecl *D) {
216 if (D->isExternallyVisible())
217 return false;
219 return true;
220 SourceLocation Loc = D->getLocation();
221 if (Loc.isInvalid())
222 return false;
223 const SourceManager &SM = Context->getSourceManager();
224 return !SM.isInSystemHeader(Loc);
225}
226
227void USRGenerator::VisitDeclContext(const DeclContext *DC) {
228 if (const NamedDecl *D = dyn_cast<NamedDecl>(DC))
229 Visit(D);
230 else if (isa<LinkageSpecDecl>(DC)) // Linkage specs are transparent in USRs.
231 VisitDeclContext(DC->getParent());
232}
233
234void USRGenerator::VisitFieldDecl(const FieldDecl *D) {
235 // The USR for an ivar declared in a class extension is based on the
236 // ObjCInterfaceDecl, not the ObjCCategoryDecl.
237 if (const ObjCInterfaceDecl *ID = Context->getObjContainingInterface(D))
238 Visit(ID);
239 else
240 VisitDeclContext(D->getDeclContext());
241 Out << (isa<ObjCIvarDecl>(D) ? "@" : "@FI@");
242 if (EmitDeclName(D)) {
243 // Bit fields can be anonymous.
244 IgnoreResults = true;
245 return;
246 }
247}
248
249void USRGenerator::VisitFunctionDecl(const FunctionDecl *D) {
250 if (ShouldGenerateLocation(D) && GenLoc(D, /*IncludeOffset=*/isLocal(D)))
251 return;
252
253 if (D->getType().isNull()) {
254 IgnoreResults = true;
255 return;
256 }
257
258 const unsigned StartSize = Buf.size();
259 VisitDeclContext(D->getDeclContext());
260 if (Buf.size() == StartSize)
261 GenExtSymbolContainer(D);
262
263 bool IsTemplate = false;
264 if (FunctionTemplateDecl *FunTmpl = D->getDescribedFunctionTemplate()) {
265 IsTemplate = true;
266 Out << "@FT@";
267 VisitTemplateParameterList(FunTmpl->getTemplateParameters());
268 } else
269 Out << "@F@";
270
271 PrintingPolicy Policy(LangOpts);
272 // Forward references can have different template argument names. Suppress the
273 // template argument names in constructors to make their USR more stable.
274 Policy.SuppressTemplateArgsInCXXConstructors = true;
275 D->getDeclName().print(Out, Policy);
276
277 if ((!LangOpts.CPlusPlus || D->isExternC()) &&
278 !D->hasAttr<OverloadableAttr>())
279 return;
280
282 Out << '<';
283 if (const TemplateArgumentList *SpecArgs =
285 for (const auto &Arg : SpecArgs->asArray()) {
286 Out << '#';
287 VisitTemplateArgument(Arg);
288 }
289 } else if (const ASTTemplateArgumentListInfo *SpecArgsWritten =
291 for (const auto &ArgLoc : SpecArgsWritten->arguments()) {
292 Out << '#';
293 VisitTemplateArgument(ArgLoc.getArgument());
294 }
295 }
296 Out << '>';
297 }
298
299 QualType CanonicalType = D->getType().getCanonicalType();
300 // Mangle in type information for the arguments.
301 if (const auto *FPT = CanonicalType->getAs<FunctionProtoType>()) {
302 for (QualType PT : FPT->param_types()) {
303 Out << '#';
304 VisitType(PT);
305 }
306 }
307 if (D->isVariadic())
308 Out << '.';
309 if (IsTemplate) {
310 // Function templates can be overloaded by return type, for example:
311 // \code
312 // template <class T> typename T::A foo() {}
313 // template <class T> typename T::B foo() {}
314 // \endcode
315 Out << '#';
316 VisitType(D->getReturnType());
317 }
318 Out << '#';
319 if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {
320 if (MD->isStatic())
321 Out << 'S';
322 // FIXME: OpenCL: Need to consider address spaces
323 if (unsigned quals = MD->getMethodQualifiers().getCVRUQualifiers())
324 Out << (char)('0' + quals);
325 switch (MD->getRefQualifier()) {
326 case RQ_None:
327 break;
328 case RQ_LValue:
329 Out << '&';
330 break;
331 case RQ_RValue:
332 Out << "&&";
333 break;
334 }
335 }
336}
337
338void USRGenerator::VisitNamedDecl(const NamedDecl *D) {
339 VisitDeclContext(D->getDeclContext());
340 Out << "@";
341
342 if (EmitDeclName(D)) {
343 // The string can be empty if the declaration has no name; e.g., it is
344 // the ParmDecl with no name for declaration of a function pointer type,
345 // e.g.: void (*f)(void *);
346 // In this case, don't generate a USR.
347 IgnoreResults = true;
348 }
349}
350
351void USRGenerator::VisitVarDecl(const VarDecl *D) {
352 // VarDecls can be declared 'extern' within a function or method body,
353 // but their enclosing DeclContext is the function, not the TU. We need
354 // to check the storage class to correctly generate the USR.
355 if (ShouldGenerateLocation(D) && GenLoc(D, /*IncludeOffset=*/isLocal(D)))
356 return;
357
358 VisitDeclContext(D->getDeclContext());
359
360 if (VarTemplateDecl *VarTmpl = D->getDescribedVarTemplate()) {
361 Out << "@VT";
362 VisitTemplateParameterList(VarTmpl->getTemplateParameters());
363 } else if (const VarTemplatePartialSpecializationDecl *PartialSpec =
364 dyn_cast<VarTemplatePartialSpecializationDecl>(D)) {
365 Out << "@VP";
366 VisitTemplateParameterList(PartialSpec->getTemplateParameters());
367 }
368
369 // Variables always have simple names.
370 StringRef s = D->getName();
371
372 // The string can be empty if the declaration has no name; e.g., it is
373 // the ParmDecl with no name for declaration of a function pointer type, e.g.:
374 // void (*f)(void *);
375 // In this case, don't generate a USR.
376 if (s.empty())
377 IgnoreResults = true;
378 else
379 Out << '@' << s;
380
381 // For a template specialization, mangle the template arguments.
382 if (const VarTemplateSpecializationDecl *Spec =
383 dyn_cast<VarTemplateSpecializationDecl>(D)) {
384 const TemplateArgumentList &Args = Spec->getTemplateArgs();
385 Out << '>';
386 for (unsigned I = 0, N = Args.size(); I != N; ++I) {
387 Out << '#';
388 VisitTemplateArgument(Args.get(I));
389 }
390 }
391}
392
393void USRGenerator::VisitBindingDecl(const BindingDecl *D) {
394 if (isLocal(D) && GenLoc(D, /*IncludeOffset=*/true))
395 return;
396 VisitNamedDecl(D);
397}
398
399void USRGenerator::VisitNonTypeTemplateParmDecl(
400 const NonTypeTemplateParmDecl *D) {
401 GenLoc(D, /*IncludeOffset=*/true);
402}
403
404void USRGenerator::VisitTemplateTemplateParmDecl(
405 const TemplateTemplateParmDecl *D) {
406 GenLoc(D, /*IncludeOffset=*/true);
407}
408
409void USRGenerator::VisitNamespaceDecl(const NamespaceDecl *D) {
410 if (IgnoreResults)
411 return;
412 VisitDeclContext(D->getDeclContext());
413 if (D->isAnonymousNamespace()) {
414 Out << "@aN";
415 return;
416 }
417 Out << "@N@" << D->getName();
418}
419
420void USRGenerator::VisitFunctionTemplateDecl(const FunctionTemplateDecl *D) {
421 VisitFunctionDecl(D->getTemplatedDecl());
422}
423
424void USRGenerator::VisitClassTemplateDecl(const ClassTemplateDecl *D) {
425 VisitTagDecl(D->getTemplatedDecl());
426}
427
428void USRGenerator::VisitNamespaceAliasDecl(const NamespaceAliasDecl *D) {
429 VisitDeclContext(D->getDeclContext());
430 if (!IgnoreResults)
431 Out << "@NA@" << D->getName();
432}
433
435 if (auto *CD = dyn_cast<ObjCCategoryDecl>(D->getDeclContext()))
436 return CD;
437 if (auto *ICD = dyn_cast<ObjCCategoryImplDecl>(D->getDeclContext()))
438 return ICD->getCategoryDecl();
439 return nullptr;
440}
441
442void USRGenerator::VisitObjCMethodDecl(const ObjCMethodDecl *D) {
443 const DeclContext *container = D->getDeclContext();
444 if (const ObjCProtocolDecl *pd = dyn_cast<ObjCProtocolDecl>(container)) {
445 Visit(pd);
446 } else {
447 // The USR for a method declared in a class extension or category is based
448 // on the ObjCInterfaceDecl, not the ObjCCategoryDecl.
449 const ObjCInterfaceDecl *ID = D->getClassInterface();
450 if (!ID) {
451 IgnoreResults = true;
452 return;
453 }
454 auto *CD = getCategoryContext(D);
455 VisitObjCContainerDecl(ID, CD);
456 }
457 // Ideally we would use 'GenObjCMethod', but this is such a hot path
458 // for Objective-C code that we don't want to use
459 // DeclarationName::getAsString().
460 Out << (D->isInstanceMethod() ? "(im)" : "(cm)")
461 << DeclarationName(D->getSelector());
462}
463
464void USRGenerator::VisitObjCContainerDecl(const ObjCContainerDecl *D,
465 const ObjCCategoryDecl *CatD) {
466 switch (D->getKind()) {
467 default:
468 llvm_unreachable("Invalid ObjC container.");
469 case Decl::ObjCInterface:
470 case Decl::ObjCImplementation:
471 GenObjCClass(D->getName(), GetExternalSourceContainer(D),
473 break;
474 case Decl::ObjCCategory: {
475 const ObjCCategoryDecl *CD = cast<ObjCCategoryDecl>(D);
476 const ObjCInterfaceDecl *ID = CD->getClassInterface();
477 if (!ID) {
478 // Handle invalid code where the @interface might not
479 // have been specified.
480 // FIXME: We should be able to generate this USR even if the
481 // @interface isn't available.
482 IgnoreResults = true;
483 return;
484 }
485 // Specially handle class extensions, which are anonymous categories.
486 // We want to mangle in the location to uniquely distinguish them.
487 if (CD->IsClassExtension()) {
488 Out << "objc(ext)" << ID->getName() << '@';
489 GenLoc(CD, /*IncludeOffset=*/true);
490 } else
491 GenObjCCategory(ID->getName(), CD->getName(),
494
495 break;
496 }
497 case Decl::ObjCCategoryImpl: {
498 const ObjCCategoryImplDecl *CD = cast<ObjCCategoryImplDecl>(D);
499 const ObjCInterfaceDecl *ID = CD->getClassInterface();
500 if (!ID) {
501 // Handle invalid code where the @interface might not
502 // have been specified.
503 // FIXME: We should be able to generate this USR even if the
504 // @interface isn't available.
505 IgnoreResults = true;
506 return;
507 }
508 GenObjCCategory(ID->getName(), CD->getName(),
511 break;
512 }
513 case Decl::ObjCProtocol: {
514 const ObjCProtocolDecl *PD = cast<ObjCProtocolDecl>(D);
515 GenObjCProtocol(PD->getName(), GetExternalSourceContainer(PD));
516 break;
517 }
518 }
519}
520
521void USRGenerator::VisitObjCPropertyDecl(const ObjCPropertyDecl *D) {
522 // The USR for a property declared in a class extension or category is based
523 // on the ObjCInterfaceDecl, not the ObjCCategoryDecl.
524 if (const ObjCInterfaceDecl *ID = Context->getObjContainingInterface(D))
525 VisitObjCContainerDecl(ID, getCategoryContext(D));
526 else
527 Visit(cast<Decl>(D->getDeclContext()));
528 GenObjCProperty(D->getName(), D->isClassProperty());
529}
530
531void USRGenerator::VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D) {
532 if (ObjCPropertyDecl *PD = D->getPropertyDecl()) {
533 VisitObjCPropertyDecl(PD);
534 return;
535 }
536
537 IgnoreResults = true;
538}
539
540void USRGenerator::VisitTagDecl(const TagDecl *D) {
541 // Add the location of the tag decl to handle resolution across
542 // translation units.
543 if (!isa<EnumDecl>(D) && ShouldGenerateLocation(D) &&
544 GenLoc(D, /*IncludeOffset=*/isLocal(D)))
545 return;
546
547 GenExtSymbolContainer(D);
548
549 D = D->getCanonicalDecl();
550 VisitDeclContext(D->getDeclContext());
551
552 bool AlreadyStarted = false;
553 if (const CXXRecordDecl *CXXRecord = dyn_cast<CXXRecordDecl>(D)) {
554 if (ClassTemplateDecl *ClassTmpl = CXXRecord->getDescribedClassTemplate()) {
555 AlreadyStarted = true;
556
557 switch (D->getTagKind()) {
558 case TagTypeKind::Interface:
559 case TagTypeKind::Class:
560 case TagTypeKind::Struct:
561 Out << "@ST";
562 break;
563 case TagTypeKind::Union:
564 Out << "@UT";
565 break;
566 case TagTypeKind::Enum:
567 llvm_unreachable("enum template");
568 }
569 VisitTemplateParameterList(ClassTmpl->getTemplateParameters());
570 } else if (const ClassTemplatePartialSpecializationDecl *PartialSpec =
571 dyn_cast<ClassTemplatePartialSpecializationDecl>(
572 CXXRecord)) {
573 AlreadyStarted = true;
574
575 switch (D->getTagKind()) {
576 case TagTypeKind::Interface:
577 case TagTypeKind::Class:
578 case TagTypeKind::Struct:
579 Out << "@SP";
580 break;
581 case TagTypeKind::Union:
582 Out << "@UP";
583 break;
584 case TagTypeKind::Enum:
585 llvm_unreachable("enum partial specialization");
586 }
587 VisitTemplateParameterList(PartialSpec->getTemplateParameters());
588 }
589 }
590
591 if (!AlreadyStarted) {
592 switch (D->getTagKind()) {
593 case TagTypeKind::Interface:
594 case TagTypeKind::Class:
595 case TagTypeKind::Struct:
596 Out << "@S";
597 break;
598 case TagTypeKind::Union:
599 Out << "@U";
600 break;
601 case TagTypeKind::Enum:
602 Out << "@E";
603 break;
604 }
605 }
606
607 Out << '@';
608 assert(Buf.size() > 0);
609 const unsigned off = Buf.size() - 1;
610
611 if (EmitDeclName(D)) {
612 if (const TypedefNameDecl *TD = D->getTypedefNameForAnonDecl()) {
613 Buf[off] = 'A';
614 Out << '@' << *TD;
615 } else {
616 if (D->isEmbeddedInDeclarator() && !D->isFreeStanding()) {
617 printLoc(Out, D->getLocation(), Context->getSourceManager(), true);
618 } else {
619 Buf[off] = 'a';
620 if (auto *ED = dyn_cast<EnumDecl>(D)) {
621 // Distinguish USRs of anonymous enums by using their first
622 // enumerator.
623 auto enum_range = ED->enumerators();
624 if (enum_range.begin() != enum_range.end()) {
625 Out << '@' << **enum_range.begin();
626 }
627 }
628 }
629 }
630 }
631
632 // For a class template specialization, mangle the template arguments.
633 if (const ClassTemplateSpecializationDecl *Spec =
634 dyn_cast<ClassTemplateSpecializationDecl>(D)) {
635 const TemplateArgumentList &Args = Spec->getTemplateArgs();
636 Out << '>';
637 for (unsigned I = 0, N = Args.size(); I != N; ++I) {
638 Out << '#';
639 VisitTemplateArgument(Args.get(I));
640 }
641 }
642}
643
644void USRGenerator::VisitTypedefDecl(const TypedefDecl *D) {
645 if (ShouldGenerateLocation(D) && GenLoc(D, /*IncludeOffset=*/isLocal(D)))
646 return;
647 const DeclContext *DC = D->getDeclContext();
648 if (const NamedDecl *DCN = dyn_cast<NamedDecl>(DC))
649 Visit(DCN);
650 Out << "@T@";
651 Out << D->getName();
652}
653
654void USRGenerator::VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D) {
655 GenLoc(D, /*IncludeOffset=*/true);
656}
657
658void USRGenerator::GenExtSymbolContainer(const NamedDecl *D) {
659 StringRef Container = GetExternalSourceContainer(D);
660 if (!Container.empty())
661 Out << "@M@" << Container;
662}
663
664bool USRGenerator::GenLoc(const Decl *D, bool IncludeOffset) {
665 // Guard against null declarations in invalid code.
666 if (!D) {
667 IgnoreResults = true;
668 return true;
669 }
670 // Do nothing if no need to print the offset nor the filename:
671 if (!IncludeOffset && GeneratedFilename)
672 return IgnoreResults;
673
674 bool PrintErr = false;
675
676 // Use the location of canonical decl.
677 D = D->getCanonicalDecl();
678 if (!GeneratedFilename) {
679 GeneratedFilename = true;
680 PrintErr = printLoc(Out, D->getBeginLoc(), Context->getSourceManager(),
681 IncludeOffset);
682 } else {
683 PrintErr =
684 printLocOffset(Out, D->getBeginLoc(), Context->getSourceManager());
685 }
686 IgnoreResults = IgnoreResults || PrintErr;
687 return IgnoreResults;
688}
689
690static void printQualifier(llvm::raw_ostream &Out, const LangOptions &LangOpts,
692 // FIXME: Encode the qualifier, don't just print it.
693 PrintingPolicy PO(LangOpts);
694 PO.SuppressTagKeyword = true;
695 PO.SuppressUnwrittenScope = true;
698 llvm::to_underlying(PrintingPolicy::AnonymousTagMode::Plain);
699 NNS.print(Out, PO);
700}
701
702void USRGenerator::VisitType(QualType T) {
703 // This method mangles in USR information for types. It can possibly
704 // just reuse the naming-mangling logic used by codegen, although the
705 // requirements for USRs might not be the same.
706 ASTContext &Ctx = *Context;
707
708 do {
709 T = Ctx.getCanonicalType(T);
710 Qualifiers Q = T.getQualifiers();
711 unsigned qVal = 0;
712 if (Q.hasConst())
713 qVal |= 0x1;
714 if (Q.hasVolatile())
715 qVal |= 0x2;
716 if (Q.hasRestrict())
717 qVal |= 0x4;
718 if (qVal)
719 Out << ((char)('0' + qVal));
720
721 // Mangle in ObjC GC qualifiers?
722
723 if (const PackExpansionType *Expansion = T->getAs<PackExpansionType>()) {
724 Out << 'P';
725 T = Expansion->getPattern();
726 }
727
728 if (const BuiltinType *BT = T->getAs<BuiltinType>()) {
729 switch (BT->getKind()) {
730 case BuiltinType::Void:
731 Out << 'v';
732 break;
733 case BuiltinType::Bool:
734 Out << 'b';
735 break;
736 case BuiltinType::UChar:
737 Out << 'c';
738 break;
739 case BuiltinType::Char8:
740 Out << 'u';
741 break;
742 case BuiltinType::Char16:
743 Out << 'q';
744 break;
745 case BuiltinType::Char32:
746 Out << 'w';
747 break;
748 case BuiltinType::UShort:
749 Out << 's';
750 break;
751 case BuiltinType::UInt:
752 Out << 'i';
753 break;
754 case BuiltinType::ULong:
755 Out << 'l';
756 break;
757 case BuiltinType::ULongLong:
758 Out << 'k';
759 break;
760 case BuiltinType::UInt128:
761 Out << 'j';
762 break;
763 case BuiltinType::Char_U:
764 case BuiltinType::Char_S:
765 Out << 'C';
766 break;
767 case BuiltinType::SChar:
768 Out << 'r';
769 break;
770 case BuiltinType::WChar_S:
771 case BuiltinType::WChar_U:
772 Out << 'W';
773 break;
774 case BuiltinType::Short:
775 Out << 'S';
776 break;
777 case BuiltinType::Int:
778 Out << 'I';
779 break;
780 case BuiltinType::Long:
781 Out << 'L';
782 break;
783 case BuiltinType::LongLong:
784 Out << 'K';
785 break;
786 case BuiltinType::Int128:
787 Out << 'J';
788 break;
789 case BuiltinType::Float16:
790 case BuiltinType::Half:
791 Out << 'h';
792 break;
793 case BuiltinType::Float:
794 Out << 'f';
795 break;
796 case BuiltinType::Double:
797 Out << 'd';
798 break;
799 case BuiltinType::LongDouble:
800 Out << 'D';
801 break;
802 case BuiltinType::Float128:
803 Out << 'Q';
804 break;
805 case BuiltinType::NullPtr:
806 Out << 'n';
807 break;
808#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
809 case BuiltinType::Id: \
810 Out << "@BT@" << #Suffix << "_" << #ImgType; \
811 break;
812#include "clang/Basic/OpenCLImageTypes.def"
813#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
814 case BuiltinType::Id: \
815 Out << "@BT@" << #ExtType; \
816 break;
817#include "clang/Basic/OpenCLExtensionTypes.def"
818 case BuiltinType::OCLEvent:
819 Out << "@BT@OCLEvent";
820 break;
821 case BuiltinType::OCLClkEvent:
822 Out << "@BT@OCLClkEvent";
823 break;
824 case BuiltinType::OCLQueue:
825 Out << "@BT@OCLQueue";
826 break;
827 case BuiltinType::OCLReserveID:
828 Out << "@BT@OCLReserveID";
829 break;
830 case BuiltinType::OCLSampler:
831 Out << "@BT@OCLSampler";
832 break;
833#define SVE_TYPE(Name, Id, SingletonId) \
834 case BuiltinType::Id: \
835 Out << "@BT@" << #Name; \
836 break;
837#include "clang/Basic/AArch64ACLETypes.def"
838#define PPC_VECTOR_TYPE(Name, Id, Size) \
839 case BuiltinType::Id: \
840 Out << "@BT@" << #Name; \
841 break;
842#include "clang/Basic/PPCTypes.def"
843#define RVV_TYPE(Name, Id, SingletonId) \
844 case BuiltinType::Id: \
845 Out << "@BT@" << Name; \
846 break;
847#include "clang/Basic/RISCVVTypes.def"
848#define WASM_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
849#include "clang/Basic/WebAssemblyReferenceTypes.def"
850#define AMDGPU_TYPE(Name, Id, SingletonId, Width, Align) \
851 case BuiltinType::Id: \
852 Out << "@BT@" << #Name; \
853 break;
854#include "clang/Basic/AMDGPUTypes.def"
855#define HLSL_INTANGIBLE_TYPE(Name, Id, SingletonId) \
856 case BuiltinType::Id: \
857 Out << "@BT@" << #Name; \
858 break;
859#include "clang/Basic/HLSLIntangibleTypes.def"
860 case BuiltinType::ShortAccum:
861 Out << "@BT@ShortAccum";
862 break;
863 case BuiltinType::Accum:
864 Out << "@BT@Accum";
865 break;
866 case BuiltinType::LongAccum:
867 Out << "@BT@LongAccum";
868 break;
869 case BuiltinType::UShortAccum:
870 Out << "@BT@UShortAccum";
871 break;
872 case BuiltinType::UAccum:
873 Out << "@BT@UAccum";
874 break;
875 case BuiltinType::ULongAccum:
876 Out << "@BT@ULongAccum";
877 break;
878 case BuiltinType::ShortFract:
879 Out << "@BT@ShortFract";
880 break;
881 case BuiltinType::Fract:
882 Out << "@BT@Fract";
883 break;
884 case BuiltinType::LongFract:
885 Out << "@BT@LongFract";
886 break;
887 case BuiltinType::UShortFract:
888 Out << "@BT@UShortFract";
889 break;
890 case BuiltinType::UFract:
891 Out << "@BT@UFract";
892 break;
893 case BuiltinType::ULongFract:
894 Out << "@BT@ULongFract";
895 break;
896 case BuiltinType::SatShortAccum:
897 Out << "@BT@SatShortAccum";
898 break;
899 case BuiltinType::SatAccum:
900 Out << "@BT@SatAccum";
901 break;
902 case BuiltinType::SatLongAccum:
903 Out << "@BT@SatLongAccum";
904 break;
905 case BuiltinType::SatUShortAccum:
906 Out << "@BT@SatUShortAccum";
907 break;
908 case BuiltinType::SatUAccum:
909 Out << "@BT@SatUAccum";
910 break;
911 case BuiltinType::SatULongAccum:
912 Out << "@BT@SatULongAccum";
913 break;
914 case BuiltinType::SatShortFract:
915 Out << "@BT@SatShortFract";
916 break;
917 case BuiltinType::SatFract:
918 Out << "@BT@SatFract";
919 break;
920 case BuiltinType::SatLongFract:
921 Out << "@BT@SatLongFract";
922 break;
923 case BuiltinType::SatUShortFract:
924 Out << "@BT@SatUShortFract";
925 break;
926 case BuiltinType::SatUFract:
927 Out << "@BT@SatUFract";
928 break;
929 case BuiltinType::SatULongFract:
930 Out << "@BT@SatULongFract";
931 break;
932 case BuiltinType::BFloat16:
933 Out << "@BT@__bf16";
934 break;
935 case BuiltinType::Ibm128:
936 Out << "@BT@__ibm128";
937 break;
938 case BuiltinType::ObjCId:
939 Out << 'o';
940 break;
941 case BuiltinType::ObjCClass:
942 Out << 'O';
943 break;
944 case BuiltinType::ObjCSel:
945 Out << 'e';
946 break;
947#define BUILTIN_TYPE(Id, SingletonId)
948#define PLACEHOLDER_TYPE(Id, SingletonId) case BuiltinType::Id:
949#include "clang/AST/BuiltinTypes.def"
950 case BuiltinType::Dependent:
951 // If you're adding a new builtin type, please add its name prefixed
952 // with "@BT@" to `Out` (see cases above).
953 IgnoreResults = true;
954 break;
955 }
956 return;
957 }
958
959 // If we have already seen this (non-built-in) type, use a substitution
960 // encoding. Otherwise, record this as a substitution.
961 auto [Substitution, Inserted] =
962 TypeSubstitutions.try_emplace(T.getTypePtr(), TypeSubstitutions.size());
963 if (!Inserted) {
964 Out << 'S' << Substitution->second << '_';
965 return;
966 }
967
968 if (const PointerType *PT = T->getAs<PointerType>()) {
969 Out << '*';
970 T = PT->getPointeeType();
971 continue;
972 }
973 if (const ObjCObjectPointerType *OPT = T->getAs<ObjCObjectPointerType>()) {
974 Out << '*';
975 T = OPT->getPointeeType();
976 continue;
977 }
978 if (const RValueReferenceType *RT = T->getAs<RValueReferenceType>()) {
979 Out << "&&";
980 T = RT->getPointeeType();
981 continue;
982 }
983 if (const ReferenceType *RT = T->getAs<ReferenceType>()) {
984 Out << '&';
985 T = RT->getPointeeType();
986 continue;
987 }
988 if (const FunctionProtoType *FT = T->getAs<FunctionProtoType>()) {
989 Out << 'F';
990 VisitType(FT->getReturnType());
991 Out << '(';
992 for (const auto &I : FT->param_types()) {
993 Out << '#';
994 VisitType(I);
995 }
996 Out << ')';
997 if (FT->isVariadic())
998 Out << '.';
999 return;
1000 }
1001 if (const BlockPointerType *BT = T->getAs<BlockPointerType>()) {
1002 Out << 'B';
1003 T = BT->getPointeeType();
1004 continue;
1005 }
1006 if (const ComplexType *CT = T->getAs<ComplexType>()) {
1007 Out << '<';
1008 T = CT->getElementType();
1009 continue;
1010 }
1011 if (const TagType *TT = T->getAs<TagType>()) {
1012 if (const auto *ICNT = dyn_cast<InjectedClassNameType>(TT)) {
1013 T = ICNT->getDecl()->getCanonicalTemplateSpecializationType(Ctx);
1014 } else {
1015 Out << '$';
1016 VisitTagDecl(TT->getDecl());
1017 return;
1018 }
1019 }
1020 if (const ObjCInterfaceType *OIT = T->getAs<ObjCInterfaceType>()) {
1021 Out << '$';
1022 VisitObjCInterfaceDecl(OIT->getDecl());
1023 return;
1024 }
1025 if (const ObjCObjectType *OIT = T->getAs<ObjCObjectType>()) {
1026 Out << 'Q';
1027 VisitType(OIT->getBaseType());
1028 for (auto *Prot : OIT->getProtocols())
1029 VisitObjCProtocolDecl(Prot);
1030 return;
1031 }
1032 if (const TemplateTypeParmType *TTP =
1033 T->getAsCanonical<TemplateTypeParmType>()) {
1034 Out << 't' << TTP->getDepth() << '.' << TTP->getIndex();
1035 return;
1036 }
1037 if (const TemplateSpecializationType *Spec =
1038 T->getAs<TemplateSpecializationType>()) {
1039 Out << '>';
1040 VisitTemplateName(Spec->getTemplateName());
1041 Out << Spec->template_arguments().size();
1042 for (const auto &Arg : Spec->template_arguments())
1043 VisitTemplateArgument(Arg);
1044 return;
1045 }
1046 if (const DependentNameType *DNT = T->getAs<DependentNameType>()) {
1047 Out << '^';
1048 printQualifier(Out, LangOpts, DNT->getQualifier());
1049 Out << ':' << DNT->getIdentifier()->getName();
1050 return;
1051 }
1052 if (const auto *VT = T->getAs<VectorType>()) {
1053 Out << (T->isExtVectorType() ? ']' : '[');
1054 Out << VT->getNumElements();
1055 T = VT->getElementType();
1056 continue;
1057 }
1058 if (const auto *const AT = dyn_cast<ArrayType>(T)) {
1059 Out << '{';
1060 switch (AT->getSizeModifier()) {
1061 case ArraySizeModifier::Static:
1062 Out << 's';
1063 break;
1064 case ArraySizeModifier::Star:
1065 Out << '*';
1066 break;
1067 case ArraySizeModifier::Normal:
1068 Out << 'n';
1069 break;
1070 }
1071 if (const auto *const CAT = dyn_cast<ConstantArrayType>(T))
1072 Out << CAT->getSize();
1073
1074 T = AT->getElementType();
1075 continue;
1076 }
1077
1078 // Unhandled type.
1079 Out << ' ';
1080 break;
1081 } while (true);
1082}
1083
1084void USRGenerator::VisitTemplateParameterList(
1085 const TemplateParameterList *Params) {
1086 if (!Params)
1087 return;
1088 Out << '>' << Params->size();
1089 for (TemplateParameterList::const_iterator P = Params->begin(),
1090 PEnd = Params->end();
1091 P != PEnd; ++P) {
1092 Out << '#';
1093 if (isa<TemplateTypeParmDecl>(*P)) {
1094 if (cast<TemplateTypeParmDecl>(*P)->isParameterPack())
1095 Out << 'p';
1096 Out << 'T';
1097 continue;
1098 }
1099
1100 if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(*P)) {
1101 if (NTTP->isParameterPack())
1102 Out << 'p';
1103 Out << 'N';
1104 VisitType(NTTP->getType());
1105 continue;
1106 }
1107
1108 TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*P);
1109 if (TTP->isParameterPack())
1110 Out << 'p';
1111 Out << 't';
1112 VisitTemplateParameterList(TTP->getTemplateParameters());
1113 }
1114}
1115
1116void USRGenerator::VisitTemplateName(TemplateName Name) {
1117 if (TemplateDecl *Template = Name.getAsTemplateDecl()) {
1118 if (TemplateTemplateParmDecl *TTP =
1119 dyn_cast<TemplateTemplateParmDecl>(Template)) {
1120 Out << 't' << TTP->getDepth() << '.' << TTP->getIndex();
1121 return;
1122 }
1123
1124 Visit(Template);
1125 return;
1126 }
1127
1128 // FIXME: Visit dependent template names.
1129}
1130
1131void USRGenerator::VisitTemplateArgument(const TemplateArgument &Arg) {
1132 switch (Arg.getKind()) {
1134 break;
1135
1137 Visit(Arg.getAsDecl());
1138 break;
1139
1141 break;
1142
1144 Out << 'P'; // pack expansion of...
1145 [[fallthrough]];
1147 VisitTemplateName(Arg.getAsTemplateOrTemplatePattern());
1148 break;
1149
1151 // FIXME: Visit expressions.
1152 break;
1153
1155 Out << 'p' << Arg.pack_size();
1156 for (const auto &P : Arg.pack_elements())
1157 VisitTemplateArgument(P);
1158 break;
1159
1161 VisitType(Arg.getAsType());
1162 break;
1163
1165 Out << 'V';
1166 VisitType(Arg.getIntegralType());
1167 Out << Arg.getAsIntegral();
1168 break;
1169
1171 Out << 'S';
1172 VisitType(Arg.getStructuralValueType());
1173 ODRHash Hash{};
1175 Out << Hash.CalculateHash();
1176 break;
1177 }
1178 }
1179}
1180
1181void USRGenerator::VisitUnresolvedUsingValueDecl(
1182 const UnresolvedUsingValueDecl *D) {
1183 if (ShouldGenerateLocation(D) && GenLoc(D, /*IncludeOffset=*/isLocal(D)))
1184 return;
1185 VisitDeclContext(D->getDeclContext());
1186 Out << "@UUV@";
1187 printQualifier(Out, LangOpts, D->getQualifier());
1188 EmitDeclName(D);
1189}
1190
1191void USRGenerator::VisitUnresolvedUsingTypenameDecl(
1192 const UnresolvedUsingTypenameDecl *D) {
1193 if (ShouldGenerateLocation(D) && GenLoc(D, /*IncludeOffset=*/isLocal(D)))
1194 return;
1195 VisitDeclContext(D->getDeclContext());
1196 Out << "@UUT@";
1197 printQualifier(Out, LangOpts, D->getQualifier());
1198 Out << D->getName(); // Simple name.
1199}
1200
1201void USRGenerator::VisitConceptDecl(const ConceptDecl *D) {
1202 if (ShouldGenerateLocation(D) && GenLoc(D, /*IncludeOffset=*/isLocal(D)))
1203 return;
1204 VisitDeclContext(D->getDeclContext());
1205 Out << "@CT@";
1206 EmitDeclName(D);
1207}
1208
1209void USRGenerator::VisitMSGuidDecl(const MSGuidDecl *D) {
1210 VisitDeclContext(D->getDeclContext());
1211 Out << "@MG@";
1212 D->NamedDecl::printName(Out);
1213}
1214
1215//===----------------------------------------------------------------------===//
1216// USR generation functions.
1217//===----------------------------------------------------------------------===//
1218
1219static void combineClassAndCategoryExtContainers(StringRef ClsSymDefinedIn,
1220 StringRef CatSymDefinedIn,
1221 raw_ostream &OS) {
1222 if (ClsSymDefinedIn.empty() && CatSymDefinedIn.empty())
1223 return;
1224 if (CatSymDefinedIn.empty()) {
1225 OS << "@M@" << ClsSymDefinedIn << '@';
1226 return;
1227 }
1228 OS << "@CM@" << CatSymDefinedIn << '@';
1229 if (ClsSymDefinedIn != CatSymDefinedIn) {
1230 OS << ClsSymDefinedIn << '@';
1231 }
1232}
1233
1235 StringRef Cls, raw_ostream &OS, StringRef ExtSymDefinedIn,
1236 StringRef CategoryContextExtSymbolDefinedIn) {
1238 CategoryContextExtSymbolDefinedIn, OS);
1239 OS << "objc(cs)" << Cls;
1240}
1241
1242void clang::index::generateUSRForObjCCategory(StringRef Cls, StringRef Cat,
1243 raw_ostream &OS,
1244 StringRef ClsSymDefinedIn,
1245 StringRef CatSymDefinedIn) {
1246 combineClassAndCategoryExtContainers(ClsSymDefinedIn, CatSymDefinedIn, OS);
1247 OS << "objc(cy)" << Cls << '@' << Cat;
1248}
1249
1250void clang::index::generateUSRForObjCIvar(StringRef Ivar, raw_ostream &OS) {
1251 OS << '@' << Ivar;
1252}
1253
1255 bool IsInstanceMethod,
1256 raw_ostream &OS) {
1257 OS << (IsInstanceMethod ? "(im)" : "(cm)") << Sel;
1258}
1259
1260void clang::index::generateUSRForObjCProperty(StringRef Prop, bool isClassProp,
1261 raw_ostream &OS) {
1262 OS << (isClassProp ? "(cpy)" : "(py)") << Prop;
1263}
1264
1265void clang::index::generateUSRForObjCProtocol(StringRef Prot, raw_ostream &OS,
1266 StringRef ExtSymDefinedIn) {
1267 if (!ExtSymDefinedIn.empty())
1268 OS << "@M@" << ExtSymDefinedIn << '@';
1269 OS << "objc(pl)" << Prot;
1270}
1271
1272void clang::index::generateUSRForGlobalEnum(StringRef EnumName, raw_ostream &OS,
1273 StringRef ExtSymDefinedIn) {
1274 if (!ExtSymDefinedIn.empty())
1275 OS << "@M@" << ExtSymDefinedIn;
1276 OS << "@E@" << EnumName;
1277}
1278
1279void clang::index::generateUSRForEnumConstant(StringRef EnumConstantName,
1280 raw_ostream &OS) {
1281 OS << '@' << EnumConstantName;
1282}
1283
1285 SmallVectorImpl<char> &Buf) {
1286 if (!D)
1287 return true;
1288 return generateUSRForDecl(D, Buf, D->getASTContext().getLangOpts());
1289}
1290
1292 const LangOptions &LangOpts) {
1293 if (!D)
1294 return true;
1295 // We don't ignore decls with invalid source locations. Implicit decls, like
1296 // C++'s operator new function, can have invalid locations but it is fine to
1297 // create USRs that can identify them.
1298
1299 // Check if the declaration has explicit external USR specified.
1300 auto *CD = D->getCanonicalDecl();
1301 if (auto *ExternalSymAttr = CD->getAttr<ExternalSourceSymbolAttr>()) {
1302 if (!ExternalSymAttr->getUSR().empty()) {
1303 llvm::raw_svector_ostream Out(Buf);
1304 Out << ExternalSymAttr->getUSR();
1305 return false;
1306 }
1307 }
1308 USRGenerator UG(&D->getASTContext(), Buf, LangOpts);
1309 UG.Visit(D);
1310 return UG.ignoreResults();
1311}
1312
1314 const SourceManager &SM,
1315 SmallVectorImpl<char> &Buf) {
1316 if (!MD)
1317 return true;
1318 return generateUSRForMacro(MD->getName()->getName(), MD->getLocation(), SM,
1319 Buf);
1320}
1321
1323 const SourceManager &SM,
1324 SmallVectorImpl<char> &Buf) {
1325 if (MacroName.empty())
1326 return true;
1327
1328 llvm::raw_svector_ostream Out(Buf);
1329
1330 // Assume that system headers are sane. Don't put source location
1331 // information into the USR if the macro comes from a system header.
1332 bool ShouldGenerateLocation = Loc.isValid() && !SM.isInSystemHeader(Loc);
1333
1334 Out << getUSRSpacePrefix();
1335 if (ShouldGenerateLocation)
1336 printLoc(Out, Loc, SM, /*IncludeOffset=*/true);
1337 Out << "@macro@";
1338 Out << MacroName;
1339 return false;
1340}
1341
1343 SmallVectorImpl<char> &Buf) {
1344 return generateUSRForType(T, Ctx, Buf, Ctx.getLangOpts());
1345}
1346
1349 const LangOptions &LangOpts) {
1350 if (T.isNull())
1351 return true;
1352 T = T.getCanonicalType();
1353
1354 USRGenerator UG(&Ctx, Buf, LangOpts);
1355 UG.VisitType(T);
1356 return UG.ignoreResults();
1357}
1358
1360 raw_ostream &OS) {
1361 if (!Mod->Parent)
1363 if (generateFullUSRForModule(Mod->Parent, OS))
1364 return true;
1365 return generateUSRFragmentForModule(Mod, OS);
1366}
1367
1369 raw_ostream &OS) {
1370 OS << getUSRSpacePrefix();
1371 return generateUSRFragmentForModuleName(ModName, OS);
1372}
1373
1375 raw_ostream &OS) {
1376 return generateUSRFragmentForModuleName(Mod->Name, OS);
1377}
1378
1380 raw_ostream &OS) {
1381 OS << "@M@" << ModName;
1382 return false;
1383}
Defines the clang::ASTContext interface.
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
Defines the C++ template declaration subclasses.
This file contains the declaration of the ODRHash class, which calculates a hash based on AST nodes,...
#define SM(sm)
static void combineClassAndCategoryExtContainers(StringRef ClsSymDefinedIn, StringRef CatSymDefinedIn, raw_ostream &OS)
static bool printLoc(llvm::raw_ostream &OS, SourceLocation Loc, const SourceManager &SM, bool IncludeOffset)
Print Loc including both the file and offset, if IncludeOffset is true.
static const ObjCCategoryDecl * getCategoryContext(const NamedDecl *D)
static void printQualifier(llvm::raw_ostream &Out, const LangOptions &LangOpts, NestedNameSpecifier NNS)
static bool printLocOffset(llvm::raw_ostream &OS, SourceLocation Loc, const SourceManager &SM)
Print only the offset part of Loc.
static StringRef GetExternalSourceContainer(const NamedDecl *D)
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:223
SourceManager & getSourceManager()
Definition ASTContext.h:863
static CanQualType getCanonicalType(QualType T)
Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...
const LangOptions & getLangOpts() const
Definition ASTContext.h:959
const ObjCInterfaceDecl * getObjContainingInterface(const NamedDecl *ND) const
Returns the Objective-C interface that ND belongs to if it is an Objective-C method/property/ivar etc...
CXXRecordDecl * getTemplatedDecl() const
Get the underlying class declarations of the template.
A simple visitor class that helps create declaration visitors.
Definition DeclVisitor.h:75
DeclContext * getParent()
getParent - Returns the containing DeclContext.
Definition DeclBase.h:2126
Decl - This represents one declaration (or definition), e.g.
Definition DeclBase.h:86
const DeclContext * getParentFunctionOrMethod(bool LexicalParent=false) const
If this decl is defined inside a function/method/block it returns the corresponding DeclContext,...
Definition DeclBase.cpp:341
T * getAttr() const
Definition DeclBase.h:581
ASTContext & getASTContext() const LLVM_READONLY
Definition DeclBase.cpp:547
ExternalSourceSymbolAttr * getExternalSourceSymbolAttr() const
Looks on this and related declarations for an applicable external source symbol attribute.
Definition DeclBase.cpp:613
SourceLocation getLocation() const
Definition DeclBase.h:447
DeclContext * getDeclContext()
Definition DeclBase.h:456
SourceLocation getBeginLoc() const LLVM_READONLY
Definition DeclBase.h:439
bool hasAttr() const
Definition DeclBase.h:585
virtual Decl * getCanonicalDecl()
Retrieves the "canonical" declaration of the given declaration.
Definition DeclBase.h:995
Kind getKind() const
Definition DeclBase.h:450
void print(raw_ostream &OS, const PrintingPolicy &Policy) const
bool isEmpty() const
Evaluates true when this declaration name is empty.
StringRef getName() const
The name of this FileEntry.
Definition FileEntry.h:61
bool isFunctionTemplateSpecialization() const
Determine whether this function is a function template specialization.
Definition Decl.cpp:4182
FunctionTemplateDecl * getDescribedFunctionTemplate() const
Retrieves the function template that is described by this function declaration.
Definition Decl.cpp:4170
QualType getReturnType() const
Definition Decl.h:2872
bool isVariadic() const
Whether this function is variadic.
Definition Decl.cpp:3110
const TemplateArgumentList * getTemplateSpecializationArgs() const
Retrieve the template arguments used to produce this function template specialization from the primar...
Definition Decl.cpp:4306
bool isExternC() const
Determines whether this function is a function with external, C linkage.
Definition Decl.cpp:3595
const ASTTemplateArgumentListInfo * getTemplateSpecializationArgsAsWritten() const
Retrieve the template argument list as written in the sources, if any.
Definition Decl.cpp:4316
FunctionDecl * getTemplatedDecl() const
Get the underlying function declaration of the template.
StringRef getName() const
Return the actual identifier string.
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
Record the location of a macro definition.
SourceLocation getLocation() const
Retrieve the location of the macro name in the definition.
const IdentifierInfo * getName() const
Retrieve the name of the macro being defined.
Module * Parent
The parent of this module.
Definition Module.h:389
std::string Name
The name of this module.
Definition Module.h:343
This represents a decl that may have a name.
Definition Decl.h:274
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
Definition Decl.h:301
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
Definition Decl.h:340
bool isExternallyVisible() const
Definition Decl.h:433
bool isAnonymousNamespace() const
Returns true if this is an anonymous namespace declaration.
Definition Decl.h:643
Represents a C++ nested name specifier, such as "\::std::vector<int>::".
void print(raw_ostream &OS, const PrintingPolicy &Policy, bool ResolveTemplateArguments=false, bool PrintFinalScopeResOp=true) const
Print this nested name specifier to the given output stream.
void AddStructuralValue(const APValue &)
Definition ODRHash.cpp:1258
unsigned CalculateHash()
Definition ODRHash.cpp:231
ObjCCategoryDecl - Represents a category declaration.
Definition DeclObjC.h:2329
ObjCInterfaceDecl * getClassInterface()
Definition DeclObjC.h:2372
bool IsClassExtension() const
Definition DeclObjC.h:2437
const ObjCInterfaceDecl * getClassInterface() const
Definition DeclObjC.h:2486
Selector getSelector() const
Definition DeclObjC.h:327
bool isInstanceMethod() const
Definition DeclObjC.h:426
ObjCInterfaceDecl * getClassInterface()
bool isClassProperty() const
Definition DeclObjC.h:855
ObjCPropertyDecl * getPropertyDecl() const
Definition DeclObjC.h:2870
A (possibly-)qualified type.
Definition TypeBase.h:937
bool isNull() const
Return true if this QualType doesn't point to a type yet.
Definition TypeBase.h:1004
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
Definition TypeBase.h:8447
Qualifiers getQualifiers() const
Retrieve the set of qualifiers applied to this type.
Definition TypeBase.h:8487
QualType getCanonicalType() const
Definition TypeBase.h:8499
bool hasConst() const
Definition TypeBase.h:457
bool hasRestrict() const
Definition TypeBase.h:477
bool hasVolatile() const
Definition TypeBase.h:467
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
This class handles loading and caching of source files into memory.
bool isInSystemHeader(SourceLocation Loc) const
Returns if a SourceLocation is in a system header.
bool isEmbeddedInDeclarator() const
True if this tag declaration is "embedded" (i.e., defined or declared for the very first time) in the...
Definition Decl.h:3873
TypedefNameDecl * getTypedefNameForAnonDecl() const
Definition Decl.h:3985
TagDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
Definition Decl.cpp:4896
bool isFreeStanding() const
True if this tag is free standing, e.g. "struct foo;".
Definition Decl.h:3884
TagKind getTagKind() const
Definition Decl.h:3948
unsigned size() const
Retrieve the number of template arguments in this template argument list.
const TemplateArgument & get(unsigned Idx) const
Retrieve the template argument at a given index.
QualType getStructuralValueType() const
Get the type of a StructuralValue.
QualType getAsType() const
Retrieve the type for a type template argument.
llvm::APSInt getAsIntegral() const
Retrieve the template argument as an integral value.
unsigned pack_size() const
The number of template arguments in the given template argument pack.
QualType getIntegralType() const
Retrieve the type of the integral value.
ValueDecl * getAsDecl() const
Retrieve the declaration for a declaration non-type template argument.
ArrayRef< TemplateArgument > pack_elements() const
Iterator range referencing all of the elements of a template argument pack.
@ Declaration
The template argument is a declaration that was provided for a pointer, reference,...
@ Template
The template argument is a template name that was provided for a template template parameter.
@ StructuralValue
The template argument is a non-type template argument that can't be represented by the special-case D...
@ Pack
The template argument is actually a parameter pack.
@ TemplateExpansion
The template argument is a pack expansion of a template name that was provided for a template templat...
@ NullPtr
The template argument is a null pointer or null pointer to member that was provided for a non-type te...
@ Type
The template argument is a type.
@ Null
Represents an empty template argument, e.g., one that has not been deduced.
@ Integral
The template argument is an integral value stored in an llvm::APSInt that was provided for an integra...
@ Expression
The template argument is an expression, and we've not resolved it to one of the other forms yet,...
ArgKind getKind() const
Return the kind of stored template argument.
TemplateName getAsTemplateOrTemplatePattern() const
Retrieve the template argument as a template name; if the argument is a pack expansion,...
const APValue & getAsStructuralValue() const
Get the value of a StructuralValue.
TemplateParameterList * getTemplateParameters() const
Get the list of template parameters.
TemplateDecl * getAsTemplateDecl(bool IgnoreDeduced=false) const
Retrieve the underlying template declaration that this template name refers to, if known.
bool isParameterPack() const
Whether this template template parameter is a template parameter pack.
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition Type.cpp:789
bool isExtVectorType() const
Definition TypeBase.h:8827
const T * getAsCanonical() const
If this type is canonically the specified type, return its canonical type cast to that specified type...
Definition TypeBase.h:2985
const T * getAs() const
Member-template getAs<specific type>'.
Definition TypeBase.h:9277
NestedNameSpecifier getQualifier() const
Retrieve the nested-name-specifier that qualifies the name.
Definition DeclCXX.h:4092
NestedNameSpecifier getQualifier() const
Retrieve the nested-name-specifier that qualifies the name.
Definition DeclCXX.h:4002
QualType getType() const
Definition Decl.h:723
VarTemplateDecl * getDescribedVarTemplate() const
Retrieves the variable template that is described by this variable declaration.
Definition Decl.cpp:2771
bool generateFullUSRForTopLevelModuleName(StringRef ModName, raw_ostream &OS)
Generate a USR for a top-level module name, including the USR prefix.
static StringRef getUSRSpacePrefix()
void generateUSRForObjCCategory(StringRef Cls, StringRef Cat, raw_ostream &OS, StringRef ClsExtSymbolDefinedIn="", StringRef CatExtSymbolDefinedIn="")
Generate a USR fragment for an Objective-C class category.
bool generateFullUSRForModule(const Module *Mod, raw_ostream &OS)
Generate a USR for a module, including the USR prefix.
bool generateUSRFragmentForModuleName(StringRef ModName, raw_ostream &OS)
Generate a USR fragment for a module name.
bool generateUSRForMacro(const MacroDefinitionRecord *MD, const SourceManager &SM, SmallVectorImpl< char > &Buf)
Generate a USR for a macro, including the USR prefix.
void generateUSRForObjCProperty(StringRef Prop, bool isClassProp, raw_ostream &OS)
Generate a USR fragment for an Objective-C property.
void generateUSRForEnumConstant(StringRef EnumConstantName, raw_ostream &OS)
Generate a USR fragment for an enum constant.
void generateUSRForObjCIvar(StringRef Ivar, raw_ostream &OS)
Generate a USR fragment for an Objective-C instance variable.
void generateUSRForObjCMethod(StringRef Sel, bool IsInstanceMethod, raw_ostream &OS)
Generate a USR fragment for an Objective-C method.
bool generateUSRForType(QualType T, ASTContext &Ctx, SmallVectorImpl< char > &Buf)
Generates a USR for a type.
void generateUSRForObjCClass(StringRef Cls, raw_ostream &OS, StringRef ExtSymbolDefinedIn="", StringRef CategoryContextExtSymbolDefinedIn="")
Generate a USR fragment for an Objective-C class.
void generateUSRForGlobalEnum(StringRef EnumName, raw_ostream &OS, StringRef ExtSymbolDefinedIn="")
Generate USR fragment for a global (non-nested) enum.
void generateUSRForObjCProtocol(StringRef Prot, raw_ostream &OS, StringRef ExtSymbolDefinedIn="")
Generate a USR fragment for an Objective-C protocol.
bool generateUSRFragmentForModule(const Module *Mod, raw_ostream &OS)
Generate a USR fragment for a module.
bool generateUSRForDecl(const Decl *D, SmallVectorImpl< char > &Buf)
Generate a USR for a Decl, including the USR prefix.
The JSON file list parser is used to communicate input to InstallAPI.
bool isa(CodeGen::Address addr)
Definition Address.h:330
CustomizableOptional< FileEntryRef > OptionalFileEntryRef
Definition FileEntry.h:196
@ RQ_None
No ref-qualifier was provided.
Definition TypeBase.h:1797
@ RQ_LValue
An lvalue ref-qualifier was provided (&).
Definition TypeBase.h:1800
@ RQ_RValue
An rvalue ref-qualifier was provided (&&).
Definition TypeBase.h:1803
@ TemplateName
The identifier is a template name. FIXME: Add an annotation for that.
Definition Parser.h:61
std::pair< FileID, unsigned > FileIDAndOffset
@ Template
We are parsing a template declaration.
Definition Parser.h:81
U cast(CodeGen::Address addr)
Definition Address.h:327
Describes how types, statements, expressions, and declarations should be printed.
unsigned SuppressUnwrittenScope
Suppress printing parts of scope specifiers that are never written, e.g., for anonymous namespaces.
unsigned ConstantArraySizeAsWritten
Whether we should print the sizes of constant array expressions as written in the sources.
unsigned SuppressTagKeyword
Whether type printing should skip printing the tag keyword.
@ Plain
E.g., (anonymous enum)/(unnamed struct)/etc.