Skip to content

Commit 5d0f8c5

Browse files
Ruturaj4daniel-grumberg
authored andcommitted
[clang][ExtractAPI] Complete declaration fragments for TagDecl types defined in a typedef
enums and structs declared inside typedefs have incorrect declaration fragments, where the typedef keyword and other syntax is missing. For the following struct: typedef struct Test { int hello; } Test; The produced declaration is: "declarationFragments": [ { "kind": "keyword", "spelling": "struct" }, { "kind": "text", "spelling": " " }, { "kind": "identifier", "spelling": "Test" } ], instead the declaration fragments should represent the following typedef struct Test { … } Test; This patch removes the condition in SymbolGraphSerializer.cpp file and completes declaration fragments Reviewed By: dang Differential Revision: https://reviews.llvm.org/D146385
1 parent 65f2547 commit 5d0f8c5

File tree

3 files changed

+494
-0
lines changed

3 files changed

+494
-0
lines changed

clang/include/clang/ExtractAPI/DeclarationFragments.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,25 @@ class DeclarationFragments {
9999

100100
const std::vector<Fragment> &getFragments() const { return Fragments; }
101101

102+
// Add a new Fragment to the beginning of the Fragments.
103+
DeclarationFragments &appendFront(StringRef Spelling, FragmentKind Kind,
104+
StringRef PreciseIdentifier = "",
105+
const Decl *Declaration = nullptr) {
106+
Fragments.emplace(Fragments.begin(), Spelling, Kind, PreciseIdentifier,
107+
Declaration);
108+
return *this;
109+
}
110+
111+
DeclarationFragments &appendFront(DeclarationFragments &&Other) {
112+
Fragments.insert(Fragments.begin(),
113+
std::make_move_iterator(Other.Fragments.begin()),
114+
std::make_move_iterator(Other.Fragments.end()));
115+
Other.Fragments.clear();
116+
return *this;
117+
}
118+
119+
void removeLast() { Fragments.pop_back(); }
120+
102121
/// Append a new Fragment to the end of the Fragments.
103122
///
104123
/// \returns a reference to the DeclarationFragments object itself after

clang/include/clang/ExtractAPI/ExtractAPIVisitor.h

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "clang/Basic/SourceManager.h"
2323
#include "clang/ExtractAPI/API.h"
2424
#include "clang/ExtractAPI/TypedefUnderlyingTypeResolver.h"
25+
#include "llvm/ADT/StringRef.h"
2526
#include <type_traits>
2627

2728
namespace clang {
@@ -105,6 +106,24 @@ class ExtractAPIVisitorBase : public RecursiveASTVisitor<Derived> {
105106
}
106107
};
107108

109+
template <typename T>
110+
static void modifyRecords(const T &Records, const StringRef &Name) {
111+
for (const auto &Record : Records) {
112+
if (Name == Record.second.get()->Name) {
113+
Record.second.get()->Declaration.removeLast();
114+
Record.second.get()
115+
->Declaration
116+
.appendFront(" ", DeclarationFragments::FragmentKind::Text)
117+
.appendFront("typedef", DeclarationFragments::FragmentKind::Keyword,
118+
"", nullptr)
119+
.append(" { ... } ", DeclarationFragments::FragmentKind::Text)
120+
.append(Name, DeclarationFragments::FragmentKind::Identifier)
121+
.append(";", DeclarationFragments::FragmentKind::Text);
122+
break;
123+
}
124+
}
125+
}
126+
108127
template <typename Derived>
109128
bool ExtractAPIVisitorBase<Derived>::VisitVarDecl(const VarDecl *Decl) {
110129
// skip function parameters.
@@ -401,6 +420,21 @@ bool ExtractAPIVisitorBase<Derived>::VisitTypedefNameDecl(
401420
if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl))
402421
return true;
403422

423+
// Add the notion of typedef for tag type (struct or enum) of the same name.
424+
if (const ElaboratedType *ET =
425+
dyn_cast<ElaboratedType>(Decl->getUnderlyingType())) {
426+
if (const TagType *TagTy = dyn_cast<TagType>(ET->desugar())) {
427+
if (Decl->getName() == TagTy->getDecl()->getName()) {
428+
if (TagTy->getDecl()->isStruct()) {
429+
modifyRecords(API.getStructs(), Decl->getName());
430+
}
431+
if (TagTy->getDecl()->isEnum()) {
432+
modifyRecords(API.getEnums(), Decl->getName());
433+
}
434+
}
435+
}
436+
}
437+
404438
PresumedLoc Loc =
405439
Context.getSourceManager().getPresumedLoc(Decl->getLocation());
406440
StringRef Name = Decl->getName();

0 commit comments

Comments
 (0)