[clang] c553212 - [clang][ExtractAPI] Ensure typedef to pointer types are preserved (#78584)
via cfe-commits
cfe-commits at lists.llvm.org
Mon Jan 22 07:41:35 PST 2024
Author: Daniel Grumberg
Date: 2024-01-22T15:41:29Z
New Revision: c5532124dc0ffc892ded0b093e92244977e748f8
URL: https://github.com/llvm/llvm-project/commit/c5532124dc0ffc892ded0b093e92244977e748f8
DIFF: https://github.com/llvm/llvm-project/commit/c5532124dc0ffc892ded0b093e92244977e748f8.diff
LOG: [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
Added:
Modified:
clang/lib/ExtractAPI/DeclarationFragments.cpp
clang/test/ExtractAPI/typedef.c
Removed:
################################################################################
diff --git a/clang/lib/ExtractAPI/DeclarationFragments.cpp b/clang/lib/ExtractAPI/DeclarationFragments.cpp
index 044ccf5dea095b9..56c1f5bf5eab068 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();
diff --git a/clang/test/ExtractAPI/typedef.c b/clang/test/ExtractAPI/typedef.c
index 7f30b4bc9bb0c2b..c30e65549f2b745 100644
--- a/clang/test/ExtractAPI/typedef.c
+++ b/clang/test/ExtractAPI/typedef.c
@@ -16,6 +16,12 @@
//--- input.h
typedef int MyInt;
+typedef struct Bar *BarPtr;
+
+void foo(BarPtr value);
+
+void baz(BarPtr *value);
+
//--- reference.output.json.in
{
"metadata": {
@@ -43,6 +49,208 @@ typedef int MyInt;
},
"relationships": [],
"symbols": [
+ {
+ "accessLevel": "public",
+ "declarationFragments": [
+ {
+ "kind": "typeIdentifier",
+ "preciseIdentifier": "c:v",
+ "spelling": "void"
+ },
+ {
+ "kind": "text",
+ "spelling": " "
+ },
+ {
+ "kind": "identifier",
+ "spelling": "foo"
+ },
+ {
+ "kind": "text",
+ "spelling": "("
+ },
+ {
+ "kind": "typeIdentifier",
+ "preciseIdentifier": "c:input.h at T@BarPtr",
+ "spelling": "BarPtr"
+ },
+ {
+ "kind": "text",
+ "spelling": " "
+ },
+ {
+ "kind": "internalParam",
+ "spelling": "value"
+ },
+ {
+ "kind": "text",
+ "spelling": ");"
+ }
+ ],
+ "functionSignature": {
+ "parameters": [
+ {
+ "declarationFragments": [
+ {
+ "kind": "typeIdentifier",
+ "preciseIdentifier": "c:input.h at T@BarPtr",
+ "spelling": "BarPtr"
+ },
+ {
+ "kind": "text",
+ "spelling": " "
+ },
+ {
+ "kind": "internalParam",
+ "spelling": "value"
+ }
+ ],
+ "name": "value"
+ }
+ ],
+ "returns": [
+ {
+ "kind": "typeIdentifier",
+ "preciseIdentifier": "c:v",
+ "spelling": "void"
+ }
+ ]
+ },
+ "identifier": {
+ "interfaceLanguage": "objective-c",
+ "precise": "c:@F at foo"
+ },
+ "kind": {
+ "displayName": "Function",
+ "identifier": "objective-c.func"
+ },
+ "location": {
+ "position": {
+ "character": 5,
+ "line": 4
+ },
+ "uri": "file://INPUT_DIR/input.h"
+ },
+ "names": {
+ "navigator": [
+ {
+ "kind": "identifier",
+ "spelling": "foo"
+ }
+ ],
+ "subHeading": [
+ {
+ "kind": "identifier",
+ "spelling": "foo"
+ }
+ ],
+ "title": "foo"
+ },
+ "pathComponents": [
+ "foo"
+ ]
+ },
+ {
+ "accessLevel": "public",
+ "declarationFragments": [
+ {
+ "kind": "typeIdentifier",
+ "preciseIdentifier": "c:v",
+ "spelling": "void"
+ },
+ {
+ "kind": "text",
+ "spelling": " "
+ },
+ {
+ "kind": "identifier",
+ "spelling": "baz"
+ },
+ {
+ "kind": "text",
+ "spelling": "("
+ },
+ {
+ "kind": "typeIdentifier",
+ "preciseIdentifier": "c:input.h at T@BarPtr",
+ "spelling": "BarPtr"
+ },
+ {
+ "kind": "text",
+ "spelling": " * "
+ },
+ {
+ "kind": "internalParam",
+ "spelling": "value"
+ },
+ {
+ "kind": "text",
+ "spelling": ");"
+ }
+ ],
+ "functionSignature": {
+ "parameters": [
+ {
+ "declarationFragments": [
+ {
+ "kind": "typeIdentifier",
+ "preciseIdentifier": "c:input.h at T@BarPtr",
+ "spelling": "BarPtr"
+ },
+ {
+ "kind": "text",
+ "spelling": " * "
+ },
+ {
+ "kind": "internalParam",
+ "spelling": "value"
+ }
+ ],
+ "name": "value"
+ }
+ ],
+ "returns": [
+ {
+ "kind": "typeIdentifier",
+ "preciseIdentifier": "c:v",
+ "spelling": "void"
+ }
+ ]
+ },
+ "identifier": {
+ "interfaceLanguage": "objective-c",
+ "precise": "c:@F at baz"
+ },
+ "kind": {
+ "displayName": "Function",
+ "identifier": "objective-c.func"
+ },
+ "location": {
+ "position": {
+ "character": 5,
+ "line": 6
+ },
+ "uri": "file://INPUT_DIR/input.h"
+ },
+ "names": {
+ "navigator": [
+ {
+ "kind": "identifier",
+ "spelling": "baz"
+ }
+ ],
+ "subHeading": [
+ {
+ "kind": "identifier",
+ "spelling": "baz"
+ }
+ ],
+ "title": "baz"
+ },
+ "pathComponents": [
+ "baz"
+ ]
+ },
{
"accessLevel": "public",
"declarationFragments": [
@@ -106,6 +314,78 @@ typedef int MyInt;
"MyInt"
],
"type": "c:I"
+ },
+ {
+ "accessLevel": "public",
+ "declarationFragments": [
+ {
+ "kind": "keyword",
+ "spelling": "typedef"
+ },
+ {
+ "kind": "text",
+ "spelling": " "
+ },
+ {
+ "kind": "keyword",
+ "spelling": "struct"
+ },
+ {
+ "kind": "text",
+ "spelling": " "
+ },
+ {
+ "kind": "typeIdentifier",
+ "preciseIdentifier": "c:@S at Bar",
+ "spelling": "Bar"
+ },
+ {
+ "kind": "text",
+ "spelling": " * "
+ },
+ {
+ "kind": "identifier",
+ "spelling": "BarPtr"
+ },
+ {
+ "kind": "text",
+ "spelling": ";"
+ }
+ ],
+ "identifier": {
+ "interfaceLanguage": "objective-c",
+ "precise": "c:input.h at T@BarPtr"
+ },
+ "kind": {
+ "displayName": "Type Alias",
+ "identifier": "objective-c.typealias"
+ },
+ "location": {
+ "position": {
+ "character": 20,
+ "line": 2
+ },
+ "uri": "file://INPUT_DIR/input.h"
+ },
+ "names": {
+ "navigator": [
+ {
+ "kind": "identifier",
+ "spelling": "BarPtr"
+ }
+ ],
+ "subHeading": [
+ {
+ "kind": "identifier",
+ "spelling": "BarPtr"
+ }
+ ],
+ "title": "BarPtr"
+ },
+ "pathComponents": [
+ "BarPtr"
+ ],
+ "type": "c:*$@S at Bar"
}
]
}
More information about the cfe-commits
mailing list