[ExtractAPI] Format pointer types correctly (#146182)
Pointer types in function signatures must place the asterisk before the identifier without a space in between. This patch removes the space and also ensures that pointers to pointers are formatted correctly. rdar://131780418 rdar://154533037
This commit is contained in:
@@ -324,10 +324,15 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForType(
|
||||
|
||||
// Declaration fragments of a pointer type is the declaration fragments of
|
||||
// the pointee type followed by a `*`,
|
||||
if (T->isPointerType() && !T->isFunctionPointerType())
|
||||
return Fragments
|
||||
.append(getFragmentsForType(T->getPointeeType(), Context, After))
|
||||
.append(" *", DeclarationFragments::FragmentKind::Text);
|
||||
if (T->isPointerType() && !T->isFunctionPointerType()) {
|
||||
QualType PointeeT = T->getPointeeType();
|
||||
Fragments.append(getFragmentsForType(PointeeT, Context, After));
|
||||
// If the pointee is itself a pointer, we do not want to insert a space
|
||||
// before the `*` as the preceding character in the type name is a `*`.
|
||||
if (!PointeeT->isAnyPointerType())
|
||||
Fragments.appendSpace();
|
||||
return Fragments.append("*", DeclarationFragments::FragmentKind::Text);
|
||||
}
|
||||
|
||||
// For Objective-C `id` and `Class` pointers
|
||||
// we do not spell out the `*`.
|
||||
@@ -631,7 +636,7 @@ DeclarationFragmentsBuilder::getFragmentsForParam(const ParmVarDecl *Param) {
|
||||
DeclarationFragments::FragmentKind::InternalParam);
|
||||
} else {
|
||||
Fragments.append(std::move(TypeFragments));
|
||||
if (!T->isBlockPointerType())
|
||||
if (!T->isAnyPointerType() && !T->isBlockPointerType())
|
||||
Fragments.appendSpace();
|
||||
Fragments
|
||||
.append(Param->getName(),
|
||||
@@ -706,18 +711,20 @@ DeclarationFragmentsBuilder::getFragmentsForFunction(const FunctionDecl *Func) {
|
||||
|
||||
// FIXME: Is `after` actually needed here?
|
||||
DeclarationFragments After;
|
||||
QualType ReturnType = Func->getReturnType();
|
||||
auto ReturnValueFragment =
|
||||
getFragmentsForType(Func->getReturnType(), Func->getASTContext(), After);
|
||||
getFragmentsForType(ReturnType, Func->getASTContext(), After);
|
||||
if (StringRef(ReturnValueFragment.begin()->Spelling)
|
||||
.starts_with("type-parameter")) {
|
||||
std::string ProperArgName = Func->getReturnType().getAsString();
|
||||
std::string ProperArgName = ReturnType.getAsString();
|
||||
ReturnValueFragment.begin()->Spelling.swap(ProperArgName);
|
||||
}
|
||||
|
||||
Fragments.append(std::move(ReturnValueFragment))
|
||||
.appendSpace()
|
||||
.append(Func->getNameAsString(),
|
||||
DeclarationFragments::FragmentKind::Identifier);
|
||||
Fragments.append(std::move(ReturnValueFragment));
|
||||
if (!ReturnType->isAnyPointerType())
|
||||
Fragments.appendSpace();
|
||||
Fragments.append(Func->getNameAsString(),
|
||||
DeclarationFragments::FragmentKind::Identifier);
|
||||
|
||||
if (Func->getTemplateSpecializationInfo()) {
|
||||
Fragments.append("<", DeclarationFragments::FragmentKind::Text);
|
||||
|
||||
@@ -185,7 +185,7 @@ char unavailable __attribute__((unavailable));
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": " * "
|
||||
"spelling": " *"
|
||||
},
|
||||
{
|
||||
"kind": "internalParam",
|
||||
@@ -341,7 +341,7 @@ char unavailable __attribute__((unavailable));
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": " * "
|
||||
"spelling": " *"
|
||||
},
|
||||
{
|
||||
"kind": "internalParam",
|
||||
|
||||
@@ -187,7 +187,7 @@ char unavailable __attribute__((unavailable));
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": " * "
|
||||
"spelling": " *"
|
||||
},
|
||||
{
|
||||
"kind": "internalParam",
|
||||
@@ -343,7 +343,7 @@ char unavailable __attribute__((unavailable));
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": " * "
|
||||
"spelling": " *"
|
||||
},
|
||||
{
|
||||
"kind": "internalParam",
|
||||
|
||||
@@ -148,7 +148,7 @@ FUNC_GEN(bar, const int *, unsigned);
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": " * "
|
||||
"spelling": " *"
|
||||
},
|
||||
{
|
||||
"kind": "internalParam",
|
||||
@@ -195,7 +195,7 @@ FUNC_GEN(bar, const int *, unsigned);
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": " * "
|
||||
"spelling": " *"
|
||||
},
|
||||
{
|
||||
"kind": "internalParam",
|
||||
|
||||
388
clang/test/ExtractAPI/pointers.c
Normal file
388
clang/test/ExtractAPI/pointers.c
Normal file
@@ -0,0 +1,388 @@
|
||||
// RUN: rm -rf %t
|
||||
// RUN: split-file %s %t
|
||||
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
|
||||
// RUN: %t/reference.output.json.in >> %t/reference.output.json
|
||||
// RUN: %clang -extract-api --pretty-sgf --product-name=Pointers -target arm64-apple-macosx \
|
||||
// RUN: %t/input.h -o %t/output.json | FileCheck -allow-empty %s
|
||||
|
||||
// Generator version is not consistent across test runs, normalize it.
|
||||
// RUN: sed -e "s@\"generator\": \".*\"@\"generator\": \"?\"@g" \
|
||||
// RUN: %t/output.json >> %t/output-normalized.json
|
||||
// RUN: diff %t/reference.output.json %t/output-normalized.json
|
||||
|
||||
// CHECK-NOT: error:
|
||||
// CHECK-NOT: warning:
|
||||
|
||||
//--- input.h
|
||||
void foo(int *a);
|
||||
void bar(int **a);
|
||||
void *baz();
|
||||
void **qux();
|
||||
|
||||
//--- reference.output.json.in
|
||||
{
|
||||
"metadata": {
|
||||
"formatVersion": {
|
||||
"major": 0,
|
||||
"minor": 5,
|
||||
"patch": 3
|
||||
},
|
||||
"generator": "?"
|
||||
},
|
||||
"module": {
|
||||
"name": "Pointers",
|
||||
"platform": {
|
||||
"architecture": "arm64",
|
||||
"operatingSystem": {
|
||||
"minimumVersion": {
|
||||
"major": 11,
|
||||
"minor": 0,
|
||||
"patch": 0
|
||||
},
|
||||
"name": "macosx"
|
||||
},
|
||||
"vendor": "apple"
|
||||
}
|
||||
},
|
||||
"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:I",
|
||||
"spelling": "int"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": " *"
|
||||
},
|
||||
{
|
||||
"kind": "internalParam",
|
||||
"spelling": "a"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": ");"
|
||||
}
|
||||
],
|
||||
"functionSignature": {
|
||||
"parameters": [
|
||||
{
|
||||
"declarationFragments": [
|
||||
{
|
||||
"kind": "typeIdentifier",
|
||||
"preciseIdentifier": "c:I",
|
||||
"spelling": "int"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": " *"
|
||||
},
|
||||
{
|
||||
"kind": "internalParam",
|
||||
"spelling": "a"
|
||||
}
|
||||
],
|
||||
"name": "a"
|
||||
}
|
||||
],
|
||||
"returns": [
|
||||
{
|
||||
"kind": "typeIdentifier",
|
||||
"preciseIdentifier": "c:v",
|
||||
"spelling": "void"
|
||||
}
|
||||
]
|
||||
},
|
||||
"identifier": {
|
||||
"interfaceLanguage": "c",
|
||||
"precise": "c:@F@foo"
|
||||
},
|
||||
"kind": {
|
||||
"displayName": "Function",
|
||||
"identifier": "c.func"
|
||||
},
|
||||
"location": {
|
||||
"position": {
|
||||
"character": 5,
|
||||
"line": 0
|
||||
},
|
||||
"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": "bar"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": "("
|
||||
},
|
||||
{
|
||||
"kind": "typeIdentifier",
|
||||
"preciseIdentifier": "c:I",
|
||||
"spelling": "int"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": " **"
|
||||
},
|
||||
{
|
||||
"kind": "internalParam",
|
||||
"spelling": "a"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": ");"
|
||||
}
|
||||
],
|
||||
"functionSignature": {
|
||||
"parameters": [
|
||||
{
|
||||
"declarationFragments": [
|
||||
{
|
||||
"kind": "typeIdentifier",
|
||||
"preciseIdentifier": "c:I",
|
||||
"spelling": "int"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": " **"
|
||||
},
|
||||
{
|
||||
"kind": "internalParam",
|
||||
"spelling": "a"
|
||||
}
|
||||
],
|
||||
"name": "a"
|
||||
}
|
||||
],
|
||||
"returns": [
|
||||
{
|
||||
"kind": "typeIdentifier",
|
||||
"preciseIdentifier": "c:v",
|
||||
"spelling": "void"
|
||||
}
|
||||
]
|
||||
},
|
||||
"identifier": {
|
||||
"interfaceLanguage": "c",
|
||||
"precise": "c:@F@bar"
|
||||
},
|
||||
"kind": {
|
||||
"displayName": "Function",
|
||||
"identifier": "c.func"
|
||||
},
|
||||
"location": {
|
||||
"position": {
|
||||
"character": 5,
|
||||
"line": 1
|
||||
},
|
||||
"uri": "file://INPUT_DIR/input.h"
|
||||
},
|
||||
"names": {
|
||||
"navigator": [
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "bar"
|
||||
}
|
||||
],
|
||||
"subHeading": [
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "bar"
|
||||
}
|
||||
],
|
||||
"title": "bar"
|
||||
},
|
||||
"pathComponents": [
|
||||
"bar"
|
||||
]
|
||||
},
|
||||
{
|
||||
"accessLevel": "public",
|
||||
"declarationFragments": [
|
||||
{
|
||||
"kind": "typeIdentifier",
|
||||
"preciseIdentifier": "c:v",
|
||||
"spelling": "void"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": " *"
|
||||
},
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "baz"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": "();"
|
||||
}
|
||||
],
|
||||
"functionSignature": {
|
||||
"returns": [
|
||||
{
|
||||
"kind": "typeIdentifier",
|
||||
"preciseIdentifier": "c:v",
|
||||
"spelling": "void"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": " *"
|
||||
}
|
||||
]
|
||||
},
|
||||
"identifier": {
|
||||
"interfaceLanguage": "c",
|
||||
"precise": "c:@F@baz"
|
||||
},
|
||||
"kind": {
|
||||
"displayName": "Function",
|
||||
"identifier": "c.func"
|
||||
},
|
||||
"location": {
|
||||
"position": {
|
||||
"character": 6,
|
||||
"line": 2
|
||||
},
|
||||
"uri": "file://INPUT_DIR/input.h"
|
||||
},
|
||||
"names": {
|
||||
"navigator": [
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "baz"
|
||||
}
|
||||
],
|
||||
"subHeading": [
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "baz"
|
||||
}
|
||||
],
|
||||
"title": "baz"
|
||||
},
|
||||
"pathComponents": [
|
||||
"baz"
|
||||
]
|
||||
},
|
||||
{
|
||||
"accessLevel": "public",
|
||||
"declarationFragments": [
|
||||
{
|
||||
"kind": "typeIdentifier",
|
||||
"preciseIdentifier": "c:v",
|
||||
"spelling": "void"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": " **"
|
||||
},
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "qux"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": "();"
|
||||
}
|
||||
],
|
||||
"functionSignature": {
|
||||
"returns": [
|
||||
{
|
||||
"kind": "typeIdentifier",
|
||||
"preciseIdentifier": "c:v",
|
||||
"spelling": "void"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": " **"
|
||||
}
|
||||
]
|
||||
},
|
||||
"identifier": {
|
||||
"interfaceLanguage": "c",
|
||||
"precise": "c:@F@qux"
|
||||
},
|
||||
"kind": {
|
||||
"displayName": "Function",
|
||||
"identifier": "c.func"
|
||||
},
|
||||
"location": {
|
||||
"position": {
|
||||
"character": 7,
|
||||
"line": 3
|
||||
},
|
||||
"uri": "file://INPUT_DIR/input.h"
|
||||
},
|
||||
"names": {
|
||||
"navigator": [
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "qux"
|
||||
}
|
||||
],
|
||||
"subHeading": [
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "qux"
|
||||
}
|
||||
],
|
||||
"title": "qux"
|
||||
},
|
||||
"pathComponents": [
|
||||
"qux"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user