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/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 //===----------------------------------------------------------------------===//
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()) {
33 Loc
= SM
.getExpansionLoc(Loc
);
34 const std::pair
<FileID
, unsigned> &Decomposed
= SM
.getDecomposedLoc(Loc
);
35 OptionalFileEntryRef FE
= SM
.getFileEntryRefForID(Decomposed
.first
);
37 OS
<< llvm::sys::path::filename(FE
->getName());
39 // This case really isn't interesting.
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
;
51 static StringRef
GetExternalSourceContainer(const NamedDecl
*D
) {
54 if (auto *attr
= D
->getExternalSourceSymbolAttr()) {
55 return attr
->getDefinedIn();
61 class USRGenerator
: public ConstDeclVisitor
<USRGenerator
> {
62 SmallVectorImpl
<char> &Buf
;
63 llvm::raw_svector_ostream Out
;
68 llvm::DenseMap
<const Type
*, unsigned> TypeSubstitutions
;
71 explicit USRGenerator(ASTContext
*Ctx
, SmallVectorImpl
<char> &Buf
)
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());
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
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
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();
192 bool USRGenerator::ShouldGenerateLocation(const NamedDecl
*D
) {
193 if (D
->isExternallyVisible())
195 if (D
->getParentFunctionOrMethod())
197 SourceLocation Loc
= D
->getLocation();
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
))
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
))
217 VisitDeclContext(D
->getDeclContext());
218 Out
<< (isa
<ObjCIvarDecl
>(D
) ? "@" : "@FI@");
219 if (EmitDeclName(D
)) {
220 // Bit fields can be anonymous.
221 IgnoreResults
= true;
226 void USRGenerator::VisitFunctionDecl(const FunctionDecl
*D
) {
227 if (ShouldGenerateLocation(D
) && GenLoc(D
, /*IncludeOffset=*/isLocal(D
)))
230 if (D
->getType().isNull()) {
231 IgnoreResults
= true;
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()) {
244 VisitTemplateParameterList(FunTmpl
->getTemplateParameters());
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
>())
259 if (const TemplateArgumentList
*
260 SpecArgs
= D
->getTemplateSpecializationArgs()) {
262 for (unsigned I
= 0, N
= SpecArgs
->size(); I
!= N
; ++I
) {
264 VisitTemplateArgument(SpecArgs
->get(I
));
269 // Mangle in type information for the arguments.
270 for (auto *PD
: D
->parameters()) {
272 VisitType(PD
->getType());
277 // Function templates can be overloaded by return type, for example:
279 // template <class T> typename T::A foo() {}
280 // template <class T> typename T::B foo() {}
283 VisitType(D
->getReturnType());
286 if (const CXXMethodDecl
*MD
= dyn_cast
<CXXMethodDecl
>(D
)) {
289 // FIXME: OpenCL: Need to consider address spaces
290 if (unsigned quals
= MD
->getMethodQualifiers().getCVRUQualifiers())
291 Out
<< (char)('0' + quals
);
292 switch (MD
->getRefQualifier()) {
294 case RQ_LValue
: Out
<< '&'; break;
295 case RQ_RValue
: Out
<< "&&"; break;
300 void USRGenerator::VisitNamedDecl(const NamedDecl
*D
) {
301 VisitDeclContext(D
->getDeclContext());
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
)))
320 VisitDeclContext(D
->getDeclContext());
322 if (VarTemplateDecl
*VarTmpl
= D
->getDescribedVarTemplate()) {
324 VisitTemplateParameterList(VarTmpl
->getTemplateParameters());
325 } else if (const VarTemplatePartialSpecializationDecl
*PartialSpec
326 = dyn_cast
<VarTemplatePartialSpecializationDecl
>(D
)) {
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.
339 IgnoreResults
= true;
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();
348 for (unsigned I
= 0, N
= Args
.size(); I
!= N
; ++I
) {
350 VisitTemplateArgument(Args
.get(I
));
355 void USRGenerator::VisitBindingDecl(const BindingDecl
*D
) {
356 if (isLocal(D
) && GenLoc(D
, /*IncludeOffset=*/true))
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
) {
374 VisitDeclContext(D
->getDeclContext());
375 if (D
->isAnonymousNamespace()) {
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());
393 Out
<< "@NA@" << D
->getName();
396 static const ObjCCategoryDecl
*getCategoryContext(const NamedDecl
*D
) {
397 if (auto *CD
= dyn_cast
<ObjCCategoryDecl
>(D
->getDeclContext()))
399 if (auto *ICD
= dyn_cast
<ObjCCategoryImplDecl
>(D
->getDeclContext()))
400 return ICD
->getCategoryDecl();
404 void USRGenerator::VisitObjCMethodDecl(const ObjCMethodDecl
*D
) {
405 const DeclContext
*container
= D
->getDeclContext();
406 if (const ObjCProtocolDecl
*pd
= dyn_cast
<ObjCProtocolDecl
>(container
)) {
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();
414 IgnoreResults
= true;
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()) {
431 llvm_unreachable("Invalid ObjC container.");
432 case Decl::ObjCInterface
:
433 case Decl::ObjCImplementation
:
434 GenObjCClass(D
->getName(), GetExternalSourceContainer(D
),
435 GetExternalSourceContainer(CatD
));
437 case Decl::ObjCCategory
: {
438 const ObjCCategoryDecl
*CD
= cast
<ObjCCategoryDecl
>(D
);
439 const ObjCInterfaceDecl
*ID
= CD
->getClassInterface();
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;
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);
455 GenObjCCategory(ID
->getName(), CD
->getName(),
456 GetExternalSourceContainer(ID
),
457 GetExternalSourceContainer(CD
));
461 case Decl::ObjCCategoryImpl
: {
462 const ObjCCategoryImplDecl
*CD
= cast
<ObjCCategoryImplDecl
>(D
);
463 const ObjCInterfaceDecl
*ID
= CD
->getClassInterface();
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;
472 GenObjCCategory(ID
->getName(), CD
->getName(),
473 GetExternalSourceContainer(ID
),
474 GetExternalSourceContainer(CD
));
477 case Decl::ObjCProtocol
: {
478 const ObjCProtocolDecl
*PD
= cast
<ObjCProtocolDecl
>(D
);
479 GenObjCProtocol(PD
->getName(), GetExternalSourceContainer(PD
));
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
));
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
);
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
)))
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()) {
524 case TTK_Struct
: Out
<< "@ST"; break;
525 case TTK_Union
: Out
<< "@UT"; break;
526 case TTK_Enum
: llvm_unreachable("enum template");
528 VisitTemplateParameterList(ClassTmpl
->getTemplateParameters());
529 } else if (const ClassTemplatePartialSpecializationDecl
*PartialSpec
530 = dyn_cast
<ClassTemplatePartialSpecializationDecl
>(CXXRecord
)) {
531 AlreadyStarted
= true;
533 switch (D
->getTagKind()) {
536 case TTK_Struct
: Out
<< "@SP"; break;
537 case TTK_Union
: Out
<< "@UP"; break;
538 case TTK_Enum
: llvm_unreachable("enum partial specialization");
540 VisitTemplateParameterList(PartialSpec
->getTemplateParameters());
544 if (!AlreadyStarted
) {
545 switch (D
->getTagKind()) {
548 case TTK_Struct
: Out
<< "@S"; break;
549 case TTK_Union
: Out
<< "@U"; break;
550 case TTK_Enum
: Out
<< "@E"; break;
555 assert(Buf
.size() > 0);
556 const unsigned off
= Buf
.size() - 1;
558 if (EmitDeclName(D
)) {
559 if (const TypedefNameDecl
*TD
= D
->getTypedefNameForAnonDecl()) {
563 if (D
->isEmbeddedInDeclarator() && !D
->isFreeStanding()) {
564 printLoc(Out
, D
->getLocation(), Context
->getSourceManager(), true);
567 if (auto *ED
= dyn_cast
<EnumDecl
>(D
)) {
568 // Distinguish USRs of anonymous enums by using their first
570 auto enum_range
= ED
->enumerators();
571 if (enum_range
.begin() != enum_range
.end()) {
572 Out
<< '@' << **enum_range
.begin();
579 // For a class template specialization, mangle the template arguments.
580 if (const ClassTemplateSpecializationDecl
*Spec
581 = dyn_cast
<ClassTemplateSpecializationDecl
>(D
)) {
582 const TemplateArgumentList
&Args
= Spec
->getTemplateArgs();
584 for (unsigned I
= 0, N
= Args
.size(); I
!= N
; ++I
) {
586 VisitTemplateArgument(Args
.get(I
));
591 void USRGenerator::VisitTypedefDecl(const TypedefDecl
*D
) {
592 if (ShouldGenerateLocation(D
) && GenLoc(D
, /*IncludeOffset=*/isLocal(D
)))
594 const DeclContext
*DC
= D
->getDeclContext();
595 if (const NamedDecl
*DCN
= dyn_cast
<NamedDecl
>(DC
))
601 void USRGenerator::VisitTemplateTypeParmDecl(const TemplateTypeParmDecl
*D
) {
602 GenLoc(D
, /*IncludeOffset=*/true);
605 void USRGenerator::GenExtSymbolContainer(const NamedDecl
*D
) {
606 StringRef Container
= GetExternalSourceContainer(D
);
607 if (!Container
.empty())
608 Out
<< "@M@" << Container
;
611 bool USRGenerator::GenLoc(const Decl
*D
, bool IncludeOffset
) {
613 return IgnoreResults
;
616 // Guard against null declarations in invalid code.
618 IgnoreResults
= true;
622 // Use the location of canonical decl.
623 D
= D
->getCanonicalDecl();
626 IgnoreResults
|| printLoc(Out
, D
->getBeginLoc(),
627 Context
->getSourceManager(), IncludeOffset
);
629 return IgnoreResults
;
632 static void printQualifier(llvm::raw_ostream
&Out
, ASTContext
&Ctx
, NestedNameSpecifier
*NNS
) {
633 // FIXME: Encode the qualifier, don't just print it.
634 PrintingPolicy
PO(Ctx
.getLangOpts());
635 PO
.SuppressTagKeyword
= true;
636 PO
.SuppressUnwrittenScope
= true;
637 PO
.ConstantArraySizeAsWritten
= false;
638 PO
.AnonymousTagLocations
= false;
642 void USRGenerator::VisitType(QualType T
) {
643 // This method mangles in USR information for types. It can possibly
644 // just reuse the naming-mangling logic used by codegen, although the
645 // requirements for USRs might not be the same.
646 ASTContext
&Ctx
= *Context
;
649 T
= Ctx
.getCanonicalType(T
);
650 Qualifiers Q
= T
.getQualifiers();
659 Out
<< ((char) ('0' + qVal
));
661 // Mangle in ObjC GC qualifiers?
663 if (const PackExpansionType
*Expansion
= T
->getAs
<PackExpansionType
>()) {
665 T
= Expansion
->getPattern();
668 if (const BuiltinType
*BT
= T
->getAs
<BuiltinType
>()) {
669 switch (BT
->getKind()) {
670 case BuiltinType::Void
:
672 case BuiltinType::Bool
:
674 case BuiltinType::UChar
:
676 case BuiltinType::Char8
:
678 case BuiltinType::Char16
:
680 case BuiltinType::Char32
:
682 case BuiltinType::UShort
:
684 case BuiltinType::UInt
:
686 case BuiltinType::ULong
:
688 case BuiltinType::ULongLong
:
690 case BuiltinType::UInt128
:
692 case BuiltinType::Char_U
:
693 case BuiltinType::Char_S
:
695 case BuiltinType::SChar
:
697 case BuiltinType::WChar_S
:
698 case BuiltinType::WChar_U
:
700 case BuiltinType::Short
:
702 case BuiltinType::Int
:
704 case BuiltinType::Long
:
706 case BuiltinType::LongLong
:
708 case BuiltinType::Int128
:
710 case BuiltinType::Float16
:
711 case BuiltinType::Half
:
713 case BuiltinType::Float
:
715 case BuiltinType::Double
:
717 case BuiltinType::LongDouble
:
719 case BuiltinType::Float128
:
721 case BuiltinType::NullPtr
:
723 #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
724 case BuiltinType::Id: \
725 Out << "@BT@" << #Suffix << "_" << #ImgType; break;
726 #include "clang/Basic/OpenCLImageTypes.def"
727 #define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
728 case BuiltinType::Id: \
729 Out << "@BT@" << #ExtType; break;
730 #include "clang/Basic/OpenCLExtensionTypes.def"
731 case BuiltinType::OCLEvent
:
732 Out
<< "@BT@OCLEvent"; break;
733 case BuiltinType::OCLClkEvent
:
734 Out
<< "@BT@OCLClkEvent"; break;
735 case BuiltinType::OCLQueue
:
736 Out
<< "@BT@OCLQueue"; break;
737 case BuiltinType::OCLReserveID
:
738 Out
<< "@BT@OCLReserveID"; break;
739 case BuiltinType::OCLSampler
:
740 Out
<< "@BT@OCLSampler"; break;
741 #define SVE_TYPE(Name, Id, SingletonId) \
742 case BuiltinType::Id: \
743 Out << "@BT@" << Name; break;
744 #include "clang/Basic/AArch64SVEACLETypes.def"
745 #define PPC_VECTOR_TYPE(Name, Id, Size) \
746 case BuiltinType::Id: \
747 Out << "@BT@" << #Name; break;
748 #include "clang/Basic/PPCTypes.def"
749 #define RVV_TYPE(Name, Id, SingletonId) \
750 case BuiltinType::Id: \
751 Out << "@BT@" << Name; break;
752 #include "clang/Basic/RISCVVTypes.def"
753 #define WASM_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
754 #include "clang/Basic/WebAssemblyReferenceTypes.def"
755 case BuiltinType::ShortAccum
:
756 Out
<< "@BT@ShortAccum"; break;
757 case BuiltinType::Accum
:
758 Out
<< "@BT@Accum"; break;
759 case BuiltinType::LongAccum
:
760 Out
<< "@BT@LongAccum"; break;
761 case BuiltinType::UShortAccum
:
762 Out
<< "@BT@UShortAccum"; break;
763 case BuiltinType::UAccum
:
764 Out
<< "@BT@UAccum"; break;
765 case BuiltinType::ULongAccum
:
766 Out
<< "@BT@ULongAccum"; break;
767 case BuiltinType::ShortFract
:
768 Out
<< "@BT@ShortFract"; break;
769 case BuiltinType::Fract
:
770 Out
<< "@BT@Fract"; break;
771 case BuiltinType::LongFract
:
772 Out
<< "@BT@LongFract"; break;
773 case BuiltinType::UShortFract
:
774 Out
<< "@BT@UShortFract"; break;
775 case BuiltinType::UFract
:
776 Out
<< "@BT@UFract"; break;
777 case BuiltinType::ULongFract
:
778 Out
<< "@BT@ULongFract"; break;
779 case BuiltinType::SatShortAccum
:
780 Out
<< "@BT@SatShortAccum"; break;
781 case BuiltinType::SatAccum
:
782 Out
<< "@BT@SatAccum"; break;
783 case BuiltinType::SatLongAccum
:
784 Out
<< "@BT@SatLongAccum"; break;
785 case BuiltinType::SatUShortAccum
:
786 Out
<< "@BT@SatUShortAccum"; break;
787 case BuiltinType::SatUAccum
:
788 Out
<< "@BT@SatUAccum"; break;
789 case BuiltinType::SatULongAccum
:
790 Out
<< "@BT@SatULongAccum"; break;
791 case BuiltinType::SatShortFract
:
792 Out
<< "@BT@SatShortFract"; break;
793 case BuiltinType::SatFract
:
794 Out
<< "@BT@SatFract"; break;
795 case BuiltinType::SatLongFract
:
796 Out
<< "@BT@SatLongFract"; break;
797 case BuiltinType::SatUShortFract
:
798 Out
<< "@BT@SatUShortFract"; break;
799 case BuiltinType::SatUFract
:
800 Out
<< "@BT@SatUFract"; break;
801 case BuiltinType::SatULongFract
:
802 Out
<< "@BT@SatULongFract"; break;
803 case BuiltinType::BFloat16
:
804 Out
<< "@BT@__bf16"; break;
805 case BuiltinType::Ibm128
:
806 Out
<< "@BT@__ibm128"; break;
807 case BuiltinType::ObjCId
:
809 case BuiltinType::ObjCClass
:
811 case BuiltinType::ObjCSel
:
813 #define BUILTIN_TYPE(Id, SingletonId)
814 #define PLACEHOLDER_TYPE(Id, SingletonId) case BuiltinType::Id:
815 #include "clang/AST/BuiltinTypes.def"
816 case BuiltinType::Dependent
:
817 // If you're adding a new builtin type, please add its name prefixed
818 // with "@BT@" to `Out` (see cases above).
819 IgnoreResults
= true;
825 // If we have already seen this (non-built-in) type, use a substitution
827 llvm::DenseMap
<const Type
*, unsigned>::iterator Substitution
828 = TypeSubstitutions
.find(T
.getTypePtr());
829 if (Substitution
!= TypeSubstitutions
.end()) {
830 Out
<< 'S' << Substitution
->second
<< '_';
833 // Record this as a substitution.
834 unsigned Number
= TypeSubstitutions
.size();
835 TypeSubstitutions
[T
.getTypePtr()] = Number
;
838 if (const PointerType
*PT
= T
->getAs
<PointerType
>()) {
840 T
= PT
->getPointeeType();
843 if (const ObjCObjectPointerType
*OPT
= T
->getAs
<ObjCObjectPointerType
>()) {
845 T
= OPT
->getPointeeType();
848 if (const RValueReferenceType
*RT
= T
->getAs
<RValueReferenceType
>()) {
850 T
= RT
->getPointeeType();
853 if (const ReferenceType
*RT
= T
->getAs
<ReferenceType
>()) {
855 T
= RT
->getPointeeType();
858 if (const FunctionProtoType
*FT
= T
->getAs
<FunctionProtoType
>()) {
860 VisitType(FT
->getReturnType());
862 for (const auto &I
: FT
->param_types()) {
867 if (FT
->isVariadic())
871 if (const BlockPointerType
*BT
= T
->getAs
<BlockPointerType
>()) {
873 T
= BT
->getPointeeType();
876 if (const ComplexType
*CT
= T
->getAs
<ComplexType
>()) {
878 T
= CT
->getElementType();
881 if (const TagType
*TT
= T
->getAs
<TagType
>()) {
883 VisitTagDecl(TT
->getDecl());
886 if (const ObjCInterfaceType
*OIT
= T
->getAs
<ObjCInterfaceType
>()) {
888 VisitObjCInterfaceDecl(OIT
->getDecl());
891 if (const ObjCObjectType
*OIT
= T
->getAs
<ObjCObjectType
>()) {
893 VisitType(OIT
->getBaseType());
894 for (auto *Prot
: OIT
->getProtocols())
895 VisitObjCProtocolDecl(Prot
);
898 if (const TemplateTypeParmType
*TTP
= T
->getAs
<TemplateTypeParmType
>()) {
899 Out
<< 't' << TTP
->getDepth() << '.' << TTP
->getIndex();
902 if (const TemplateSpecializationType
*Spec
903 = T
->getAs
<TemplateSpecializationType
>()) {
905 VisitTemplateName(Spec
->getTemplateName());
906 Out
<< Spec
->template_arguments().size();
907 for (const auto &Arg
: Spec
->template_arguments())
908 VisitTemplateArgument(Arg
);
911 if (const DependentNameType
*DNT
= T
->getAs
<DependentNameType
>()) {
913 printQualifier(Out
, Ctx
, DNT
->getQualifier());
914 Out
<< ':' << DNT
->getIdentifier()->getName();
917 if (const InjectedClassNameType
*InjT
= T
->getAs
<InjectedClassNameType
>()) {
918 T
= InjT
->getInjectedSpecializationType();
921 if (const auto *VT
= T
->getAs
<VectorType
>()) {
922 Out
<< (T
->isExtVectorType() ? ']' : '[');
923 Out
<< VT
->getNumElements();
924 T
= VT
->getElementType();
927 if (const auto *const AT
= dyn_cast
<ArrayType
>(T
)) {
929 switch (AT
->getSizeModifier()) {
930 case ArraySizeModifier::Static
:
933 case ArraySizeModifier::Star
:
936 case ArraySizeModifier::Normal
:
940 if (const auto *const CAT
= dyn_cast
<ConstantArrayType
>(T
))
941 Out
<< CAT
->getSize();
943 T
= AT
->getElementType();
953 void USRGenerator::VisitTemplateParameterList(
954 const TemplateParameterList
*Params
) {
957 Out
<< '>' << Params
->size();
958 for (TemplateParameterList::const_iterator P
= Params
->begin(),
959 PEnd
= Params
->end();
962 if (isa
<TemplateTypeParmDecl
>(*P
)) {
963 if (cast
<TemplateTypeParmDecl
>(*P
)->isParameterPack())
969 if (NonTypeTemplateParmDecl
*NTTP
= dyn_cast
<NonTypeTemplateParmDecl
>(*P
)) {
970 if (NTTP
->isParameterPack())
973 VisitType(NTTP
->getType());
977 TemplateTemplateParmDecl
*TTP
= cast
<TemplateTemplateParmDecl
>(*P
);
978 if (TTP
->isParameterPack())
981 VisitTemplateParameterList(TTP
->getTemplateParameters());
985 void USRGenerator::VisitTemplateName(TemplateName Name
) {
986 if (TemplateDecl
*Template
= Name
.getAsTemplateDecl()) {
987 if (TemplateTemplateParmDecl
*TTP
988 = dyn_cast
<TemplateTemplateParmDecl
>(Template
)) {
989 Out
<< 't' << TTP
->getDepth() << '.' << TTP
->getIndex();
997 // FIXME: Visit dependent template names.
1000 void USRGenerator::VisitTemplateArgument(const TemplateArgument
&Arg
) {
1001 switch (Arg
.getKind()) {
1002 case TemplateArgument::Null
:
1005 case TemplateArgument::Declaration
:
1006 Visit(Arg
.getAsDecl());
1009 case TemplateArgument::NullPtr
:
1012 case TemplateArgument::TemplateExpansion
:
1013 Out
<< 'P'; // pack expansion of...
1015 case TemplateArgument::Template
:
1016 VisitTemplateName(Arg
.getAsTemplateOrTemplatePattern());
1019 case TemplateArgument::Expression
:
1020 // FIXME: Visit expressions.
1023 case TemplateArgument::Pack
:
1024 Out
<< 'p' << Arg
.pack_size();
1025 for (const auto &P
: Arg
.pack_elements())
1026 VisitTemplateArgument(P
);
1029 case TemplateArgument::Type
:
1030 VisitType(Arg
.getAsType());
1033 case TemplateArgument::Integral
:
1035 VisitType(Arg
.getIntegralType());
1036 Out
<< Arg
.getAsIntegral();
1041 void USRGenerator::VisitUnresolvedUsingValueDecl(const UnresolvedUsingValueDecl
*D
) {
1042 if (ShouldGenerateLocation(D
) && GenLoc(D
, /*IncludeOffset=*/isLocal(D
)))
1044 VisitDeclContext(D
->getDeclContext());
1046 printQualifier(Out
, D
->getASTContext(), D
->getQualifier());
1050 void USRGenerator::VisitUnresolvedUsingTypenameDecl(const UnresolvedUsingTypenameDecl
*D
) {
1051 if (ShouldGenerateLocation(D
) && GenLoc(D
, /*IncludeOffset=*/isLocal(D
)))
1053 VisitDeclContext(D
->getDeclContext());
1055 printQualifier(Out
, D
->getASTContext(), D
->getQualifier());
1056 Out
<< D
->getName(); // Simple name.
1059 void USRGenerator::VisitConceptDecl(const ConceptDecl
*D
) {
1060 if (ShouldGenerateLocation(D
) && GenLoc(D
, /*IncludeOffset=*/isLocal(D
)))
1062 VisitDeclContext(D
->getDeclContext());
1067 void USRGenerator::VisitMSGuidDecl(const MSGuidDecl
*D
) {
1068 VisitDeclContext(D
->getDeclContext());
1070 D
->NamedDecl::printName(Out
);
1073 //===----------------------------------------------------------------------===//
1074 // USR generation functions.
1075 //===----------------------------------------------------------------------===//
1077 static void combineClassAndCategoryExtContainers(StringRef ClsSymDefinedIn
,
1078 StringRef CatSymDefinedIn
,
1080 if (ClsSymDefinedIn
.empty() && CatSymDefinedIn
.empty())
1082 if (CatSymDefinedIn
.empty()) {
1083 OS
<< "@M@" << ClsSymDefinedIn
<< '@';
1086 OS
<< "@CM@" << CatSymDefinedIn
<< '@';
1087 if (ClsSymDefinedIn
!= CatSymDefinedIn
) {
1088 OS
<< ClsSymDefinedIn
<< '@';
1092 void clang::index::generateUSRForObjCClass(StringRef Cls
, raw_ostream
&OS
,
1093 StringRef ExtSymDefinedIn
,
1094 StringRef CategoryContextExtSymbolDefinedIn
) {
1095 combineClassAndCategoryExtContainers(ExtSymDefinedIn
,
1096 CategoryContextExtSymbolDefinedIn
, OS
);
1097 OS
<< "objc(cs)" << Cls
;
1100 void clang::index::generateUSRForObjCCategory(StringRef Cls
, StringRef Cat
,
1102 StringRef ClsSymDefinedIn
,
1103 StringRef CatSymDefinedIn
) {
1104 combineClassAndCategoryExtContainers(ClsSymDefinedIn
, CatSymDefinedIn
, OS
);
1105 OS
<< "objc(cy)" << Cls
<< '@' << Cat
;
1108 void clang::index::generateUSRForObjCIvar(StringRef Ivar
, raw_ostream
&OS
) {
1112 void clang::index::generateUSRForObjCMethod(StringRef Sel
,
1113 bool IsInstanceMethod
,
1115 OS
<< (IsInstanceMethod
? "(im)" : "(cm)") << Sel
;
1118 void clang::index::generateUSRForObjCProperty(StringRef Prop
, bool isClassProp
,
1120 OS
<< (isClassProp
? "(cpy)" : "(py)") << Prop
;
1123 void clang::index::generateUSRForObjCProtocol(StringRef Prot
, raw_ostream
&OS
,
1124 StringRef ExtSymDefinedIn
) {
1125 if (!ExtSymDefinedIn
.empty())
1126 OS
<< "@M@" << ExtSymDefinedIn
<< '@';
1127 OS
<< "objc(pl)" << Prot
;
1130 void clang::index::generateUSRForGlobalEnum(StringRef EnumName
, raw_ostream
&OS
,
1131 StringRef ExtSymDefinedIn
) {
1132 if (!ExtSymDefinedIn
.empty())
1133 OS
<< "@M@" << ExtSymDefinedIn
;
1134 OS
<< "@E@" << EnumName
;
1137 void clang::index::generateUSRForEnumConstant(StringRef EnumConstantName
,
1139 OS
<< '@' << EnumConstantName
;
1142 bool clang::index::generateUSRForDecl(const Decl
*D
,
1143 SmallVectorImpl
<char> &Buf
) {
1146 // We don't ignore decls with invalid source locations. Implicit decls, like
1147 // C++'s operator new function, can have invalid locations but it is fine to
1148 // create USRs that can identify them.
1150 // Check if the declaration has explicit external USR specified.
1151 auto *CD
= D
->getCanonicalDecl();
1152 if (auto *ExternalSymAttr
= CD
->getAttr
<ExternalSourceSymbolAttr
>()) {
1153 if (!ExternalSymAttr
->getUSR().empty()) {
1154 llvm::raw_svector_ostream
Out(Buf
);
1155 Out
<< ExternalSymAttr
->getUSR();
1159 USRGenerator
UG(&D
->getASTContext(), Buf
);
1161 return UG
.ignoreResults();
1164 bool clang::index::generateUSRForMacro(const MacroDefinitionRecord
*MD
,
1165 const SourceManager
&SM
,
1166 SmallVectorImpl
<char> &Buf
) {
1169 return generateUSRForMacro(MD
->getName()->getName(), MD
->getLocation(),
1174 bool clang::index::generateUSRForMacro(StringRef MacroName
, SourceLocation Loc
,
1175 const SourceManager
&SM
,
1176 SmallVectorImpl
<char> &Buf
) {
1177 if (MacroName
.empty())
1180 llvm::raw_svector_ostream
Out(Buf
);
1182 // Assume that system headers are sane. Don't put source location
1183 // information into the USR if the macro comes from a system header.
1184 bool ShouldGenerateLocation
= Loc
.isValid() && !SM
.isInSystemHeader(Loc
);
1186 Out
<< getUSRSpacePrefix();
1187 if (ShouldGenerateLocation
)
1188 printLoc(Out
, Loc
, SM
, /*IncludeOffset=*/true);
1194 bool clang::index::generateUSRForType(QualType T
, ASTContext
&Ctx
,
1195 SmallVectorImpl
<char> &Buf
) {
1198 T
= T
.getCanonicalType();
1200 USRGenerator
UG(&Ctx
, Buf
);
1202 return UG
.ignoreResults();
1205 bool clang::index::generateFullUSRForModule(const Module
*Mod
,
1208 return generateFullUSRForTopLevelModuleName(Mod
->Name
, OS
);
1209 if (generateFullUSRForModule(Mod
->Parent
, OS
))
1211 return generateUSRFragmentForModule(Mod
, OS
);
1214 bool clang::index::generateFullUSRForTopLevelModuleName(StringRef ModName
,
1216 OS
<< getUSRSpacePrefix();
1217 return generateUSRFragmentForModuleName(ModName
, OS
);
1220 bool clang::index::generateUSRFragmentForModule(const Module
*Mod
,
1222 return generateUSRFragmentForModuleName(Mod
->Name
, OS
);
1225 bool clang::index::generateUSRFragmentForModuleName(StringRef ModName
,
1227 OS
<< "@M@" << ModName
;