diff --git a/clang/lib/ExtractAPI/DeclarationFragments.cpp b/clang/lib/ExtractAPI/DeclarationFragments.cpp index 044ccf5dea095..56c1f5bf5eab0 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(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(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(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(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 7f30b4bc9bb0c..c30e65549f2b7 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@T@BarPtr", + "spelling": "BarPtr" + }, + { + "kind": "text", + "spelling": " " + }, + { + "kind": "internalParam", + "spelling": "value" + }, + { + "kind": "text", + "spelling": ");" + } + ], + "functionSignature": { + "parameters": [ + { + "declarationFragments": [ + { + "kind": "typeIdentifier", + "preciseIdentifier": "c:input.h@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@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@T@BarPtr", + "spelling": "BarPtr" + }, + { + "kind": "text", + "spelling": " * " + }, + { + "kind": "internalParam", + "spelling": "value" + }, + { + "kind": "text", + "spelling": ");" + } + ], + "functionSignature": { + "parameters": [ + { + "declarationFragments": [ + { + "kind": "typeIdentifier", + "preciseIdentifier": "c:input.h@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@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@Bar", + "spelling": "Bar" + }, + { + "kind": "text", + "spelling": " * " + }, + { + "kind": "identifier", + "spelling": "BarPtr" + }, + { + "kind": "text", + "spelling": ";" + } + ], + "identifier": { + "interfaceLanguage": "objective-c", + "precise": "c:input.h@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@Bar" } ] }