clang_generator: Correctly emit nested C-like structs
- Add more tests for this
PiperOrigin-RevId: 435296715
Change-Id: I7b42dbc58dc054d2565af9ad22498d98416b7af7
diff --git a/sandboxed_api/tools/clang_generator/emitter.cc b/sandboxed_api/tools/clang_generator/emitter.cc
index 2b6c644..5e6381c 100644
--- a/sandboxed_api/tools/clang_generator/emitter.cc
+++ b/sandboxed_api/tools/clang_generator/emitter.cc
@@ -238,10 +238,12 @@
}
if (const auto* record_decl = llvm::dyn_cast<clang::CXXRecordDecl>(decl)) {
- // For C++ classes/structs, only emit a forward declaration.
- return absl::StrCat(PrintRecordTemplateArguments(record_decl),
- record_decl->isClass() ? "class " : "struct ",
- ToStringView(record_decl->getName()));
+ if (!record_decl->isCLike()) {
+ // For C++ classes/structs, only emit a forward declaration.
+ return absl::StrCat(PrintRecordTemplateArguments(record_decl),
+ record_decl->isClass() ? "class " : "struct ",
+ ToStringView(record_decl->getName()));
+ }
}
return PrintDecl(decl);
}
@@ -423,8 +425,7 @@
return;
}
}
- ns_name = absl::StrCat(ns_path[0].empty() ? "" : " ",
- absl::StrJoin(ns_path, "::"));
+ ns_name = absl::StrJoin(ns_path, "::");
}
rendered_types_[ns_name].push_back(GetSpelling(decl));
diff --git a/sandboxed_api/tools/clang_generator/emitter_test.cc b/sandboxed_api/tools/clang_generator/emitter_test.cc
index 42739c7..9fb82b9 100644
--- a/sandboxed_api/tools/clang_generator/emitter_test.cc
+++ b/sandboxed_api/tools/clang_generator/emitter_test.cc
@@ -93,10 +93,68 @@
}
EXPECT_THAT(ugly_types,
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"));
}
+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) {
// Copybara will transform the string. This is intentional.
constexpr absl::string_view kGeneratedHeaderPrefix =