1 //===- USRGeneration.cpp - Routines for USR generation --------------------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "clang/Index/USRGeneration.h"
10 #include "clang/AST/ASTContext.h"
11 #include "clang/AST/DeclTemplate.h"
12 #include "clang/AST/DeclVisitor.h"
13 #include "clang/Lex/PreprocessingRecord.h"
14 #include "llvm/Support/Path.h"
15 #include "llvm/Support/raw_ostream.h"
17 using namespace clang;
18 using namespace clang::index;
20 //===----------------------------------------------------------------------===//
22 //===----------------------------------------------------------------------===//
24 /// \returns true on error.
25 static bool printLoc(llvm::raw_ostream &OS, SourceLocation Loc,
26 const SourceManager &SM, bool IncludeOffset) {
27 if (Loc.isInvalid()) {
30 Loc = SM.getExpansionLoc(Loc);
31 const std::pair<FileID, unsigned> &Decomposed = SM.getDecomposedLoc(Loc);
32 const FileEntry *FE = SM.getFileEntryForID(Decomposed.first);
34 OS << llvm::sys::path::filename(FE->getName());
36 // This case really isn't interesting.
40 // Use the offest into the FileID to represent the location. Using
41 // a line/column can cause us to look back at the original source file,
42 // which is expensive.
43 OS << '@' << Decomposed.second;
48 static StringRef GetExternalSourceContainer(const NamedDecl *D) {
51 if (auto *attr = D->getExternalSourceSymbolAttr()) {
52 return attr->getDefinedIn();
58 class USRGenerator : public ConstDeclVisitor<USRGenerator> {
59 SmallVectorImpl<char> &Buf;
60 llvm::raw_svector_ostream Out;
65 llvm::DenseMap<const Type *, unsigned> TypeSubstitutions;
68 explicit USRGenerator(ASTContext *Ctx, SmallVectorImpl<char> &Buf)
75 // Add the USR space prefix.
76 Out << getUSRSpacePrefix();
79 bool ignoreResults() const { return IgnoreResults; }
81 // Visitation methods from generating USRs from AST elements.
82 void VisitDeclContext(const DeclContext *D);
83 void VisitFieldDecl(const FieldDecl *D);
84 void VisitFunctionDecl(const FunctionDecl *D);
85 void VisitNamedDecl(const NamedDecl *D);
86 void VisitNamespaceDecl(const NamespaceDecl *D);
87 void VisitNamespaceAliasDecl(const NamespaceAliasDecl *D);
88 void VisitFunctionTemplateDecl(const FunctionTemplateDecl *D);
89 void VisitClassTemplateDecl(const ClassTemplateDecl *D);
90 void VisitObjCContainerDecl(const ObjCContainerDecl *CD,
91 const ObjCCategoryDecl *CatD = nullptr);
92 void VisitObjCMethodDecl(const ObjCMethodDecl *MD);
93 void VisitObjCPropertyDecl(const ObjCPropertyDecl *D);
94 void VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D);
95 void VisitTagDecl(const TagDecl *D);
96 void VisitTypedefDecl(const TypedefDecl *D);
97 void VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D);
98 void VisitVarDecl(const VarDecl *D);
99 void VisitBindingDecl(const BindingDecl *D);
100 void VisitNonTypeTemplateParmDecl(const NonTypeTemplateParmDecl *D);
101 void VisitTemplateTemplateParmDecl(const TemplateTemplateParmDecl *D);
102 void VisitUnresolvedUsingValueDecl(const UnresolvedUsingValueDecl *D);
103 void VisitUnresolvedUsingTypenameDecl(const UnresolvedUsingTypenameDecl *D);
105 void VisitLinkageSpecDecl(const LinkageSpecDecl *D) {
106 IgnoreResults = true; // No USRs for linkage specs themselves.
109 void VisitUsingDirectiveDecl(const UsingDirectiveDecl *D) {
110 IgnoreResults = true;
113 void VisitUsingDecl(const UsingDecl *D) {
114 VisitDeclContext(D->getDeclContext());
117 bool EmittedDeclName = !EmitDeclName(D);
118 assert(EmittedDeclName && "EmitDeclName can not fail for UsingDecls");
119 (void)EmittedDeclName;
122 bool ShouldGenerateLocation(const NamedDecl *D);
124 bool isLocal(const NamedDecl *D) {
125 return D->getParentFunctionOrMethod() != nullptr;
128 void GenExtSymbolContainer(const NamedDecl *D);
130 /// Generate the string component containing the location of the
132 bool GenLoc(const Decl *D, bool IncludeOffset);
134 /// String generation methods used both by the visitation methods
135 /// and from other clients that want to directly generate USRs. These
136 /// methods do not construct complete USRs (which incorporate the parents
137 /// of an AST element), but only the fragments concerning the AST element
140 /// Generate a USR for an Objective-C class.
141 void GenObjCClass(StringRef cls, StringRef ExtSymDefinedIn,
142 StringRef CategoryContextExtSymbolDefinedIn) {
143 generateUSRForObjCClass(cls, Out, ExtSymDefinedIn,
144 CategoryContextExtSymbolDefinedIn);
147 /// Generate a USR for an Objective-C class category.
148 void GenObjCCategory(StringRef cls, StringRef cat,
149 StringRef clsExt, StringRef catExt) {
150 generateUSRForObjCCategory(cls, cat, Out, clsExt, catExt);
153 /// Generate a USR fragment for an Objective-C property.
154 void GenObjCProperty(StringRef prop, bool isClassProp) {
155 generateUSRForObjCProperty(prop, isClassProp, Out);
158 /// Generate a USR for an Objective-C protocol.
159 void GenObjCProtocol(StringRef prot, StringRef ext) {
160 generateUSRForObjCProtocol(prot, Out, ext);
163 void VisitType(QualType T);
164 void VisitTemplateParameterList(const TemplateParameterList *Params);
165 void VisitTemplateName(TemplateName Name);
166 void VisitTemplateArgument(const TemplateArgument &Arg);
168 /// Emit a Decl's name using NamedDecl::printName() and return true if
169 /// the decl had no name.
170 bool EmitDeclName(const NamedDecl *D);
172 } // end anonymous namespace
174 //===----------------------------------------------------------------------===//
175 // Generating USRs from ASTS.
176 //===----------------------------------------------------------------------===//
178 bool USRGenerator::EmitDeclName(const NamedDecl *D) {
179 const unsigned startSize = Buf.size();
181 const unsigned endSize = Buf.size();
182 return startSize == endSize;
185 bool USRGenerator::ShouldGenerateLocation(const NamedDecl *D) {
186 if (D->isExternallyVisible())
188 if (D->getParentFunctionOrMethod())
190 SourceLocation Loc = D->getLocation();
193 const SourceManager &SM = Context->getSourceManager();
194 return !SM.isInSystemHeader(Loc);
197 void USRGenerator::VisitDeclContext(const DeclContext *DC) {
198 if (const NamedDecl *D = dyn_cast<NamedDecl>(DC))
200 else if (isa<LinkageSpecDecl>(DC)) // Linkage specs are transparent in USRs.
201 VisitDeclContext(DC->getParent());
204 void USRGenerator::VisitFieldDecl(const FieldDecl *D) {
205 // The USR for an ivar declared in a class extension is based on the
206 // ObjCInterfaceDecl, not the ObjCCategoryDecl.
207 if (const ObjCInterfaceDecl *ID = Context->getObjContainingInterface(D))
210 VisitDeclContext(D->getDeclContext());
211 Out << (isa<ObjCIvarDecl>(D) ? "@" : "@FI@");
212 if (EmitDeclName(D)) {
213 // Bit fields can be anonymous.
214 IgnoreResults = true;
219 void USRGenerator::VisitFunctionDecl(const FunctionDecl *D) {
220 if (ShouldGenerateLocation(D) && GenLoc(D, /*IncludeOffset=*/isLocal(D)))
223 const unsigned StartSize = Buf.size();
224 VisitDeclContext(D->getDeclContext());
225 if (Buf.size() == StartSize)
226 GenExtSymbolContainer(D);
228 bool IsTemplate = false;
229 if (FunctionTemplateDecl *FunTmpl = D->getDescribedFunctionTemplate()) {
232 VisitTemplateParameterList(FunTmpl->getTemplateParameters());
236 PrintingPolicy Policy(Context->getLangOpts());
237 // Forward references can have different template argument names. Suppress the
238 // template argument names in constructors to make their USR more stable.
239 Policy.SuppressTemplateArgsInCXXConstructors = true;
240 D->getDeclName().print(Out, Policy);
242 ASTContext &Ctx = *Context;
243 if ((!Ctx.getLangOpts().CPlusPlus || D->isExternC()) &&
244 !D->hasAttr<OverloadableAttr>())
247 if (const TemplateArgumentList *
248 SpecArgs = D->getTemplateSpecializationArgs()) {
250 for (unsigned I = 0, N = SpecArgs->size(); I != N; ++I) {
252 VisitTemplateArgument(SpecArgs->get(I));
257 // Mangle in type information for the arguments.
258 for (auto PD : D->parameters()) {
260 VisitType(PD->getType());
265 // Function templates can be overloaded by return type, for example:
267 // template <class T> typename T::A foo() {}
268 // template <class T> typename T::B foo() {}
271 VisitType(D->getReturnType());
274 if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {
277 // FIXME: OpenCL: Need to consider address spaces
278 if (unsigned quals = MD->getMethodQualifiers().getCVRUQualifiers())
279 Out << (char)('0' + quals);
280 switch (MD->getRefQualifier()) {
282 case RQ_LValue: Out << '&'; break;
283 case RQ_RValue: Out << "&&"; break;
288 void USRGenerator::VisitNamedDecl(const NamedDecl *D) {
289 VisitDeclContext(D->getDeclContext());
292 if (EmitDeclName(D)) {
293 // The string can be empty if the declaration has no name; e.g., it is
294 // the ParmDecl with no name for declaration of a function pointer type,
295 // e.g.: void (*f)(void *);
296 // In this case, don't generate a USR.
297 IgnoreResults = true;
301 void USRGenerator::VisitVarDecl(const VarDecl *D) {
302 // VarDecls can be declared 'extern' within a function or method body,
303 // but their enclosing DeclContext is the function, not the TU. We need
304 // to check the storage class to correctly generate the USR.
305 if (ShouldGenerateLocation(D) && GenLoc(D, /*IncludeOffset=*/isLocal(D)))
308 VisitDeclContext(D->getDeclContext());
310 if (VarTemplateDecl *VarTmpl = D->getDescribedVarTemplate()) {
312 VisitTemplateParameterList(VarTmpl->getTemplateParameters());
313 } else if (const VarTemplatePartialSpecializationDecl *PartialSpec
314 = dyn_cast<VarTemplatePartialSpecializationDecl>(D)) {
316 VisitTemplateParameterList(PartialSpec->getTemplateParameters());
319 // Variables always have simple names.
320 StringRef s = D->getName();
322 // The string can be empty if the declaration has no name; e.g., it is
323 // the ParmDecl with no name for declaration of a function pointer type, e.g.:
324 // void (*f)(void *);
325 // In this case, don't generate a USR.
327 IgnoreResults = true;
331 // For a template specialization, mangle the template arguments.
332 if (const VarTemplateSpecializationDecl *Spec
333 = dyn_cast<VarTemplateSpecializationDecl>(D)) {
334 const TemplateArgumentList &Args = Spec->getTemplateArgs();
336 for (unsigned I = 0, N = Args.size(); I != N; ++I) {
338 VisitTemplateArgument(Args.get(I));
343 void USRGenerator::VisitBindingDecl(const BindingDecl *D) {
344 if (isLocal(D) && GenLoc(D, /*IncludeOffset=*/true))
349 void USRGenerator::VisitNonTypeTemplateParmDecl(
350 const NonTypeTemplateParmDecl *D) {
351 GenLoc(D, /*IncludeOffset=*/true);
354 void USRGenerator::VisitTemplateTemplateParmDecl(
355 const TemplateTemplateParmDecl *D) {
356 GenLoc(D, /*IncludeOffset=*/true);
359 void USRGenerator::VisitNamespaceDecl(const NamespaceDecl *D) {
360 if (D->isAnonymousNamespace()) {
365 VisitDeclContext(D->getDeclContext());
367 Out << "@N@" << D->getName();
370 void USRGenerator::VisitFunctionTemplateDecl(const FunctionTemplateDecl *D) {
371 VisitFunctionDecl(D->getTemplatedDecl());
374 void USRGenerator::VisitClassTemplateDecl(const ClassTemplateDecl *D) {
375 VisitTagDecl(D->getTemplatedDecl());
378 void USRGenerator::VisitNamespaceAliasDecl(const NamespaceAliasDecl *D) {
379 VisitDeclContext(D->getDeclContext());
381 Out << "@NA@" << D->getName();
384 void USRGenerator::VisitObjCMethodDecl(const ObjCMethodDecl *D) {
385 const DeclContext *container = D->getDeclContext();
386 if (const ObjCProtocolDecl *pd = dyn_cast<ObjCProtocolDecl>(container)) {
390 // The USR for a method declared in a class extension or category is based on
391 // the ObjCInterfaceDecl, not the ObjCCategoryDecl.
392 const ObjCInterfaceDecl *ID = D->getClassInterface();
394 IgnoreResults = true;
397 auto getCategoryContext = [](const ObjCMethodDecl *D) ->
398 const ObjCCategoryDecl * {
399 if (auto *CD = dyn_cast<ObjCCategoryDecl>(D->getDeclContext()))
401 if (auto *ICD = dyn_cast<ObjCCategoryImplDecl>(D->getDeclContext()))
402 return ICD->getCategoryDecl();
405 auto *CD = getCategoryContext(D);
406 VisitObjCContainerDecl(ID, CD);
408 // Ideally we would use 'GenObjCMethod', but this is such a hot path
409 // for Objective-C code that we don't want to use
410 // DeclarationName::getAsString().
411 Out << (D->isInstanceMethod() ? "(im)" : "(cm)")
412 << DeclarationName(D->getSelector());
415 void USRGenerator::VisitObjCContainerDecl(const ObjCContainerDecl *D,
416 const ObjCCategoryDecl *CatD) {
417 switch (D->getKind()) {
419 llvm_unreachable("Invalid ObjC container.");
420 case Decl::ObjCInterface:
421 case Decl::ObjCImplementation:
422 GenObjCClass(D->getName(), GetExternalSourceContainer(D),
423 GetExternalSourceContainer(CatD));
425 case Decl::ObjCCategory: {
426 const ObjCCategoryDecl *CD = cast<ObjCCategoryDecl>(D);
427 const ObjCInterfaceDecl *ID = CD->getClassInterface();
429 // Handle invalid code where the @interface might not
430 // have been specified.
431 // FIXME: We should be able to generate this USR even if the
432 // @interface isn't available.
433 IgnoreResults = true;
436 // Specially handle class extensions, which are anonymous categories.
437 // We want to mangle in the location to uniquely distinguish them.
438 if (CD->IsClassExtension()) {
439 Out << "objc(ext)" << ID->getName() << '@';
440 GenLoc(CD, /*IncludeOffset=*/true);
443 GenObjCCategory(ID->getName(), CD->getName(),
444 GetExternalSourceContainer(ID),
445 GetExternalSourceContainer(CD));
449 case Decl::ObjCCategoryImpl: {
450 const ObjCCategoryImplDecl *CD = cast<ObjCCategoryImplDecl>(D);
451 const ObjCInterfaceDecl *ID = CD->getClassInterface();
453 // Handle invalid code where the @interface might not
454 // have been specified.
455 // FIXME: We should be able to generate this USR even if the
456 // @interface isn't available.
457 IgnoreResults = true;
460 GenObjCCategory(ID->getName(), CD->getName(),
461 GetExternalSourceContainer(ID),
462 GetExternalSourceContainer(CD));
465 case Decl::ObjCProtocol: {
466 const ObjCProtocolDecl *PD = cast<ObjCProtocolDecl>(D);
467 GenObjCProtocol(PD->getName(), GetExternalSourceContainer(PD));
473 void USRGenerator::VisitObjCPropertyDecl(const ObjCPropertyDecl *D) {
474 // The USR for a property declared in a class extension or category is based
475 // on the ObjCInterfaceDecl, not the ObjCCategoryDecl.
476 if (const ObjCInterfaceDecl *ID = Context->getObjContainingInterface(D))
479 Visit(cast<Decl>(D->getDeclContext()));
480 GenObjCProperty(D->getName(), D->isClassProperty());
483 void USRGenerator::VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D) {
484 if (ObjCPropertyDecl *PD = D->getPropertyDecl()) {
485 VisitObjCPropertyDecl(PD);
489 IgnoreResults = true;
492 void USRGenerator::VisitTagDecl(const TagDecl *D) {
493 // Add the location of the tag decl to handle resolution across
494 // translation units.
495 if (!isa<EnumDecl>(D) &&
496 ShouldGenerateLocation(D) && GenLoc(D, /*IncludeOffset=*/isLocal(D)))
499 GenExtSymbolContainer(D);
501 D = D->getCanonicalDecl();
502 VisitDeclContext(D->getDeclContext());
504 bool AlreadyStarted = false;
505 if (const CXXRecordDecl *CXXRecord = dyn_cast<CXXRecordDecl>(D)) {
506 if (ClassTemplateDecl *ClassTmpl = CXXRecord->getDescribedClassTemplate()) {
507 AlreadyStarted = true;
509 switch (D->getTagKind()) {
512 case TTK_Struct: Out << "@ST"; break;
513 case TTK_Union: Out << "@UT"; break;
514 case TTK_Enum: llvm_unreachable("enum template");
516 VisitTemplateParameterList(ClassTmpl->getTemplateParameters());
517 } else if (const ClassTemplatePartialSpecializationDecl *PartialSpec
518 = dyn_cast<ClassTemplatePartialSpecializationDecl>(CXXRecord)) {
519 AlreadyStarted = true;
521 switch (D->getTagKind()) {
524 case TTK_Struct: Out << "@SP"; break;
525 case TTK_Union: Out << "@UP"; break;
526 case TTK_Enum: llvm_unreachable("enum partial specialization");
528 VisitTemplateParameterList(PartialSpec->getTemplateParameters());
532 if (!AlreadyStarted) {
533 switch (D->getTagKind()) {
536 case TTK_Struct: Out << "@S"; break;
537 case TTK_Union: Out << "@U"; break;
538 case TTK_Enum: Out << "@E"; break;
543 assert(Buf.size() > 0);
544 const unsigned off = Buf.size() - 1;
546 if (EmitDeclName(D)) {
547 if (const TypedefNameDecl *TD = D->getTypedefNameForAnonDecl()) {
552 if (D->isEmbeddedInDeclarator() && !D->isFreeStanding()) {
553 printLoc(Out, D->getLocation(), Context->getSourceManager(), true);
556 if (auto *ED = dyn_cast<EnumDecl>(D)) {
557 // Distinguish USRs of anonymous enums by using their first enumerator.
558 auto enum_range = ED->enumerators();
559 if (enum_range.begin() != enum_range.end()) {
560 Out << '@' << **enum_range.begin();
567 // For a class template specialization, mangle the template arguments.
568 if (const ClassTemplateSpecializationDecl *Spec
569 = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
570 const TemplateArgumentList &Args = Spec->getTemplateArgs();
572 for (unsigned I = 0, N = Args.size(); I != N; ++I) {
574 VisitTemplateArgument(Args.get(I));
579 void USRGenerator::VisitTypedefDecl(const TypedefDecl *D) {
580 if (ShouldGenerateLocation(D) && GenLoc(D, /*IncludeOffset=*/isLocal(D)))
582 const DeclContext *DC = D->getDeclContext();
583 if (const NamedDecl *DCN = dyn_cast<NamedDecl>(DC))
589 void USRGenerator::VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D) {
590 GenLoc(D, /*IncludeOffset=*/true);
593 void USRGenerator::GenExtSymbolContainer(const NamedDecl *D) {
594 StringRef Container = GetExternalSourceContainer(D);
595 if (!Container.empty())
596 Out << "@M@" << Container;
599 bool USRGenerator::GenLoc(const Decl *D, bool IncludeOffset) {
601 return IgnoreResults;
604 // Guard against null declarations in invalid code.
606 IgnoreResults = true;
610 // Use the location of canonical decl.
611 D = D->getCanonicalDecl();
614 IgnoreResults || printLoc(Out, D->getBeginLoc(),
615 Context->getSourceManager(), IncludeOffset);
617 return IgnoreResults;
620 static void printQualifier(llvm::raw_ostream &Out, ASTContext &Ctx, NestedNameSpecifier *NNS) {
621 // FIXME: Encode the qualifier, don't just print it.
622 PrintingPolicy PO(Ctx.getLangOpts());
623 PO.SuppressTagKeyword = true;
624 PO.SuppressUnwrittenScope = true;
625 PO.ConstantArraySizeAsWritten = false;
626 PO.AnonymousTagLocations = false;
630 void USRGenerator::VisitType(QualType T) {
631 // This method mangles in USR information for types. It can possibly
632 // just reuse the naming-mangling logic used by codegen, although the
633 // requirements for USRs might not be the same.
634 ASTContext &Ctx = *Context;
637 T = Ctx.getCanonicalType(T);
638 Qualifiers Q = T.getQualifiers();
647 Out << ((char) ('0' + qVal));
649 // Mangle in ObjC GC qualifiers?
651 if (const PackExpansionType *Expansion = T->getAs<PackExpansionType>()) {
653 T = Expansion->getPattern();
656 if (const BuiltinType *BT = T->getAs<BuiltinType>()) {
657 unsigned char c = '\0';
658 switch (BT->getKind()) {
659 case BuiltinType::Void:
661 case BuiltinType::Bool:
663 case BuiltinType::UChar:
665 case BuiltinType::Char8:
666 c = 'u'; break; // FIXME: Check this doesn't collide
667 case BuiltinType::Char16:
669 case BuiltinType::Char32:
671 case BuiltinType::UShort:
673 case BuiltinType::UInt:
675 case BuiltinType::ULong:
677 case BuiltinType::ULongLong:
679 case BuiltinType::UInt128:
681 case BuiltinType::Char_U:
682 case BuiltinType::Char_S:
684 case BuiltinType::SChar:
686 case BuiltinType::WChar_S:
687 case BuiltinType::WChar_U:
689 case BuiltinType::Short:
691 case BuiltinType::Int:
693 case BuiltinType::Long:
695 case BuiltinType::LongLong:
697 case BuiltinType::Int128:
699 case BuiltinType::Float16:
700 case BuiltinType::Half:
702 case BuiltinType::Float:
704 case BuiltinType::Double:
706 case BuiltinType::LongDouble:
708 case BuiltinType::Float128:
710 case BuiltinType::NullPtr:
712 #define BUILTIN_TYPE(Id, SingletonId)
713 #define PLACEHOLDER_TYPE(Id, SingletonId) case BuiltinType::Id:
714 #include "clang/AST/BuiltinTypes.def"
715 case BuiltinType::Dependent:
716 #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
717 case BuiltinType::Id:
718 #include "clang/Basic/OpenCLImageTypes.def"
719 #define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
720 case BuiltinType::Id:
721 #include "clang/Basic/OpenCLExtensionTypes.def"
722 case BuiltinType::OCLEvent:
723 case BuiltinType::OCLClkEvent:
724 case BuiltinType::OCLQueue:
725 case BuiltinType::OCLReserveID:
726 case BuiltinType::OCLSampler:
727 #define SVE_TYPE(Name, Id, SingletonId) \
728 case BuiltinType::Id:
729 #include "clang/Basic/AArch64SVEACLETypes.def"
730 case BuiltinType::ShortAccum:
731 case BuiltinType::Accum:
732 case BuiltinType::LongAccum:
733 case BuiltinType::UShortAccum:
734 case BuiltinType::UAccum:
735 case BuiltinType::ULongAccum:
736 case BuiltinType::ShortFract:
737 case BuiltinType::Fract:
738 case BuiltinType::LongFract:
739 case BuiltinType::UShortFract:
740 case BuiltinType::UFract:
741 case BuiltinType::ULongFract:
742 case BuiltinType::SatShortAccum:
743 case BuiltinType::SatAccum:
744 case BuiltinType::SatLongAccum:
745 case BuiltinType::SatUShortAccum:
746 case BuiltinType::SatUAccum:
747 case BuiltinType::SatULongAccum:
748 case BuiltinType::SatShortFract:
749 case BuiltinType::SatFract:
750 case BuiltinType::SatLongFract:
751 case BuiltinType::SatUShortFract:
752 case BuiltinType::SatUFract:
753 case BuiltinType::SatULongFract:
754 IgnoreResults = true;
756 case BuiltinType::ObjCId:
758 case BuiltinType::ObjCClass:
760 case BuiltinType::ObjCSel:
767 // If we have already seen this (non-built-in) type, use a substitution
769 llvm::DenseMap<const Type *, unsigned>::iterator Substitution
770 = TypeSubstitutions.find(T.getTypePtr());
771 if (Substitution != TypeSubstitutions.end()) {
772 Out << 'S' << Substitution->second << '_';
775 // Record this as a substitution.
776 unsigned Number = TypeSubstitutions.size();
777 TypeSubstitutions[T.getTypePtr()] = Number;
780 if (const PointerType *PT = T->getAs<PointerType>()) {
782 T = PT->getPointeeType();
785 if (const ObjCObjectPointerType *OPT = T->getAs<ObjCObjectPointerType>()) {
787 T = OPT->getPointeeType();
790 if (const RValueReferenceType *RT = T->getAs<RValueReferenceType>()) {
792 T = RT->getPointeeType();
795 if (const ReferenceType *RT = T->getAs<ReferenceType>()) {
797 T = RT->getPointeeType();
800 if (const FunctionProtoType *FT = T->getAs<FunctionProtoType>()) {
802 VisitType(FT->getReturnType());
804 for (const auto &I : FT->param_types()) {
809 if (FT->isVariadic())
813 if (const BlockPointerType *BT = T->getAs<BlockPointerType>()) {
815 T = BT->getPointeeType();
818 if (const ComplexType *CT = T->getAs<ComplexType>()) {
820 T = CT->getElementType();
823 if (const TagType *TT = T->getAs<TagType>()) {
825 VisitTagDecl(TT->getDecl());
828 if (const ObjCInterfaceType *OIT = T->getAs<ObjCInterfaceType>()) {
830 VisitObjCInterfaceDecl(OIT->getDecl());
833 if (const ObjCObjectType *OIT = T->getAs<ObjCObjectType>()) {
835 VisitType(OIT->getBaseType());
836 for (auto *Prot : OIT->getProtocols())
837 VisitObjCProtocolDecl(Prot);
840 if (const TemplateTypeParmType *TTP = T->getAs<TemplateTypeParmType>()) {
841 Out << 't' << TTP->getDepth() << '.' << TTP->getIndex();
844 if (const TemplateSpecializationType *Spec
845 = T->getAs<TemplateSpecializationType>()) {
847 VisitTemplateName(Spec->getTemplateName());
848 Out << Spec->getNumArgs();
849 for (unsigned I = 0, N = Spec->getNumArgs(); I != N; ++I)
850 VisitTemplateArgument(Spec->getArg(I));
853 if (const DependentNameType *DNT = T->getAs<DependentNameType>()) {
855 printQualifier(Out, Ctx, DNT->getQualifier());
856 Out << ':' << DNT->getIdentifier()->getName();
859 if (const InjectedClassNameType *InjT = T->getAs<InjectedClassNameType>()) {
860 T = InjT->getInjectedSpecializationType();
863 if (const auto *VT = T->getAs<VectorType>()) {
864 Out << (T->isExtVectorType() ? ']' : '[');
865 Out << VT->getNumElements();
866 T = VT->getElementType();
869 if (const auto *const AT = dyn_cast<ArrayType>(T)) {
871 switch (AT->getSizeModifier()) {
872 case ArrayType::Static:
875 case ArrayType::Star:
878 case ArrayType::Normal:
882 if (const auto *const CAT = dyn_cast<ConstantArrayType>(T))
883 Out << CAT->getSize();
885 T = AT->getElementType();
895 void USRGenerator::VisitTemplateParameterList(
896 const TemplateParameterList *Params) {
899 Out << '>' << Params->size();
900 for (TemplateParameterList::const_iterator P = Params->begin(),
901 PEnd = Params->end();
904 if (isa<TemplateTypeParmDecl>(*P)) {
905 if (cast<TemplateTypeParmDecl>(*P)->isParameterPack())
911 if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(*P)) {
912 if (NTTP->isParameterPack())
915 VisitType(NTTP->getType());
919 TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*P);
920 if (TTP->isParameterPack())
923 VisitTemplateParameterList(TTP->getTemplateParameters());
927 void USRGenerator::VisitTemplateName(TemplateName Name) {
928 if (TemplateDecl *Template = Name.getAsTemplateDecl()) {
929 if (TemplateTemplateParmDecl *TTP
930 = dyn_cast<TemplateTemplateParmDecl>(Template)) {
931 Out << 't' << TTP->getDepth() << '.' << TTP->getIndex();
939 // FIXME: Visit dependent template names.
942 void USRGenerator::VisitTemplateArgument(const TemplateArgument &Arg) {
943 switch (Arg.getKind()) {
944 case TemplateArgument::Null:
947 case TemplateArgument::Declaration:
948 Visit(Arg.getAsDecl());
951 case TemplateArgument::NullPtr:
954 case TemplateArgument::TemplateExpansion:
955 Out << 'P'; // pack expansion of...
957 case TemplateArgument::Template:
958 VisitTemplateName(Arg.getAsTemplateOrTemplatePattern());
961 case TemplateArgument::Expression:
962 // FIXME: Visit expressions.
965 case TemplateArgument::Pack:
966 Out << 'p' << Arg.pack_size();
967 for (const auto &P : Arg.pack_elements())
968 VisitTemplateArgument(P);
971 case TemplateArgument::Type:
972 VisitType(Arg.getAsType());
975 case TemplateArgument::Integral:
977 VisitType(Arg.getIntegralType());
978 Out << Arg.getAsIntegral();
983 void USRGenerator::VisitUnresolvedUsingValueDecl(const UnresolvedUsingValueDecl *D) {
984 if (ShouldGenerateLocation(D) && GenLoc(D, /*IncludeOffset=*/isLocal(D)))
986 VisitDeclContext(D->getDeclContext());
988 printQualifier(Out, D->getASTContext(), D->getQualifier());
992 void USRGenerator::VisitUnresolvedUsingTypenameDecl(const UnresolvedUsingTypenameDecl *D) {
993 if (ShouldGenerateLocation(D) && GenLoc(D, /*IncludeOffset=*/isLocal(D)))
995 VisitDeclContext(D->getDeclContext());
997 printQualifier(Out, D->getASTContext(), D->getQualifier());
998 Out << D->getName(); // Simple name.
1003 //===----------------------------------------------------------------------===//
1004 // USR generation functions.
1005 //===----------------------------------------------------------------------===//
1007 static void combineClassAndCategoryExtContainers(StringRef ClsSymDefinedIn,
1008 StringRef CatSymDefinedIn,
1010 if (ClsSymDefinedIn.empty() && CatSymDefinedIn.empty())
1012 if (CatSymDefinedIn.empty()) {
1013 OS << "@M@" << ClsSymDefinedIn << '@';
1016 OS << "@CM@" << CatSymDefinedIn << '@';
1017 if (ClsSymDefinedIn != CatSymDefinedIn) {
1018 OS << ClsSymDefinedIn << '@';
1022 void clang::index::generateUSRForObjCClass(StringRef Cls, raw_ostream &OS,
1023 StringRef ExtSymDefinedIn,
1024 StringRef CategoryContextExtSymbolDefinedIn) {
1025 combineClassAndCategoryExtContainers(ExtSymDefinedIn,
1026 CategoryContextExtSymbolDefinedIn, OS);
1027 OS << "objc(cs)" << Cls;
1030 void clang::index::generateUSRForObjCCategory(StringRef Cls, StringRef Cat,
1032 StringRef ClsSymDefinedIn,
1033 StringRef CatSymDefinedIn) {
1034 combineClassAndCategoryExtContainers(ClsSymDefinedIn, CatSymDefinedIn, OS);
1035 OS << "objc(cy)" << Cls << '@' << Cat;
1038 void clang::index::generateUSRForObjCIvar(StringRef Ivar, raw_ostream &OS) {
1042 void clang::index::generateUSRForObjCMethod(StringRef Sel,
1043 bool IsInstanceMethod,
1045 OS << (IsInstanceMethod ? "(im)" : "(cm)") << Sel;
1048 void clang::index::generateUSRForObjCProperty(StringRef Prop, bool isClassProp,
1050 OS << (isClassProp ? "(cpy)" : "(py)") << Prop;
1053 void clang::index::generateUSRForObjCProtocol(StringRef Prot, raw_ostream &OS,
1054 StringRef ExtSymDefinedIn) {
1055 if (!ExtSymDefinedIn.empty())
1056 OS << "@M@" << ExtSymDefinedIn << '@';
1057 OS << "objc(pl)" << Prot;
1060 void clang::index::generateUSRForGlobalEnum(StringRef EnumName, raw_ostream &OS,
1061 StringRef ExtSymDefinedIn) {
1062 if (!ExtSymDefinedIn.empty())
1063 OS << "@M@" << ExtSymDefinedIn;
1064 OS << "@E@" << EnumName;
1067 void clang::index::generateUSRForEnumConstant(StringRef EnumConstantName,
1069 OS << '@' << EnumConstantName;
1072 bool clang::index::generateUSRForDecl(const Decl *D,
1073 SmallVectorImpl<char> &Buf) {
1076 // We don't ignore decls with invalid source locations. Implicit decls, like
1077 // C++'s operator new function, can have invalid locations but it is fine to
1078 // create USRs that can identify them.
1080 USRGenerator UG(&D->getASTContext(), Buf);
1082 return UG.ignoreResults();
1085 bool clang::index::generateUSRForMacro(const MacroDefinitionRecord *MD,
1086 const SourceManager &SM,
1087 SmallVectorImpl<char> &Buf) {
1090 return generateUSRForMacro(MD->getName()->getName(), MD->getLocation(),
1095 bool clang::index::generateUSRForMacro(StringRef MacroName, SourceLocation Loc,
1096 const SourceManager &SM,
1097 SmallVectorImpl<char> &Buf) {
1098 // Don't generate USRs for things with invalid locations.
1099 if (MacroName.empty() || Loc.isInvalid())
1102 llvm::raw_svector_ostream Out(Buf);
1104 // Assume that system headers are sane. Don't put source location
1105 // information into the USR if the macro comes from a system header.
1106 bool ShouldGenerateLocation = !SM.isInSystemHeader(Loc);
1108 Out << getUSRSpacePrefix();
1109 if (ShouldGenerateLocation)
1110 printLoc(Out, Loc, SM, /*IncludeOffset=*/true);
1116 bool clang::index::generateUSRForType(QualType T, ASTContext &Ctx,
1117 SmallVectorImpl<char> &Buf) {
1120 T = T.getCanonicalType();
1122 USRGenerator UG(&Ctx, Buf);
1124 return UG.ignoreResults();
1127 bool clang::index::generateFullUSRForModule(const Module *Mod,
1130 return generateFullUSRForTopLevelModuleName(Mod->Name, OS);
1131 if (generateFullUSRForModule(Mod->Parent, OS))
1133 return generateUSRFragmentForModule(Mod, OS);
1136 bool clang::index::generateFullUSRForTopLevelModuleName(StringRef ModName,
1138 OS << getUSRSpacePrefix();
1139 return generateUSRFragmentForModuleName(ModName, OS);
1142 bool clang::index::generateUSRFragmentForModule(const Module *Mod,
1144 return generateUSRFragmentForModuleName(Mod->Name, OS);
1147 bool clang::index::generateUSRFragmentForModuleName(StringRef ModName,
1149 OS << "@M@" << ModName;