Skip to content

Commit ba96d90

Browse files
committed
Deduplicate the code that turns transparent structs into typedefs
1 parent 58c6156 commit ba96d90

File tree

5 files changed

+52
-40
lines changed

5 files changed

+52
-40
lines changed

src/bindgen/ir/structure.rs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use crate::bindgen::declarationtyperesolver::DeclarationTypeResolver;
1111
use crate::bindgen::dependencies::Dependencies;
1212
use crate::bindgen::ir::{
1313
AnnotationSet, Cfg, Constant, Documentation, Field, GenericArgument, GenericParams, Item,
14-
ItemContainer, Path, Repr, ReprAlign, ReprStyle, Type,
14+
ItemContainer, Path, Repr, ReprAlign, ReprStyle, Type, Typedef,
1515
};
1616
use crate::bindgen::library::Library;
1717
use crate::bindgen::mangle;
@@ -150,6 +150,23 @@ impl Struct {
150150
}
151151
}
152152

153+
/// Attempts to convert this struct to a typedef (only works for transparent structs).
154+
pub fn as_typedef(&self) -> Option<Typedef> {
155+
if self.is_transparent {
156+
// NOTE: A `#[repr(transparent)]` struct with 2+ NZT fields fails to compile, but 0
157+
// fields is allowed for some strange reason. Don't emit the typedef in that case.
158+
if let Some(field) = self.fields.first() {
159+
return Some(Typedef::new_from_struct_field(self, field));
160+
} else {
161+
error!(
162+
"Cannot convert empty transparent struct {} to typedef",
163+
self.name()
164+
);
165+
}
166+
}
167+
None
168+
}
169+
153170
pub fn add_monomorphs(&self, library: &Library, out: &mut Monomorphs) {
154171
// Generic structs can instantiate monomorphs only once they've been
155172
// instantiated. See `instantiate_monomorph` for more details.

src/bindgen/ir/typedef.rs

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ use crate::bindgen::config::Config;
1010
use crate::bindgen::declarationtyperesolver::DeclarationTypeResolver;
1111
use crate::bindgen::dependencies::Dependencies;
1212
use crate::bindgen::ir::{
13-
AnnotationSet, Cfg, Documentation, GenericArgument, GenericParams, Item, ItemContainer, Path,
14-
Type,
13+
AnnotationSet, Cfg, Documentation, Field, GenericArgument, GenericParams, Item, ItemContainer,
14+
Path, Struct, Type,
1515
};
1616
use crate::bindgen::library::Library;
1717
use crate::bindgen::mangle;
@@ -70,6 +70,19 @@ impl Typedef {
7070
self.aliased.simplify_standard_types(config);
7171
}
7272

73+
// Used to convert a transparent Struct to a Typedef.
74+
pub fn new_from_struct_field(item: &Struct, field: &Field) -> Self {
75+
Self {
76+
path: item.path().clone(),
77+
export_name: item.export_name().to_string(),
78+
generic_params: item.generic_params.clone(),
79+
aliased: field.ty.clone(),
80+
cfg: item.cfg().cloned(),
81+
annotations: item.annotations().clone(),
82+
documentation: item.documentation().clone(),
83+
}
84+
}
85+
7386
pub fn transfer_annotations(&mut self, out: &mut HashMap<Path, AnnotationSet>) {
7487
if self.annotations.is_empty() {
7588
return;

src/bindgen/language_backend/clike.rs

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -540,24 +540,6 @@ impl LanguageBackend for CLikeLanguageBackend<'_> {
540540
}
541541

542542
fn write_struct<W: Write>(&mut self, out: &mut SourceWriter<W>, s: &Struct) {
543-
if s.is_transparent {
544-
let typedef = Typedef {
545-
path: s.path.clone(),
546-
export_name: s.export_name.to_owned(),
547-
generic_params: s.generic_params.clone(),
548-
aliased: s.fields[0].ty.clone(),
549-
cfg: s.cfg.clone(),
550-
annotations: s.annotations.clone(),
551-
documentation: s.documentation.clone(),
552-
};
553-
self.write_type_def(out, &typedef);
554-
for constant in &s.associated_constants {
555-
out.new_line();
556-
constant.write(self.config, self, out, Some(s));
557-
}
558-
return;
559-
}
560-
561543
let condition = s.cfg.to_condition(self.config);
562544
condition.write_before(self.config, out);
563545

src/bindgen/language_backend/cython.rs

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -159,24 +159,6 @@ impl LanguageBackend for CythonLanguageBackend<'_> {
159159
}
160160

161161
fn write_struct<W: Write>(&mut self, out: &mut SourceWriter<W>, s: &Struct) {
162-
if s.is_transparent {
163-
let typedef = Typedef {
164-
path: s.path.clone(),
165-
export_name: s.export_name.to_owned(),
166-
generic_params: s.generic_params.clone(),
167-
aliased: s.fields[0].ty.clone(),
168-
cfg: s.cfg.clone(),
169-
annotations: s.annotations.clone(),
170-
documentation: s.documentation.clone(),
171-
};
172-
self.write_type_def(out, &typedef);
173-
for constant in &s.associated_constants {
174-
out.new_line();
175-
constant.write(self.config, self, out, Some(s));
176-
}
177-
return;
178-
}
179-
180162
let condition = s.cfg.to_condition(self.config);
181163
condition.write_before(self.config, out);
182164

src/bindgen/language_backend/mod.rs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,24 @@ pub trait LanguageBackend: Sized {
139139
}
140140
}
141141

142+
/// If the struct is transparent, emit a typedef of its NZST field type instead.
143+
fn write_struct_or_typedef<W: Write>(
144+
&mut self,
145+
out: &mut SourceWriter<W>,
146+
s: &Struct,
147+
b: &Bindings,
148+
) {
149+
if let Some(typedef) = s.as_typedef() {
150+
self.write_type_def(out, &typedef);
151+
for constant in &s.associated_constants {
152+
out.new_line();
153+
constant.write(&b.config, self, out, Some(s));
154+
}
155+
} else {
156+
self.write_struct(out, s);
157+
}
158+
}
159+
142160
fn write_items<W: Write>(&mut self, out: &mut SourceWriter<W>, b: &Bindings) {
143161
for item in &b.items {
144162
if item
@@ -155,7 +173,7 @@ pub trait LanguageBackend: Sized {
155173
ItemContainer::Constant(..) => unreachable!(),
156174
ItemContainer::Static(..) => unreachable!(),
157175
ItemContainer::Enum(ref x) => self.write_enum(out, x),
158-
ItemContainer::Struct(ref x) => self.write_struct(out, x),
176+
ItemContainer::Struct(ref x) => self.write_struct_or_typedef(out, x, b),
159177
ItemContainer::Union(ref x) => self.write_union(out, x),
160178
ItemContainer::OpaqueItem(ref x) => self.write_opaque_item(out, x),
161179
ItemContainer::Typedef(ref x) => self.write_type_def(out, x),

0 commit comments

Comments
 (0)