aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/ExtractAPI/DeclarationFragments.cpp
diff options
context:
space:
mode:
authorDaniel Grumberg <dgrumberg@apple.com>2022-04-01 19:14:23 +0100
committerDaniel Grumberg <dgrumberg@apple.com>2022-04-06 19:14:05 +0100
commit9fc45ca00a19336c0724631aa1b1985dd4f4d536 (patch)
tree4c3464c52f2079530bccc5c34a14a7a97bcb6012 /clang/lib/ExtractAPI/DeclarationFragments.cpp
parent482fad4a3fcb013aa19e97661e3d66583d026bb8 (diff)
downloadllvm-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.cpp48
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) {