Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add custom attributes to fn items #3088

Open
wants to merge 19 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 5 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
24 changes: 20 additions & 4 deletions bindgen/callbacks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
pub use crate::ir::analysis::DeriveTrait;
pub use crate::ir::derive::CanDerive as ImplementsTrait;
pub use crate::ir::enum_ty::{EnumVariantCustomBehavior, EnumVariantValue};
pub use crate::ir::function::FunctionKind;
pub use crate::ir::int::IntKind;
use std::fmt;

Expand Down Expand Up @@ -231,15 +232,30 @@ pub struct DeriveInfo<'a> {
pub kind: TypeKind,
}

/// Relevant information about a type to which new attributes will be added using
/// Relevant information about an item to which new attributes will be added using
/// [`ParseCallbacks::add_attributes`].
#[derive(Debug)]
#[non_exhaustive]
pub struct AttributeInfo<'a> {
/// The name of the type.
/// The name of the item.
pub name: &'a str,
/// The kind of the type.
pub kind: TypeKind,
/// The kind of the item.
pub kind: AttributeItemKind,
/// The kind of a method item.
pub fn_kind: Option<FunctionKind>,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
/// The kind of the current item.
pub enum AttributeItemKind {
/// The item is a Rust `struct`.
Struct,
/// The item is a Rust `enum`.
Enum,
/// The item is a Rust `union`.
Union,
/// The item is a Rust `fn`.
Function,
oberrich marked this conversation as resolved.
Show resolved Hide resolved
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
Expand Down
39 changes: 30 additions & 9 deletions bindgen/codegen/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ use self::struct_layout::StructLayoutTracker;
use super::BindgenOptions;

use crate::callbacks::{
AttributeInfo, DeriveInfo, DiscoveredItem, DiscoveredItemId, FieldInfo,
TypeKind as DeriveTypeKind,
AttributeInfo, AttributeItemKind, DeriveInfo, DiscoveredItem,
DiscoveredItemId, FieldInfo, TypeKind as DeriveTypeKind,
};
use crate::codegen::error::Error;
use crate::ir::analysis::{HasVtable, Sizedness};
Expand Down Expand Up @@ -1070,7 +1070,8 @@ impl CodeGenerator for Type {
ctx.options().all_callbacks(|cb| {
cb.add_attributes(&AttributeInfo {
name: &name,
kind: DeriveTypeKind::Struct,
kind: AttributeItemKind::Struct,
fn_kind: None,
})
});
attributes.extend(
Expand Down Expand Up @@ -2533,10 +2534,11 @@ impl CodeGenerator for CompInfo {
cb.add_attributes(&AttributeInfo {
name: &canonical_name,
kind: if is_rust_union {
DeriveTypeKind::Union
AttributeItemKind::Union
} else {
DeriveTypeKind::Struct
AttributeItemKind::Struct
},
fn_kind: None,
})
});
attributes.extend(custom_attributes.iter().map(|s| s.parse().unwrap()));
Expand Down Expand Up @@ -3064,11 +3066,11 @@ impl Method {

method_names.insert(name.clone());

let mut function_name = function_item.canonical_name(ctx);
let mut canonical_name = function_item.canonical_name(ctx);
if times_seen > 0 {
write!(&mut function_name, "{times_seen}").unwrap();
write!(&mut canonical_name, "{times_seen}").unwrap();
}
let function_name = ctx.rust_ident(function_name);
let function_name = ctx.rust_ident(&canonical_name);
let mut args = utils::fnsig_arguments(ctx, signature);
let mut ret = utils::fnsig_return_ty(ctx, signature);

Expand Down Expand Up @@ -3148,6 +3150,15 @@ impl Method {

let mut attrs = vec![attributes::inline()];

let custom_attributes = ctx.options().all_callbacks(|cb| {
cb.add_attributes(&AttributeInfo {
name: &canonical_name,
kind: AttributeItemKind::Function,
fn_kind: Some(FunctionKind::Method(self.kind())),
})
});
attrs.extend(custom_attributes.iter().map(|s| s.parse().unwrap()));

if signature.must_use() {
attrs.push(attributes::must_use());
}
Expand Down Expand Up @@ -3728,7 +3739,8 @@ impl CodeGenerator for Enum {
let custom_attributes = ctx.options().all_callbacks(|cb| {
cb.add_attributes(&AttributeInfo {
name: &name,
kind: DeriveTypeKind::Enum,
kind: AttributeItemKind::Enum,
fn_kind: None,
})
});
attrs.extend(custom_attributes.iter().map(|s| s.parse().unwrap()));
Expand Down Expand Up @@ -4593,6 +4605,15 @@ impl CodeGenerator for Function {

let mut attributes = vec![];

let custom_attributes = ctx.options().all_callbacks(|cb| {
cb.add_attributes(&AttributeInfo {
name: &canonical_name,
kind: AttributeItemKind::Function,
fn_kind: Some(self.kind()),
})
});
attributes.extend(custom_attributes.iter().map(|s| s.parse().unwrap()));

if true {
let must_use = signature.must_use() || {
let ret_ty = signature
Expand Down
2 changes: 1 addition & 1 deletion bindgen/ir/comp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ pub(crate) enum CompKind {

/// The kind of C++ method.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub(crate) enum MethodKind {
pub enum MethodKind {
/// A constructor. We represent it as method for convenience, to avoid code
/// duplication.
Constructor,
Expand Down
2 changes: 1 addition & 1 deletion bindgen/ir/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ const RUST_DERIVE_FUNPTR_LIMIT: usize = 12;

/// What kind of function are we looking at?
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub(crate) enum FunctionKind {
pub enum FunctionKind {
/// A plain, free function.
Function,
/// A method of some kind.
Expand Down
35 changes: 26 additions & 9 deletions bindgen/options/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
use crate::{
builder,
callbacks::{
AttributeInfo, DeriveInfo, ItemInfo, ParseCallbacks, TypeKind,
AttributeInfo, AttributeItemKind, DeriveInfo, ItemInfo, ParseCallbacks,
TypeKind,
},
features::{RustEdition, EARLIEST_STABLE_RUST},
regex_set::RegexSet,
Expand Down Expand Up @@ -477,7 +478,7 @@ struct BindgenCommand {
/// Derive custom traits on a `union`. The CUSTOM value must be of the shape REGEX=DERIVE where DERIVE is a coma-separated list of derive macros.
#[arg(long, value_name = "CUSTOM", value_parser = parse_custom_derive)]
with_derive_custom_union: Vec<(Vec<String>, String)>,
/// Add custom attributes on any kind of type. The CUSTOM value must be of the shape REGEX=ATTRIBUTE where ATTRIBUTE is a coma-separated list of attributes.
/// Add custom attributes on any item. The CUSTOM value must be of the shape REGEX=ATTRIBUTE where ATTRIBUTE is a coma-separated list of attributes.
#[arg(long, value_name = "CUSTOM", value_parser = parse_custom_attribute)]
with_attribute_custom: Vec<(Vec<String>, String)>,
/// Add custom attributes on a `struct`. The CUSTOM value must be of the shape REGEX=ATTRIBUTE where ATTRIBUTE is a coma-separated list of attributes.
Expand All @@ -489,6 +490,9 @@ struct BindgenCommand {
/// Add custom attributes on a `union`. The CUSTOM value must be of the shape REGEX=ATTRIBUTE where ATTRIBUTE is a coma-separated list of attributes.
#[arg(long, value_name = "CUSTOM", value_parser = parse_custom_attribute)]
with_attribute_custom_union: Vec<(Vec<String>, String)>,
/// Add custom attributes on an `fn`. The CUSTOM value must be of the shape REGEX=ATTRIBUTE where ATTRIBUTE is a coma-separated list of attributes.
#[arg(long, value_name = "CUSTOM", value_parser = parse_custom_attribute)]
with_attribute_custom_function: Vec<(Vec<String>, String)>,
/// Generate wrappers for `static` and `static inline` functions.
#[arg(long)]
wrap_static_fns: bool,
Expand Down Expand Up @@ -645,6 +649,7 @@ where
with_attribute_custom_struct,
with_attribute_custom_enum,
with_attribute_custom_union,
with_attribute_custom_function,
wrap_static_fns,
wrap_static_fns_path,
wrap_static_fns_suffix,
Expand Down Expand Up @@ -745,7 +750,7 @@ where
#[derive(Debug)]
struct CustomAttributeCallback {
attributes: Vec<String>,
kind: Option<TypeKind>,
kind: Option<AttributeItemKind>,
regex_set: RegexSet,
}

Expand All @@ -755,9 +760,16 @@ where

let flag = match &self.kind {
None => "--with-attribute-custom",
Some(TypeKind::Struct) => "--with-attribute-custom-struct",
Some(TypeKind::Enum) => "--with-attribute-custom-enum",
Some(TypeKind::Union) => "--with-attribute-custom-union",
Some(AttributeItemKind::Struct) => {
"--with-attribute-custom-struct"
}
Some(AttributeItemKind::Enum) => "--with-attribute-custom-enum",
Some(AttributeItemKind::Union) => {
"--with-attribute-custom-union"
}
Some(AttributeItemKind::Function) => {
"--with-attribute-custom-function"
}
};

let attributes = self.attributes.join(",");
Expand Down Expand Up @@ -1010,19 +1022,24 @@ where
(with_attribute_custom, None, "--with-attribute-custom"),
(
with_attribute_custom_struct,
Some(TypeKind::Struct),
Some(AttributeItemKind::Struct),
"--with-attribute-custom-struct",
),
(
with_attribute_custom_enum,
Some(TypeKind::Enum),
Some(AttributeItemKind::Enum),
"--with-attribute-custom-enum",
),
(
with_attribute_custom_union,
Some(TypeKind::Union),
Some(AttributeItemKind::Union),
"--with-attribute-custom-union",
),
(
with_attribute_custom_function,
Some(AttributeItemKind::Function),
"--with-attribute-custom-function",
),
] {
#[cfg(feature = "experimental")]
let name = emit_diagnostics.then_some(_name);
Expand Down
Loading