clang_generator: Correctly emit nested C-like structs

- Add more tests for this

PiperOrigin-RevId: 435296715
Change-Id: I7b42dbc58dc054d2565af9ad22498d98416b7af7
This commit is contained in:
Christian Blichmann 2022-03-17 03:12:46 -07:00 committed by Copybara-Service
parent b8579e4746
commit 92ccfeae67
2 changed files with 66 additions and 7 deletions

View File

@ -238,11 +238,13 @@ std::string GetSpelling(const clang::Decl* decl) {
} }
if (const auto* record_decl = llvm::dyn_cast<clang::CXXRecordDecl>(decl)) { if (const auto* record_decl = llvm::dyn_cast<clang::CXXRecordDecl>(decl)) {
if (!record_decl->isCLike()) {
// For C++ classes/structs, only emit a forward declaration. // For C++ classes/structs, only emit a forward declaration.
return absl::StrCat(PrintRecordTemplateArguments(record_decl), return absl::StrCat(PrintRecordTemplateArguments(record_decl),
record_decl->isClass() ? "class " : "struct ", record_decl->isClass() ? "class " : "struct ",
ToStringView(record_decl->getName())); ToStringView(record_decl->getName()));
} }
}
return PrintDecl(decl); return PrintDecl(decl);
} }
@ -423,8 +425,7 @@ void Emitter::CollectType(clang::QualType qual) {
return; return;
} }
} }
ns_name = absl::StrCat(ns_path[0].empty() ? "" : " ", ns_name = absl::StrJoin(ns_path, "::");
absl::StrJoin(ns_path, "::"));
} }
rendered_types_[ns_name].push_back(GetSpelling(decl)); rendered_types_[ns_name].push_back(GetSpelling(decl));

View File

@ -93,10 +93,68 @@ TEST_F(EmitterTest, RelatedTypes) {
} }
EXPECT_THAT(ugly_types, EXPECT_THAT(ugly_types,
ElementsAre("typedef enum { kRed, kGreen, kBlue } Color", ElementsAre("typedef enum { kRed, kGreen, kBlue } Color",
"struct Channel", "struct ByValue", "struct Channel {"
" Color color;"
" std::size_t width;"
" std::size_t height; }",
"struct ByValue { int value; }",
"typedef struct { int member; } MyStruct")); "typedef struct { int member; } MyStruct"));
} }
TEST_F(EmitterTest, NestedStruct) {
EmitterForTesting emitter;
RunFrontendAction(
R"(
struct A {
struct B {
int number;
};
B b;
int data;
};
extern "C" void Structize(A* s);
)",
absl::make_unique<GeneratorAction>(emitter, GeneratorOptions()));
std::vector<std::string> ugly_types;
for (const auto& type : emitter.rendered_types_[""]) {
ugly_types.push_back(Uglify(type));
}
EXPECT_THAT(ugly_types, ElementsAre("struct A {"
" struct B {"
" int number;"
" };"
" A::B b;"
" int data; "
"}"));
}
TEST_F(EmitterTest, NestedAnonymousStruct) {
EmitterForTesting emitter;
RunFrontendAction(
R"(
struct A {
struct {
int number;
} b;
int data;
};
extern "C" void Structize(A* s);
)",
absl::make_unique<GeneratorAction>(emitter, GeneratorOptions()));
std::vector<std::string> ugly_types;
for (const auto& type : emitter.rendered_types_[""]) {
ugly_types.push_back(Uglify(type));
}
EXPECT_THAT(ugly_types, ElementsAre("struct A {"
" struct {"
" int number;"
" } b;"
" int data; "
"}"));
}
TEST(IncludeGuard, CreatesRandomizedGuardForEmptyFilename) { TEST(IncludeGuard, CreatesRandomizedGuardForEmptyFilename) {
// Copybara will transform the string. This is intentional. // Copybara will transform the string. This is intentional.
constexpr absl::string_view kGeneratedHeaderPrefix = constexpr absl::string_view kGeneratedHeaderPrefix =