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);
100 IgnoreResults =
true;
103 IgnoreResults =
true;
106 IgnoreResults =
true;
109 bool ShouldGenerateLocation(
const NamedDecl *D);
117 bool GenLoc(
const Decl *D,
bool IncludeOffset);
126 void GenObjCClass(StringRef cls) {
130 void GenObjCCategory(StringRef cls, StringRef cat) {
134 void GenObjCProperty(StringRef prop) {
138 void GenObjCProtocol(StringRef prot) {
158 bool USRGenerator::EmitDeclName(
const NamedDecl *D) {
160 const unsigned startSize = Buf.size();
163 const unsigned endSize = Buf.size();
164 return startSize == endSize;
167 bool USRGenerator::ShouldGenerateLocation(
const NamedDecl *D) {
176 void USRGenerator::VisitDeclContext(
const DeclContext *DC) {
177 if (
const NamedDecl *D = dyn_cast<NamedDecl>(DC))
181 void USRGenerator::VisitFieldDecl(
const FieldDecl *D) {
188 Out << (isa<ObjCIvarDecl>(D) ?
"@" :
"@FI@");
189 if (EmitDeclName(D)) {
191 IgnoreResults =
true;
196 void USRGenerator::VisitFunctionDecl(
const FunctionDecl *D) {
197 if (ShouldGenerateLocation(D) && GenLoc(D, isLocal(D)))
201 bool IsTemplate =
false;
205 VisitTemplateParameterList(FunTmpl->getTemplateParameters());
217 for (
unsigned I = 0, N = SpecArgs->size(); I != N; ++I) {
219 VisitTemplateArgument(SpecArgs->get(I));
224 // Mangle in type information for the arguments.
225 for (auto PD : D->params()) {
227 VisitType(PD->getType());
232 // Function templates can be overloaded by return type, for example:
234 // template <class T> typename T::A foo() {}
235 // template <class T> typename T::B foo() {}
238 VisitType(D->getReturnType());
241 if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {
244 if (unsigned quals = MD->getTypeQualifiers())
245 Out << (char)('0
' + quals);
246 switch (MD->getRefQualifier()) {
248 case RQ_LValue: Out << '&
'; break;
249 case RQ_RValue: Out << "&&"; break;
254 void USRGenerator::VisitNamedDecl(const NamedDecl *D) {
255 VisitDeclContext(D->getDeclContext());
258 if (EmitDeclName(D)) {
259 // The string can be empty if the declaration has no name; e.g., it is
260 // the ParmDecl with no name for declaration of a function pointer type,
261 // e.g.: void (*f)(void *);
262 // In this case, don't generate a USR.
263 IgnoreResults =
true;
267 void USRGenerator::VisitVarDecl(
const VarDecl *D) {
271 if (ShouldGenerateLocation(D) && GenLoc(D, isLocal(D)))
284 IgnoreResults =
true;
289 void USRGenerator::VisitNonTypeTemplateParmDecl(
295 void USRGenerator::VisitTemplateTemplateParmDecl(
301 void USRGenerator::VisitNamespaceDecl(
const NamespaceDecl *D) {
336 IgnoreResults =
true;
351 llvm_unreachable(
"Invalid ObjC container.");
352 case Decl::ObjCInterface:
353 case Decl::ObjCImplementation:
356 case Decl::ObjCCategory: {
364 IgnoreResults =
true;
370 Out <<
"objc(ext)" << ID->
getName() <<
'@';
374 GenObjCCategory(ID->getName(), CD->
getName());
378 case Decl::ObjCCategoryImpl: {
386 IgnoreResults =
true;
389 GenObjCCategory(ID->getName(), CD->
getName());
392 case Decl::ObjCProtocol:
393 GenObjCProtocol(cast<ObjCProtocolDecl>(D)->getName());
410 VisitObjCPropertyDecl(PD);
414 IgnoreResults =
true;
417 void USRGenerator::VisitTagDecl(
const TagDecl *D) {
420 if (ShouldGenerateLocation(D) && GenLoc(D, isLocal(D)))
426 bool AlreadyStarted =
false;
427 if (
const CXXRecordDecl *CXXRecord = dyn_cast<CXXRecordDecl>(D)) {
429 AlreadyStarted =
true;
436 case TTK_Enum: llvm_unreachable(
"enum template");
438 VisitTemplateParameterList(ClassTmpl->getTemplateParameters());
440 = dyn_cast<ClassTemplatePartialSpecializationDecl>(CXXRecord)) {
441 AlreadyStarted =
true;
448 case TTK_Enum: llvm_unreachable(
"enum partial specialization");
450 VisitTemplateParameterList(PartialSpec->getTemplateParameters());
454 if (!AlreadyStarted) {
466 assert(Buf.size() > 0);
467 const unsigned off = Buf.size() - 1;
469 if (EmitDeclName(D)) {
484 = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
487 for (unsigned I = 0, N = Args.size(); I != N; ++I) {
489 VisitTemplateArgument(Args.get(I));
494 void USRGenerator::VisitTypedefDecl(const TypedefDecl *D) {
495 if (ShouldGenerateLocation(D) && GenLoc(D, /*IncludeOffset=*/isLocal(D)))
497 const DeclContext *DC = D->getDeclContext();
498 if (const NamedDecl *DCN = dyn_cast<NamedDecl>(DC))
504 void USRGenerator::VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D) {
505 GenLoc(D, /*IncludeOffset=*/true);
509 bool USRGenerator::GenLoc(const Decl *D, bool IncludeOffset) {
511 return IgnoreResults;
514 // Guard against null declarations in invalid code.
516 IgnoreResults = true;
520 // Use the location of canonical decl.
521 D = D->getCanonicalDecl();
524 IgnoreResults || printLoc(Out, D->getLocStart(),
525 Context->getSourceManager(), IncludeOffset);
527 return IgnoreResults;
530 void USRGenerator::VisitType(QualType T) {
531 // This method mangles in USR information for types. It can possibly
532 // just reuse the naming-mangling logic used by codegen, although the
533 // requirements for USRs might not be the same.
534 ASTContext &Ctx = *Context;
537 T = Ctx.getCanonicalType(T);
538 Qualifiers Q = T.getQualifiers();
547 Out << ((char) ('0
' + qVal));
549 // Mangle in ObjC GC qualifiers?
551 if (const PackExpansionType *Expansion = T->getAs<PackExpansionType>()) {
553 T = Expansion->getPattern();
556 if (const BuiltinType *BT = T->getAs<BuiltinType>()) {
557 unsigned char c = '\0
';
558 switch (BT->getKind()) {
559 case BuiltinType::Void:
561 case BuiltinType::Bool:
563 case BuiltinType::UChar:
565 case BuiltinType::Char16:
567 case BuiltinType::Char32:
569 case BuiltinType::UShort:
571 case BuiltinType::UInt:
573 case BuiltinType::ULong:
575 case BuiltinType::ULongLong:
577 case BuiltinType::UInt128:
579 case BuiltinType::Char_U:
580 case BuiltinType::Char_S:
582 case BuiltinType::SChar:
584 case BuiltinType::WChar_S:
585 case BuiltinType::WChar_U:
587 case BuiltinType::Short:
589 case BuiltinType::Int:
591 case BuiltinType::Long:
593 case BuiltinType::LongLong:
595 case BuiltinType::Int128:
597 case BuiltinType::Half:
599 case BuiltinType::Float:
601 case BuiltinType::Double:
603 case BuiltinType::LongDouble:
605 case BuiltinType::NullPtr:
607 #define BUILTIN_TYPE(Id, SingletonId)
608 #define PLACEHOLDER_TYPE(Id, SingletonId) case BuiltinType::Id:
609 #include "clang/AST/BuiltinTypes.def"
610 case BuiltinType::Dependent:
611 case BuiltinType::OCLImage1d:
612 case BuiltinType::OCLImage1dArray:
613 case BuiltinType::OCLImage1dBuffer:
614 case BuiltinType::OCLImage2d:
615 case BuiltinType::OCLImage2dArray:
616 case BuiltinType::OCLImage3d:
617 case BuiltinType::OCLEvent:
618 case BuiltinType::OCLSampler:
619 IgnoreResults = true;
621 case BuiltinType::ObjCId:
623 case BuiltinType::ObjCClass:
625 case BuiltinType::ObjCSel:
632 // If we have already seen this (non-built-in) type, use a substitution
634 llvm::DenseMap<const Type *, unsigned>::iterator Substitution
635 = TypeSubstitutions.find(T.getTypePtr());
636 if (Substitution != TypeSubstitutions.end()) {
637 Out << 'S' << Substitution->second << '_
';
640 // Record this as a substitution.
641 unsigned Number = TypeSubstitutions.size();
642 TypeSubstitutions[T.getTypePtr()] = Number;
645 if (const PointerType *PT = T->getAs<PointerType>()) {
647 T = PT->getPointeeType();
650 if (const RValueReferenceType *RT = T->getAs<RValueReferenceType>()) {
652 T = RT->getPointeeType();
655 if (const ReferenceType *RT = T->getAs<ReferenceType>()) {
657 T = RT->getPointeeType();
660 if (const FunctionProtoType *FT = T->getAs<FunctionProtoType>()) {
662 VisitType(FT->getReturnType());
663 for (const auto &I : FT->param_types())
665 if (FT->isVariadic())
669 if (const BlockPointerType *BT = T->getAs<BlockPointerType>()) {
671 T = BT->getPointeeType();
674 if (const ComplexType *CT = T->getAs<ComplexType>()) {
676 T = CT->getElementType();
679 if (const TagType *TT = T->getAs<TagType>()) {
681 VisitTagDecl(TT->getDecl());
684 if (const TemplateTypeParmType *TTP = T->getAs<TemplateTypeParmType>()) {
685 Out << 't
' << TTP->getDepth() << '.
' << TTP->getIndex();
688 if (const TemplateSpecializationType *Spec
689 = T->getAs<TemplateSpecializationType>()) {
691 VisitTemplateName(Spec->getTemplateName());
692 Out << Spec->getNumArgs();
693 for (unsigned I = 0, N = Spec->getNumArgs(); I != N; ++I)
694 VisitTemplateArgument(Spec->getArg(I));
697 if (const DependentNameType *DNT = T->getAs<DependentNameType>()) {
699 // FIXME: Encode the qualifier, don't just print it.
702 PO.SuppressUnwrittenScope =
true;
703 PO.ConstantArraySizeAsWritten =
false;
704 PO.AnonymousTagLocations =
false;
705 DNT->getQualifier()->print(Out, PO);
706 Out <<
':' << DNT->getIdentifier()->getName();
710 T = InjT->getInjectedSpecializationType();
720 void USRGenerator::VisitTemplateParameterList(
724 Out << '>
' << Params->size();
725 for (TemplateParameterList::const_iterator P = Params->begin(),
726 PEnd = Params->end();
729 if (isa<TemplateTypeParmDecl>(*P)) {
730 if (cast<TemplateTypeParmDecl>(*P)->isParameterPack())
736 if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(*P)) {
737 if (NTTP->isParameterPack())
740 VisitType(NTTP->getType());
744 TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*P);
745 if (TTP->isParameterPack())
748 VisitTemplateParameterList(TTP->getTemplateParameters());
752 void USRGenerator::VisitTemplateName(TemplateName Name) {
753 if (TemplateDecl *Template = Name.getAsTemplateDecl()) {
754 if (TemplateTemplateParmDecl *TTP
755 = dyn_cast<TemplateTemplateParmDecl>(Template)) {
756 Out << 't
' << TTP->getDepth() << '.
' << TTP->getIndex();
764 // FIXME: Visit dependent template names.
767 void USRGenerator::VisitTemplateArgument(const TemplateArgument &Arg) {
768 switch (Arg.getKind()) {
769 case TemplateArgument::Null:
772 case TemplateArgument::Declaration:
773 Visit(Arg.getAsDecl());
776 case TemplateArgument::NullPtr:
779 case TemplateArgument::TemplateExpansion:
780 Out << 'P
'; // pack expansion of...
782 case TemplateArgument::Template:
783 VisitTemplateName(Arg.getAsTemplateOrTemplatePattern());
786 case TemplateArgument::Expression:
787 // FIXME: Visit expressions.
790 case TemplateArgument::Pack:
791 Out << 'p' << Arg.pack_size();
792 for (const auto &P : Arg.pack_elements())
793 VisitTemplateArgument(P);
796 case TemplateArgument::Type:
797 VisitType(Arg.getAsType());
800 case TemplateArgument::Integral:
802 VisitType(Arg.getIntegralType());
803 Out << Arg.getAsIntegral();
808 //===----------------------------------------------------------------------===//
809 // USR generation functions.
810 //===----------------------------------------------------------------------===//
812 void clang::index::generateUSRForObjCClass(StringRef Cls, raw_ostream &OS) {
813 OS << "objc(cs)" << Cls;
816 void clang::index::generateUSRForObjCCategory(StringRef Cls, StringRef Cat,
818 OS << "objc(cy)" << Cls << '@
' << Cat;
821 void clang::index::generateUSRForObjCIvar(StringRef Ivar, raw_ostream &OS) {
825 void clang::index::generateUSRForObjCMethod(StringRef Sel,
826 bool IsInstanceMethod,
828 OS << (IsInstanceMethod ? "(im)" : "(cm)") << Sel;
831 void clang::index::generateUSRForObjCProperty(StringRef Prop, raw_ostream &OS) {
832 OS << "(py)" << Prop;
835 void clang::index::generateUSRForObjCProtocol(StringRef Prot, raw_ostream &OS) {
836 OS << "objc(pl)" << Prot;
839 bool clang::index::generateUSRForDecl(const Decl *D,
840 SmallVectorImpl<char> &Buf) {
841 // Don't generate USRs
for things with invalid locations.
847 return UG.ignoreResults();
857 llvm::raw_svector_ostream Out(Buf);
865 if (ShouldGenerateLocation)
Defines the clang::ASTContext interface.
StringRef getName() const
bool generateUSRForMacro(const MacroDefinitionRecord *MD, const SourceManager &SM, SmallVectorImpl< char > &Buf)
Generate a USR for a macro, including the USR prefix.
ObjCInterfaceDecl * getClassInterface()
ObjCInterfaceDecl * getClassInterface()
CXXRecordDecl * getTemplatedDecl() const
Get the underlying class declarations of the template.
const DeclContext * getParentFunctionOrMethod() const
If this decl is defined inside a function/method/block it returns the corresponding DeclContext...
Defines the C++ template declaration subclasses.
NamespaceDecl - Represent a C++ namespace.
The "__interface" keyword.
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...
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)
FunctionDecl * getTemplatedDecl() const
Get the underlying function declaration of the template.
bool isAnonymousNamespace() const
Returns true if this is an anonymous namespace declaration.
TagKind getTagKind() const
bool IsClassExtension() const
Represents a C++ using-declaration.
const LangOptions & getLangOpts() const
Represents an Objective-C protocol declaration.
Represents an ObjC class declaration.
Represents a linkage specification.
const FileEntry * getFileEntryForID(FileID FID) const
Returns the FileEntry record for the provided FileID.
SourceLocation getLocStart() const LLVM_READONLY
ID
Defines the set of possible language-specific address spaces.
StringRef getName() const
Return the actual identifier string.
Declaration of a template type parameter.
DeclContext * getDeclContext()
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
TypedefNameDecl * getTypedefNameForAnonDecl() const
bool isEmbeddedInDeclarator() const
const char * getName() const
Encodes a location in the source. The SourceManager can decode this to get at the full include stack...
FunctionTemplateDecl * getDescribedFunctionTemplate() const
Retrieves the function template that is described by this function declaration.
TagDecl - Represents the declaration of a struct/union/class/enum.
ASTContext & getASTContext() const LLVM_READONLY
TagDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
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
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. Used to record that a type was spelled with a bare identifier rather than as a template-id; the equivalent for non-templated classes is just RecordType.
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.
static __inline__ uint32_t volatile uint32_t * p
bool isFreeStanding() const
Represents a dependent using declaration which was marked with typename.
Selector getSelector() const
SourceManager & getSourceManager()
A template argument list.
ObjCPropertyDecl * getPropertyDecl() const
Represents a C++ struct/union/class.
StringRef getName() const
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...
SourceLocation getLocation() const
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.
This class handles loading and caching of source files into memory.
Declaration of a template function.
void generateUSRForObjCProperty(StringRef Prop, raw_ostream &OS)
Generate a USR fragment for an Objective-C property.