Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 10 additions & 6 deletions common/code_gen_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -378,12 +378,16 @@ impl NamespaceQualifier {

/// Returns `foo::bar::baz::` (reporting errors for C++ keywords).
pub fn format_for_cc(&self) -> Result<TokenStream> {
let namespace_cc_idents = self.cc_idents()?;
Ok(quote! { #(#namespace_cc_idents::)* })
}

pub fn cc_idents(&self) -> Result<Vec<Ident>> {
self.parts().map(|ns| format_cc_ident(ns)).collect()
let mut path = quote! {};
for namespace in &self.namespaces {
let namespace = format_cc_ident(namespace)?;
path.extend(quote! { #namespace :: });
}
for (_rs_name, cc_name) in &self.nested_records {
let cc_name = format_cc_type_name(cc_name)?;
path.extend(quote! { #cc_name ::});
}
Ok(path)
}
}

Expand Down
23 changes: 2 additions & 21 deletions rs_bindings_from_cc/generate_bindings/cpp_type_name.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,25 +137,6 @@ pub fn format_cpp_type_inner(
/// For example, for `namespace x { struct Y { using X = int; }; }`, the name
/// for `X` is `x::Y::X`.
pub fn tagless_cpp_type_name_for_item(item: &ir::Item, ir: &IR) -> Result<TokenStream> {
/// Returns the namespace / class qualifiers necessary to access the item.
///
/// For example, for `namespace x { struct Y { using X = int; }; }`, the prefix
/// for `X` is `x::Y::`.
fn cpp_qualified_path_prefix(item: &ir::Item, ir: &ir::IR) -> Result<TokenStream> {
let Some(parent) = item.enclosing_item_id() else {
return Ok(quote! {});
};
let parent: &ir::Item = ir.find_decl(parent)?;
match parent {
ir::Item::Namespace(_) => Ok(ir.namespace_qualifier(item).format_for_cc()?),
ir::Item::Record(r) => {
let name = cpp_tagless_type_name_for_record(r, ir)?;
Ok(quote! {#name ::})
}
_ => bail!("Unexpected enclosing item: {item:?}"),
}
}

match item {
Item::IncompleteRecord(incomplete_record) => {
let ident = expect_format_cc_type_name(incomplete_record.cc_name.identifier.as_ref());
Expand All @@ -165,12 +146,12 @@ pub fn tagless_cpp_type_name_for_item(item: &ir::Item, ir: &IR) -> Result<TokenS
Item::Record(record) => cpp_tagless_type_name_for_record(record, ir),
Item::Enum(enum_) => {
let ident = expect_format_cc_type_name(&enum_.rs_name.identifier);
let namespace_qualifier = cpp_qualified_path_prefix(item, ir)?;
let namespace_qualifier = ir.namespace_qualifier(item).format_for_cc()?;
Ok(quote! { #namespace_qualifier #ident })
}
Item::TypeAlias(type_alias) => {
let ident = expect_format_cc_type_name(&type_alias.cc_name.identifier);
let namespace_qualifier = cpp_qualified_path_prefix(item, ir)?;
let namespace_qualifier = ir.namespace_qualifier(item).format_for_cc()?;
Ok(quote! { #namespace_qualifier #ident })
}
Item::ExistingRustType(existing_rust_type) => existing_rust_type
Expand Down
73 changes: 25 additions & 48 deletions rs_bindings_from_cc/generate_bindings/generate_function_thunk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -260,44 +260,32 @@ fn generate_function_assertation_for_identifier(
let ir = db.ir();

let fn_ident = expect_format_cc_ident(&id.identifier);
let path_to_func = ir.namespace_qualifier(func).format_for_cc()?;
let implementation_function = quote! { :: #path_to_func #fn_ident };
let method_qualification;
let implementation_function;
let member_function_prefix;
let func_params;
if let Some(meta) = func.member_func_metadata.as_ref() {
let record: &Rc<Record> = ir.find_decl(meta.record_id)?;
let record_ident = expect_format_cc_type_name(record.cc_name.identifier.as_ref());
let namespace_qualifier = ir.namespace_qualifier(record).format_for_cc()?;
if let Some(instance_method_metadata) = meta.instance_method_metadata.as_ref() {
let const_qualifier = if instance_method_metadata.is_const {
quote! {const}
} else {
quote! {}
};

method_qualification = match instance_method_metadata.reference {
ir::ReferenceQualification::Unqualified => const_qualifier,
ir::ReferenceQualification::LValue => {
quote! { #const_qualifier & }
}
ir::ReferenceQualification::RValue => {
quote! { #const_qualifier && }
}
};
implementation_function = quote! { #namespace_qualifier #record_ident :: #fn_ident };
member_function_prefix = quote! { :: #namespace_qualifier #record_ident :: };
// The first parameter of instance methods is `this`.
func_params = &func.params[1..];
if let Some(instance_method_metadata) = func.instance_method_metadata() {
let const_qualifier = if instance_method_metadata.is_const {
quote! {const}
} else {
method_qualification = quote! {};
implementation_function = quote! { #namespace_qualifier #record_ident :: #fn_ident };
member_function_prefix = quote! {};
func_params = &func.params[..];
}
quote! {}
};

method_qualification = match instance_method_metadata.reference {
ir::ReferenceQualification::Unqualified => const_qualifier,
ir::ReferenceQualification::LValue => {
quote! { #const_qualifier & }
}
ir::ReferenceQualification::RValue => {
quote! { #const_qualifier && }
}
};
member_function_prefix = path_to_func;
// The first parameter of instance methods is `this`.
func_params = &func.params[1..];
} else {
let namespace_qualifier = ir.namespace_qualifier(func).format_for_cc()?;
method_qualification = quote! {};
implementation_function = quote! { #namespace_qualifier #fn_ident };
member_function_prefix = quote! {};
func_params = &func.params[..];
}
Expand Down Expand Up @@ -394,22 +382,11 @@ pub fn generate_function_thunk_impl(
}
UnqualifiedIdentifier::Identifier(id) => {
let fn_ident = expect_format_cc_ident(&id.identifier);
match func.member_func_metadata.as_ref() {
Some(meta) => {
if meta.instance_method_metadata.is_some() {
quote! { #fn_ident }
} else {
let record: &Rc<Record> = ir.find_decl(meta.record_id)?;
let record_name =
expect_format_cc_type_name(record.cc_name.identifier.as_ref());
let namespace_qualifier = ir.namespace_qualifier(record).format_for_cc()?;
quote! { #namespace_qualifier #record_name :: #fn_ident }
}
}
None => {
let namespace_qualifier = ir.namespace_qualifier(func).format_for_cc()?;
quote! { #namespace_qualifier #fn_ident }
}
let namespace_qualifier = ir.namespace_qualifier(func).format_for_cc()?;
if func.instance_method_metadata().is_some() {
quote! {#fn_ident}
} else {
quote! { #namespace_qualifier #fn_ident }
}
}
// Use `destroy_at` to avoid needing to spell out the class name. Destructor identiifers
Expand Down
13 changes: 9 additions & 4 deletions rs_bindings_from_cc/ir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -909,11 +909,16 @@ impl GenericItem for Func {
}

impl Func {
pub fn instance_method_metadata(&self) -> Option<&InstanceMethodMetadata> {
if let Some(meta) = &self.member_func_metadata {
if let Some(instance_method_metadata) = &meta.instance_method_metadata {
return Some(instance_method_metadata);
}
}
None
}
pub fn is_instance_method(&self) -> bool {
self.member_func_metadata
.as_ref()
.filter(|meta| meta.instance_method_metadata.is_some())
.is_some()
self.instance_method_metadata().is_some()
}
}

Expand Down
10 changes: 5 additions & 5 deletions rs_bindings_from_cc/test/annotations/do_not_bind_api_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ __rust_thunk___ZN6crubit4test11DoNotBindFnENS0_23ArgumentToBoundOverloadE(
crubit::test::DoNotBindFn(std::move(*__param_0));
}

static_assert((void (*)(
struct crubit::test::ArgumentToBoundOverload))&crubit::test::DoNotBindFn);
static_assert((void (*)(struct crubit::test::ArgumentToBoundOverload)) &
::crubit::test::DoNotBindFn);

static_assert(sizeof(struct crubit::test::StructWithDoNotBindConstructor) == 1);
static_assert(alignof(struct crubit::test::StructWithDoNotBindConstructor) ==
Expand Down Expand Up @@ -70,8 +70,8 @@ __rust_thunk___ZN6crubit4test25StructWithDoNotBindMethod15DoNotBindMethodENS0_23
__this->DoNotBindMethod(std::move(*__param_0));
}

static_assert((void (::crubit::test::StructWithDoNotBindMethod::*)(
struct crubit::test::ArgumentToBoundOverload))&crubit::test::
StructWithDoNotBindMethod::DoNotBindMethod);
static_assert((void (crubit::test::StructWithDoNotBindMethod::*)(
struct crubit::test::ArgumentToBoundOverload)) &
::crubit::test::StructWithDoNotBindMethod::DoNotBindMethod);

#pragma clang diagnostic pop
2 changes: 1 addition & 1 deletion rs_bindings_from_cc/test/annotations/owned_ptr_api_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,6 @@ extern "C" void __rust_thunk___ZN5Thing5CloseEv(struct Thing* __this) {
__this->Close();
}

static_assert((void (::Thing::*)())&Thing::Close);
static_assert((void (Thing::*)()) & ::Thing::Close);

#pragma clang diagnostic pop
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wthread-safety-analysis"

static_assert((struct Thing * (*)(int)) & MakeOwnedThing);
static_assert((struct Thing * (*)(int)) & ::MakeOwnedThing);

static_assert((struct Thing * (*)(int)) & MakeThing);
static_assert((struct Thing * (*)(int)) & ::MakeThing);

static_assert((int (*)(struct Thing*))&ThingToValue);
static_assert((int (*)(struct Thing*)) & ::ThingToValue);

static_assert((int (*)(struct Thing*))&GetThingValue);
static_assert((int (*)(struct Thing*)) & ::GetThingValue);

#pragma clang diagnostic pop
6 changes: 3 additions & 3 deletions rs_bindings_from_cc/test/annotations/rust_name_api_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ extern "C" void __rust_thunk___ZN6crubit4test13FreeFnOldNameEv() {
crubit::test::FreeFnOldName();
}

static_assert((void (*)())&crubit::test::FreeFnOldName);
static_assert((void (*)()) & ::crubit::test::FreeFnOldName);

static_assert(sizeof(struct crubit::test::StructOldName) == 1);
static_assert(alignof(struct crubit::test::StructOldName) == 1);
Expand Down Expand Up @@ -53,7 +53,7 @@ extern "C" void __rust_thunk___ZNK6crubit4test10SomeStruct13MethodOldNameEv(
__this->MethodOldName();
}

static_assert((void (::crubit::test::SomeStruct::*)() const) &
crubit::test::SomeStruct::MethodOldName);
static_assert((void (crubit::test::SomeStruct::*)() const) &
::crubit::test::SomeStruct::MethodOldName);

#pragma clang diagnostic pop
8 changes: 4 additions & 4 deletions rs_bindings_from_cc/test/function/inline/inline_api_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ extern "C" int __rust_thunk___Z18hello_world_inlinev() {
return hello_world_inline();
}

static_assert((int (*)())&hello_world_inline);
static_assert((int (*)()) & ::hello_world_inline);

static_assert(CRUBIT_SIZEOF(struct SomeStruct) == 4);
static_assert(alignof(struct SomeStruct) == 4);
Expand All @@ -38,19 +38,19 @@ extern "C" int __rust_thunk___Z24take_struct_by_const_ptrPK10SomeStruct(
return take_struct_by_const_ptr(s);
}

static_assert((int (*)(struct SomeStruct const*))&take_struct_by_const_ptr);
static_assert((int (*)(struct SomeStruct const*)) & ::take_struct_by_const_ptr);

extern "C" unsigned int __rust_thunk___Z19double_unsigned_intj(unsigned int i) {
return double_unsigned_int(i);
}

static_assert((unsigned int (*)(unsigned int))&double_unsigned_int);
static_assert((unsigned int (*)(unsigned int)) & ::double_unsigned_int);

extern "C" int __rust_thunk___ZN10namespaced24forward_declared_doublerEi(
int x) {
return namespaced::forward_declared_doubler(x);
}

static_assert((int (*)(int))&namespaced::forward_declared_doubler);
static_assert((int (*)(int)) & ::namespaced::forward_declared_doubler);

#pragma clang diagnostic pop
35 changes: 18 additions & 17 deletions rs_bindings_from_cc/test/function/simple/simple_api_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -19,50 +19,51 @@
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wthread-safety-analysis"

static_assert((int (*)())&return_value);
static_assert((int (*)()) & ::return_value);

static_assert((int* (*)())&return_pointer);
static_assert((int* (*)()) & ::return_pointer);

static_assert((int& (*)())&return_reference);
static_assert((int& (*)()) & ::return_reference);

static_assert((void (*)(int*))&take_pointer);
static_assert((void (*)(int*)) & ::take_pointer);

static_assert((void (*)(int&))&take_reference);
static_assert((void (*)(int&)) & ::take_reference);

static_assert((int const* (*)(int const*)) & forward_pointer);
static_assert((int const* (*)(int const*)) & ::forward_pointer);

static_assert((int const& (*)(int const&)) & forward_reference);
static_assert((int const& (*)(int const&)) & ::forward_reference);

static_assert((int (*)(int, int))&multiply);
static_assert((int (*)(int, int)) & ::multiply);

static_assert((int (*)(int, int))&multiply_with_unnamed_parameters);
static_assert((int (*)(int, int)) & ::multiply_with_unnamed_parameters);

static_assert((int (*)(int, int, int))&multiply_with_keyword_named_parameters);
static_assert((int (*)(int, int, int)) &
::multiply_with_keyword_named_parameters);

static_assert((int (*)())&llvm_no_mangle_marker);
static_assert((int (*)()) & ::llvm_no_mangle_marker);

static_assert((int (*)())&asm_name_with_dollar_sign);
static_assert((int (*)()) & ::asm_name_with_dollar_sign);

static_assert((crubit::type_identity_t<int(int, int)> * (*)()) &
get_pointer_to_multiply_function);
::get_pointer_to_multiply_function);

static_assert((crubit::type_identity_t<int(int, int)> & (*)()) &
get_reference_to_multiply_function);
::get_reference_to_multiply_function);

extern "C" crubit::type_identity_t<int(int, int)>*
__rust_thunk___Z39inline_get_pointer_to_multiply_functionv() {
return inline_get_pointer_to_multiply_function();
}

static_assert((crubit::type_identity_t<int(int, int)> * (*)()) &
inline_get_pointer_to_multiply_function);
::inline_get_pointer_to_multiply_function);

extern "C" int __rust_thunk___Z15apply_binary_opiiPFiiiE(
int x, int y, crubit::type_identity_t<int(int, int)>* op) {
return apply_binary_op(x, y, op);
}

static_assert((int (*)(
int, int, crubit::type_identity_t<int(int, int)>*))&apply_binary_op);
static_assert((int (*)(int, int, crubit::type_identity_t<int(int, int)>*)) &
::apply_binary_op);

#pragma clang diagnostic pop
4 changes: 2 additions & 2 deletions rs_bindings_from_cc/test/golden/bridge_type_rs_api_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ extern "C" void __rust_thunk___Z15ReturnCppStructv(void* __return) {
cpp_to_rust_converter(&__original_cpp_struct, __return);
}

static_assert((struct CppStruct (*)())&ReturnCppStruct);
static_assert((struct CppStruct (*)()) & ::ReturnCppStruct);

extern "C" void rust_to_cpp_converter(void* rust_struct, void* cpp_struct);
extern "C" void __rust_thunk___Z13TakeCppStruct9CppStruct(void* __param_0) {
Expand All @@ -34,6 +34,6 @@ extern "C" void __rust_thunk___Z13TakeCppStruct9CppStruct(void* __param_0) {
TakeCppStruct(std::move(*&(__converted___param_0.val)));
}

static_assert((void (*)(struct CppStruct))&TakeCppStruct);
static_assert((void (*)(struct CppStruct)) & ::TakeCppStruct);

#pragma clang diagnostic pop
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,12 @@ extern "C" MyI8 __rust_thunk___Z3ffi4MyI81X(MyI8 a, struct X* b) {
return ffi(std::move(a), std::move(*b));
}

static_assert((MyI8 (*)(MyI8, struct X))&ffi);
static_assert((MyI8 (*)(MyI8, struct X)) & ::ffi);

extern "C" void __rust_thunk___Z1fiPvi(MyTypedefDecl a, void* b, int c) {
f(a, b, c);
}

static_assert((void (*)(MyTypedefDecl, void*, int))&f);
static_assert((void (*)(MyTypedefDecl, void*, int)) & ::f);

#pragma clang diagnostic pop
2 changes: 1 addition & 1 deletion rs_bindings_from_cc/test/golden/callables_rs_api_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,6 @@ extern "C" int __rust_thunk___ZNK17NotCABICompatible3getEv(
return __this->get();
}

static_assert((int (::NotCABICompatible::*)() const) & NotCABICompatible::get);
static_assert((int (NotCABICompatible::*)() const) & ::NotCABICompatible::get);

#pragma clang diagnostic pop
2 changes: 1 addition & 1 deletion rs_bindings_from_cc/test/golden/comment_rs_api_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ extern "C" void __rust_thunk___ZN3FooC1Ev(struct Foo* __this) {

extern "C" void __rust_thunk___Z3foov() { foo(); }

static_assert((void (*)())&foo);
static_assert((void (*)()) & ::foo);

static_assert(CRUBIT_SIZEOF(struct Bar) == 4);
static_assert(alignof(struct Bar) == 4);
Expand Down
Loading