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()) {
522 case TagTypeKind::Interface
:
523 case TagTypeKind::Class
:
524 case TagTypeKind::Struct
:
527 case TagTypeKind::Union
:
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
:
544 case TagTypeKind::Union
:
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
:
561 case TagTypeKind::Union
:
564 case TagTypeKind::Enum
:
571 assert(Buf
.size() > 0);
572 const unsigned off
= Buf
.size() - 1;
574 if (EmitDeclName(D
)) {
575 if (const TypedefNameDecl
*TD
= D
->getTypedefNameForAnonDecl()) {
579 if (D
->isEmbeddedInDeclarator() && !D
->isFreeStanding()) {
580 printLoc(Out
, D
->getLocation(), Context
->getSourceManager(), true);
583 if (auto *ED
= dyn_cast
<EnumDecl
>(D
)) {
584 // Distinguish USRs of anonymous enums by using their first
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();
600 for (unsigned I
= 0, N
= Args
.size(); I
!= N
; ++I
) {
602 VisitTemplateArgument(Args
.get(I
));
607 void USRGenerator::VisitTypedefDecl(const TypedefDecl
*D
) {
608 if (ShouldGenerateLocation(D
) && GenLoc(D
, /*IncludeOffset=*/isLocal(D
)))
610 const DeclContext
*DC
= D
->getDeclContext();
611 if (const NamedDecl
*DCN
= dyn_cast
<NamedDecl
>(DC
))
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
) {
629 return IgnoreResults
;
632 // Guard against null declarations in invalid code.
634 IgnoreResults
= true;
638 // Use the location of canonical decl.
639 D
= D
->getCanonicalDecl();
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;
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
;
665 T
= Ctx
.getCanonicalType(T
);
666 Qualifiers Q
= T
.getQualifiers();
675 Out
<< ((char) ('0' + qVal
));
677 // Mangle in ObjC GC qualifiers?
679 if (const PackExpansionType
*Expansion
= T
->getAs
<PackExpansionType
>()) {
681 T
= Expansion
->getPattern();
684 if (const BuiltinType
*BT
= T
->getAs
<BuiltinType
>()) {
685 switch (BT
->getKind()) {
686 case BuiltinType::Void
:
688 case BuiltinType::Bool
:
690 case BuiltinType::UChar
:
692 case BuiltinType::Char8
:
694 case BuiltinType::Char16
:
696 case BuiltinType::Char32
:
698 case BuiltinType::UShort
:
700 case BuiltinType::UInt
:
702 case BuiltinType::ULong
:
704 case BuiltinType::ULongLong
:
706 case BuiltinType::UInt128
:
708 case BuiltinType::Char_U
:
709 case BuiltinType::Char_S
:
711 case BuiltinType::SChar
:
713 case BuiltinType::WChar_S
:
714 case BuiltinType::WChar_U
:
716 case BuiltinType::Short
:
718 case BuiltinType::Int
:
720 case BuiltinType::Long
:
722 case BuiltinType::LongLong
:
724 case BuiltinType::Int128
:
726 case BuiltinType::Float16
:
727 case BuiltinType::Half
:
729 case BuiltinType::Float
:
731 case BuiltinType::Double
:
733 case BuiltinType::LongDouble
:
735 case BuiltinType::Float128
:
737 case BuiltinType::NullPtr
:
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
:
825 case BuiltinType::ObjCClass
:
827 case BuiltinType::ObjCSel
:
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;
841 // If we have already seen this (non-built-in) type, use a substitution
843 llvm::DenseMap
<const Type
*, unsigned>::iterator Substitution
844 = TypeSubstitutions
.find(T
.getTypePtr());
845 if (Substitution
!= TypeSubstitutions
.end()) {
846 Out
<< 'S' << Substitution
->second
<< '_';
849 // Record this as a substitution.
850 unsigned Number
= TypeSubstitutions
.size();
851 TypeSubstitutions
[T
.getTypePtr()] = Number
;
854 if (const PointerType
*PT
= T
->getAs
<PointerType
>()) {
856 T
= PT
->getPointeeType();
859 if (const ObjCObjectPointerType
*OPT
= T
->getAs
<ObjCObjectPointerType
>()) {
861 T
= OPT
->getPointeeType();
864 if (const RValueReferenceType
*RT
= T
->getAs
<RValueReferenceType
>()) {
866 T
= RT
->getPointeeType();
869 if (const ReferenceType
*RT
= T
->getAs
<ReferenceType
>()) {
871 T
= RT
->getPointeeType();
874 if (const FunctionProtoType
*FT
= T
->getAs
<FunctionProtoType
>()) {
876 VisitType(FT
->getReturnType());
878 for (const auto &I
: FT
->param_types()) {
883 if (FT
->isVariadic())
887 if (const BlockPointerType
*BT
= T
->getAs
<BlockPointerType
>()) {
889 T
= BT
->getPointeeType();
892 if (const ComplexType
*CT
= T
->getAs
<ComplexType
>()) {
894 T
= CT
->getElementType();
897 if (const TagType
*TT
= T
->getAs
<TagType
>()) {
899 VisitTagDecl(TT
->getDecl());
902 if (const ObjCInterfaceType
*OIT
= T
->getAs
<ObjCInterfaceType
>()) {
904 VisitObjCInterfaceDecl(OIT
->getDecl());
907 if (const ObjCObjectType
*OIT
= T
->getAs
<ObjCObjectType
>()) {
909 VisitType(OIT
->getBaseType());
910 for (auto *Prot
: OIT
->getProtocols())
911 VisitObjCProtocolDecl(Prot
);
914 if (const TemplateTypeParmType
*TTP
= T
->getAs
<TemplateTypeParmType
>()) {
915 Out
<< 't' << TTP
->getDepth() << '.' << TTP
->getIndex();
918 if (const TemplateSpecializationType
*Spec
919 = T
->getAs
<TemplateSpecializationType
>()) {
921 VisitTemplateName(Spec
->getTemplateName());
922 Out
<< Spec
->template_arguments().size();
923 for (const auto &Arg
: Spec
->template_arguments())
924 VisitTemplateArgument(Arg
);
927 if (const DependentNameType
*DNT
= T
->getAs
<DependentNameType
>()) {
929 printQualifier(Out
, Ctx
, DNT
->getQualifier());
930 Out
<< ':' << DNT
->getIdentifier()->getName();
933 if (const InjectedClassNameType
*InjT
= T
->getAs
<InjectedClassNameType
>()) {
934 T
= InjT
->getInjectedSpecializationType();
937 if (const auto *VT
= T
->getAs
<VectorType
>()) {
938 Out
<< (T
->isExtVectorType() ? ']' : '[');
939 Out
<< VT
->getNumElements();
940 T
= VT
->getElementType();
943 if (const auto *const AT
= dyn_cast
<ArrayType
>(T
)) {
945 switch (AT
->getSizeModifier()) {
946 case ArraySizeModifier::Static
:
949 case ArraySizeModifier::Star
:
952 case ArraySizeModifier::Normal
:
956 if (const auto *const CAT
= dyn_cast
<ConstantArrayType
>(T
))
957 Out
<< CAT
->getSize();
959 T
= AT
->getElementType();
969 void USRGenerator::VisitTemplateParameterList(
970 const TemplateParameterList
*Params
) {
973 Out
<< '>' << Params
->size();
974 for (TemplateParameterList::const_iterator P
= Params
->begin(),
975 PEnd
= Params
->end();
978 if (isa
<TemplateTypeParmDecl
>(*P
)) {
979 if (cast
<TemplateTypeParmDecl
>(*P
)->isParameterPack())
985 if (NonTypeTemplateParmDecl
*NTTP
= dyn_cast
<NonTypeTemplateParmDecl
>(*P
)) {
986 if (NTTP
->isParameterPack())
989 VisitType(NTTP
->getType());
993 TemplateTemplateParmDecl
*TTP
= cast
<TemplateTemplateParmDecl
>(*P
);
994 if (TTP
->isParameterPack())
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();
1013 // FIXME: Visit dependent template names.
1016 void USRGenerator::VisitTemplateArgument(const TemplateArgument
&Arg
) {
1017 switch (Arg
.getKind()) {
1018 case TemplateArgument::Null
:
1021 case TemplateArgument::Declaration
:
1022 Visit(Arg
.getAsDecl());
1025 case TemplateArgument::NullPtr
:
1028 case TemplateArgument::TemplateExpansion
:
1029 Out
<< 'P'; // pack expansion of...
1031 case TemplateArgument::Template
:
1032 VisitTemplateName(Arg
.getAsTemplateOrTemplatePattern());
1035 case TemplateArgument::Expression
:
1036 // FIXME: Visit expressions.
1039 case TemplateArgument::Pack
:
1040 Out
<< 'p' << Arg
.pack_size();
1041 for (const auto &P
: Arg
.pack_elements())
1042 VisitTemplateArgument(P
);
1045 case TemplateArgument::Type
:
1046 VisitType(Arg
.getAsType());
1049 case TemplateArgument::Integral
:
1051 VisitType(Arg
.getIntegralType());
1052 Out
<< Arg
.getAsIntegral();
1057 void USRGenerator::VisitUnresolvedUsingValueDecl(const UnresolvedUsingValueDecl
*D
) {
1058 if (ShouldGenerateLocation(D
) && GenLoc(D
, /*IncludeOffset=*/isLocal(D
)))
1060 VisitDeclContext(D
->getDeclContext());
1062 printQualifier(Out
, D
->getASTContext(), D
->getQualifier());
1066 void USRGenerator::VisitUnresolvedUsingTypenameDecl(const UnresolvedUsingTypenameDecl
*D
) {
1067 if (ShouldGenerateLocation(D
) && GenLoc(D
, /*IncludeOffset=*/isLocal(D
)))
1069 VisitDeclContext(D
->getDeclContext());
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
)))
1078 VisitDeclContext(D
->getDeclContext());
1083 void USRGenerator::VisitMSGuidDecl(const MSGuidDecl
*D
) {
1084 VisitDeclContext(D
->getDeclContext());
1086 D
->NamedDecl::printName(Out
);
1089 //===----------------------------------------------------------------------===//
1090 // USR generation functions.
1091 //===----------------------------------------------------------------------===//
1093 static void combineClassAndCategoryExtContainers(StringRef ClsSymDefinedIn
,
1094 StringRef CatSymDefinedIn
,
1096 if (ClsSymDefinedIn
.empty() && CatSymDefinedIn
.empty())
1098 if (CatSymDefinedIn
.empty()) {
1099 OS
<< "@M@" << ClsSymDefinedIn
<< '@';
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
,
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
) {
1128 void clang::index::generateUSRForObjCMethod(StringRef Sel
,
1129 bool IsInstanceMethod
,
1131 OS
<< (IsInstanceMethod
? "(im)" : "(cm)") << Sel
;
1134 void clang::index::generateUSRForObjCProperty(StringRef Prop
, bool isClassProp
,
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
,
1155 OS
<< '@' << EnumConstantName
;
1158 bool clang::index::generateUSRForDecl(const Decl
*D
,
1159 SmallVectorImpl
<char> &Buf
) {
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();
1175 USRGenerator
UG(&D
->getASTContext(), Buf
);
1177 return UG
.ignoreResults();
1180 bool clang::index::generateUSRForMacro(const MacroDefinitionRecord
*MD
,
1181 const SourceManager
&SM
,
1182 SmallVectorImpl
<char> &Buf
) {
1185 return generateUSRForMacro(MD
->getName()->getName(), MD
->getLocation(),
1190 bool clang::index::generateUSRForMacro(StringRef MacroName
, SourceLocation Loc
,
1191 const SourceManager
&SM
,
1192 SmallVectorImpl
<char> &Buf
) {
1193 if (MacroName
.empty())
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);
1210 bool clang::index::generateUSRForType(QualType T
, ASTContext
&Ctx
,
1211 SmallVectorImpl
<char> &Buf
) {
1214 T
= T
.getCanonicalType();
1216 USRGenerator
UG(&Ctx
, Buf
);
1218 return UG
.ignoreResults();
1221 bool clang::index::generateFullUSRForModule(const Module
*Mod
,
1224 return generateFullUSRForTopLevelModuleName(Mod
->Name
, OS
);
1225 if (generateFullUSRForModule(Mod
->Parent
, OS
))
1227 return generateUSRFragmentForModule(Mod
, OS
);
1230 bool clang::index::generateFullUSRForTopLevelModuleName(StringRef ModName
,
1232 OS
<< getUSRSpacePrefix();
1233 return generateUSRFragmentForModuleName(ModName
, OS
);
1236 bool clang::index::generateUSRFragmentForModule(const Module
*Mod
,
1238 return generateUSRFragmentForModuleName(Mod
->Name
, OS
);
1241 bool clang::index::generateUSRFragmentForModuleName(StringRef ModName
,
1243 OS
<< "@M@" << ModName
;