[RISCV] Reduce redundancy in vnsrl tests
[llvm-project.git] / clang / lib / Index / USRGeneration.cpp
blob493123459a5a4dbc505660605c50e4bdccff2fec
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 //===----------------------------------------------------------------------===//
9 #include "clang/Index/USRGeneration.h"
10 #include "clang/AST/ASTContext.h"
11 #include "clang/AST/Attr.h"
12 #include "clang/AST/DeclCXX.h"
13 #include "clang/AST/DeclTemplate.h"
14 #include "clang/AST/DeclVisitor.h"
15 #include "clang/AST/ODRHash.h"
16 #include "clang/Basic/FileManager.h"
17 #include "clang/Lex/PreprocessingRecord.h"
18 #include "llvm/Support/Path.h"
19 #include "llvm/Support/raw_ostream.h"
21 using namespace clang;
22 using namespace clang::index;
24 //===----------------------------------------------------------------------===//
25 // USR generation.
26 //===----------------------------------------------------------------------===//
28 /// \returns true on error.
29 static bool printLoc(llvm::raw_ostream &OS, SourceLocation Loc,
30 const SourceManager &SM, bool IncludeOffset) {
31 if (Loc.isInvalid()) {
32 return true;
34 Loc = SM.getExpansionLoc(Loc);
35 const std::pair<FileID, unsigned> &Decomposed = SM.getDecomposedLoc(Loc);
36 OptionalFileEntryRef FE = SM.getFileEntryRefForID(Decomposed.first);
37 if (FE) {
38 OS << llvm::sys::path::filename(FE->getName());
39 } else {
40 // This case really isn't interesting.
41 return true;
43 if (IncludeOffset) {
44 // Use the offest into the FileID to represent the location. Using
45 // a line/column can cause us to look back at the original source file,
46 // which is expensive.
47 OS << '@' << Decomposed.second;
49 return false;
52 static StringRef GetExternalSourceContainer(const NamedDecl *D) {
53 if (!D)
54 return StringRef();
55 if (auto *attr = D->getExternalSourceSymbolAttr()) {
56 return attr->getDefinedIn();
58 return StringRef();
61 namespace {
62 class USRGenerator : public ConstDeclVisitor<USRGenerator> {
63 SmallVectorImpl<char> &Buf;
64 llvm::raw_svector_ostream Out;
65 ASTContext *Context;
66 const LangOptions &LangOpts;
67 bool IgnoreResults = false;
68 bool generatedLoc = false;
70 llvm::DenseMap<const Type *, unsigned> TypeSubstitutions;
72 public:
73 USRGenerator(ASTContext *Ctx, SmallVectorImpl<char> &Buf,
74 const LangOptions &LangOpts)
75 : Buf(Buf), Out(Buf), Context(Ctx), LangOpts(LangOpts) {
76 // Add the USR space prefix.
77 Out << getUSRSpacePrefix();
80 bool ignoreResults() const { return IgnoreResults; }
82 // Visitation methods from generating USRs from AST elements.
83 void VisitDeclContext(const DeclContext *D);
84 void VisitFieldDecl(const FieldDecl *D);
85 void VisitFunctionDecl(const FunctionDecl *D);
86 void VisitNamedDecl(const NamedDecl *D);
87 void VisitNamespaceDecl(const NamespaceDecl *D);
88 void VisitNamespaceAliasDecl(const NamespaceAliasDecl *D);
89 void VisitFunctionTemplateDecl(const FunctionTemplateDecl *D);
90 void VisitClassTemplateDecl(const ClassTemplateDecl *D);
91 void VisitObjCContainerDecl(const ObjCContainerDecl *CD,
92 const ObjCCategoryDecl *CatD = nullptr);
93 void VisitObjCMethodDecl(const ObjCMethodDecl *MD);
94 void VisitObjCPropertyDecl(const ObjCPropertyDecl *D);
95 void VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D);
96 void VisitTagDecl(const TagDecl *D);
97 void VisitTypedefDecl(const TypedefDecl *D);
98 void VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D);
99 void VisitVarDecl(const VarDecl *D);
100 void VisitBindingDecl(const BindingDecl *D);
101 void VisitNonTypeTemplateParmDecl(const NonTypeTemplateParmDecl *D);
102 void VisitTemplateTemplateParmDecl(const TemplateTemplateParmDecl *D);
103 void VisitUnresolvedUsingValueDecl(const UnresolvedUsingValueDecl *D);
104 void VisitUnresolvedUsingTypenameDecl(const UnresolvedUsingTypenameDecl *D);
105 void VisitConceptDecl(const ConceptDecl *D);
107 void VisitLinkageSpecDecl(const LinkageSpecDecl *D) {
108 IgnoreResults = true; // No USRs for linkage specs themselves.
111 void VisitUsingDirectiveDecl(const UsingDirectiveDecl *D) {
112 IgnoreResults = true;
115 void VisitUsingDecl(const UsingDecl *D) {
116 VisitDeclContext(D->getDeclContext());
117 Out << "@UD@";
119 bool EmittedDeclName = !EmitDeclName(D);
120 assert(EmittedDeclName && "EmitDeclName can not fail for UsingDecls");
121 (void)EmittedDeclName;
124 bool ShouldGenerateLocation(const NamedDecl *D);
126 bool isLocal(const NamedDecl *D) {
127 return D->getParentFunctionOrMethod() != nullptr;
130 void GenExtSymbolContainer(const NamedDecl *D);
132 /// Generate the string component containing the location of the
133 /// declaration.
134 bool GenLoc(const Decl *D, bool IncludeOffset);
136 /// String generation methods used both by the visitation methods
137 /// and from other clients that want to directly generate USRs. These
138 /// methods do not construct complete USRs (which incorporate the parents
139 /// of an AST element), but only the fragments concerning the AST element
140 /// itself.
142 /// Generate a USR for an Objective-C class.
143 void GenObjCClass(StringRef cls, StringRef ExtSymDefinedIn,
144 StringRef CategoryContextExtSymbolDefinedIn) {
145 generateUSRForObjCClass(cls, Out, ExtSymDefinedIn,
146 CategoryContextExtSymbolDefinedIn);
149 /// Generate a USR for an Objective-C class category.
150 void GenObjCCategory(StringRef cls, StringRef cat,
151 StringRef clsExt, StringRef catExt) {
152 generateUSRForObjCCategory(cls, cat, Out, clsExt, catExt);
155 /// Generate a USR fragment for an Objective-C property.
156 void GenObjCProperty(StringRef prop, bool isClassProp) {
157 generateUSRForObjCProperty(prop, isClassProp, Out);
160 /// Generate a USR for an Objective-C protocol.
161 void GenObjCProtocol(StringRef prot, StringRef ext) {
162 generateUSRForObjCProtocol(prot, Out, ext);
165 void VisitType(QualType T);
166 void VisitTemplateParameterList(const TemplateParameterList *Params);
167 void VisitTemplateName(TemplateName Name);
168 void VisitTemplateArgument(const TemplateArgument &Arg);
170 void VisitMSGuidDecl(const MSGuidDecl *D);
172 /// Emit a Decl's name using NamedDecl::printName() and return true if
173 /// the decl had no name.
174 bool EmitDeclName(const NamedDecl *D);
176 } // end anonymous namespace
178 //===----------------------------------------------------------------------===//
179 // Generating USRs from ASTS.
180 //===----------------------------------------------------------------------===//
182 bool USRGenerator::EmitDeclName(const NamedDecl *D) {
183 DeclarationName N = D->getDeclName();
184 if (N.isEmpty())
185 return true;
186 Out << N;
187 return false;
190 bool USRGenerator::ShouldGenerateLocation(const NamedDecl *D) {
191 if (D->isExternallyVisible())
192 return false;
193 if (D->getParentFunctionOrMethod())
194 return true;
195 SourceLocation Loc = D->getLocation();
196 if (Loc.isInvalid())
197 return false;
198 const SourceManager &SM = Context->getSourceManager();
199 return !SM.isInSystemHeader(Loc);
202 void USRGenerator::VisitDeclContext(const DeclContext *DC) {
203 if (const NamedDecl *D = dyn_cast<NamedDecl>(DC))
204 Visit(D);
205 else if (isa<LinkageSpecDecl>(DC)) // Linkage specs are transparent in USRs.
206 VisitDeclContext(DC->getParent());
209 void USRGenerator::VisitFieldDecl(const FieldDecl *D) {
210 // The USR for an ivar declared in a class extension is based on the
211 // ObjCInterfaceDecl, not the ObjCCategoryDecl.
212 if (const ObjCInterfaceDecl *ID = Context->getObjContainingInterface(D))
213 Visit(ID);
214 else
215 VisitDeclContext(D->getDeclContext());
216 Out << (isa<ObjCIvarDecl>(D) ? "@" : "@FI@");
217 if (EmitDeclName(D)) {
218 // Bit fields can be anonymous.
219 IgnoreResults = true;
220 return;
224 void USRGenerator::VisitFunctionDecl(const FunctionDecl *D) {
225 if (ShouldGenerateLocation(D) && GenLoc(D, /*IncludeOffset=*/isLocal(D)))
226 return;
228 if (D->getType().isNull()) {
229 IgnoreResults = true;
230 return;
233 const unsigned StartSize = Buf.size();
234 VisitDeclContext(D->getDeclContext());
235 if (Buf.size() == StartSize)
236 GenExtSymbolContainer(D);
238 bool IsTemplate = false;
239 if (FunctionTemplateDecl *FunTmpl = D->getDescribedFunctionTemplate()) {
240 IsTemplate = true;
241 Out << "@FT@";
242 VisitTemplateParameterList(FunTmpl->getTemplateParameters());
243 } else
244 Out << "@F@";
246 PrintingPolicy Policy(LangOpts);
247 // Forward references can have different template argument names. Suppress the
248 // template argument names in constructors to make their USR more stable.
249 Policy.SuppressTemplateArgsInCXXConstructors = true;
250 D->getDeclName().print(Out, Policy);
252 if ((!LangOpts.CPlusPlus || D->isExternC()) &&
253 !D->hasAttr<OverloadableAttr>())
254 return;
256 if (D->isFunctionTemplateSpecialization()) {
257 Out << '<';
258 if (const TemplateArgumentList *SpecArgs =
259 D->getTemplateSpecializationArgs()) {
260 for (const auto &Arg : SpecArgs->asArray()) {
261 Out << '#';
262 VisitTemplateArgument(Arg);
264 } else if (const ASTTemplateArgumentListInfo *SpecArgsWritten =
265 D->getTemplateSpecializationArgsAsWritten()) {
266 for (const auto &ArgLoc : SpecArgsWritten->arguments()) {
267 Out << '#';
268 VisitTemplateArgument(ArgLoc.getArgument());
271 Out << '>';
274 QualType CanonicalType = D->getType().getCanonicalType();
275 // Mangle in type information for the arguments.
276 if (const auto *FPT = CanonicalType->getAs<FunctionProtoType>()) {
277 for (QualType PT : FPT->param_types()) {
278 Out << '#';
279 VisitType(PT);
282 if (D->isVariadic())
283 Out << '.';
284 if (IsTemplate) {
285 // Function templates can be overloaded by return type, for example:
286 // \code
287 // template <class T> typename T::A foo() {}
288 // template <class T> typename T::B foo() {}
289 // \endcode
290 Out << '#';
291 VisitType(D->getReturnType());
293 Out << '#';
294 if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {
295 if (MD->isStatic())
296 Out << 'S';
297 // FIXME: OpenCL: Need to consider address spaces
298 if (unsigned quals = MD->getMethodQualifiers().getCVRUQualifiers())
299 Out << (char)('0' + quals);
300 switch (MD->getRefQualifier()) {
301 case RQ_None: break;
302 case RQ_LValue: Out << '&'; break;
303 case RQ_RValue: Out << "&&"; break;
308 void USRGenerator::VisitNamedDecl(const NamedDecl *D) {
309 VisitDeclContext(D->getDeclContext());
310 Out << "@";
312 if (EmitDeclName(D)) {
313 // The string can be empty if the declaration has no name; e.g., it is
314 // the ParmDecl with no name for declaration of a function pointer type,
315 // e.g.: void (*f)(void *);
316 // In this case, don't generate a USR.
317 IgnoreResults = true;
321 void USRGenerator::VisitVarDecl(const VarDecl *D) {
322 // VarDecls can be declared 'extern' within a function or method body,
323 // but their enclosing DeclContext is the function, not the TU. We need
324 // to check the storage class to correctly generate the USR.
325 if (ShouldGenerateLocation(D) && GenLoc(D, /*IncludeOffset=*/isLocal(D)))
326 return;
328 VisitDeclContext(D->getDeclContext());
330 if (VarTemplateDecl *VarTmpl = D->getDescribedVarTemplate()) {
331 Out << "@VT";
332 VisitTemplateParameterList(VarTmpl->getTemplateParameters());
333 } else if (const VarTemplatePartialSpecializationDecl *PartialSpec
334 = dyn_cast<VarTemplatePartialSpecializationDecl>(D)) {
335 Out << "@VP";
336 VisitTemplateParameterList(PartialSpec->getTemplateParameters());
339 // Variables always have simple names.
340 StringRef s = D->getName();
342 // The string can be empty if the declaration has no name; e.g., it is
343 // the ParmDecl with no name for declaration of a function pointer type, e.g.:
344 // void (*f)(void *);
345 // In this case, don't generate a USR.
346 if (s.empty())
347 IgnoreResults = true;
348 else
349 Out << '@' << s;
351 // For a template specialization, mangle the template arguments.
352 if (const VarTemplateSpecializationDecl *Spec
353 = dyn_cast<VarTemplateSpecializationDecl>(D)) {
354 const TemplateArgumentList &Args = Spec->getTemplateArgs();
355 Out << '>';
356 for (unsigned I = 0, N = Args.size(); I != N; ++I) {
357 Out << '#';
358 VisitTemplateArgument(Args.get(I));
363 void USRGenerator::VisitBindingDecl(const BindingDecl *D) {
364 if (isLocal(D) && GenLoc(D, /*IncludeOffset=*/true))
365 return;
366 VisitNamedDecl(D);
369 void USRGenerator::VisitNonTypeTemplateParmDecl(
370 const NonTypeTemplateParmDecl *D) {
371 GenLoc(D, /*IncludeOffset=*/true);
374 void USRGenerator::VisitTemplateTemplateParmDecl(
375 const TemplateTemplateParmDecl *D) {
376 GenLoc(D, /*IncludeOffset=*/true);
379 void USRGenerator::VisitNamespaceDecl(const NamespaceDecl *D) {
380 if (IgnoreResults)
381 return;
382 VisitDeclContext(D->getDeclContext());
383 if (D->isAnonymousNamespace()) {
384 Out << "@aN";
385 return;
387 Out << "@N@" << D->getName();
390 void USRGenerator::VisitFunctionTemplateDecl(const FunctionTemplateDecl *D) {
391 VisitFunctionDecl(D->getTemplatedDecl());
394 void USRGenerator::VisitClassTemplateDecl(const ClassTemplateDecl *D) {
395 VisitTagDecl(D->getTemplatedDecl());
398 void USRGenerator::VisitNamespaceAliasDecl(const NamespaceAliasDecl *D) {
399 VisitDeclContext(D->getDeclContext());
400 if (!IgnoreResults)
401 Out << "@NA@" << D->getName();
404 static const ObjCCategoryDecl *getCategoryContext(const NamedDecl *D) {
405 if (auto *CD = dyn_cast<ObjCCategoryDecl>(D->getDeclContext()))
406 return CD;
407 if (auto *ICD = dyn_cast<ObjCCategoryImplDecl>(D->getDeclContext()))
408 return ICD->getCategoryDecl();
409 return nullptr;
412 void USRGenerator::VisitObjCMethodDecl(const ObjCMethodDecl *D) {
413 const DeclContext *container = D->getDeclContext();
414 if (const ObjCProtocolDecl *pd = dyn_cast<ObjCProtocolDecl>(container)) {
415 Visit(pd);
417 else {
418 // The USR for a method declared in a class extension or category is based on
419 // the ObjCInterfaceDecl, not the ObjCCategoryDecl.
420 const ObjCInterfaceDecl *ID = D->getClassInterface();
421 if (!ID) {
422 IgnoreResults = true;
423 return;
425 auto *CD = getCategoryContext(D);
426 VisitObjCContainerDecl(ID, CD);
428 // Ideally we would use 'GenObjCMethod', but this is such a hot path
429 // for Objective-C code that we don't want to use
430 // DeclarationName::getAsString().
431 Out << (D->isInstanceMethod() ? "(im)" : "(cm)")
432 << DeclarationName(D->getSelector());
435 void USRGenerator::VisitObjCContainerDecl(const ObjCContainerDecl *D,
436 const ObjCCategoryDecl *CatD) {
437 switch (D->getKind()) {
438 default:
439 llvm_unreachable("Invalid ObjC container.");
440 case Decl::ObjCInterface:
441 case Decl::ObjCImplementation:
442 GenObjCClass(D->getName(), GetExternalSourceContainer(D),
443 GetExternalSourceContainer(CatD));
444 break;
445 case Decl::ObjCCategory: {
446 const ObjCCategoryDecl *CD = cast<ObjCCategoryDecl>(D);
447 const ObjCInterfaceDecl *ID = CD->getClassInterface();
448 if (!ID) {
449 // Handle invalid code where the @interface might not
450 // have been specified.
451 // FIXME: We should be able to generate this USR even if the
452 // @interface isn't available.
453 IgnoreResults = true;
454 return;
456 // Specially handle class extensions, which are anonymous categories.
457 // We want to mangle in the location to uniquely distinguish them.
458 if (CD->IsClassExtension()) {
459 Out << "objc(ext)" << ID->getName() << '@';
460 GenLoc(CD, /*IncludeOffset=*/true);
462 else
463 GenObjCCategory(ID->getName(), CD->getName(),
464 GetExternalSourceContainer(ID),
465 GetExternalSourceContainer(CD));
467 break;
469 case Decl::ObjCCategoryImpl: {
470 const ObjCCategoryImplDecl *CD = cast<ObjCCategoryImplDecl>(D);
471 const ObjCInterfaceDecl *ID = CD->getClassInterface();
472 if (!ID) {
473 // Handle invalid code where the @interface might not
474 // have been specified.
475 // FIXME: We should be able to generate this USR even if the
476 // @interface isn't available.
477 IgnoreResults = true;
478 return;
480 GenObjCCategory(ID->getName(), CD->getName(),
481 GetExternalSourceContainer(ID),
482 GetExternalSourceContainer(CD));
483 break;
485 case Decl::ObjCProtocol: {
486 const ObjCProtocolDecl *PD = cast<ObjCProtocolDecl>(D);
487 GenObjCProtocol(PD->getName(), GetExternalSourceContainer(PD));
488 break;
493 void USRGenerator::VisitObjCPropertyDecl(const ObjCPropertyDecl *D) {
494 // The USR for a property declared in a class extension or category is based
495 // on the ObjCInterfaceDecl, not the ObjCCategoryDecl.
496 if (const ObjCInterfaceDecl *ID = Context->getObjContainingInterface(D))
497 VisitObjCContainerDecl(ID, getCategoryContext(D));
498 else
499 Visit(cast<Decl>(D->getDeclContext()));
500 GenObjCProperty(D->getName(), D->isClassProperty());
503 void USRGenerator::VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D) {
504 if (ObjCPropertyDecl *PD = D->getPropertyDecl()) {
505 VisitObjCPropertyDecl(PD);
506 return;
509 IgnoreResults = true;
512 void USRGenerator::VisitTagDecl(const TagDecl *D) {
513 // Add the location of the tag decl to handle resolution across
514 // translation units.
515 if (!isa<EnumDecl>(D) &&
516 ShouldGenerateLocation(D) && GenLoc(D, /*IncludeOffset=*/isLocal(D)))
517 return;
519 GenExtSymbolContainer(D);
521 D = D->getCanonicalDecl();
522 VisitDeclContext(D->getDeclContext());
524 bool AlreadyStarted = false;
525 if (const CXXRecordDecl *CXXRecord = dyn_cast<CXXRecordDecl>(D)) {
526 if (ClassTemplateDecl *ClassTmpl = CXXRecord->getDescribedClassTemplate()) {
527 AlreadyStarted = true;
529 switch (D->getTagKind()) {
530 case TagTypeKind::Interface:
531 case TagTypeKind::Class:
532 case TagTypeKind::Struct:
533 Out << "@ST";
534 break;
535 case TagTypeKind::Union:
536 Out << "@UT";
537 break;
538 case TagTypeKind::Enum:
539 llvm_unreachable("enum template");
541 VisitTemplateParameterList(ClassTmpl->getTemplateParameters());
542 } else if (const ClassTemplatePartialSpecializationDecl *PartialSpec
543 = dyn_cast<ClassTemplatePartialSpecializationDecl>(CXXRecord)) {
544 AlreadyStarted = true;
546 switch (D->getTagKind()) {
547 case TagTypeKind::Interface:
548 case TagTypeKind::Class:
549 case TagTypeKind::Struct:
550 Out << "@SP";
551 break;
552 case TagTypeKind::Union:
553 Out << "@UP";
554 break;
555 case TagTypeKind::Enum:
556 llvm_unreachable("enum partial specialization");
558 VisitTemplateParameterList(PartialSpec->getTemplateParameters());
562 if (!AlreadyStarted) {
563 switch (D->getTagKind()) {
564 case TagTypeKind::Interface:
565 case TagTypeKind::Class:
566 case TagTypeKind::Struct:
567 Out << "@S";
568 break;
569 case TagTypeKind::Union:
570 Out << "@U";
571 break;
572 case TagTypeKind::Enum:
573 Out << "@E";
574 break;
578 Out << '@';
579 assert(Buf.size() > 0);
580 const unsigned off = Buf.size() - 1;
582 if (EmitDeclName(D)) {
583 if (const TypedefNameDecl *TD = D->getTypedefNameForAnonDecl()) {
584 Buf[off] = 'A';
585 Out << '@' << *TD;
586 } else {
587 if (D->isEmbeddedInDeclarator() && !D->isFreeStanding()) {
588 printLoc(Out, D->getLocation(), Context->getSourceManager(), true);
589 } else {
590 Buf[off] = 'a';
591 if (auto *ED = dyn_cast<EnumDecl>(D)) {
592 // Distinguish USRs of anonymous enums by using their first
593 // enumerator.
594 auto enum_range = ED->enumerators();
595 if (enum_range.begin() != enum_range.end()) {
596 Out << '@' << **enum_range.begin();
603 // For a class template specialization, mangle the template arguments.
604 if (const ClassTemplateSpecializationDecl *Spec
605 = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
606 const TemplateArgumentList &Args = Spec->getTemplateArgs();
607 Out << '>';
608 for (unsigned I = 0, N = Args.size(); I != N; ++I) {
609 Out << '#';
610 VisitTemplateArgument(Args.get(I));
615 void USRGenerator::VisitTypedefDecl(const TypedefDecl *D) {
616 if (ShouldGenerateLocation(D) && GenLoc(D, /*IncludeOffset=*/isLocal(D)))
617 return;
618 const DeclContext *DC = D->getDeclContext();
619 if (const NamedDecl *DCN = dyn_cast<NamedDecl>(DC))
620 Visit(DCN);
621 Out << "@T@";
622 Out << D->getName();
625 void USRGenerator::VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D) {
626 GenLoc(D, /*IncludeOffset=*/true);
629 void USRGenerator::GenExtSymbolContainer(const NamedDecl *D) {
630 StringRef Container = GetExternalSourceContainer(D);
631 if (!Container.empty())
632 Out << "@M@" << Container;
635 bool USRGenerator::GenLoc(const Decl *D, bool IncludeOffset) {
636 if (generatedLoc)
637 return IgnoreResults;
638 generatedLoc = true;
640 // Guard against null declarations in invalid code.
641 if (!D) {
642 IgnoreResults = true;
643 return true;
646 // Use the location of canonical decl.
647 D = D->getCanonicalDecl();
649 IgnoreResults =
650 IgnoreResults || printLoc(Out, D->getBeginLoc(),
651 Context->getSourceManager(), IncludeOffset);
653 return IgnoreResults;
656 static void printQualifier(llvm::raw_ostream &Out, const LangOptions &LangOpts,
657 NestedNameSpecifier *NNS) {
658 // FIXME: Encode the qualifier, don't just print it.
659 PrintingPolicy PO(LangOpts);
660 PO.SuppressTagKeyword = true;
661 PO.SuppressUnwrittenScope = true;
662 PO.ConstantArraySizeAsWritten = false;
663 PO.AnonymousTagLocations = false;
664 NNS->print(Out, PO);
667 void USRGenerator::VisitType(QualType T) {
668 // This method mangles in USR information for types. It can possibly
669 // just reuse the naming-mangling logic used by codegen, although the
670 // requirements for USRs might not be the same.
671 ASTContext &Ctx = *Context;
673 do {
674 T = Ctx.getCanonicalType(T);
675 Qualifiers Q = T.getQualifiers();
676 unsigned qVal = 0;
677 if (Q.hasConst())
678 qVal |= 0x1;
679 if (Q.hasVolatile())
680 qVal |= 0x2;
681 if (Q.hasRestrict())
682 qVal |= 0x4;
683 if(qVal)
684 Out << ((char) ('0' + qVal));
686 // Mangle in ObjC GC qualifiers?
688 if (const PackExpansionType *Expansion = T->getAs<PackExpansionType>()) {
689 Out << 'P';
690 T = Expansion->getPattern();
693 if (const BuiltinType *BT = T->getAs<BuiltinType>()) {
694 switch (BT->getKind()) {
695 case BuiltinType::Void:
696 Out << 'v'; break;
697 case BuiltinType::Bool:
698 Out << 'b'; break;
699 case BuiltinType::UChar:
700 Out << 'c'; break;
701 case BuiltinType::Char8:
702 Out << 'u'; break;
703 case BuiltinType::Char16:
704 Out << 'q'; break;
705 case BuiltinType::Char32:
706 Out << 'w'; break;
707 case BuiltinType::UShort:
708 Out << 's'; break;
709 case BuiltinType::UInt:
710 Out << 'i'; break;
711 case BuiltinType::ULong:
712 Out << 'l'; break;
713 case BuiltinType::ULongLong:
714 Out << 'k'; break;
715 case BuiltinType::UInt128:
716 Out << 'j'; break;
717 case BuiltinType::Char_U:
718 case BuiltinType::Char_S:
719 Out << 'C'; break;
720 case BuiltinType::SChar:
721 Out << 'r'; break;
722 case BuiltinType::WChar_S:
723 case BuiltinType::WChar_U:
724 Out << 'W'; break;
725 case BuiltinType::Short:
726 Out << 'S'; break;
727 case BuiltinType::Int:
728 Out << 'I'; break;
729 case BuiltinType::Long:
730 Out << 'L'; break;
731 case BuiltinType::LongLong:
732 Out << 'K'; break;
733 case BuiltinType::Int128:
734 Out << 'J'; break;
735 case BuiltinType::Float16:
736 case BuiltinType::Half:
737 Out << 'h'; break;
738 case BuiltinType::Float:
739 Out << 'f'; break;
740 case BuiltinType::Double:
741 Out << 'd'; break;
742 case BuiltinType::LongDouble:
743 Out << 'D'; break;
744 case BuiltinType::Float128:
745 Out << 'Q'; break;
746 case BuiltinType::NullPtr:
747 Out << 'n'; break;
748 #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
749 case BuiltinType::Id: \
750 Out << "@BT@" << #Suffix << "_" << #ImgType; break;
751 #include "clang/Basic/OpenCLImageTypes.def"
752 #define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
753 case BuiltinType::Id: \
754 Out << "@BT@" << #ExtType; break;
755 #include "clang/Basic/OpenCLExtensionTypes.def"
756 case BuiltinType::OCLEvent:
757 Out << "@BT@OCLEvent"; break;
758 case BuiltinType::OCLClkEvent:
759 Out << "@BT@OCLClkEvent"; break;
760 case BuiltinType::OCLQueue:
761 Out << "@BT@OCLQueue"; break;
762 case BuiltinType::OCLReserveID:
763 Out << "@BT@OCLReserveID"; break;
764 case BuiltinType::OCLSampler:
765 Out << "@BT@OCLSampler"; break;
766 #define SVE_TYPE(Name, Id, SingletonId) \
767 case BuiltinType::Id: \
768 Out << "@BT@" << Name; break;
769 #include "clang/Basic/AArch64SVEACLETypes.def"
770 #define PPC_VECTOR_TYPE(Name, Id, Size) \
771 case BuiltinType::Id: \
772 Out << "@BT@" << #Name; break;
773 #include "clang/Basic/PPCTypes.def"
774 #define RVV_TYPE(Name, Id, SingletonId) \
775 case BuiltinType::Id: \
776 Out << "@BT@" << Name; break;
777 #include "clang/Basic/RISCVVTypes.def"
778 #define WASM_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
779 #include "clang/Basic/WebAssemblyReferenceTypes.def"
780 #define AMDGPU_TYPE(Name, Id, SingletonId, Width, Align) \
781 case BuiltinType::Id: \
782 Out << "@BT@" << #Name; \
783 break;
784 #include "clang/Basic/AMDGPUTypes.def"
785 #define HLSL_INTANGIBLE_TYPE(Name, Id, SingletonId) \
786 case BuiltinType::Id: \
787 Out << "@BT@" << #Name; \
788 break;
789 #include "clang/Basic/HLSLIntangibleTypes.def"
790 case BuiltinType::ShortAccum:
791 Out << "@BT@ShortAccum"; break;
792 case BuiltinType::Accum:
793 Out << "@BT@Accum"; break;
794 case BuiltinType::LongAccum:
795 Out << "@BT@LongAccum"; break;
796 case BuiltinType::UShortAccum:
797 Out << "@BT@UShortAccum"; break;
798 case BuiltinType::UAccum:
799 Out << "@BT@UAccum"; break;
800 case BuiltinType::ULongAccum:
801 Out << "@BT@ULongAccum"; break;
802 case BuiltinType::ShortFract:
803 Out << "@BT@ShortFract"; break;
804 case BuiltinType::Fract:
805 Out << "@BT@Fract"; break;
806 case BuiltinType::LongFract:
807 Out << "@BT@LongFract"; break;
808 case BuiltinType::UShortFract:
809 Out << "@BT@UShortFract"; break;
810 case BuiltinType::UFract:
811 Out << "@BT@UFract"; break;
812 case BuiltinType::ULongFract:
813 Out << "@BT@ULongFract"; break;
814 case BuiltinType::SatShortAccum:
815 Out << "@BT@SatShortAccum"; break;
816 case BuiltinType::SatAccum:
817 Out << "@BT@SatAccum"; break;
818 case BuiltinType::SatLongAccum:
819 Out << "@BT@SatLongAccum"; break;
820 case BuiltinType::SatUShortAccum:
821 Out << "@BT@SatUShortAccum"; break;
822 case BuiltinType::SatUAccum:
823 Out << "@BT@SatUAccum"; break;
824 case BuiltinType::SatULongAccum:
825 Out << "@BT@SatULongAccum"; break;
826 case BuiltinType::SatShortFract:
827 Out << "@BT@SatShortFract"; break;
828 case BuiltinType::SatFract:
829 Out << "@BT@SatFract"; break;
830 case BuiltinType::SatLongFract:
831 Out << "@BT@SatLongFract"; break;
832 case BuiltinType::SatUShortFract:
833 Out << "@BT@SatUShortFract"; break;
834 case BuiltinType::SatUFract:
835 Out << "@BT@SatUFract"; break;
836 case BuiltinType::SatULongFract:
837 Out << "@BT@SatULongFract"; break;
838 case BuiltinType::BFloat16:
839 Out << "@BT@__bf16"; break;
840 case BuiltinType::Ibm128:
841 Out << "@BT@__ibm128"; break;
842 case BuiltinType::ObjCId:
843 Out << 'o'; break;
844 case BuiltinType::ObjCClass:
845 Out << 'O'; break;
846 case BuiltinType::ObjCSel:
847 Out << 'e'; break;
848 #define BUILTIN_TYPE(Id, SingletonId)
849 #define PLACEHOLDER_TYPE(Id, SingletonId) case BuiltinType::Id:
850 #include "clang/AST/BuiltinTypes.def"
851 case BuiltinType::Dependent:
852 // If you're adding a new builtin type, please add its name prefixed
853 // with "@BT@" to `Out` (see cases above).
854 IgnoreResults = true;
855 break;
857 return;
860 // If we have already seen this (non-built-in) type, use a substitution
861 // encoding.
862 llvm::DenseMap<const Type *, unsigned>::iterator Substitution
863 = TypeSubstitutions.find(T.getTypePtr());
864 if (Substitution != TypeSubstitutions.end()) {
865 Out << 'S' << Substitution->second << '_';
866 return;
867 } else {
868 // Record this as a substitution.
869 unsigned Number = TypeSubstitutions.size();
870 TypeSubstitutions[T.getTypePtr()] = Number;
873 if (const PointerType *PT = T->getAs<PointerType>()) {
874 Out << '*';
875 T = PT->getPointeeType();
876 continue;
878 if (const ObjCObjectPointerType *OPT = T->getAs<ObjCObjectPointerType>()) {
879 Out << '*';
880 T = OPT->getPointeeType();
881 continue;
883 if (const RValueReferenceType *RT = T->getAs<RValueReferenceType>()) {
884 Out << "&&";
885 T = RT->getPointeeType();
886 continue;
888 if (const ReferenceType *RT = T->getAs<ReferenceType>()) {
889 Out << '&';
890 T = RT->getPointeeType();
891 continue;
893 if (const FunctionProtoType *FT = T->getAs<FunctionProtoType>()) {
894 Out << 'F';
895 VisitType(FT->getReturnType());
896 Out << '(';
897 for (const auto &I : FT->param_types()) {
898 Out << '#';
899 VisitType(I);
901 Out << ')';
902 if (FT->isVariadic())
903 Out << '.';
904 return;
906 if (const BlockPointerType *BT = T->getAs<BlockPointerType>()) {
907 Out << 'B';
908 T = BT->getPointeeType();
909 continue;
911 if (const ComplexType *CT = T->getAs<ComplexType>()) {
912 Out << '<';
913 T = CT->getElementType();
914 continue;
916 if (const TagType *TT = T->getAs<TagType>()) {
917 Out << '$';
918 VisitTagDecl(TT->getDecl());
919 return;
921 if (const ObjCInterfaceType *OIT = T->getAs<ObjCInterfaceType>()) {
922 Out << '$';
923 VisitObjCInterfaceDecl(OIT->getDecl());
924 return;
926 if (const ObjCObjectType *OIT = T->getAs<ObjCObjectType>()) {
927 Out << 'Q';
928 VisitType(OIT->getBaseType());
929 for (auto *Prot : OIT->getProtocols())
930 VisitObjCProtocolDecl(Prot);
931 return;
933 if (const TemplateTypeParmType *TTP = T->getAs<TemplateTypeParmType>()) {
934 Out << 't' << TTP->getDepth() << '.' << TTP->getIndex();
935 return;
937 if (const TemplateSpecializationType *Spec
938 = T->getAs<TemplateSpecializationType>()) {
939 Out << '>';
940 VisitTemplateName(Spec->getTemplateName());
941 Out << Spec->template_arguments().size();
942 for (const auto &Arg : Spec->template_arguments())
943 VisitTemplateArgument(Arg);
944 return;
946 if (const DependentNameType *DNT = T->getAs<DependentNameType>()) {
947 Out << '^';
948 printQualifier(Out, LangOpts, DNT->getQualifier());
949 Out << ':' << DNT->getIdentifier()->getName();
950 return;
952 if (const InjectedClassNameType *InjT = T->getAs<InjectedClassNameType>()) {
953 T = InjT->getInjectedSpecializationType();
954 continue;
956 if (const auto *VT = T->getAs<VectorType>()) {
957 Out << (T->isExtVectorType() ? ']' : '[');
958 Out << VT->getNumElements();
959 T = VT->getElementType();
960 continue;
962 if (const auto *const AT = dyn_cast<ArrayType>(T)) {
963 Out << '{';
964 switch (AT->getSizeModifier()) {
965 case ArraySizeModifier::Static:
966 Out << 's';
967 break;
968 case ArraySizeModifier::Star:
969 Out << '*';
970 break;
971 case ArraySizeModifier::Normal:
972 Out << 'n';
973 break;
975 if (const auto *const CAT = dyn_cast<ConstantArrayType>(T))
976 Out << CAT->getSize();
978 T = AT->getElementType();
979 continue;
982 // Unhandled type.
983 Out << ' ';
984 break;
985 } while (true);
988 void USRGenerator::VisitTemplateParameterList(
989 const TemplateParameterList *Params) {
990 if (!Params)
991 return;
992 Out << '>' << Params->size();
993 for (TemplateParameterList::const_iterator P = Params->begin(),
994 PEnd = Params->end();
995 P != PEnd; ++P) {
996 Out << '#';
997 if (isa<TemplateTypeParmDecl>(*P)) {
998 if (cast<TemplateTypeParmDecl>(*P)->isParameterPack())
999 Out<< 'p';
1000 Out << 'T';
1001 continue;
1004 if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(*P)) {
1005 if (NTTP->isParameterPack())
1006 Out << 'p';
1007 Out << 'N';
1008 VisitType(NTTP->getType());
1009 continue;
1012 TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*P);
1013 if (TTP->isParameterPack())
1014 Out << 'p';
1015 Out << 't';
1016 VisitTemplateParameterList(TTP->getTemplateParameters());
1020 void USRGenerator::VisitTemplateName(TemplateName Name) {
1021 if (TemplateDecl *Template = Name.getAsTemplateDecl()) {
1022 if (TemplateTemplateParmDecl *TTP
1023 = dyn_cast<TemplateTemplateParmDecl>(Template)) {
1024 Out << 't' << TTP->getDepth() << '.' << TTP->getIndex();
1025 return;
1028 Visit(Template);
1029 return;
1032 // FIXME: Visit dependent template names.
1035 void USRGenerator::VisitTemplateArgument(const TemplateArgument &Arg) {
1036 switch (Arg.getKind()) {
1037 case TemplateArgument::Null:
1038 break;
1040 case TemplateArgument::Declaration:
1041 Visit(Arg.getAsDecl());
1042 break;
1044 case TemplateArgument::NullPtr:
1045 break;
1047 case TemplateArgument::TemplateExpansion:
1048 Out << 'P'; // pack expansion of...
1049 [[fallthrough]];
1050 case TemplateArgument::Template:
1051 VisitTemplateName(Arg.getAsTemplateOrTemplatePattern());
1052 break;
1054 case TemplateArgument::Expression:
1055 // FIXME: Visit expressions.
1056 break;
1058 case TemplateArgument::Pack:
1059 Out << 'p' << Arg.pack_size();
1060 for (const auto &P : Arg.pack_elements())
1061 VisitTemplateArgument(P);
1062 break;
1064 case TemplateArgument::Type:
1065 VisitType(Arg.getAsType());
1066 break;
1068 case TemplateArgument::Integral:
1069 Out << 'V';
1070 VisitType(Arg.getIntegralType());
1071 Out << Arg.getAsIntegral();
1072 break;
1074 case TemplateArgument::StructuralValue: {
1075 Out << 'S';
1076 VisitType(Arg.getStructuralValueType());
1077 ODRHash Hash{};
1078 Hash.AddStructuralValue(Arg.getAsStructuralValue());
1079 Out << Hash.CalculateHash();
1080 break;
1085 void USRGenerator::VisitUnresolvedUsingValueDecl(const UnresolvedUsingValueDecl *D) {
1086 if (ShouldGenerateLocation(D) && GenLoc(D, /*IncludeOffset=*/isLocal(D)))
1087 return;
1088 VisitDeclContext(D->getDeclContext());
1089 Out << "@UUV@";
1090 printQualifier(Out, LangOpts, D->getQualifier());
1091 EmitDeclName(D);
1094 void USRGenerator::VisitUnresolvedUsingTypenameDecl(const UnresolvedUsingTypenameDecl *D) {
1095 if (ShouldGenerateLocation(D) && GenLoc(D, /*IncludeOffset=*/isLocal(D)))
1096 return;
1097 VisitDeclContext(D->getDeclContext());
1098 Out << "@UUT@";
1099 printQualifier(Out, LangOpts, D->getQualifier());
1100 Out << D->getName(); // Simple name.
1103 void USRGenerator::VisitConceptDecl(const ConceptDecl *D) {
1104 if (ShouldGenerateLocation(D) && GenLoc(D, /*IncludeOffset=*/isLocal(D)))
1105 return;
1106 VisitDeclContext(D->getDeclContext());
1107 Out << "@CT@";
1108 EmitDeclName(D);
1111 void USRGenerator::VisitMSGuidDecl(const MSGuidDecl *D) {
1112 VisitDeclContext(D->getDeclContext());
1113 Out << "@MG@";
1114 D->NamedDecl::printName(Out);
1117 //===----------------------------------------------------------------------===//
1118 // USR generation functions.
1119 //===----------------------------------------------------------------------===//
1121 static void combineClassAndCategoryExtContainers(StringRef ClsSymDefinedIn,
1122 StringRef CatSymDefinedIn,
1123 raw_ostream &OS) {
1124 if (ClsSymDefinedIn.empty() && CatSymDefinedIn.empty())
1125 return;
1126 if (CatSymDefinedIn.empty()) {
1127 OS << "@M@" << ClsSymDefinedIn << '@';
1128 return;
1130 OS << "@CM@" << CatSymDefinedIn << '@';
1131 if (ClsSymDefinedIn != CatSymDefinedIn) {
1132 OS << ClsSymDefinedIn << '@';
1136 void clang::index::generateUSRForObjCClass(StringRef Cls, raw_ostream &OS,
1137 StringRef ExtSymDefinedIn,
1138 StringRef CategoryContextExtSymbolDefinedIn) {
1139 combineClassAndCategoryExtContainers(ExtSymDefinedIn,
1140 CategoryContextExtSymbolDefinedIn, OS);
1141 OS << "objc(cs)" << Cls;
1144 void clang::index::generateUSRForObjCCategory(StringRef Cls, StringRef Cat,
1145 raw_ostream &OS,
1146 StringRef ClsSymDefinedIn,
1147 StringRef CatSymDefinedIn) {
1148 combineClassAndCategoryExtContainers(ClsSymDefinedIn, CatSymDefinedIn, OS);
1149 OS << "objc(cy)" << Cls << '@' << Cat;
1152 void clang::index::generateUSRForObjCIvar(StringRef Ivar, raw_ostream &OS) {
1153 OS << '@' << Ivar;
1156 void clang::index::generateUSRForObjCMethod(StringRef Sel,
1157 bool IsInstanceMethod,
1158 raw_ostream &OS) {
1159 OS << (IsInstanceMethod ? "(im)" : "(cm)") << Sel;
1162 void clang::index::generateUSRForObjCProperty(StringRef Prop, bool isClassProp,
1163 raw_ostream &OS) {
1164 OS << (isClassProp ? "(cpy)" : "(py)") << Prop;
1167 void clang::index::generateUSRForObjCProtocol(StringRef Prot, raw_ostream &OS,
1168 StringRef ExtSymDefinedIn) {
1169 if (!ExtSymDefinedIn.empty())
1170 OS << "@M@" << ExtSymDefinedIn << '@';
1171 OS << "objc(pl)" << Prot;
1174 void clang::index::generateUSRForGlobalEnum(StringRef EnumName, raw_ostream &OS,
1175 StringRef ExtSymDefinedIn) {
1176 if (!ExtSymDefinedIn.empty())
1177 OS << "@M@" << ExtSymDefinedIn;
1178 OS << "@E@" << EnumName;
1181 void clang::index::generateUSRForEnumConstant(StringRef EnumConstantName,
1182 raw_ostream &OS) {
1183 OS << '@' << EnumConstantName;
1186 bool clang::index::generateUSRForDecl(const Decl *D,
1187 SmallVectorImpl<char> &Buf) {
1188 if (!D)
1189 return true;
1190 return generateUSRForDecl(D, Buf, D->getASTContext().getLangOpts());
1193 bool clang::index::generateUSRForDecl(const Decl *D, SmallVectorImpl<char> &Buf,
1194 const LangOptions &LangOpts) {
1195 if (!D)
1196 return true;
1197 // We don't ignore decls with invalid source locations. Implicit decls, like
1198 // C++'s operator new function, can have invalid locations but it is fine to
1199 // create USRs that can identify them.
1201 // Check if the declaration has explicit external USR specified.
1202 auto *CD = D->getCanonicalDecl();
1203 if (auto *ExternalSymAttr = CD->getAttr<ExternalSourceSymbolAttr>()) {
1204 if (!ExternalSymAttr->getUSR().empty()) {
1205 llvm::raw_svector_ostream Out(Buf);
1206 Out << ExternalSymAttr->getUSR();
1207 return false;
1210 USRGenerator UG(&D->getASTContext(), Buf, LangOpts);
1211 UG.Visit(D);
1212 return UG.ignoreResults();
1215 bool clang::index::generateUSRForMacro(const MacroDefinitionRecord *MD,
1216 const SourceManager &SM,
1217 SmallVectorImpl<char> &Buf) {
1218 if (!MD)
1219 return true;
1220 return generateUSRForMacro(MD->getName()->getName(), MD->getLocation(),
1221 SM, Buf);
1225 bool clang::index::generateUSRForMacro(StringRef MacroName, SourceLocation Loc,
1226 const SourceManager &SM,
1227 SmallVectorImpl<char> &Buf) {
1228 if (MacroName.empty())
1229 return true;
1231 llvm::raw_svector_ostream Out(Buf);
1233 // Assume that system headers are sane. Don't put source location
1234 // information into the USR if the macro comes from a system header.
1235 bool ShouldGenerateLocation = Loc.isValid() && !SM.isInSystemHeader(Loc);
1237 Out << getUSRSpacePrefix();
1238 if (ShouldGenerateLocation)
1239 printLoc(Out, Loc, SM, /*IncludeOffset=*/true);
1240 Out << "@macro@";
1241 Out << MacroName;
1242 return false;
1245 bool clang::index::generateUSRForType(QualType T, ASTContext &Ctx,
1246 SmallVectorImpl<char> &Buf) {
1247 return generateUSRForType(T, Ctx, Buf, Ctx.getLangOpts());
1250 bool clang::index::generateUSRForType(QualType T, ASTContext &Ctx,
1251 SmallVectorImpl<char> &Buf,
1252 const LangOptions &LangOpts) {
1253 if (T.isNull())
1254 return true;
1255 T = T.getCanonicalType();
1257 USRGenerator UG(&Ctx, Buf, LangOpts);
1258 UG.VisitType(T);
1259 return UG.ignoreResults();
1262 bool clang::index::generateFullUSRForModule(const Module *Mod,
1263 raw_ostream &OS) {
1264 if (!Mod->Parent)
1265 return generateFullUSRForTopLevelModuleName(Mod->Name, OS);
1266 if (generateFullUSRForModule(Mod->Parent, OS))
1267 return true;
1268 return generateUSRFragmentForModule(Mod, OS);
1271 bool clang::index::generateFullUSRForTopLevelModuleName(StringRef ModName,
1272 raw_ostream &OS) {
1273 OS << getUSRSpacePrefix();
1274 return generateUSRFragmentForModuleName(ModName, OS);
1277 bool clang::index::generateUSRFragmentForModule(const Module *Mod,
1278 raw_ostream &OS) {
1279 return generateUSRFragmentForModuleName(Mod->Name, OS);
1282 bool clang::index::generateUSRFragmentForModuleName(StringRef ModName,
1283 raw_ostream &OS) {
1284 OS << "@M@" << ModName;
1285 return false;