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