Use mangled type names in `cc_struct_upcast_impl`'s `cast_fn_name`.
PiperOrigin-RevId: 471545380
diff --git a/rs_bindings_from_cc/importer.cc b/rs_bindings_from_cc/importer.cc
index 7bda89f..2db25fa 100644
--- a/rs_bindings_from_cc/importer.cc
+++ b/rs_bindings_from_cc/importer.cc
@@ -854,24 +854,30 @@
}
std::string Importer::GetMangledName(const clang::NamedDecl* named_decl) const {
- if (auto specialization_decl =
- clang::dyn_cast<clang::ClassTemplateSpecializationDecl>(named_decl)) {
- // Itanium mangler produces valid Rust identifiers, use it to generate a
- // name for this instantiation.
+ if (auto record_decl = clang::dyn_cast<clang::RecordDecl>(named_decl)) {
+ // Mangled record names are used to 1) provide valid Rust identifiers for
+ // C++ template specializations, and 2) help build unique names for virtual
+ // upcast thunks.
llvm::SmallString<128> storage;
llvm::raw_svector_ostream buffer(storage);
- mangler_->mangleTypeName(ctx_.getRecordType(specialization_decl), buffer);
+ mangler_->mangleTypeName(ctx_.getRecordType(record_decl), buffer);
// The Itanium mangler does not provide a way to get the mangled
// representation of a type. Instead, we call mangleTypeName() that
// returns the name of the RTTI typeinfo symbol, and remove the _ZTS
- // prefix. Then we prepend __CcTemplateInst to reduce chances of conflict
- // with regular C and C++ structs.
+ // prefix.
constexpr llvm::StringRef kZtsPrefix = "_ZTS";
- constexpr llvm::StringRef kCcTemplatePrefix = "__CcTemplateInst";
CHECK(buffer.str().take_front(4) == kZtsPrefix);
- return llvm::formatv("{0}{1}", kCcTemplatePrefix,
- buffer.str().drop_front(kZtsPrefix.size()));
+ llvm::StringRef mangled_record_name =
+ buffer.str().drop_front(kZtsPrefix.size());
+
+ if (clang::isa<clang::ClassTemplateSpecializationDecl>(named_decl)) {
+ // We prepend __CcTemplateInst to reduce chances of conflict
+ // with regular C and C++ structs.
+ constexpr llvm::StringRef kCcTemplatePrefix = "__CcTemplateInst";
+ return llvm::formatv("{0}{1}", kCcTemplatePrefix, mangled_record_name);
+ }
+ return std::string(mangled_record_name);
}
clang::GlobalDecl decl;
diff --git a/rs_bindings_from_cc/importers/cxx_record.cc b/rs_bindings_from_cc/importers/cxx_record.cc
index 30aee17..f9c1ea7 100644
--- a/rs_bindings_from_cc/importers/cxx_record.cc
+++ b/rs_bindings_from_cc/importers/cxx_record.cc
@@ -203,6 +203,7 @@
return Record{
.rs_name = std::move(rs_name),
.cc_name = std::move(cc_name),
+ .mangled_cc_name = ictx_.GetMangledName(record_decl),
.id = GenerateItemId(record_decl),
.owning_target = ictx_.GetOwningTarget(record_decl),
.doc_comment = std::move(doc_comment),
diff --git a/rs_bindings_from_cc/ir.cc b/rs_bindings_from_cc/ir.cc
index e883223..9e4b77c 100644
--- a/rs_bindings_from_cc/ir.cc
+++ b/rs_bindings_from_cc/ir.cc
@@ -399,6 +399,7 @@
llvm::json::Object record{
{"rs_name", rs_name},
{"cc_name", cc_name},
+ {"mangled_cc_name", mangled_cc_name},
{"id", id},
{"owning_target", owning_target},
{"doc_comment", doc_comment},
diff --git a/rs_bindings_from_cc/ir.h b/rs_bindings_from_cc/ir.h
index b3eab93..5573849 100644
--- a/rs_bindings_from_cc/ir.h
+++ b/rs_bindings_from_cc/ir.h
@@ -576,6 +576,7 @@
// `rs_name` is similar to "__CcTemplateInst8MyStructIiE").
std::string rs_name;
std::string cc_name;
+ std::string mangled_cc_name;
ItemId id;
BazelLabel owning_target;
diff --git a/rs_bindings_from_cc/ir.rs b/rs_bindings_from_cc/ir.rs
index 4e3e404..05123ee 100644
--- a/rs_bindings_from_cc/ir.rs
+++ b/rs_bindings_from_cc/ir.rs
@@ -400,6 +400,7 @@
pub struct Record {
pub rs_name: String,
pub cc_name: String,
+ pub mangled_cc_name: String,
pub id: ItemId,
pub owning_target: BazelLabel,
pub doc_comment: Option<String>,
diff --git a/rs_bindings_from_cc/ir_from_cc_test.rs b/rs_bindings_from_cc/ir_from_cc_test.rs
index e1d3777..bad43c1 100644
--- a/rs_bindings_from_cc/ir_from_cc_test.rs
+++ b/rs_bindings_from_cc/ir_from_cc_test.rs
@@ -2170,6 +2170,7 @@
Record {
rs_name: "DerivedClass",
cc_name: "DerivedClass",
+ mangled_cc_name: "12DerivedClass",
id: ItemId(...),
owning_target: BazelLabel("//test:testing_target"),
doc_comment: Some(...),
@@ -2308,6 +2309,7 @@
Record {
rs_name: "SomeStruct" ...
cc_name: "SomeStruct" ...
+ mangled_cc_name: "10SomeStruct" ...
fields: [
Field {
identifier: Some("first_field"), ...
diff --git a/rs_bindings_from_cc/src_code_gen.rs b/rs_bindings_from_cc/src_code_gen.rs
index bd8bc85..f96b863 100644
--- a/rs_bindings_from_cc/src_code_gen.rs
+++ b/rs_bindings_from_cc/src_code_gen.rs
@@ -3165,11 +3165,9 @@
let offset = Literal::i64_unsuffixed(offset);
body = quote! {(derived as *const _ as *const u8).offset(#offset) as *const #base_name};
} else {
- // TODO(b/216195042): use mangled names here, or otherwise guarantee
- // non-collision.
let cast_fn_name = make_rs_ident(&format!(
"__crubit_dynamic_upcast__{}__to__{}",
- record.rs_name, base_record.rs_name
+ record.mangled_cc_name, base_record.mangled_cc_name
));
let base_cc_name = cc_type_name_for_record(base_record.as_ref(), ir)?;
let derived_cc_name = cc_type_name_for_record(record.as_ref(), ir)?;
@@ -5526,7 +5524,7 @@
quote! {
unsafe impl oops::Inherits<crate::VirtualBase> for crate::Derived {
unsafe fn upcast_ptr(derived: *const Self) -> *const crate::VirtualBase {
- crate::detail::__crubit_dynamic_upcast__Derived__to__VirtualBase(derived)
+ crate::detail::__crubit_dynamic_upcast__7Derived__to__11VirtualBase(derived)
}
}
}
diff --git a/rs_bindings_from_cc/test/golden/inheritance_rs_api.rs b/rs_bindings_from_cc/test/golden/inheritance_rs_api.rs
index 3fe1815..8930056 100644
--- a/rs_bindings_from_cc/test/golden/inheritance_rs_api.rs
+++ b/rs_bindings_from_cc/test/golden/inheritance_rs_api.rs
@@ -471,7 +471,7 @@
unsafe impl oops::Inherits<crate::Base1> for crate::VirtualBase1 {
unsafe fn upcast_ptr(derived: *const Self) -> *const crate::Base1 {
- crate::detail::__crubit_dynamic_upcast__VirtualBase1__to__Base1(derived)
+ crate::detail::__crubit_dynamic_upcast__12VirtualBase1__to__5Base1(derived)
}
}
@@ -574,7 +574,7 @@
unsafe impl oops::Inherits<crate::Base1> for crate::VirtualBase2 {
unsafe fn upcast_ptr(derived: *const Self) -> *const crate::Base1 {
- crate::detail::__crubit_dynamic_upcast__VirtualBase2__to__Base1(derived)
+ crate::detail::__crubit_dynamic_upcast__12VirtualBase2__to__5Base1(derived)
}
}
@@ -683,17 +683,17 @@
unsafe impl oops::Inherits<crate::VirtualBase1> for crate::VirtualDerived {
unsafe fn upcast_ptr(derived: *const Self) -> *const crate::VirtualBase1 {
- crate::detail::__crubit_dynamic_upcast__VirtualDerived__to__VirtualBase1(derived)
+ crate::detail::__crubit_dynamic_upcast__14VirtualDerived__to__12VirtualBase1(derived)
}
}
unsafe impl oops::Inherits<crate::Base1> for crate::VirtualDerived {
unsafe fn upcast_ptr(derived: *const Self) -> *const crate::Base1 {
- crate::detail::__crubit_dynamic_upcast__VirtualDerived__to__Base1(derived)
+ crate::detail::__crubit_dynamic_upcast__14VirtualDerived__to__5Base1(derived)
}
}
unsafe impl oops::Inherits<crate::VirtualBase2> for crate::VirtualDerived {
unsafe fn upcast_ptr(derived: *const Self) -> *const crate::VirtualBase2 {
- crate::detail::__crubit_dynamic_upcast__VirtualDerived__to__VirtualBase2(derived)
+ crate::detail::__crubit_dynamic_upcast__14VirtualDerived__to__12VirtualBase2(derived)
}
}
@@ -1091,7 +1091,7 @@
__this: ::std::pin::Pin<&'a mut crate::VirtualBase1>,
__param_0: ::ctor::RvalueReference<'b, crate::VirtualBase1>,
) -> ::std::pin::Pin<&'a mut crate::VirtualBase1>;
- pub fn __crubit_dynamic_upcast__VirtualBase1__to__Base1(
+ pub fn __crubit_dynamic_upcast__12VirtualBase1__to__5Base1(
from: *const crate::VirtualBase1,
) -> *const crate::Base1;
pub(crate) fn __rust_thunk___ZN12VirtualBase2C1Ev<'a>(
@@ -1113,7 +1113,7 @@
__this: ::std::pin::Pin<&'a mut crate::VirtualBase2>,
__param_0: ::ctor::RvalueReference<'b, crate::VirtualBase2>,
) -> ::std::pin::Pin<&'a mut crate::VirtualBase2>;
- pub fn __crubit_dynamic_upcast__VirtualBase2__to__Base1(
+ pub fn __crubit_dynamic_upcast__12VirtualBase2__to__5Base1(
from: *const crate::VirtualBase2,
) -> *const crate::Base1;
pub(crate) fn __rust_thunk___ZN14VirtualDerivedC1Ev<'a>(
@@ -1135,13 +1135,13 @@
__this: ::std::pin::Pin<&'a mut crate::VirtualDerived>,
__param_0: ::ctor::RvalueReference<'b, crate::VirtualDerived>,
) -> ::std::pin::Pin<&'a mut crate::VirtualDerived>;
- pub fn __crubit_dynamic_upcast__VirtualDerived__to__VirtualBase1(
+ pub fn __crubit_dynamic_upcast__14VirtualDerived__to__12VirtualBase1(
from: *const crate::VirtualDerived,
) -> *const crate::VirtualBase1;
- pub fn __crubit_dynamic_upcast__VirtualDerived__to__Base1(
+ pub fn __crubit_dynamic_upcast__14VirtualDerived__to__5Base1(
from: *const crate::VirtualDerived,
) -> *const crate::Base1;
- pub fn __crubit_dynamic_upcast__VirtualDerived__to__VirtualBase2(
+ pub fn __crubit_dynamic_upcast__14VirtualDerived__to__12VirtualBase2(
from: *const crate::VirtualDerived,
) -> *const crate::VirtualBase2;
pub(crate) fn __rust_thunk___ZN15MyAbstractClassaSERKS_<'a, 'b>(
diff --git a/rs_bindings_from_cc/test/golden/inheritance_rs_api_impl.cc b/rs_bindings_from_cc/test/golden/inheritance_rs_api_impl.cc
index 099a94c..ddf5f6d 100644
--- a/rs_bindings_from_cc/test/golden/inheritance_rs_api_impl.cc
+++ b/rs_bindings_from_cc/test/golden/inheritance_rs_api_impl.cc
@@ -222,28 +222,30 @@
#pragma clang diagnostic pop
-extern "C" const class Base1& __crubit_dynamic_upcast__VirtualBase1__to__Base1(
+extern "C" const class Base1&
+__crubit_dynamic_upcast__12VirtualBase1__to__5Base1(
const class VirtualBase1& from) {
return from;
}
-extern "C" const class Base1& __crubit_dynamic_upcast__VirtualBase2__to__Base1(
+extern "C" const class Base1&
+__crubit_dynamic_upcast__12VirtualBase2__to__5Base1(
const class VirtualBase2& from) {
return from;
}
extern "C" const class VirtualBase1&
-__crubit_dynamic_upcast__VirtualDerived__to__VirtualBase1(
+__crubit_dynamic_upcast__14VirtualDerived__to__12VirtualBase1(
const class VirtualDerived& from) {
return from;
}
extern "C" const class Base1&
-__crubit_dynamic_upcast__VirtualDerived__to__Base1(
+__crubit_dynamic_upcast__14VirtualDerived__to__5Base1(
const class VirtualDerived& from) {
return from;
}
extern "C" const class VirtualBase2&
-__crubit_dynamic_upcast__VirtualDerived__to__VirtualBase2(
+__crubit_dynamic_upcast__14VirtualDerived__to__12VirtualBase2(
const class VirtualDerived& from) {
return from;
}
diff --git a/rs_bindings_from_cc/test/golden/user_of_base_class_rs_api.rs b/rs_bindings_from_cc/test/golden/user_of_base_class_rs_api.rs
index 11382e8..5b5082d 100644
--- a/rs_bindings_from_cc/test/golden/user_of_base_class_rs_api.rs
+++ b/rs_bindings_from_cc/test/golden/user_of_base_class_rs_api.rs
@@ -120,7 +120,7 @@
unsafe impl oops::Inherits<inheritance_cc::Base0> for crate::Derived2 {
unsafe fn upcast_ptr(derived: *const Self) -> *const inheritance_cc::Base0 {
- crate::detail::__crubit_dynamic_upcast__Derived2__to__Base0(derived)
+ crate::detail::__crubit_dynamic_upcast__8Derived2__to__5Base0(derived)
}
}
unsafe impl oops::Inherits<inheritance_cc::Base1> for crate::Derived2 {
@@ -246,17 +246,17 @@
unsafe impl oops::Inherits<inheritance_cc::VirtualBase1> for crate::VirtualDerived2 {
unsafe fn upcast_ptr(derived: *const Self) -> *const inheritance_cc::VirtualBase1 {
- crate::detail::__crubit_dynamic_upcast__VirtualDerived2__to__VirtualBase1(derived)
+ crate::detail::__crubit_dynamic_upcast__15VirtualDerived2__to__12VirtualBase1(derived)
}
}
unsafe impl oops::Inherits<inheritance_cc::Base1> for crate::VirtualDerived2 {
unsafe fn upcast_ptr(derived: *const Self) -> *const inheritance_cc::Base1 {
- crate::detail::__crubit_dynamic_upcast__VirtualDerived2__to__Base1(derived)
+ crate::detail::__crubit_dynamic_upcast__15VirtualDerived2__to__5Base1(derived)
}
}
unsafe impl oops::Inherits<inheritance_cc::VirtualBase2> for crate::VirtualDerived2 {
unsafe fn upcast_ptr(derived: *const Self) -> *const inheritance_cc::VirtualBase2 {
- crate::detail::__crubit_dynamic_upcast__VirtualDerived2__to__VirtualBase2(derived)
+ crate::detail::__crubit_dynamic_upcast__15VirtualDerived2__to__12VirtualBase2(derived)
}
}
@@ -285,7 +285,7 @@
__this: ::std::pin::Pin<&'a mut crate::Derived2>,
__param_0: ::ctor::RvalueReference<'b, crate::Derived2>,
) -> ::std::pin::Pin<&'a mut crate::Derived2>;
- pub fn __crubit_dynamic_upcast__Derived2__to__Base0(
+ pub fn __crubit_dynamic_upcast__8Derived2__to__5Base0(
from: *const crate::Derived2,
) -> *const inheritance_cc::Base0;
pub(crate) fn __rust_thunk___ZN15VirtualDerived2C1Ev<'a>(
@@ -307,13 +307,13 @@
__this: ::std::pin::Pin<&'a mut crate::VirtualDerived2>,
__param_0: ::ctor::RvalueReference<'b, crate::VirtualDerived2>,
) -> ::std::pin::Pin<&'a mut crate::VirtualDerived2>;
- pub fn __crubit_dynamic_upcast__VirtualDerived2__to__VirtualBase1(
+ pub fn __crubit_dynamic_upcast__15VirtualDerived2__to__12VirtualBase1(
from: *const crate::VirtualDerived2,
) -> *const inheritance_cc::VirtualBase1;
- pub fn __crubit_dynamic_upcast__VirtualDerived2__to__Base1(
+ pub fn __crubit_dynamic_upcast__15VirtualDerived2__to__5Base1(
from: *const crate::VirtualDerived2,
) -> *const inheritance_cc::Base1;
- pub fn __crubit_dynamic_upcast__VirtualDerived2__to__VirtualBase2(
+ pub fn __crubit_dynamic_upcast__15VirtualDerived2__to__12VirtualBase2(
from: *const crate::VirtualDerived2,
) -> *const inheritance_cc::VirtualBase2;
}
diff --git a/rs_bindings_from_cc/test/golden/user_of_base_class_rs_api_impl.cc b/rs_bindings_from_cc/test/golden/user_of_base_class_rs_api_impl.cc
index 30e9905..95975fc 100644
--- a/rs_bindings_from_cc/test/golden/user_of_base_class_rs_api_impl.cc
+++ b/rs_bindings_from_cc/test/golden/user_of_base_class_rs_api_impl.cc
@@ -60,23 +60,23 @@
#pragma clang diagnostic pop
-extern "C" const class Base0& __crubit_dynamic_upcast__Derived2__to__Base0(
+extern "C" const class Base0& __crubit_dynamic_upcast__8Derived2__to__5Base0(
const struct Derived2& from) {
return from;
}
extern "C" const class VirtualBase1&
-__crubit_dynamic_upcast__VirtualDerived2__to__VirtualBase1(
+__crubit_dynamic_upcast__15VirtualDerived2__to__12VirtualBase1(
const class VirtualDerived2& from) {
return from;
}
extern "C" const class Base1&
-__crubit_dynamic_upcast__VirtualDerived2__to__Base1(
+__crubit_dynamic_upcast__15VirtualDerived2__to__5Base1(
const class VirtualDerived2& from) {
return from;
}
extern "C" const class VirtualBase2&
-__crubit_dynamic_upcast__VirtualDerived2__to__VirtualBase2(
+__crubit_dynamic_upcast__15VirtualDerived2__to__12VirtualBase2(
const class VirtualDerived2& from) {
return from;
}
diff --git a/rs_bindings_from_cc/test/struct/inheritance/upcast.h b/rs_bindings_from_cc/test/struct/inheritance/upcast.h
index a72e3fa..0174b77 100644
--- a/rs_bindings_from_cc/test/struct/inheritance/upcast.h
+++ b/rs_bindings_from_cc/test/struct/inheritance/upcast.h
@@ -82,4 +82,21 @@
} // namespace virtual_inheritance
+namespace another_namespace {
+
+// This class has the same name as another `VirtualBase2` above (in another
+// namespace) to check that upcast thunks have unique names that take the
+// namespace into account.
+class VirtualBase2 : public virtual Base1 {
+ public:
+ VirtualBase2() = default;
+
+ size_t base1_address() const {
+ const Base1* base = this;
+ return reinterpret_cast<size_t>(base);
+ }
+};
+
+} // namespace another_namespace
+
#endif // CRUBIT_RS_BINDINGS_FROM_CC_TEST_STRUCT_INHERITANCE_UPCAST_H_
diff --git a/rs_bindings_from_cc/test/struct/inheritance/upcast_test.rs b/rs_bindings_from_cc/test/struct/inheritance/upcast_test.rs
index be479b3..c3f9eae 100644
--- a/rs_bindings_from_cc/test/struct/inheritance/upcast_test.rs
+++ b/rs_bindings_from_cc/test/struct/inheritance/upcast_test.rs
@@ -5,7 +5,6 @@
mod tests {
use ctor::CtorNew as _;
use oops::Upcast as _;
- use upcast::virtual_inheritance::*;
use upcast::*;
#[test]
@@ -27,6 +26,7 @@
#[test]
fn test_virtual_upcast() {
+ use upcast::virtual_inheritance::*;
ctor::emplace! {
let derived = VirtualDerived::ctor_new(());
}
@@ -45,4 +45,16 @@
let base1: &Base1 = base3.upcast();
assert_eq!(base1 as *const _ as usize, base1_address);
}
+
+ #[test]
+ fn test_upcast_thunk_name_uniqueness() {
+ ctor::emplace! {
+ let derived = another_namespace::VirtualBase2::ctor_new(());
+ }
+ let derived = &*derived;
+
+ let base1: &Base1 = derived.upcast();
+ let base1_address = base1 as *const _ as usize;
+ assert_eq!(base1_address, derived.base1_address());
+ }
}