aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/ExtractAPI/DeclarationFragments.cpp
diff options
context:
space:
mode:
authorDaniel Grumberg <dgrumberg@apple.com>2024-01-22 15:41:29 +0000
committerGitHub <noreply@github.com>2024-01-22 15:41:29 +0000
commitc5532124dc0ffc892ded0b093e92244977e748f8 (patch)
tree098e2177f1bee7d241561b9d45c54110e471b9c7 /clang/lib/ExtractAPI/DeclarationFragments.cpp
parent74ab7958bdda4d10b082129151f434176f99320e (diff)
downloadllvm-c5532124dc0ffc892ded0b093e92244977e748f8.zip
llvm-c5532124dc0ffc892ded0b093e92244977e748f8.tar.gz
llvm-c5532124dc0ffc892ded0b093e92244977e748f8.tar.bz2
[clang][ExtractAPI] Ensure typedef to pointer types are preserved (#78584)
When generating declaration fragments for types that use typedefs to pointer types ensure that we keep the user-defined typedef form instead of desugaring the typedef. rdar://102137655
Diffstat (limited to 'clang/lib/ExtractAPI/DeclarationFragments.cpp')
-rw-r--r--clang/lib/ExtractAPI/DeclarationFragments.cpp80
1 files changed, 40 insertions, 40 deletions
diff --git a/clang/lib/ExtractAPI/DeclarationFragments.cpp b/clang/lib/ExtractAPI/DeclarationFragments.cpp
index 044ccf5..56c1f5b 100644
--- a/clang/lib/ExtractAPI/DeclarationFragments.cpp
+++ b/clang/lib/ExtractAPI/DeclarationFragments.cpp
@@ -252,6 +252,46 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForType(
DeclarationFragments Fragments;
+ // An ElaboratedType is a sugar for types that are referred to using an
+ // elaborated keyword, e.g., `struct S`, `enum E`, or (in C++) via a
+ // qualified name, e.g., `N::M::type`, or both.
+ if (const ElaboratedType *ET = dyn_cast<ElaboratedType>(T)) {
+ ElaboratedTypeKeyword Keyword = ET->getKeyword();
+ if (Keyword != ElaboratedTypeKeyword::None) {
+ Fragments
+ .append(ElaboratedType::getKeywordName(Keyword),
+ DeclarationFragments::FragmentKind::Keyword)
+ .appendSpace();
+ }
+
+ if (const NestedNameSpecifier *NNS = ET->getQualifier())
+ Fragments.append(getFragmentsForNNS(NNS, Context, After));
+
+ // After handling the elaborated keyword or qualified name, build
+ // declaration fragments for the desugared underlying type.
+ return Fragments.append(getFragmentsForType(ET->desugar(), Context, After));
+ }
+
+ // If the type is a typedefed type, get the underlying TypedefNameDecl for a
+ // direct reference to the typedef instead of the wrapped type.
+
+ // 'id' type is a typedef for an ObjCObjectPointerType
+ // we treat it as a typedef
+ if (const TypedefType *TypedefTy = dyn_cast<TypedefType>(T)) {
+ const TypedefNameDecl *Decl = TypedefTy->getDecl();
+ TypedefUnderlyingTypeResolver TypedefResolver(Context);
+ std::string USR = TypedefResolver.getUSRForType(QualType(T, 0));
+
+ if (T->isObjCIdType()) {
+ return Fragments.append(Decl->getName(),
+ DeclarationFragments::FragmentKind::Keyword);
+ }
+
+ return Fragments.append(
+ Decl->getName(), DeclarationFragments::FragmentKind::TypeIdentifier,
+ USR, TypedefResolver.getUnderlyingTypeDecl(QualType(T, 0)));
+ }
+
// Declaration fragments of a pointer type is the declaration fragments of
// the pointee type followed by a `*`,
if (T->isPointerType() && !T->isFunctionPointerType())
@@ -328,46 +368,6 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForType(
getFragmentsForType(AT->getElementType(), Context, After));
}
- // An ElaboratedType is a sugar for types that are referred to using an
- // elaborated keyword, e.g., `struct S`, `enum E`, or (in C++) via a
- // qualified name, e.g., `N::M::type`, or both.
- if (const ElaboratedType *ET = dyn_cast<ElaboratedType>(T)) {
- ElaboratedTypeKeyword Keyword = ET->getKeyword();
- if (Keyword != ElaboratedTypeKeyword::None) {
- Fragments
- .append(ElaboratedType::getKeywordName(Keyword),
- DeclarationFragments::FragmentKind::Keyword)
- .appendSpace();
- }
-
- if (const NestedNameSpecifier *NNS = ET->getQualifier())
- Fragments.append(getFragmentsForNNS(NNS, Context, After));
-
- // After handling the elaborated keyword or qualified name, build
- // declaration fragments for the desugared underlying type.
- return Fragments.append(getFragmentsForType(ET->desugar(), Context, After));
- }
-
- // If the type is a typedefed type, get the underlying TypedefNameDecl for a
- // direct reference to the typedef instead of the wrapped type.
-
- // 'id' type is a typedef for an ObjCObjectPointerType
- // we treat it as a typedef
- if (const TypedefType *TypedefTy = dyn_cast<TypedefType>(T)) {
- const TypedefNameDecl *Decl = TypedefTy->getDecl();
- TypedefUnderlyingTypeResolver TypedefResolver(Context);
- std::string USR = TypedefResolver.getUSRForType(QualType(T, 0));
-
- if (T->isObjCIdType()) {
- return Fragments.append(Decl->getName(),
- DeclarationFragments::FragmentKind::Keyword);
- }
-
- return Fragments.append(
- Decl->getName(), DeclarationFragments::FragmentKind::TypeIdentifier,
- USR, TypedefResolver.getUnderlyingTypeDecl(QualType(T, 0)));
- }
-
// Everything we care about has been handled now, reduce to the canonical
// unqualified base type.
QualType Base = T->getCanonicalTypeUnqualified();