Skip to content
Open
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
2 changes: 1 addition & 1 deletion bindgen-tests/tests/expectations/tests/macro-redef.rs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 9 additions & 0 deletions bindgen/ir/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1496,6 +1496,15 @@ If you encounter an error missing from this list, please file an issue or a PR!"
}
}

/// Resolve the given `ItemId` into a mutable reference to an `Item`, or
/// `None` if no such item exists.
pub(crate) fn resolve_item_mut<Id: Into<ItemId>>(
&mut self,
id: Id,
) -> Option<&mut Item> {
self.items.get_mut(id.into().0)?.as_mut()
}

/// Get the current module.
pub(crate) fn current_module(&self) -> ModuleId {
self.current_module
Expand Down
9 changes: 9 additions & 0 deletions bindgen/ir/item_kind.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,15 @@ impl ItemKind {
}
}

/// Get a mutable reference to this `ItemKind`'s underlying `Var`, or
/// `None` if it is some other kind.
pub(crate) fn as_var_mut(&mut self) -> Option<&mut Var> {
match *self {
ItemKind::Var(ref mut v) => Some(v),
_ => None,
}
}

/// Is this a variable?
pub(crate) fn is_var(&self) -> bool {
self.as_var().is_some()
Expand Down
37 changes: 30 additions & 7 deletions bindgen/ir/var.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,13 @@ impl Var {
pub fn link_name(&self) -> Option<&str> {
self.link_name.as_deref()
}

/// Overwrite this variable's type and value, e.g. when a macro that
/// backs it has been redefined to a new value.
fn set_val(&mut self, ty: TypeId, val: Option<VarType>) {
self.ty = ty;
self.val = val;
}
}

impl DotAttributes for Var {
Expand Down Expand Up @@ -212,12 +219,6 @@ impl ClangSubItemParser for Var {
// derived macros.
ctx.note_parsed_macro(id.clone(), value.clone());

if previously_defined {
let name = String::from_utf8(id).unwrap();
duplicated_macro_diagnostic(&name, cursor.location(), ctx);
return Err(ParseError::Continue);
}

// NOTE: Unwrapping, here and above, is safe, because the
// identifier of a token comes straight from clang, and we
// enforce utf8 there, so we should have already panicked at
Expand Down Expand Up @@ -264,6 +265,28 @@ impl ClangSubItemParser for Var {

let ty = Item::builtin_type(type_kind, true, ctx);

if previously_defined {
let existing_id = ctx.items().find_map(|(id, item)| {

@emilio emilio Sep 5, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This linear lookup seems bad, let's avoid this. It's also a bit bad to mutate the IR like this after the fact but...

View changes since the review

let var = item.kind().as_var()?;
(var.name() == name).then_some(id)
});

if let Some(existing_id) = existing_id {
duplicated_macro_diagnostic(
&name,
cursor.location(),
ctx,
);
if let Some(existing_var) = ctx
.resolve_item_mut(existing_id)
.and_then(|item| item.kind_mut().as_var_mut())
{
existing_var.set_val(ty, Some(val));
}
return Ok(ParseResult::AlreadyResolved(existing_id));
}
}

Ok(ParseResult::New(
Var::new(name, None, None, ty, Some(val), true),
Some(cursor),
Expand Down Expand Up @@ -481,7 +504,7 @@ fn duplicated_macro_diagnostic(
_location: clang::SourceLocation,
_ctx: &BindgenContext,
) {
warn!("Duplicated macro definition: {macro_name}");
warn!("Macro '{macro_name}' redefined; using the latest definition");

#[cfg(feature = "experimental")]
// FIXME (pvdrz & amanjeev): This diagnostic message shows way too often to be actually
Expand Down
Loading