diff --git a/clang/include/clang/ExtractAPI/DeclarationFragments.h b/clang/include/clang/ExtractAPI/DeclarationFragments.h --- a/clang/include/clang/ExtractAPI/DeclarationFragments.h +++ b/clang/include/clang/ExtractAPI/DeclarationFragments.h @@ -116,6 +116,8 @@ return *this; } + void removeLast() { Fragments.pop_back(); } + /// Append a new Fragment to the end of the Fragments. /// /// \returns a reference to the DeclarationFragments object itself after diff --git a/clang/lib/ExtractAPI/ExtractAPIVisitor.cpp b/clang/lib/ExtractAPI/ExtractAPIVisitor.cpp --- a/clang/lib/ExtractAPI/ExtractAPIVisitor.cpp +++ b/clang/lib/ExtractAPI/ExtractAPIVisitor.cpp @@ -48,6 +48,24 @@ return Context.getSourceManager().isInSystemHeader(D->getLocation()); } +template +void modifyRecord(const T &Records, const llvm::StringRef &name) { + for (const auto &Record : Records) { + if (name == Record.second.get()->Name) { + Record.second.get()->Declaration.removeLast(); + Record.second.get() + ->Declaration + .appendFront(" ", DeclarationFragments::FragmentKind::Text) + .appendFront("typedef", DeclarationFragments::FragmentKind::Keyword, + "", nullptr) + .append(" { ... } ", DeclarationFragments::FragmentKind::Text) + .append(name, DeclarationFragments::FragmentKind::Identifier) + .append(";", DeclarationFragments::FragmentKind::Text); + break; + } + } +} + } // namespace bool ExtractAPIVisitor::VisitVarDecl(const VarDecl *Decl) { @@ -344,30 +362,10 @@ if (const TagType *TagTy = dyn_cast(ET->desugar())) { if (Decl->getName() == TagTy->getDecl()->getName()) { if (TagTy->getDecl()->isStruct()) { - for (const auto &Struct : API.getStructs()) { - if (Decl->getName() == Struct.second.get()->Name) { - Struct.second.get() - ->Declaration - .appendFront(" ", DeclarationFragments::FragmentKind::Text) - .appendFront("typedef", - DeclarationFragments::FragmentKind::Keyword, "", - nullptr); - break; - } - } + modifyRecord(API.getStructs(), Decl->getName()); } if (TagTy->getDecl()->isEnum()) { - for (const auto &Enum : API.getEnums()) { - if (Decl->getName() == Enum.second.get()->Name) { - Enum.second.get() - ->Declaration - .appendFront(" ", DeclarationFragments::FragmentKind::Text) - .appendFront("typedef", - DeclarationFragments::FragmentKind::Keyword, "", - nullptr); - break; - } - } + modifyRecord(API.getEnums(), Decl->getName()); } } } diff --git a/clang/test/ExtractAPI/typedef_struct_enum.c b/clang/test/ExtractAPI/typedef_struct_enum.c --- a/clang/test/ExtractAPI/typedef_struct_enum.c +++ b/clang/test/ExtractAPI/typedef_struct_enum.c @@ -21,6 +21,12 @@ simple } Test2; +struct Foo; +typedef struct Foo TypedefedFoo; +struct Foo { + int bar; +}; + //--- reference.output.json.in { "metadata": { @@ -36,6 +42,11 @@ "platform": { "architecture": "arm64", "operatingSystem": { + "minimumVersion": { + "major": 11, + "minor": 0, + "patch": 0 + }, "name": "macosx" }, "vendor": "apple" @@ -47,6 +58,12 @@ "source": "c:@E@Test2@simple", "target": "c:@E@Test2", "targetFallback": "Test2" + }, + { + "kind": "memberOf", + "source": "c:@S@Foo@FI@bar", + "target": "c:@S@Foo", + "targetFallback": "Foo" } ], "symbols": [ @@ -82,6 +99,14 @@ "preciseIdentifier": "c:i", "spelling": "unsigned int" }, + { + "kind": "text", + "spelling": " { ... } " + }, + { + "kind": "identifier", + "spelling": "Test2" + }, { "kind": "text", "spelling": ";" @@ -187,6 +212,14 @@ "kind": "identifier", "spelling": "Test" }, + { + "kind": "text", + "spelling": " { ... } " + }, + { + "kind": "identifier", + "spelling": "Test" + }, { "kind": "text", "spelling": ";" @@ -225,6 +258,184 @@ "pathComponents": [ "Test" ] + }, + { + "accessLevel": "public", + "declarationFragments": [ + { + "kind": "keyword", + "spelling": "struct" + }, + { + "kind": "text", + "spelling": " " + }, + { + "kind": "identifier", + "spelling": "Foo" + }, + { + "kind": "text", + "spelling": ";" + } + ], + "identifier": { + "interfaceLanguage": "c", + "precise": "c:@S@Foo" + }, + "kind": { + "displayName": "Structure", + "identifier": "c.struct" + }, + "location": { + "position": { + "character": 8, + "line": 10 + }, + "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:I", + "spelling": "int" + }, + { + "kind": "text", + "spelling": " " + }, + { + "kind": "identifier", + "spelling": "bar" + } + ], + "identifier": { + "interfaceLanguage": "c", + "precise": "c:@S@Foo@FI@bar" + }, + "kind": { + "displayName": "Instance Property", + "identifier": "c.property" + }, + "location": { + "position": { + "character": 9, + "line": 11 + }, + "uri": "file://INPUT_DIR/input.h" + }, + "names": { + "navigator": [ + { + "kind": "identifier", + "spelling": "bar" + } + ], + "subHeading": [ + { + "kind": "identifier", + "spelling": "bar" + } + ], + "title": "bar" + }, + "pathComponents": [ + "Foo", + "bar" + ] + }, + { + "accessLevel": "public", + "declarationFragments": [ + { + "kind": "keyword", + "spelling": "typedef" + }, + { + "kind": "text", + "spelling": " " + }, + { + "kind": "keyword", + "spelling": "struct" + }, + { + "kind": "text", + "spelling": " " + }, + { + "kind": "typeIdentifier", + "preciseIdentifier": "c:@S@Foo", + "spelling": "Foo" + }, + { + "kind": "text", + "spelling": " " + }, + { + "kind": "identifier", + "spelling": "TypedefedFoo" + }, + { + "kind": "text", + "spelling": ";" + } + ], + "identifier": { + "interfaceLanguage": "c", + "precise": "c:input.h@T@TypedefedFoo" + }, + "kind": { + "displayName": "Type Alias", + "identifier": "c.typealias" + }, + "location": { + "position": { + "character": 20, + "line": 9 + }, + "uri": "file://INPUT_DIR/input.h" + }, + "names": { + "navigator": [ + { + "kind": "identifier", + "spelling": "TypedefedFoo" + } + ], + "subHeading": [ + { + "kind": "identifier", + "spelling": "TypedefedFoo" + } + ], + "title": "TypedefedFoo" + }, + "pathComponents": [ + "TypedefedFoo" + ], + "type": "c:@S@Foo" } ] }