diff options
author | Daniel Grumberg <dgrumberg@apple.com> | 2022-04-01 19:14:23 +0100 |
---|---|---|
committer | Daniel Grumberg <dgrumberg@apple.com> | 2022-04-06 19:14:05 +0100 |
commit | 9fc45ca00a19336c0724631aa1b1985dd4f4d536 (patch) | |
tree | 4c3464c52f2079530bccc5c34a14a7a97bcb6012 /clang/lib/ExtractAPI/DeclarationFragments.cpp | |
parent | 482fad4a3fcb013aa19e97661e3d66583d026bb8 (diff) | |
download | llvm-9fc45ca00a19336c0724631aa1b1985dd4f4d536.zip llvm-9fc45ca00a19336c0724631aa1b1985dd4f4d536.tar.gz llvm-9fc45ca00a19336c0724631aa1b1985dd4f4d536.tar.bz2 |
[clang][extract-api] Add support for typedefs
Typedef records consist of the symbol associated with the underlying
TypedefDecl and a SymbolReference to the underlying type. Additionally
typedefs for anonymous TagTypes use the typedef'd name as the symbol
name in their respective records and USRs. As a result the declaration
fragments for the anonymous TagType are those for the associated
typedef. This means that when the user is defining a typedef to a
typedef to a anonymous type, we use a reference the anonymous TagType
itself and do not emit the typedef to the anonymous type in the
generated symbol graph, including in the type destination of further
typedef symbol records.
Differential Revision: https://reviews.llvm.org/D123019
Diffstat (limited to 'clang/lib/ExtractAPI/DeclarationFragments.cpp')
-rw-r--r-- | clang/lib/ExtractAPI/DeclarationFragments.cpp | 48 |
1 files changed, 44 insertions, 4 deletions
diff --git a/clang/lib/ExtractAPI/DeclarationFragments.cpp b/clang/lib/ExtractAPI/DeclarationFragments.cpp index 5997a8f..4e0e8da 100644 --- a/clang/lib/ExtractAPI/DeclarationFragments.cpp +++ b/clang/lib/ExtractAPI/DeclarationFragments.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "clang/ExtractAPI/DeclarationFragments.h" +#include "TypedefUnderlyingTypeResolver.h" #include "clang/Index/USRGeneration.h" #include "llvm/ADT/StringSwitch.h" @@ -250,6 +251,31 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForType( return Fragments.append(Base.getAsString(), DeclarationFragments::FragmentKind::Keyword); + // If the type is a typedefed type, get the underlying TypedefNameDecl for a + // direct reference to the typedef instead of the wrapped type. + if (const TypedefType *TypedefTy = dyn_cast<TypedefType>(T)) { + const TypedefNameDecl *Decl = TypedefTy->getDecl(); + std::string USR = + TypedefUnderlyingTypeResolver(Context).getUSRForType(QualType(T, 0)); + return Fragments.append(Decl->getName(), + DeclarationFragments::FragmentKind::TypeIdentifier, + USR); + } + + // If the base type is a TagType (struct/interface/union/class/enum), let's + // get the underlying Decl for better names and USRs. + if (const TagType *TagTy = dyn_cast<TagType>(Base)) { + const TagDecl *Decl = TagTy->getDecl(); + // Anonymous decl, skip this fragment. + if (Decl->getName().empty()) + return Fragments; + SmallString<128> TagUSR; + clang::index::generateUSRForDecl(Decl, TagUSR); + return Fragments.append(Decl->getName(), + DeclarationFragments::FragmentKind::TypeIdentifier, + TagUSR); + } + // If the base type is an ObjCInterfaceType, use the underlying // ObjCInterfaceDecl for the true USR. if (const auto *ObjCIT = dyn_cast<ObjCInterfaceType>(Base)) { @@ -426,8 +452,8 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForEnumConstant( DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForEnum(const EnumDecl *EnumDecl) { - // TODO: After we support typedef records, if there's a typedef for this enum - // just use the declaration fragments of the typedef decl. + if (const auto *TypedefNameDecl = EnumDecl->getTypedefNameForAnonDecl()) + return getFragmentsForTypedef(TypedefNameDecl); DeclarationFragments Fragments, After; Fragments.append("enum", DeclarationFragments::FragmentKind::Keyword); @@ -457,8 +483,8 @@ DeclarationFragmentsBuilder::getFragmentsForField(const FieldDecl *Field) { DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForStruct(const RecordDecl *Record) { - // TODO: After we support typedef records, if there's a typedef for this - // struct just use the declaration fragments of the typedef decl. + if (const auto *TypedefNameDecl = Record->getTypedefNameForAnonDecl()) + return getFragmentsForTypedef(TypedefNameDecl); DeclarationFragments Fragments; Fragments.append("struct", DeclarationFragments::FragmentKind::Keyword); @@ -680,6 +706,20 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCProtocol( return Fragments; } +DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForTypedef( + const TypedefNameDecl *Decl) { + DeclarationFragments Fragments, After; + Fragments.append("typedef", DeclarationFragments::FragmentKind::Keyword) + .appendSpace() + .append(getFragmentsForType(Decl->getUnderlyingType(), + Decl->getASTContext(), After)) + .append(std::move(After)) + .appendSpace() + .append(Decl->getName(), DeclarationFragments::FragmentKind::Identifier); + + return Fragments; +} + template <typename FunctionT> FunctionSignature DeclarationFragmentsBuilder::getFunctionSignature(const FunctionT *Function) { |