Clang tool: Emit aggregates with default initialized members

PiperOrigin-RevId: 556765694
Change-Id: I2547919cdc1fcb048c99de325a8b2c24800b0e06
This commit is contained in:
Christian Blichmann 2023-08-14 06:13:51 -07:00 committed by Copybara-Service
parent 8b70461db4
commit 352d1f8fb2
2 changed files with 60 additions and 5 deletions

View File

@ -247,12 +247,20 @@ std::string GetSpelling(const clang::Decl* 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.
return absl::StrCat(PrintRecordTemplateArguments(record_decl),
record_decl->isClass() ? "class " : "struct ",
ToStringView(record_decl->getName()));
if (record_decl->hasDefinition() &&
// Aggregates capture all C-like structs, but also structs with
// non-static members that have default initializers.
record_decl->isAggregate() &&
// Make sure to skip types with user-defined methods (including
// constructors).
record_decl->methods().empty()) {
return PrintDecl(decl);
}
// For unsupported types or types with no definition, only emit a forward
// declaration.
return absl::StrCat(PrintRecordTemplateArguments(record_decl),
record_decl->isClass() ? "class " : "struct ",
ToStringView(record_decl->getName()));
}
return PrintDecl(decl);
}

View File

@ -201,6 +201,53 @@ TEST_F(EmitterTest, ParentNotCollected) {
" int data; }"));
}
TEST_F(EmitterTest, StructForwardDecl) {
EmitterForTesting emitter;
ASSERT_THAT(
RunFrontendAction(
R"(struct A;
extern "C" void UsingForwardDeclaredStruct(A* s);)",
std::make_unique<GeneratorAction>(emitter, GeneratorOptions())),
IsOk());
EXPECT_THAT(UglifyAll(emitter.SpellingsForNS("")), ElementsAre("struct A"));
}
TEST_F(EmitterTest, AggregateStructWithDefaultedMembers) {
EmitterForTesting emitter;
ASSERT_THAT(
RunFrontendAction(
R"(struct A {
int a = 0;
int b = 42;
};
extern "C" void AggregateStruct(A* s);)",
std::make_unique<GeneratorAction>(emitter, GeneratorOptions())),
IsOk());
EXPECT_THAT(UglifyAll(emitter.SpellingsForNS("")),
ElementsAre("struct A {"
" int a = 0;"
" int b = 42; }"));
}
TEST_F(EmitterTest, AggregateStructWithMethods) {
EmitterForTesting emitter;
ASSERT_THAT(
RunFrontendAction(
R"(struct A {
int a = 0;
int b = 42;
int my_mem_fn();
};
extern "C" void AggregateStruct(A* s);)",
std::make_unique<GeneratorAction>(emitter, GeneratorOptions())),
IsOk());
// Expect a forward decl in this case
EXPECT_THAT(UglifyAll(emitter.SpellingsForNS("")), ElementsAre("struct A"));
}
TEST_F(EmitterTest, RemoveQualifiers) {
EmitterForTesting emitter;
ASSERT_THAT(