From 96c5b2500922efdc2468957a95c8df9f32ffc35a Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Thu, 20 Oct 2022 18:02:24 -0700 Subject: [PATCH] Fix handling of anonymous names in Clang 16. In trunk, Clang started emitting names like `"(unnamed enum at foo.cpp:4:2)"` for unnamed enums, structs, and unions, while previous versions emitted the empty string. This caused panics. This commit simply rewrites such names back to the empty string so that we stay compatible with both old and new versions of Clang. Closes #2312. --- bindgen/ir/comp.rs | 5 ++++- bindgen/ir/item.rs | 13 +++++++++++++ bindgen/ir/ty.rs | 5 +++++ 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/bindgen/ir/comp.rs b/bindgen/ir/comp.rs index f44c5d6725..dfbbdcb483 100644 --- a/bindgen/ir/comp.rs +++ b/bindgen/ir/comp.rs @@ -12,6 +12,7 @@ use super::ty::RUST_DERIVE_IN_ARRAY_LIMIT; use crate::clang; use crate::codegen::struct_layout::{align_to, bytes_from_bits_pow2}; use crate::ir::derive::CanDeriveCopy; +use crate::ir::item; use crate::parse::{ClangItemParser, ParseError}; use crate::HashMap; use crate::NonCopyUnionStyle; @@ -1422,7 +1423,9 @@ impl CompInfo { // A declaration of an union or a struct without name // could also be an unnamed field, unfortunately. - if cur.spelling().is_empty() && + let mut spelling = cur.spelling(); + item::normalize_name_for_clang_16(&mut spelling); + if spelling.is_empty() && cur.kind() != CXCursor_EnumDecl { let ty = cur.cur_type(); diff --git a/bindgen/ir/item.rs b/bindgen/ir/item.rs index 3b15cd6ed6..a52a30e856 100644 --- a/bindgen/ir/item.rs +++ b/bindgen/ir/item.rs @@ -2016,3 +2016,16 @@ impl<'a> NameOptions<'a> { self.item.real_canonical_name(self.ctx, self) } } + +/// Normalizes names so that we can handle them identically in Clang 16 and earlier versions. +/// +/// In Clang 16, anonymous names have names like `(anonymous union at foo.c:16)`, whereas in earlier +/// versions of Clang they were the empty string. This function normalizes all such names to the +/// empty string so that we can handle them identically. +pub fn normalize_name_for_clang_16(name: &mut String) { + // This may seem fragile, but ")" is not a valid character in C identifiers, so it should + // actually be a reasonably robust check. + if name.ends_with(")") { + name.truncate(0); + } +} diff --git a/bindgen/ir/ty.rs b/bindgen/ir/ty.rs index 6a3fd0e8c8..174ed4a6db 100644 --- a/bindgen/ir/ty.rs +++ b/bindgen/ir/ty.rs @@ -14,6 +14,7 @@ use super::template::{ }; use super::traversal::{EdgeKind, Trace, Tracer}; use crate::clang::{self, Cursor}; +use crate::ir::item; use crate::parse::{ClangItemParser, ParseError, ParseResult}; use std::borrow::Cow; use std::io; @@ -1112,6 +1113,8 @@ impl Type { } } + item::normalize_name_for_clang_16(&mut name); + TypeKind::Enum(enum_) } CXType_Record => { @@ -1132,6 +1135,8 @@ impl Type { } } + item::normalize_name_for_clang_16(&mut name); + TypeKind::Comp(complex) } CXType_Vector => {