Add trivial destructor flags to the IR.
Actually we don't need this, but I had it written anyway...
At the very least, we can omit calls to the destructor if it's trivial, and have an empty Drop impl. At the *most*, we can omit the Drop impl entirely, but this would mean that adding a nontrivial destructor can trigger dropck in Rust code, and isn't super compatible -- we need to talk about this separately.
In order to walk source files that even *have* destructors defined in them, without crashing, we actually also need to check that the identifier for the function is representable before converting to an Identifier, so we do that also.
PiperOrigin-RevId: 400951408
diff --git a/rs_bindings_from_cc/ast_visitor.cc b/rs_bindings_from_cc/ast_visitor.cc
index 131f938..009c2a5 100644
--- a/rs_bindings_from_cc/ast_visitor.cc
+++ b/rs_bindings_from_cc/ast_visitor.cc
@@ -54,7 +54,12 @@
// TODO(b/200239975): Add diagnostics for declarations we can't import
return true;
}
- params.push_back({*param_type, GetTranslatedName(param)});
+ std::optional<Identifier> param_name = GetTranslatedName(param);
+ if (!param_name.has_value()) {
+ // TODO(b/200239975): Add diagnostics for declarations we can't import
+ return true;
+ }
+ params.push_back({*param_type, *std::move(param_name)});
}
auto return_type = ConvertType(function_decl->getReturnType(),
@@ -62,8 +67,13 @@
if (!return_type.ok()) {
return true;
}
+ std::optional<Identifier> translated_name = GetTranslatedName(function_decl);
+ if (!translated_name.has_value()) {
+ // For example, the destructor.
+ return true;
+ }
ir_.items.push_back(Func{
- .identifier = GetTranslatedName(function_decl),
+ .identifier = *translated_name,
.mangled_name = GetMangledName(function_decl),
.return_type = *return_type,
.params = std::move(params),
@@ -102,6 +112,10 @@
.definition = SpecialMemberFunc::Definition::kTrivial,
.access = kPublic,
};
+ SpecialMemberFunc dtor = {
+ .definition = SpecialMemberFunc::Definition::kTrivial,
+ .access = kPublic,
+ };
if (const auto* cxx_record_decl =
clang::dyn_cast<clang::CXXRecordDecl>(record_decl)) {
if (cxx_record_decl->isClass()) {
@@ -128,6 +142,12 @@
move_ctor.definition = SpecialMemberFunc::Definition::kDeleted;
}
+ if (cxx_record_decl->hasTrivialDestructor()) {
+ dtor.definition = SpecialMemberFunc::Definition::kTrivial;
+ } else {
+ dtor.definition = SpecialMemberFunc::Definition::kNontrivial;
+ }
+
for (clang::CXXConstructorDecl* ctor_decl : cxx_record_decl->ctors()) {
if (ctor_decl->isCopyConstructor()) {
copy_ctor.access = TranslateAccessSpecifier(ctor_decl->getAccess());
@@ -141,6 +161,13 @@
}
}
}
+ clang::CXXDestructorDecl* dtor_decl = cxx_record_decl->getDestructor();
+ if (dtor_decl != nullptr) {
+ dtor.access = TranslateAccessSpecifier(dtor_decl->getAccess());
+ if (dtor_decl->isDeleted()) {
+ dtor.definition = SpecialMemberFunc::Definition::kDeleted;
+ }
+ }
}
const clang::ASTRecordLayout& layout =
record_decl->getASTContext().getASTRecordLayout(record_decl);
@@ -154,19 +181,29 @@
if (access == clang::AS_none) {
access = default_access;
}
+
+ std::optional<Identifier> field_name = GetTranslatedName(field_decl);
+ if (!field_name.has_value()) {
+ return true;
+ }
fields.push_back(
- {.identifier = GetTranslatedName(field_decl),
+ {.identifier = *std::move(field_name),
.type = *type,
.access = TranslateAccessSpecifier(access),
.offset = layout.getFieldOffset(field_decl->getFieldIndex())});
}
+ std::optional<Identifier> record_name = GetTranslatedName(record_decl);
+ if (!record_name.has_value()) {
+ return true;
+ }
ir_.items.push_back(
- Record{.identifier = GetTranslatedName(record_decl),
+ Record{.identifier = *record_name,
.fields = std::move(fields),
.size = layout.getSize().getQuantity(),
.alignment = layout.getAlignment().getQuantity(),
.copy_constructor = copy_ctor,
.move_constructor = move_ctor,
+ .destructor = dtor,
.is_trivial_abi = record_decl->canPassInRegisters()});
return true;
}
@@ -240,9 +277,13 @@
return name;
}
-Identifier AstVisitor::GetTranslatedName(
+std::optional<Identifier> AstVisitor::GetTranslatedName(
const clang::NamedDecl* named_decl) const {
- return Identifier(std::string(named_decl->getName()));
+ clang::IdentifierInfo* id = named_decl->getIdentifier();
+ if (id == nullptr) {
+ return std::nullopt;
+ }
+ return Identifier(std::string(id->getName()));
}
} // namespace rs_bindings_from_cc