clang 24.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 void VisitTemplateParamObjectDecl(const TemplateParamObjectDecl *D);
197
198 /// Emit a Decl's name using NamedDecl::printName() and return true if
199 /// the decl had no name.
200 bool EmitDeclName(const NamedDecl *D);
201};
202} // end anonymous namespace
203
204//===----------------------------------------------------------------------===//
205// Generating USRs from ASTS.
206//===----------------------------------------------------------------------===//
207
208bool USRGenerator::EmitDeclName(const NamedDecl *D) {
209 DeclarationName N = D->getDeclName();
210 if (N.isEmpty())
211 return true;
212 Out << N;
213 return false;
214}
215
216bool USRGenerator::ShouldGenerateLocation(const NamedDecl *D) {
217 if (D->isExternallyVisible())
218 return false;
220 return true;
221 SourceLocation Loc = D->getLocation();
222 if (Loc.isInvalid())
223 return false;
224 const SourceManager &SM = Context->getSourceManager();
225 return !SM.isInSystemHeader(Loc);
226}
227
228void USRGenerator::VisitDeclContext(const DeclContext *DC) {
229 if (const NamedDecl *D = dyn_cast<NamedDecl>(DC))
230 Visit(D);
231 else if (isa<LinkageSpecDecl>(DC)) // Linkage specs are transparent in USRs.
232 VisitDeclContext(DC->getParent());
233}
234
235void USRGenerator::VisitFieldDecl(const FieldDecl *D) {
236 // The USR for an ivar declared in a class extension is based on the
237 // ObjCInterfaceDecl, not the ObjCCategoryDecl.
238 if (const ObjCInterfaceDecl *ID = Context->getObjContainingInterface(D))
239 Visit(ID);
240 else
241 VisitDeclContext(D->getDeclContext());
242 Out << (isa<ObjCIvarDecl>(D) ? "@" : "@FI@");
243 if (EmitDeclName(D)) {
244 // Bit fields can be anonymous.
245 IgnoreResults = true;
246 return;
247 }
248}
249
250void USRGenerator::VisitFunctionDecl(const FunctionDecl *D) {
251 if (ShouldGenerateLocation(D) && GenLoc(D, /*IncludeOffset=*/isLocal(D)))
252 return;
253
254 if (D->getType().isNull()) {
255 IgnoreResults = true;
256 return;
257 }
258
259 const unsigned StartSize = Buf.size();
260 VisitDeclContext(D->getDeclContext());
261 if (Buf.size() == StartSize)
262 GenExtSymbolContainer(D);
263
264 bool IsTemplate = false;
265 if (FunctionTemplateDecl *FunTmpl = D->getDescribedFunctionTemplate()) {
266 IsTemplate = true;
267 Out << "@FT@";
268 VisitTemplateParameterList(FunTmpl->getTemplateParameters());
269 } else
270 Out << "@F@";
271
272 PrintingPolicy Policy(LangOpts);
273 // Forward references can have different template argument names. Suppress the
274 // template argument names in constructors to make their USR more stable.
275 Policy.SuppressTemplateArgsInCXXConstructors = true;
276 D->getDeclName().print(Out, Policy);
277
278 if ((!LangOpts.CPlusPlus || D->isExternC()) &&
279 !D->hasAttr<OverloadableAttr>())
280 return;
281
283 Out << '<';
284 if (const TemplateArgumentList *SpecArgs =
286 for (const auto &Arg : SpecArgs->asArray()) {
287 Out << '#';
288 VisitTemplateArgument(Arg);
289 }
290 } else if (const ASTTemplateArgumentListInfo *SpecArgsWritten =
292 for (const auto &ArgLoc : SpecArgsWritten->arguments()) {
293 Out << '#';
294 VisitTemplateArgument(ArgLoc.getArgument());
295 }
296 }
297 Out << '>';
298 }
299
300 QualType CanonicalType = D->getType().getCanonicalType();
301 // Mangle in type information for the arguments.
302 if (const auto *FPT = CanonicalType->getAs<FunctionProtoType>()) {
303 for (QualType PT : FPT->param_types()) {
304 Out << '#';
305 VisitType(PT);
306 }
307 }
308 if (D->isVariadic())
309 Out << '.';
310 if (IsTemplate) {
311 // Function templates can be overloaded by return type, for example:
312 // \code
313 // template <class T> typename T::A foo() {}
314 // template <class T> typename T::B foo() {}
315 // \endcode
316 Out << '#';
317 VisitType(D->getReturnType());
318 }
319 Out << '#';
320 if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {
321 if (MD->isStatic())
322 Out << 'S';
323 // FIXME: OpenCL: Need to consider address spaces
324 if (unsigned quals = MD->getMethodQualifiers().getCVRUQualifiers())
325 Out << (char)('0' + quals);
326 switch (MD->getRefQualifier()) {
327 case RQ_None:
328 break;
329 case RQ_LValue:
330 Out << '&';
331 break;
332 case RQ_RValue:
333 Out << "&&";
334 break;
335 }
336 }
337}
338
339void USRGenerator::VisitNamedDecl(const NamedDecl *D) {
340 VisitDeclContext(D->getDeclContext());
341 Out << "@";
342
343 if (EmitDeclName(D)) {
344 // The string can be empty if the declaration has no name; e.g., it is
345 // the ParmDecl with no name for declaration of a function pointer type,
346 // e.g.: void (*f)(void *);
347 // In this case, don't generate a USR.
348 IgnoreResults = true;
349 }
350}
351
352void USRGenerator::VisitVarDecl(const VarDecl *D) {
353 // VarDecls can be declared 'extern' within a function or method body,
354 // but their enclosing DeclContext is the function, not the TU. We need
355 // to check the storage class to correctly generate the USR.
356 if (ShouldGenerateLocation(D) && GenLoc(D, /*IncludeOffset=*/isLocal(D)))
357 return;
358
359 VisitDeclContext(D->getDeclContext());
360
361 if (VarTemplateDecl *VarTmpl = D->getDescribedVarTemplate()) {
362 Out << "@VT";
363 VisitTemplateParameterList(VarTmpl->getTemplateParameters());
364 } else if (const VarTemplatePartialSpecializationDecl *PartialSpec =
365 dyn_cast<VarTemplatePartialSpecializationDecl>(D)) {
366 Out << "@VP";
367 VisitTemplateParameterList(PartialSpec->getTemplateParameters());
368 }
369
370 // Variables always have simple names.
371 StringRef s = D->getName();
372
373 // The string can be empty if the declaration has no name; e.g., it is
374 // the ParmDecl with no name for declaration of a function pointer type, e.g.:
375 // void (*f)(void *);
376 // In this case, don't generate a USR.
377 if (s.empty())
378 IgnoreResults = true;
379 else
380 Out << '@' << s;
381
382 // For a template specialization, mangle the template arguments.
383 if (const VarTemplateSpecializationDecl *Spec =
384 dyn_cast<VarTemplateSpecializationDecl>(D)) {
385 const TemplateArgumentList &Args = Spec->getTemplateArgs();
386 Out << '>';
387 for (unsigned I = 0, N = Args.size(); I != N; ++I) {
388 Out << '#';
389 VisitTemplateArgument(Args.get(I));
390 }
391 }
392}
393
394void USRGenerator::VisitBindingDecl(const BindingDecl *D) {
395 if (isLocal(D) && GenLoc(D, /*IncludeOffset=*/true))
396 return;
397 VisitNamedDecl(D);
398}
399
400void USRGenerator::VisitNonTypeTemplateParmDecl(
401 const NonTypeTemplateParmDecl *D) {
402 GenLoc(D, /*IncludeOffset=*/true);
403}
404
405void USRGenerator::VisitTemplateTemplateParmDecl(
406 const TemplateTemplateParmDecl *D) {
407 GenLoc(D, /*IncludeOffset=*/true);
408}
409
410void USRGenerator::VisitNamespaceDecl(const NamespaceDecl *D) {
411 if (IgnoreResults)
412 return;
413 VisitDeclContext(D->getDeclContext());
414 if (D->isAnonymousNamespace()) {
415 Out << "@aN";
416 return;
417 }
418 Out << "@N@" << D->getName();
419}
420
421void USRGenerator::VisitFunctionTemplateDecl(const FunctionTemplateDecl *D) {
422 VisitFunctionDecl(D->getTemplatedDecl());
423}
424
425void USRGenerator::VisitClassTemplateDecl(const ClassTemplateDecl *D) {
426 VisitTagDecl(D->getTemplatedDecl());
427}
428
429void USRGenerator::VisitNamespaceAliasDecl(const NamespaceAliasDecl *D) {
430 VisitDeclContext(D->getDeclContext());
431 if (!IgnoreResults)
432 Out << "@NA@" << D->getName();
433}
434
436 if (auto *CD = dyn_cast<ObjCCategoryDecl>(D->getDeclContext()))
437 return CD;
438 if (auto *ICD = dyn_cast<ObjCCategoryImplDecl>(D->getDeclContext()))
439 return ICD->getCategoryDecl();
440 return nullptr;
441}
442
443void USRGenerator::VisitObjCMethodDecl(const ObjCMethodDecl *D) {
444 const DeclContext *container = D->getDeclContext();
445 if (const ObjCProtocolDecl *pd = dyn_cast<ObjCProtocolDecl>(container)) {
446 Visit(pd);
447 } else {
448 // The USR for a method declared in a class extension or category is based
449 // on the ObjCInterfaceDecl, not the ObjCCategoryDecl.
450 const ObjCInterfaceDecl *ID = D->getClassInterface();
451 if (!ID) {
452 IgnoreResults = true;
453 return;
454 }
455 auto *CD = getCategoryContext(D);
456 VisitObjCContainerDecl(ID, CD);
457 }
458 // Ideally we would use 'GenObjCMethod', but this is such a hot path
459 // for Objective-C code that we don't want to use
460 // DeclarationName::getAsString().
461 Out << (D->isInstanceMethod() ? "(im)" : "(cm)")
462 << DeclarationName(D->getSelector());
463}
464
465void USRGenerator::VisitObjCContainerDecl(const ObjCContainerDecl *D,
466 const ObjCCategoryDecl *CatD) {
467 switch (D->getKind()) {
468 default:
469 llvm_unreachable("Invalid ObjC container.");
470 case Decl::ObjCInterface:
471 case Decl::ObjCImplementation:
472 GenObjCClass(D->getName(), GetExternalSourceContainer(D),
474 break;
475 case Decl::ObjCCategory: {
476 const ObjCCategoryDecl *CD = cast<ObjCCategoryDecl>(D);
477 const ObjCInterfaceDecl *ID = CD->getClassInterface();
478 if (!ID) {
479 // Handle invalid code where the @interface might not
480 // have been specified.
481 // FIXME: We should be able to generate this USR even if the
482 // @interface isn't available.
483 IgnoreResults = true;
484 return;
485 }
486 // Specially handle class extensions, which are anonymous categories.
487 // We want to mangle in the location to uniquely distinguish them.
488 if (CD->IsClassExtension()) {
489 Out << "objc(ext)" << ID->getName() << '@';
490 GenLoc(CD, /*IncludeOffset=*/true);
491 } else
492 GenObjCCategory(ID->getName(), CD->getName(),
495
496 break;
497 }
498 case Decl::ObjCCategoryImpl: {
499 const ObjCCategoryImplDecl *CD = cast<ObjCCategoryImplDecl>(D);
500 const ObjCInterfaceDecl *ID = CD->getClassInterface();
501 if (!ID) {
502 // Handle invalid code where the @interface might not
503 // have been specified.
504 // FIXME: We should be able to generate this USR even if the
505 // @interface isn't available.
506 IgnoreResults = true;
507 return;
508 }
509 GenObjCCategory(ID->getName(), CD->getName(),
512 break;
513 }
514 case Decl::ObjCProtocol: {
515 const ObjCProtocolDecl *PD = cast<ObjCProtocolDecl>(D);
516 GenObjCProtocol(PD->getName(), GetExternalSourceContainer(PD));
517 break;
518 }
519 }
520}
521
522void USRGenerator::VisitObjCPropertyDecl(const ObjCPropertyDecl *D) {
523 // The USR for a property declared in a class extension or category is based
524 // on the ObjCInterfaceDecl, not the ObjCCategoryDecl.
525 if (const ObjCInterfaceDecl *ID = Context->getObjContainingInterface(D))
526 VisitObjCContainerDecl(ID, getCategoryContext(D));
527 else
528 Visit(cast<Decl>(D->getDeclContext()));
529 GenObjCProperty(D->getName(), D->isClassProperty());
530}
531
532void USRGenerator::VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D) {
533 if (ObjCPropertyDecl *PD = D->getPropertyDecl()) {
534 VisitObjCPropertyDecl(PD);
535 return;
536 }
537
538 IgnoreResults = true;
539}
540
541void USRGenerator::VisitTagDecl(const TagDecl *D) {
542 // Add the location of the tag decl to handle resolution across
543 // translation units.
544 if (!isa<EnumDecl>(D) && ShouldGenerateLocation(D) &&
545 GenLoc(D, /*IncludeOffset=*/isLocal(D)))
546 return;
547
548 GenExtSymbolContainer(D);
549
550 D = D->getCanonicalDecl();
551 VisitDeclContext(D->getDeclContext());
552
553 bool AlreadyStarted = false;
554 if (const CXXRecordDecl *CXXRecord = dyn_cast<CXXRecordDecl>(D)) {
555 if (ClassTemplateDecl *ClassTmpl = CXXRecord->getDescribedClassTemplate()) {
556 AlreadyStarted = true;
557
558 switch (D->getTagKind()) {
559 case TagTypeKind::Interface:
560 case TagTypeKind::Class:
561 case TagTypeKind::Struct:
562 Out << "@ST";
563 break;
564 case TagTypeKind::Union:
565 Out << "@UT";
566 break;
567 case TagTypeKind::Enum:
568 llvm_unreachable("enum template");
569 }
570 VisitTemplateParameterList(ClassTmpl->getTemplateParameters());
571 } else if (const ClassTemplatePartialSpecializationDecl *PartialSpec =
572 dyn_cast<ClassTemplatePartialSpecializationDecl>(
573 CXXRecord)) {
574 AlreadyStarted = true;
575
576 switch (D->getTagKind()) {
577 case TagTypeKind::Interface:
578 case TagTypeKind::Class:
579 case TagTypeKind::Struct:
580 Out << "@SP";
581 break;
582 case TagTypeKind::Union:
583 Out << "@UP";
584 break;
585 case TagTypeKind::Enum:
586 llvm_unreachable("enum partial specialization");
587 }
588 VisitTemplateParameterList(PartialSpec->getTemplateParameters());
589 }
590 }
591
592 if (!AlreadyStarted) {
593 switch (D->getTagKind()) {
594 case TagTypeKind::Interface:
595 case TagTypeKind::Class:
596 case TagTypeKind::Struct:
597 Out << "@S";
598 break;
599 case TagTypeKind::Union:
600 Out << "@U";
601 break;
602 case TagTypeKind::Enum:
603 Out << "@E";
604 break;
605 }
606 }
607
608 Out << '@';
609 assert(Buf.size() > 0);
610 const unsigned off = Buf.size() - 1;
611
612 if (EmitDeclName(D)) {
613 if (const TypedefNameDecl *TD = D->getTypedefNameForAnonDecl()) {
614 Buf[off] = 'A';
615 Out << '@' << *TD;
616 } else {
617 if (D->isEmbeddedInDeclarator() && !D->isFreeStanding()) {
618 printLoc(Out, D->getLocation(), Context->getSourceManager(), true);
619 } else {
620 Buf[off] = 'a';
621 if (auto *ED = dyn_cast<EnumDecl>(D)) {
622 // Distinguish USRs of anonymous enums by using their first
623 // enumerator.
624 auto enum_range = ED->enumerators();
625 if (enum_range.begin() != enum_range.end()) {
626 Out << '@' << **enum_range.begin();
627 }
628 }
629 }
630 }
631 }
632
633 // For a class template specialization, mangle the template arguments.
634 if (const ClassTemplateSpecializationDecl *Spec =
635 dyn_cast<ClassTemplateSpecializationDecl>(D)) {
636 const TemplateArgumentList &Args = Spec->getTemplateArgs();
637 Out << '>';
638 for (unsigned I = 0, N = Args.size(); I != N; ++I) {
639 Out << '#';
640 VisitTemplateArgument(Args.get(I));
641 }
642 }
643}
644
645void USRGenerator::VisitTypedefDecl(const TypedefDecl *D) {
646 if (ShouldGenerateLocation(D) && GenLoc(D, /*IncludeOffset=*/isLocal(D)))
647 return;
648 const DeclContext *DC = D->getDeclContext();
649 if (const NamedDecl *DCN = dyn_cast<NamedDecl>(DC))
650 Visit(DCN);
651 Out << "@T@";
652 Out << D->getName();
653}
654
655void USRGenerator::VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D) {
656 GenLoc(D, /*IncludeOffset=*/true);
657}
658
659void USRGenerator::GenExtSymbolContainer(const NamedDecl *D) {
660 StringRef Container = GetExternalSourceContainer(D);
661 if (!Container.empty())
662 Out << "@M@" << Container;
663}
664
665bool USRGenerator::GenLoc(const Decl *D, bool IncludeOffset) {
666 // Guard against null declarations in invalid code.
667 if (!D) {
668 IgnoreResults = true;
669 return true;
670 }
671 // Do nothing if no need to print the offset nor the filename:
672 if (!IncludeOffset && GeneratedFilename)
673 return IgnoreResults;
674
675 bool PrintErr = false;
676
677 // Use the location of canonical decl.
678 D = D->getCanonicalDecl();
679 if (!GeneratedFilename) {
680 GeneratedFilename = true;
681 PrintErr = printLoc(Out, D->getBeginLoc(), Context->getSourceManager(),
682 IncludeOffset);
683 } else {
684 PrintErr =
685 printLocOffset(Out, D->getBeginLoc(), Context->getSourceManager());
686 }
687 IgnoreResults = IgnoreResults || PrintErr;
688 return IgnoreResults;
689}
690
691static void printQualifier(llvm::raw_ostream &Out, const LangOptions &LangOpts,
693 // FIXME: Encode the qualifier, don't just print it.
694 PrintingPolicy PO(LangOpts);
695 PO.SuppressTagKeyword = true;
696 PO.SuppressUnwrittenScope = true;
699 llvm::to_underlying(PrintingPolicy::AnonymousTagMode::Plain);
700 NNS.print(Out, PO);
701}
702
703void USRGenerator::VisitType(QualType T) {
704 // This method mangles in USR information for types. It can possibly
705 // just reuse the naming-mangling logic used by codegen, although the
706 // requirements for USRs might not be the same.
707 ASTContext &Ctx = *Context;
708
709 do {
710 T = Ctx.getCanonicalType(T);
711 Qualifiers Q = T.getQualifiers();
712 unsigned qVal = 0;
713 if (Q.hasConst())
714 qVal |= 0x1;
715 if (Q.hasVolatile())
716 qVal |= 0x2;
717 if (Q.hasRestrict())
718 qVal |= 0x4;
719 if (qVal)
720 Out << ((char)('0' + qVal));
721
722 // Mangle in ObjC GC qualifiers?
723
724 if (const PackExpansionType *Expansion = T->getAs<PackExpansionType>()) {
725 Out << 'P';
726 T = Expansion->getPattern();
727 }
728
729 if (const BuiltinType *BT = T->getAs<BuiltinType>()) {
730 switch (BT->getKind()) {
731 case BuiltinType::Void:
732 Out << 'v';
733 break;
734 case BuiltinType::Bool:
735 Out << 'b';
736 break;
737 case BuiltinType::UChar:
738 Out << 'c';
739 break;
740 case BuiltinType::Char8:
741 Out << 'u';
742 break;
743 case BuiltinType::Char16:
744 Out << 'q';
745 break;
746 case BuiltinType::Char32:
747 Out << 'w';
748 break;
749 case BuiltinType::UShort:
750 Out << 's';
751 break;
752 case BuiltinType::UInt:
753 Out << 'i';
754 break;
755 case BuiltinType::ULong:
756 Out << 'l';
757 break;
758 case BuiltinType::ULongLong:
759 Out << 'k';
760 break;
761 case BuiltinType::UInt128:
762 Out << 'j';
763 break;
764 case BuiltinType::Char_U:
765 case BuiltinType::Char_S:
766 Out << 'C';
767 break;
768 case BuiltinType::SChar:
769 Out << 'r';
770 break;
771 case BuiltinType::WChar_S:
772 case BuiltinType::WChar_U:
773 Out << 'W';
774 break;
775 case BuiltinType::Short:
776 Out << 'S';
777 break;
778 case BuiltinType::Int:
779 Out << 'I';
780 break;
781 case BuiltinType::Long:
782 Out << 'L';
783 break;
784 case BuiltinType::LongLong:
785 Out << 'K';
786 break;
787 case BuiltinType::Int128:
788 Out << 'J';
789 break;
790 case BuiltinType::Float16:
791 case BuiltinType::Half:
792 Out << 'h';
793 break;
794 case BuiltinType::Float:
795 Out << 'f';
796 break;
797 case BuiltinType::Double:
798 Out << 'd';
799 break;
800 case BuiltinType::LongDouble:
801 Out << 'D';
802 break;
803 case BuiltinType::Float128:
804 Out << 'Q';
805 break;
806 case BuiltinType::NullPtr:
807 Out << 'n';
808 break;
809 case BuiltinType::MetaInfo:
810 Out << "@BT@MetaInfo";
811 break;
812#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
813 case BuiltinType::Id: \
814 Out << "@BT@" << #Suffix << "_" << #ImgType; \
815 break;
816#include "clang/Basic/OpenCLImageTypes.def"
817#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
818 case BuiltinType::Id: \
819 Out << "@BT@" << #ExtType; \
820 break;
821#include "clang/Basic/OpenCLExtensionTypes.def"
822 case BuiltinType::OCLEvent:
823 Out << "@BT@OCLEvent";
824 break;
825 case BuiltinType::OCLClkEvent:
826 Out << "@BT@OCLClkEvent";
827 break;
828 case BuiltinType::OCLQueue:
829 Out << "@BT@OCLQueue";
830 break;
831 case BuiltinType::OCLReserveID:
832 Out << "@BT@OCLReserveID";
833 break;
834 case BuiltinType::OCLSampler:
835 Out << "@BT@OCLSampler";
836 break;
837#define SVE_TYPE(Name, Id, SingletonId) \
838 case BuiltinType::Id: \
839 Out << "@BT@" << #Name; \
840 break;
841#include "clang/Basic/AArch64ACLETypes.def"
842#define PPC_VECTOR_TYPE(Name, Id, Size) \
843 case BuiltinType::Id: \
844 Out << "@BT@" << #Name; \
845 break;
846#include "clang/Basic/PPCTypes.def"
847#define RVV_TYPE(Name, Id, SingletonId) \
848 case BuiltinType::Id: \
849 Out << "@BT@" << Name; \
850 break;
851#include "clang/Basic/RISCVVTypes.def"
852#define WASM_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
853#include "clang/Basic/WebAssemblyReferenceTypes.def"
854#define AMDGPU_TYPE(Name, Id, SingletonId, Width, Align) \
855 case BuiltinType::Id: \
856 Out << "@BT@" << #Name; \
857 break;
858#include "clang/Basic/AMDGPUTypes.def"
859#define HLSL_INTANGIBLE_TYPE(Name, Id, SingletonId) \
860 case BuiltinType::Id: \
861 Out << "@BT@" << #Name; \
862 break;
863#include "clang/Basic/HLSLIntangibleTypes.def"
864#define HLSL_PACKED_TYPE(Name, Id, SingletonId) \
865 case BuiltinType::Id: \
866 Out << "@BT@" << #Name; \
867 break;
868#include "clang/Basic/HLSLPackedTypes.def"
869#define SPIRV_TYPE(Name, Id, SingletonId) \
870 case BuiltinType::Id: \
871 Out << "@BT@" << Name; \
872 break;
873#include "clang/Basic/SPIRVTypes.def"
874 case BuiltinType::ShortAccum:
875 Out << "@BT@ShortAccum";
876 break;
877 case BuiltinType::Accum:
878 Out << "@BT@Accum";
879 break;
880 case BuiltinType::LongAccum:
881 Out << "@BT@LongAccum";
882 break;
883 case BuiltinType::UShortAccum:
884 Out << "@BT@UShortAccum";
885 break;
886 case BuiltinType::UAccum:
887 Out << "@BT@UAccum";
888 break;
889 case BuiltinType::ULongAccum:
890 Out << "@BT@ULongAccum";
891 break;
892 case BuiltinType::ShortFract:
893 Out << "@BT@ShortFract";
894 break;
895 case BuiltinType::Fract:
896 Out << "@BT@Fract";
897 break;
898 case BuiltinType::LongFract:
899 Out << "@BT@LongFract";
900 break;
901 case BuiltinType::UShortFract:
902 Out << "@BT@UShortFract";
903 break;
904 case BuiltinType::UFract:
905 Out << "@BT@UFract";
906 break;
907 case BuiltinType::ULongFract:
908 Out << "@BT@ULongFract";
909 break;
910 case BuiltinType::SatShortAccum:
911 Out << "@BT@SatShortAccum";
912 break;
913 case BuiltinType::SatAccum:
914 Out << "@BT@SatAccum";
915 break;
916 case BuiltinType::SatLongAccum:
917 Out << "@BT@SatLongAccum";
918 break;
919 case BuiltinType::SatUShortAccum:
920 Out << "@BT@SatUShortAccum";
921 break;
922 case BuiltinType::SatUAccum:
923 Out << "@BT@SatUAccum";
924 break;
925 case BuiltinType::SatULongAccum:
926 Out << "@BT@SatULongAccum";
927 break;
928 case BuiltinType::SatShortFract:
929 Out << "@BT@SatShortFract";
930 break;
931 case BuiltinType::SatFract:
932 Out << "@BT@SatFract";
933 break;
934 case BuiltinType::SatLongFract:
935 Out << "@BT@SatLongFract";
936 break;
937 case BuiltinType::SatUShortFract:
938 Out << "@BT@SatUShortFract";
939 break;
940 case BuiltinType::SatUFract:
941 Out << "@BT@SatUFract";
942 break;
943 case BuiltinType::SatULongFract:
944 Out << "@BT@SatULongFract";
945 break;
946 case BuiltinType::BFloat16:
947 Out << "@BT@__bf16";
948 break;
949 case BuiltinType::Ibm128:
950 Out << "@BT@__ibm128";
951 break;
952 case BuiltinType::ObjCId:
953 Out << 'o';
954 break;
955 case BuiltinType::ObjCClass:
956 Out << 'O';
957 break;
958 case BuiltinType::ObjCSel:
959 Out << 'e';
960 break;
961#define BUILTIN_TYPE(Id, SingletonId)
962#define PLACEHOLDER_TYPE(Id, SingletonId) case BuiltinType::Id:
963#include "clang/AST/BuiltinTypes.def"
964 case BuiltinType::Dependent:
965 // If you're adding a new builtin type, please add its name prefixed
966 // with "@BT@" to `Out` (see cases above).
967 IgnoreResults = true;
968 break;
969 }
970 return;
971 }
972
973 // If we have already seen this (non-built-in) type, use a substitution
974 // encoding. Otherwise, record this as a substitution.
975 auto [Substitution, Inserted] =
976 TypeSubstitutions.try_emplace(T.getTypePtr(), TypeSubstitutions.size());
977 if (!Inserted) {
978 Out << 'S' << Substitution->second << '_';
979 return;
980 }
981
982 if (const PointerType *PT = T->getAs<PointerType>()) {
983 Out << '*';
984 T = PT->getPointeeType();
985 continue;
986 }
987 if (const ObjCObjectPointerType *OPT = T->getAs<ObjCObjectPointerType>()) {
988 Out << '*';
989 T = OPT->getPointeeType();
990 continue;
991 }
992 if (const RValueReferenceType *RT = T->getAs<RValueReferenceType>()) {
993 Out << "&&";
994 T = RT->getPointeeType();
995 continue;
996 }
997 if (const ReferenceType *RT = T->getAs<ReferenceType>()) {
998 Out << '&';
999 T = RT->getPointeeType();
1000 continue;
1001 }
1002 if (const FunctionProtoType *FT = T->getAs<FunctionProtoType>()) {
1003 Out << 'F';
1004 VisitType(FT->getReturnType());
1005 Out << '(';
1006 for (const auto &I : FT->param_types()) {
1007 Out << '#';
1008 VisitType(I);
1009 }
1010 Out << ')';
1011 if (FT->isVariadic())
1012 Out << '.';
1013 return;
1014 }
1015 if (const BlockPointerType *BT = T->getAs<BlockPointerType>()) {
1016 Out << 'B';
1017 T = BT->getPointeeType();
1018 continue;
1019 }
1020 if (const ComplexType *CT = T->getAs<ComplexType>()) {
1021 Out << '<';
1022 T = CT->getElementType();
1023 continue;
1024 }
1025 if (const TagType *TT = T->getAs<TagType>()) {
1026 if (const auto *ICNT = dyn_cast<InjectedClassNameType>(TT)) {
1027 T = ICNT->getDecl()->getCanonicalTemplateSpecializationType(Ctx);
1028 } else {
1029 Out << '$';
1030 VisitTagDecl(TT->getDecl());
1031 return;
1032 }
1033 }
1034 if (const ObjCInterfaceType *OIT = T->getAs<ObjCInterfaceType>()) {
1035 Out << '$';
1036 VisitObjCInterfaceDecl(OIT->getDecl());
1037 return;
1038 }
1039 if (const ObjCObjectType *OIT = T->getAs<ObjCObjectType>()) {
1040 Out << 'Q';
1041 VisitType(OIT->getBaseType());
1042 for (auto *Prot : OIT->getProtocols())
1043 VisitObjCProtocolDecl(Prot);
1044 return;
1045 }
1046 if (const TemplateTypeParmType *TTP =
1047 T->getAsCanonical<TemplateTypeParmType>()) {
1048 Out << 't' << TTP->getDepth() << '.' << TTP->getIndex();
1049 return;
1050 }
1051 if (const TemplateSpecializationType *Spec =
1052 T->getAs<TemplateSpecializationType>()) {
1053 Out << '>';
1054 VisitTemplateName(Spec->getTemplateName());
1055 Out << Spec->template_arguments().size();
1056 for (const auto &Arg : Spec->template_arguments())
1057 VisitTemplateArgument(Arg);
1058 return;
1059 }
1060 if (const DependentNameType *DNT = T->getAs<DependentNameType>()) {
1061 Out << '^';
1062 printQualifier(Out, LangOpts, DNT->getQualifier());
1063 Out << ':' << DNT->getIdentifier()->getName();
1064 return;
1065 }
1066 if (const auto *VT = T->getAs<VectorType>()) {
1067 Out << (T->isExtVectorType() ? ']' : '[');
1068 Out << VT->getNumElements();
1069 T = VT->getElementType();
1070 continue;
1071 }
1072 if (const auto *const AT = dyn_cast<ArrayType>(T)) {
1073 Out << '{';
1074 switch (AT->getSizeModifier()) {
1075 case ArraySizeModifier::Static:
1076 Out << 's';
1077 break;
1078 case ArraySizeModifier::Star:
1079 Out << '*';
1080 break;
1081 case ArraySizeModifier::Normal:
1082 Out << 'n';
1083 break;
1084 }
1085 if (const auto *const CAT = dyn_cast<ConstantArrayType>(T))
1086 Out << CAT->getSize();
1087
1088 T = AT->getElementType();
1089 continue;
1090 }
1091
1092 // Unhandled type.
1093 Out << ' ';
1094 break;
1095 } while (true);
1096}
1097
1098void USRGenerator::VisitTemplateParameterList(
1099 const TemplateParameterList *Params) {
1100 if (!Params)
1101 return;
1102 Out << '>' << Params->size();
1103 for (TemplateParameterList::const_iterator P = Params->begin(),
1104 PEnd = Params->end();
1105 P != PEnd; ++P) {
1106 Out << '#';
1107 if (isa<TemplateTypeParmDecl>(*P)) {
1108 if (cast<TemplateTypeParmDecl>(*P)->isParameterPack())
1109 Out << 'p';
1110 Out << 'T';
1111 continue;
1112 }
1113
1114 if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(*P)) {
1115 if (NTTP->isParameterPack())
1116 Out << 'p';
1117 Out << 'N';
1118 VisitType(NTTP->getType());
1119 continue;
1120 }
1121
1122 TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*P);
1123 if (TTP->isParameterPack())
1124 Out << 'p';
1125 Out << 't';
1126 VisitTemplateParameterList(TTP->getTemplateParameters());
1127 }
1128}
1129
1130void USRGenerator::VisitTemplateName(TemplateName Name) {
1131 if (TemplateDecl *Template = Name.getAsTemplateDecl()) {
1132 if (TemplateTemplateParmDecl *TTP =
1133 dyn_cast<TemplateTemplateParmDecl>(Template)) {
1134 Out << 't' << TTP->getDepth() << '.' << TTP->getIndex();
1135 return;
1136 }
1137
1138 Visit(Template);
1139 return;
1140 }
1141
1142 // FIXME: Visit dependent template names.
1143}
1144
1145void USRGenerator::VisitTemplateArgument(const TemplateArgument &Arg) {
1146 switch (Arg.getKind()) {
1148 break;
1149
1151 Visit(Arg.getAsDecl());
1152 break;
1153
1155 break;
1156
1158 Out << 'P'; // pack expansion of...
1159 [[fallthrough]];
1161 VisitTemplateName(Arg.getAsTemplateOrTemplatePattern());
1162 break;
1163
1165 // FIXME: Visit expressions.
1166 break;
1167
1169 Out << 'p' << Arg.pack_size();
1170 for (const auto &P : Arg.pack_elements())
1171 VisitTemplateArgument(P);
1172 break;
1173
1175 VisitType(Arg.getAsType());
1176 break;
1177
1179 Out << 'V';
1180 VisitType(Arg.getIntegralType());
1181 Out << Arg.getAsIntegral();
1182 break;
1183
1185 Out << 'S';
1186 VisitType(Arg.getStructuralValueType());
1187 ODRHash Hash{};
1189 Out << Hash.CalculateHash();
1190 break;
1191 }
1192 }
1193}
1194
1195void USRGenerator::VisitUnresolvedUsingValueDecl(
1196 const UnresolvedUsingValueDecl *D) {
1197 if (ShouldGenerateLocation(D) && GenLoc(D, /*IncludeOffset=*/isLocal(D)))
1198 return;
1199 VisitDeclContext(D->getDeclContext());
1200 Out << "@UUV@";
1201 printQualifier(Out, LangOpts, D->getQualifier());
1202 EmitDeclName(D);
1203}
1204
1205void USRGenerator::VisitUnresolvedUsingTypenameDecl(
1206 const UnresolvedUsingTypenameDecl *D) {
1207 if (ShouldGenerateLocation(D) && GenLoc(D, /*IncludeOffset=*/isLocal(D)))
1208 return;
1209 VisitDeclContext(D->getDeclContext());
1210 Out << "@UUT@";
1211 printQualifier(Out, LangOpts, D->getQualifier());
1212 Out << D->getName(); // Simple name.
1213}
1214
1215void USRGenerator::VisitConceptDecl(const ConceptDecl *D) {
1216 if (ShouldGenerateLocation(D) && GenLoc(D, /*IncludeOffset=*/isLocal(D)))
1217 return;
1218 VisitDeclContext(D->getDeclContext());
1219 Out << "@CT@";
1220 EmitDeclName(D);
1221}
1222
1223void USRGenerator::VisitMSGuidDecl(const MSGuidDecl *D) {
1224 VisitDeclContext(D->getDeclContext());
1225 Out << "@MG@";
1226 D->NamedDecl::printName(Out);
1227}
1228
1229void USRGenerator::VisitTemplateParamObjectDecl(
1230 const TemplateParamObjectDecl *D) {
1231 Out << "@TPO@";
1232 VisitType(D->getType());
1233 ODRHash Hash{};
1234 Hash.AddStructuralValue(D->getValue());
1235 Out << Hash.CalculateHash();
1236}
1237
1238//===----------------------------------------------------------------------===//
1239// USR generation functions.
1240//===----------------------------------------------------------------------===//
1241
1242static void combineClassAndCategoryExtContainers(StringRef ClsSymDefinedIn,
1243 StringRef CatSymDefinedIn,
1244 raw_ostream &OS) {
1245 if (ClsSymDefinedIn.empty() && CatSymDefinedIn.empty())
1246 return;
1247 if (CatSymDefinedIn.empty()) {
1248 OS << "@M@" << ClsSymDefinedIn << '@';
1249 return;
1250 }
1251 OS << "@CM@" << CatSymDefinedIn << '@';
1252 if (ClsSymDefinedIn != CatSymDefinedIn) {
1253 OS << ClsSymDefinedIn << '@';
1254 }
1255}
1256
1258 StringRef Cls, raw_ostream &OS, StringRef ExtSymDefinedIn,
1259 StringRef CategoryContextExtSymbolDefinedIn) {
1261 CategoryContextExtSymbolDefinedIn, OS);
1262 OS << "objc(cs)" << Cls;
1263}
1264
1265void clang::index::generateUSRForObjCCategory(StringRef Cls, StringRef Cat,
1266 raw_ostream &OS,
1267 StringRef ClsSymDefinedIn,
1268 StringRef CatSymDefinedIn) {
1269 combineClassAndCategoryExtContainers(ClsSymDefinedIn, CatSymDefinedIn, OS);
1270 OS << "objc(cy)" << Cls << '@' << Cat;
1271}
1272
1273void clang::index::generateUSRForObjCIvar(StringRef Ivar, raw_ostream &OS) {
1274 OS << '@' << Ivar;
1275}
1276
1278 bool IsInstanceMethod,
1279 raw_ostream &OS) {
1280 OS << (IsInstanceMethod ? "(im)" : "(cm)") << Sel;
1281}
1282
1283void clang::index::generateUSRForObjCProperty(StringRef Prop, bool isClassProp,
1284 raw_ostream &OS) {
1285 OS << (isClassProp ? "(cpy)" : "(py)") << Prop;
1286}
1287
1288void clang::index::generateUSRForObjCProtocol(StringRef Prot, raw_ostream &OS,
1289 StringRef ExtSymDefinedIn) {
1290 if (!ExtSymDefinedIn.empty())
1291 OS << "@M@" << ExtSymDefinedIn << '@';
1292 OS << "objc(pl)" << Prot;
1293}
1294
1295void clang::index::generateUSRForGlobalEnum(StringRef EnumName, raw_ostream &OS,
1296 StringRef ExtSymDefinedIn) {
1297 if (!ExtSymDefinedIn.empty())
1298 OS << "@M@" << ExtSymDefinedIn;
1299 OS << "@E@" << EnumName;
1300}
1301
1302void clang::index::generateUSRForEnumConstant(StringRef EnumConstantName,
1303 raw_ostream &OS) {
1304 OS << '@' << EnumConstantName;
1305}
1306
1308 SmallVectorImpl<char> &Buf) {
1309 if (!D)
1310 return true;
1311 return generateUSRForDecl(D, Buf, D->getASTContext().getLangOpts());
1312}
1313
1315 const LangOptions &LangOpts) {
1316 if (!D)
1317 return true;
1318 // We don't ignore decls with invalid source locations. Implicit decls, like
1319 // C++'s operator new function, can have invalid locations but it is fine to
1320 // create USRs that can identify them.
1321
1322 // Check if the declaration has explicit external USR specified.
1323 auto *CD = D->getCanonicalDecl();
1324 if (auto *ExternalSymAttr = CD->getAttr<ExternalSourceSymbolAttr>()) {
1325 if (!ExternalSymAttr->getUSR().empty()) {
1326 llvm::raw_svector_ostream Out(Buf);
1327 Out << ExternalSymAttr->getUSR();
1328 return false;
1329 }
1330 }
1331 USRGenerator UG(&D->getASTContext(), Buf, LangOpts);
1332 UG.Visit(D);
1333 return UG.ignoreResults();
1334}
1335
1337 const SourceManager &SM,
1338 SmallVectorImpl<char> &Buf) {
1339 if (!MD)
1340 return true;
1341 return generateUSRForMacro(MD->getName()->getName(), MD->getLocation(), SM,
1342 Buf);
1343}
1344
1346 const SourceManager &SM,
1347 SmallVectorImpl<char> &Buf) {
1348 if (MacroName.empty())
1349 return true;
1350
1351 llvm::raw_svector_ostream Out(Buf);
1352
1353 // Assume that system headers are sane. Don't put source location
1354 // information into the USR if the macro comes from a system header.
1355 bool ShouldGenerateLocation = Loc.isValid() && !SM.isInSystemHeader(Loc);
1356
1357 Out << getUSRSpacePrefix();
1358 if (ShouldGenerateLocation)
1359 printLoc(Out, Loc, SM, /*IncludeOffset=*/true);
1360 Out << "@macro@";
1361 Out << MacroName;
1362 return false;
1363}
1364
1369
1372 const LangOptions &LangOpts) {
1373 if (T.isNull())
1374 return true;
1375 T = T.getCanonicalType();
1376
1377 USRGenerator UG(&Ctx, Buf, LangOpts);
1378 UG.VisitType(T);
1379 return UG.ignoreResults();
1380}
1381
1383 raw_ostream &OS) {
1384 if (!Mod->Parent)
1386 if (generateFullUSRForModule(Mod->Parent, OS))
1387 return true;
1388 return generateUSRFragmentForModule(Mod, OS);
1389}
1390
1392 raw_ostream &OS) {
1393 OS << getUSRSpacePrefix();
1394 return generateUSRFragmentForModuleName(ModName, OS);
1395}
1396
1398 raw_ostream &OS) {
1399 return generateUSRFragmentForModuleName(Mod->Name, OS);
1400}
1401
1403 raw_ostream &OS) {
1404 OS << "@M@" << ModName;
1405 return false;
1406}
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,...
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:239
SourceManager & getSourceManager()
Definition ASTContext.h:911
static CanQualType getCanonicalType(QualType T)
Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...
const LangOptions & getLangOpts() const
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:344
T * getAttr() const
Definition DeclBase.h:581
ASTContext & getASTContext() const LLVM_READONLY
Definition DeclBase.cpp:550
ExternalSourceSymbolAttr * getExternalSourceSymbolAttr() const
Looks on this and related declarations for an applicable external source symbol attribute.
Definition DeclBase.cpp:616
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:4244
FunctionTemplateDecl * getDescribedFunctionTemplate() const
Retrieves the function template that is described by this function declaration.
Definition Decl.cpp:4232
QualType getReturnType() const
Definition Decl.h:2976
bool isVariadic() const
Whether this function is variadic.
Definition Decl.cpp:3119
const TemplateArgumentList * getTemplateSpecializationArgs() const
Retrieve the template arguments used to produce this function template specialization from the primar...
Definition Decl.cpp:4368
bool isExternC() const
Determines whether this function is a function with external, C linkage.
Definition Decl.cpp:3660
const ASTTemplateArgumentListInfo * getTemplateSpecializationArgsAsWritten() const
Retrieve the template argument list as written in the sources, if any.
Definition Decl.cpp:4378
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:275
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
Definition Decl.h:302
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
Definition Decl.h:341
bool isExternallyVisible() const
Definition Decl.h:434
bool isAnonymousNamespace() const
Returns true if this is an anonymous namespace declaration.
Definition Decl.h:644
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:1294
unsigned CalculateHash()
Definition ODRHash.cpp:244
ObjCCategoryDecl - Represents a category declaration.
Definition DeclObjC.h:2335
ObjCInterfaceDecl * getClassInterface()
Definition DeclObjC.h:2378
bool IsClassExtension() const
Definition DeclObjC.h:2443
const ObjCInterfaceDecl * getClassInterface() const
Definition DeclObjC.h:2492
Selector getSelector() const
Definition DeclObjC.h:330
bool isInstanceMethod() const
Definition DeclObjC.h:429
ObjCInterfaceDecl * getClassInterface()
bool isClassProperty() const
Definition DeclObjC.h:861
ObjCPropertyDecl * getPropertyDecl() const
Definition DeclObjC.h:2876
A (possibly-)qualified type.
Definition TypeBase.h:938
bool isNull() const
Return true if this QualType doesn't point to a type yet.
Definition TypeBase.h:1005
QualType getCanonicalType() const
Definition TypeBase.h:8498
bool hasConst() const
Definition TypeBase.h:458
bool hasRestrict() const
Definition TypeBase.h:478
bool hasVolatile() const
Definition TypeBase.h:468
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.
FileIDAndOffset getDecomposedLoc(SourceLocation Loc) const
Decompose the specified location into a raw FileID + Offset pair.
OptionalFileEntryRef getFileEntryRefForID(FileID FID) const
Returns the FileEntryRef for the provided FileID.
SourceLocation getSpellingLoc(SourceLocation Loc) const
Given a SourceLocation object, return the spelling location referenced by the ID.
bool isInSystemHeader(SourceLocation Loc) const
Returns if a SourceLocation is in a system header.
SourceLocation getExpansionLoc(SourceLocation Loc) const
Given a SourceLocation object Loc, return the expansion location referenced by the ID.
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:3977
TypedefNameDecl * getTypedefNameForAnonDecl() const
Definition Decl.h:4089
TagDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
Definition Decl.cpp:4970
bool isFreeStanding() const
True if this tag is free standing, e.g. "struct foo;".
Definition Decl.h:3988
TagKind getTagKind() const
Definition Decl.h:4052
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.
const APValue & getValue() const
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:883
bool isExtVectorType() const
Definition TypeBase.h:8826
const T * getAsCanonical() const
If this type is canonically the specified type, return its canonical type cast to that specified type...
Definition TypeBase.h:3002
const T * getAs() const
Member-template getAs<specific type>'.
Definition TypeBase.h:9299
NestedNameSpecifier getQualifier() const
Retrieve the nested-name-specifier that qualifies the name.
Definition DeclCXX.h:4104
NestedNameSpecifier getQualifier() const
Retrieve the nested-name-specifier that qualifies the name.
Definition DeclCXX.h:4014
QualType getType() const
Definition Decl.h:724
VarTemplateDecl * getDescribedVarTemplate() const
Retrieves the variable template that is described by this variable declaration.
Definition Decl.cpp:2780
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.
Top level wrappers for InstallAPI frontend operations.
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:1801
@ RQ_LValue
An lvalue ref-qualifier was provided (&).
Definition TypeBase.h:1804
@ RQ_RValue
An rvalue ref-qualifier was provided (&&).
Definition TypeBase.h:1807
@ TemplateName
The identifier is a template name. FIXME: Add an annotation for that.
Definition Parser.h:61
std::pair< FileID, unsigned > FileIDAndOffset
const FunctionProtoType * T
@ 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.