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,13 +247,21 @@ 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()) { if (record_decl->hasDefinition() &&
// For C++ classes/structs, only emit a forward declaration. // 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), 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);
} }

View File

@ -201,6 +201,53 @@ TEST_F(EmitterTest, ParentNotCollected) {
" int data; }")); " 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) { TEST_F(EmitterTest, RemoveQualifiers) {
EmitterForTesting emitter; EmitterForTesting emitter;
ASSERT_THAT( ASSERT_THAT(