Unique names for parameters expanded from a template parameter pack.
Before this CL, all parameters expanded from a template parameter pack
would have the same name in the IR.
PiperOrigin-RevId: 449008529
diff --git a/rs_bindings_from_cc/importer.cc b/rs_bindings_from_cc/importer.cc
index 49c30cb..3c27643 100644
--- a/rs_bindings_from_cc/importer.cc
+++ b/rs_bindings_from_cc/importer.cc
@@ -810,12 +810,20 @@
switch (named_decl->getDeclName().getNameKind()) {
case clang::DeclarationName::Identifier: {
auto name = std::string(named_decl->getName());
- if (name.empty()) {
- if (const clang::ParmVarDecl* param_decl =
- clang::dyn_cast<clang::ParmVarDecl>(named_decl)) {
- int param_pos = param_decl->getFunctionScopeIndex();
+ if (const clang::ParmVarDecl* param_decl =
+ clang::dyn_cast<clang::ParmVarDecl>(named_decl)) {
+ int param_pos = param_decl->getFunctionScopeIndex();
+ if (name.empty()) {
return {Identifier(absl::StrCat("__param_", param_pos))};
}
+ if (auto* sttpt = param_decl->getType()
+ ->getAs<clang::SubstTemplateTypeParmType>();
+ sttpt && sttpt->getReplacedParameter()->isParameterPack()) {
+ // Avoid giving the same name to all parameters expanded from a pack.
+ return {Identifier(absl::StrCat("__", name, "_", param_pos))};
+ }
+ }
+ if (name.empty()) {
// TODO(lukasza): Handle anonymous structs (probably this won't be an
// issue until nested types are handled - b/200067824).
return std::nullopt;
diff --git a/rs_bindings_from_cc/ir_from_cc_test.rs b/rs_bindings_from_cc/ir_from_cc_test.rs
index d978e75..0898e09 100644
--- a/rs_bindings_from_cc/ir_from_cc_test.rs
+++ b/rs_bindings_from_cc/ir_from_cc_test.rs
@@ -1066,6 +1066,53 @@
}
#[test]
+fn test_subst_template_type_parm_pack_type() -> Result<()> {
+ let ir = ir_from_cc(
+ r#" #pragma clang lifetime_elision
+ template <typename... TArgs>
+ struct MyStruct {
+ static int GetSum(TArgs... my_args) { return (0 + ... + my_args); }
+ };
+ using MyTypeAlias = MyStruct<int, int>; "#,
+ )?;
+ assert_ir_matches!(
+ ir,
+ quote! {
+ Record(Record {
+ rs_name: "__CcTemplateInst8MyStructIJiiEE", ...
+ cc_name: "MyStruct<int, int>", ...
+ }),
+ }
+ );
+ assert_ir_matches!(
+ ir,
+ quote! {
+ Func {
+ name: "GetSum", ...
+ mangled_name: "_ZN8MyStructIJiiEE6GetSumEii___test_testing_target", ...
+ params: [
+ FuncParam {
+ type_: MappedType {
+ rs_type: RsType { name: Some("i32"), ... },
+ cc_type: CcType { name: Some("int"), ... },
+ },
+ identifier: "__my_args_0",
+ },
+ FuncParam {
+ type_: MappedType {
+ rs_type: RsType { name: Some("i32"), ... },
+ cc_type: CcType { name: Some("int"), ... },
+ },
+ identifier: "__my_args_1",
+ },
+ ], ...
+ }
+ }
+ );
+ Ok(())
+}
+
+#[test]
fn test_no_instantiation_of_template_only_used_in_private_field() -> Result<()> {
let ir = ir_from_cc(
r#" #pragma clang lifetime_elision