15 #include "llvm/ADT/SmallString.h"
16 #include "llvm/Support/Path.h"
17 #include "llvm/Support/raw_ostream.h"
19 using namespace clang;
20 using namespace clang::index;
36 OS << llvm::sys::path::filename(FE->
getName());
45 OS <<
'@' << Decomposed.second;
53 llvm::raw_svector_ostream Out;
58 llvm::DenseMap<const Type *, unsigned> TypeSubstitutions;
72 bool ignoreResults()
const {
return IgnoreResults; }
87 void VisitTagDecl(
const TagDecl *D);
90 void VisitVarDecl(
const VarDecl *D);
102 void VisitUsingDecl(
const UsingDecl *D) {
103 IgnoreResults =
true;
107 IgnoreResults =
true;
111 IgnoreResults =
true;
114 bool ShouldGenerateLocation(
const NamedDecl *D);
117 return D->getParentFunctionOrMethod() !=
nullptr;
122 bool GenLoc(
const Decl *D,
bool IncludeOffset);
131 void GenObjCClass(StringRef cls) {
136 void GenObjCCategory(StringRef cls, StringRef cat) {
141 void GenObjCProperty(StringRef prop,
bool isClassProp) {
146 void GenObjCProtocol(StringRef prot) {
165 bool USRGenerator::EmitDeclName(
const NamedDecl *D) {
166 const unsigned startSize = Buf.size();
168 const unsigned endSize = Buf.size();
169 return startSize == endSize;
172 bool USRGenerator::ShouldGenerateLocation(
const NamedDecl *D) {
175 if (D->getParentFunctionOrMethod())
181 void USRGenerator::VisitDeclContext(
const DeclContext *DC) {
182 if (
const NamedDecl *D = dyn_cast<NamedDecl>(DC))
186 void USRGenerator::VisitFieldDecl(
const FieldDecl *D) {
192 VisitDeclContext(D->getDeclContext());
193 Out << (isa<ObjCIvarDecl>(D) ?
"@" :
"@FI@");
194 if (EmitDeclName(D)) {
196 IgnoreResults =
true;
201 void USRGenerator::VisitFunctionDecl(
const FunctionDecl *D) {
202 if (ShouldGenerateLocation(D) && GenLoc(D, isLocal(D)))
205 VisitDeclContext(D->getDeclContext());
206 bool IsTemplate =
false;
210 VisitTemplateParameterList(FunTmpl->getTemplateParameters());
222 !D->hasAttr<OverloadableAttr>())
228 for (
unsigned I = 0, N = SpecArgs->size();
I != N; ++
I) {
230 VisitTemplateArgument(SpecArgs->get(
I));
235 // Mangle in type information for the arguments.
236 for (auto PD : D->parameters()) {
238 VisitType(PD->getType());
243 // Function templates can be overloaded by return type, for example:
245 // template <class T> typename T::A foo() {}
246 // template <class T> typename T::B foo() {}
249 VisitType(D->getReturnType());
252 if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {
255 if (unsigned quals = MD->getTypeQualifiers())
256 Out << (char)('0
' + quals);
257 switch (MD->getRefQualifier()) {
259 case RQ_LValue: Out << '&
'; break;
260 case RQ_RValue: Out << "&&"; break;
265 void USRGenerator::VisitNamedDecl(const NamedDecl *D) {
266 VisitDeclContext(D->getDeclContext());
269 if (EmitDeclName(D)) {
270 // The string can be empty if the declaration has no name; e.g., it is
271 // the ParmDecl with no name for declaration of a function pointer type,
272 // e.g.: void (*f)(void *);
273 // In this case, don't generate a USR.
274 IgnoreResults =
true;
278 void USRGenerator::VisitVarDecl(
const VarDecl *D) {
282 if (ShouldGenerateLocation(D) && GenLoc(D, isLocal(D)))
285 VisitDeclContext(D->getDeclContext());
295 IgnoreResults =
true;
300 void USRGenerator::VisitNonTypeTemplateParmDecl(
305 void USRGenerator::VisitTemplateTemplateParmDecl(
310 void USRGenerator::VisitNamespaceDecl(
const NamespaceDecl *D) {
316 VisitDeclContext(D->getDeclContext());
330 VisitDeclContext(D->getDeclContext());
336 const DeclContext *container = D->getDeclContext();
345 IgnoreResults =
true;
358 switch (D->getKind()) {
360 llvm_unreachable(
"Invalid ObjC container.");
361 case Decl::ObjCInterface:
362 case Decl::ObjCImplementation:
365 case Decl::ObjCCategory: {
373 IgnoreResults =
true;
379 Out <<
"objc(ext)" << ID->
getName() <<
'@';
383 GenObjCCategory(ID->getName(), CD->
getName());
387 case Decl::ObjCCategoryImpl: {
395 IgnoreResults =
true;
398 GenObjCCategory(ID->getName(), CD->
getName());
401 case Decl::ObjCProtocol:
402 GenObjCProtocol(cast<ObjCProtocolDecl>(D)->getName());
413 Visit(cast<Decl>(D->getDeclContext()));
419 VisitObjCPropertyDecl(PD);
423 IgnoreResults =
true;
426 void USRGenerator::VisitTagDecl(
const TagDecl *D) {
429 if (!isa<EnumDecl>(D) &&
430 ShouldGenerateLocation(D) && GenLoc(D, isLocal(D)))
434 VisitDeclContext(D->getDeclContext());
436 bool AlreadyStarted =
false;
437 if (
const CXXRecordDecl *CXXRecord = dyn_cast<CXXRecordDecl>(D)) {
439 AlreadyStarted =
true;
446 case TTK_Enum: llvm_unreachable(
"enum template");
448 VisitTemplateParameterList(ClassTmpl->getTemplateParameters());
450 = dyn_cast<ClassTemplatePartialSpecializationDecl>(CXXRecord)) {
451 AlreadyStarted =
true;
458 case TTK_Enum: llvm_unreachable(
"enum partial specialization");
460 VisitTemplateParameterList(PartialSpec->getTemplateParameters());
464 if (!AlreadyStarted) {
475 assert(Buf.size() > 0);
476 const unsigned off = Buf.size() - 1;
478 if (EmitDeclName(D)) {
488 if (
auto *ED = dyn_cast<EnumDecl>(D)) {
490 auto enum_range = ED->enumerators();
491 if (enum_range.begin() != enum_range.end()) {
492 Out <<
'@' << **enum_range.begin();
501 = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
504 for (unsigned I = 0, N = Args.size(); I != N; ++I) {
506 VisitTemplateArgument(Args.get(I));
511 void USRGenerator::VisitTypedefDecl(const TypedefDecl *D) {
512 if (ShouldGenerateLocation(D) && GenLoc(D, /*IncludeOffset=*/isLocal(D)))
514 const DeclContext *DC = D->getDeclContext();
515 if (const NamedDecl *DCN = dyn_cast<NamedDecl>(DC))
521 void USRGenerator::VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D) {
522 GenLoc(D, /*IncludeOffset=*/true);
525 bool USRGenerator::GenLoc(const Decl *D, bool IncludeOffset) {
527 return IgnoreResults;
530 // Guard against null declarations in invalid code.
532 IgnoreResults = true;
536 // Use the location of canonical decl.
537 D = D->getCanonicalDecl();
540 IgnoreResults || printLoc(Out, D->getLocStart(),
541 Context->getSourceManager(), IncludeOffset);
543 return IgnoreResults;
546 void USRGenerator::VisitType(QualType T) {
547 // This method mangles in USR information for types. It can possibly
548 // just reuse the naming-mangling logic used by codegen, although the
549 // requirements for USRs might not be the same.
550 ASTContext &Ctx = *Context;
553 T = Ctx.getCanonicalType(T);
554 Qualifiers Q = T.getQualifiers();
563 Out << ((char) ('0
' + qVal));
565 // Mangle in ObjC GC qualifiers?
567 if (const PackExpansionType *Expansion = T->getAs<PackExpansionType>()) {
569 T = Expansion->getPattern();
572 if (const BuiltinType *BT = T->getAs<BuiltinType>()) {
573 unsigned char c = '\0
';
574 switch (BT->getKind()) {
575 case BuiltinType::Void:
577 case BuiltinType::Bool:
579 case BuiltinType::UChar:
581 case BuiltinType::Char16:
583 case BuiltinType::Char32:
585 case BuiltinType::UShort:
587 case BuiltinType::UInt:
589 case BuiltinType::ULong:
591 case BuiltinType::ULongLong:
593 case BuiltinType::UInt128:
595 case BuiltinType::Char_U:
596 case BuiltinType::Char_S:
598 case BuiltinType::SChar:
600 case BuiltinType::WChar_S:
601 case BuiltinType::WChar_U:
603 case BuiltinType::Short:
605 case BuiltinType::Int:
607 case BuiltinType::Long:
609 case BuiltinType::LongLong:
611 case BuiltinType::Int128:
613 case BuiltinType::Half:
615 case BuiltinType::Float:
617 case BuiltinType::Double:
619 case BuiltinType::LongDouble:
621 case BuiltinType::Float128:
623 case BuiltinType::NullPtr:
625 #define BUILTIN_TYPE(Id, SingletonId)
626 #define PLACEHOLDER_TYPE(Id, SingletonId) case BuiltinType::Id:
627 #include "clang/AST/BuiltinTypes.def"
628 case BuiltinType::Dependent:
629 #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
630 case BuiltinType::Id:
631 #include "clang/Basic/OpenCLImageTypes.def"
632 case BuiltinType::OCLEvent:
633 case BuiltinType::OCLClkEvent:
634 case BuiltinType::OCLQueue:
635 case BuiltinType::OCLNDRange:
636 case BuiltinType::OCLReserveID:
637 case BuiltinType::OCLSampler:
638 IgnoreResults = true;
640 case BuiltinType::ObjCId:
642 case BuiltinType::ObjCClass:
644 case BuiltinType::ObjCSel:
651 // If we have already seen this (non-built-in) type, use a substitution
653 llvm::DenseMap<const Type *, unsigned>::iterator Substitution
654 = TypeSubstitutions.find(T.getTypePtr());
655 if (Substitution != TypeSubstitutions.end()) {
656 Out << 'S' << Substitution->second << '_
';
659 // Record this as a substitution.
660 unsigned Number = TypeSubstitutions.size();
661 TypeSubstitutions[T.getTypePtr()] = Number;
664 if (const PointerType *PT = T->getAs<PointerType>()) {
666 T = PT->getPointeeType();
669 if (const ObjCObjectPointerType *OPT = T->getAs<ObjCObjectPointerType>()) {
671 T = OPT->getPointeeType();
674 if (const RValueReferenceType *RT = T->getAs<RValueReferenceType>()) {
676 T = RT->getPointeeType();
679 if (const ReferenceType *RT = T->getAs<ReferenceType>()) {
681 T = RT->getPointeeType();
684 if (const FunctionProtoType *FT = T->getAs<FunctionProtoType>()) {
686 VisitType(FT->getReturnType());
687 for (const auto &I : FT->param_types())
689 if (FT->isVariadic())
693 if (const BlockPointerType *BT = T->getAs<BlockPointerType>()) {
695 T = BT->getPointeeType();
698 if (const ComplexType *CT = T->getAs<ComplexType>()) {
700 T = CT->getElementType();
703 if (const TagType *TT = T->getAs<TagType>()) {
705 VisitTagDecl(TT->getDecl());
708 if (const ObjCInterfaceType *OIT = T->getAs<ObjCInterfaceType>()) {
710 VisitObjCInterfaceDecl(OIT->getDecl());
713 if (const ObjCObjectType *OIT = T->getAs<ObjCObjectType>()) {
715 VisitType(OIT->getBaseType());
716 for (auto *Prot : OIT->getProtocols())
717 VisitObjCProtocolDecl(Prot);
720 if (const TemplateTypeParmType *TTP = T->getAs<TemplateTypeParmType>()) {
721 Out << 't
' << TTP->getDepth() << '.
' << TTP->getIndex();
724 if (const TemplateSpecializationType *Spec
725 = T->getAs<TemplateSpecializationType>()) {
727 VisitTemplateName(Spec->getTemplateName());
728 Out << Spec->getNumArgs();
729 for (unsigned I = 0, N = Spec->getNumArgs(); I != N; ++I)
730 VisitTemplateArgument(Spec->getArg(I));
733 if (const DependentNameType *DNT = T->getAs<DependentNameType>()) {
735 // FIXME: Encode the qualifier, don't just print it.
738 PO.SuppressUnwrittenScope =
true;
739 PO.ConstantArraySizeAsWritten =
false;
740 PO.AnonymousTagLocations =
false;
741 DNT->getQualifier()->print(Out, PO);
742 Out <<
':' << DNT->getIdentifier()->getName();
746 T = InjT->getInjectedSpecializationType();
756 void USRGenerator::VisitTemplateParameterList(
760 Out << '>
' << Params->size();
761 for (TemplateParameterList::const_iterator P = Params->begin(),
762 PEnd = Params->end();
765 if (isa<TemplateTypeParmDecl>(*P)) {
766 if (cast<TemplateTypeParmDecl>(*P)->isParameterPack())
772 if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(*P)) {
773 if (NTTP->isParameterPack())
776 VisitType(NTTP->getType());
780 TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*P);
781 if (TTP->isParameterPack())
784 VisitTemplateParameterList(TTP->getTemplateParameters());
788 void USRGenerator::VisitTemplateName(TemplateName Name) {
789 if (TemplateDecl *Template = Name.getAsTemplateDecl()) {
790 if (TemplateTemplateParmDecl *TTP
791 = dyn_cast<TemplateTemplateParmDecl>(Template)) {
792 Out << 't
' << TTP->getDepth() << '.
' << TTP->getIndex();
800 // FIXME: Visit dependent template names.
803 void USRGenerator::VisitTemplateArgument(const TemplateArgument &Arg) {
804 switch (Arg.getKind()) {
805 case TemplateArgument::Null:
808 case TemplateArgument::Declaration:
809 Visit(Arg.getAsDecl());
812 case TemplateArgument::NullPtr:
815 case TemplateArgument::TemplateExpansion:
816 Out << 'P
'; // pack expansion of...
818 case TemplateArgument::Template:
819 VisitTemplateName(Arg.getAsTemplateOrTemplatePattern());
822 case TemplateArgument::Expression:
823 // FIXME: Visit expressions.
826 case TemplateArgument::Pack:
827 Out << 'p
' << Arg.pack_size();
828 for (const auto &P : Arg.pack_elements())
829 VisitTemplateArgument(P);
832 case TemplateArgument::Type:
833 VisitType(Arg.getAsType());
836 case TemplateArgument::Integral:
838 VisitType(Arg.getIntegralType());
839 Out << Arg.getAsIntegral();
844 //===----------------------------------------------------------------------===//
845 // USR generation functions.
846 //===----------------------------------------------------------------------===//
848 void clang::index::generateUSRForObjCClass(StringRef Cls, raw_ostream &OS) {
849 OS << "objc(cs)" << Cls;
852 void clang::index::generateUSRForObjCCategory(StringRef Cls, StringRef Cat,
854 OS << "objc(cy)" << Cls << '@
' << Cat;
857 void clang::index::generateUSRForObjCIvar(StringRef Ivar, raw_ostream &OS) {
861 void clang::index::generateUSRForObjCMethod(StringRef Sel,
862 bool IsInstanceMethod,
864 OS << (IsInstanceMethod ? "(im)" : "(cm)") << Sel;
867 void clang::index::generateUSRForObjCProperty(StringRef Prop, bool isClassProp,
869 OS << (isClassProp ? "(cpy)" : "(py)") << Prop;
872 void clang::index::generateUSRForObjCProtocol(StringRef Prot, raw_ostream &OS) {
873 OS << "objc(pl)" << Prot;
876 bool clang::index::generateUSRForDecl(const Decl *D,
877 SmallVectorImpl<char> &Buf) {
878 // Don't generate USRs
for things with invalid locations.
882 USRGenerator UG(&D->getASTContext(), Buf);
884 return UG.ignoreResults();
894 llvm::raw_svector_ostream Out(Buf);
902 if (ShouldGenerateLocation)
Defines the clang::ASTContext interface.
FunctionDecl - An instance of this class is created to represent a function declaration or definition...
StringRef getName() const
getName - Get the name of identifier for this declaration as a StringRef.
bool generateUSRForMacro(const MacroDefinitionRecord *MD, const SourceManager &SM, SmallVectorImpl< char > &Buf)
Generate a USR for a macro, including the USR prefix.
A (possibly-)qualified type.
ObjCInterfaceDecl * getClassInterface()
ObjCInterfaceDecl * getClassInterface()
bool isClassProperty() const
TypedefDecl - Represents the declaration of a typedef-name via the 'typedef' type specifier...
CXXRecordDecl * getTemplatedDecl() const
Get the underlying class declarations of the template.
Defines the C++ template declaration subclasses.
NamespaceDecl - Represent a C++ namespace.
VarDecl - An instance of this class is created to represent a variable declaration or definition...
The "__interface" keyword.
ObjCMethodDecl - Represents an instance or class method declaration.
Stores a list of template parameters for a TemplateDecl and its derived classes.
Describes how types, statements, expressions, and declarations should be printed. ...
bool isExternC() const
Determines whether this function is a function with external, C linkage.
Represents a class template specialization, which refers to a class template with a given set of temp...
class LLVM_ALIGNAS(8) DependentTemplateSpecializationType const IdentifierInfo * Name
Represents a template specialization type whose template cannot be resolved, e.g. ...
static StringRef getUSRSpacePrefix()
const TemplateArgumentList * getTemplateSpecializationArgs() const
Retrieve the template arguments used to produce this function template specialization from the primar...
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Record the location of a macro definition.
static bool printLoc(llvm::raw_ostream &OS, SourceLocation Loc, const SourceManager &SM, bool IncludeOffset)
FieldDecl - An instance of this class is created by Sema::ActOnField to represent a member of a struc...
FunctionDecl * getTemplatedDecl() const
Get the underlying function declaration of the template.
void print(raw_ostream &OS, const PrintingPolicy &Policy)
bool isAnonymousNamespace() const
Returns true if this is an anonymous namespace declaration.
TagKind getTagKind() const
bool IsClassExtension() const
Represents a C++ using-declaration.
ObjCContainerDecl - Represents a container for method declarations.
const LangOptions & getLangOpts() const
Represents an Objective-C protocol declaration.
FunctionTemplateDecl * getDescribedFunctionTemplate() const
Retrieves the function template that is described by this function declaration.
Represents an ObjC class declaration.
Represents a linkage specification.
detail::InMemoryDirectory::const_iterator I
unsigned SuppressTemplateArgsInCXXConstructors
When true, suppresses printing template arguments in names of C++ constructors.
ObjCPropertyImplDecl - Represents implementation declaration of a property in a class or category imp...
const FileEntry * getFileEntryForID(FileID FID) const
Returns the FileEntry record for the provided FileID.
SourceLocation getLocStart() const LLVM_READONLY
StringRef getName() const
Return the actual identifier string.
Declaration of a template type parameter.
NonTypeTemplateParmDecl - Declares a non-type template parameter, e.g., "Size" in.
Represents a C++ template name within the type system.
bool isInSystemHeader(SourceLocation Loc) const
Returns if a SourceLocation is in a system header.
bool isInstanceMethod() const
bool isExternallyVisible() const
DeclarationName getDeclName() const
getDeclName - Get the actual, stored name of the declaration, which may be a special name...
TemplateTemplateParmDecl - Declares a template template parameter, e.g., "T" in.
TypedefNameDecl * getTypedefNameForAnonDecl() const
bool isEmbeddedInDeclarator() const
const char * getName() const
Encodes a location in the source.
TagDecl - Represents the declaration of a struct/union/class/enum.
TagDecl * getCanonicalDecl() override
Represents a dependent using declaration which was not marked with typename.
Cached information about one file (either on disk or in the virtual file system). ...
void printName(raw_ostream &os) const
ObjCCategoryDecl - Represents a category declaration.
const ObjCInterfaceDecl * getClassInterface() const
Represents one property declaration in an Objective-C interface.
bool SuppressTagKeyword
Whether type printing should skip printing the tag keyword.
const IdentifierInfo * getName() const
Retrieve the name of the macro being defined.
The injected class name of a C++ class template or class template partial specialization.
Base class for declarations which introduce a typedef-name.
Represents a template argument.
void generateUSRForObjCProtocol(StringRef Prot, raw_ostream &OS)
Generate a USR fragment for an Objective-C protocol.
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
bool isFreeStanding() const
Represents a dependent using declaration which was marked with typename.
DeclarationName - The name of a declaration.
Selector getSelector() const
const T * getAs() const
Member-template getAs<specific type>'.
SourceManager & getSourceManager()
A template argument list.
ObjCPropertyDecl * getPropertyDecl() const
Represents a C++ struct/union/class.
StringRef getName() const
getName - Get the name of identifier for the class interface associated with this implementation as a...
void generateUSRForObjCProperty(StringRef Prop, bool isClassProp, raw_ostream &OS)
Generate a USR fragment for an Objective-C property.
Declaration of a class template.
void generateUSRForObjCClass(StringRef Cls, raw_ostream &OS)
Generate a USR fragment for an Objective-C class.
SourceLocation getLocation() const
Retrieve the location of the macro name in the definition.
void generateUSRForObjCCategory(StringRef Cls, StringRef Cat, raw_ostream &OS)
Generate a USR fragment for an Objective-C class category.
const ObjCInterfaceDecl * getObjContainingInterface(const NamedDecl *ND) const
Returns the Objective-C interface that ND belongs to if it is an Objective-C method/property/ivar etc...
NamedDecl - This represents a decl with a name.
SourceLocation getExpansionLoc(SourceLocation Loc) const
Given a SourceLocation object Loc, return the expansion location referenced by the ID...
Represents a C++ namespace alias.
std::pair< FileID, unsigned > getDecomposedLoc(SourceLocation Loc) const
Decompose the specified location into a raw FileID + Offset pair.
Represents C++ using-directive.
A simple visitor class that helps create declaration visitors.
ObjCCategoryImplDecl - An object of this class encapsulates a category @implementation declaration...
This class handles loading and caching of source files into memory.
Declaration of a template function.