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)| {
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