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