Skip to content

Commit 832d4bd

Browse files
authored
Add support for __auto_type (#1782)
Fixes #1779
2 parents 35eee04 + 93ab31b commit 832d4bd

11 files changed

Lines changed: 116 additions & 0 deletions

File tree

c2rust-ast-exporter/src/AstExporter.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -674,6 +674,22 @@ class TypeEncoder final : public TypeVisitor<TypeEncoder> {
674674

675675
VisitQualType(t);
676676
}
677+
678+
void VisitAutoType(const AutoType *T) {
679+
if (!T->isGNUAutoType()) {
680+
printDiag(Context, DiagnosticsEngine::Warning,
681+
"Encountered unexpected auto type",
682+
src_loc, src_range);
683+
return;
684+
}
685+
686+
auto t = T->desugar();
687+
auto qt = encodeQualType(t);
688+
encodeType(T, TagAutoType,
689+
[qt](CborEncoder *local) { cbor_encode_uint(local, qt); });
690+
691+
VisitQualType(t);
692+
}
677693
};
678694

679695
class TranslateASTVisitor final

c2rust-ast-exporter/src/ast_tags.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,8 @@ enum TypeTag {
152152

153153
TagFloat128,
154154
TagAtomicType,
155+
156+
TagAutoType,
155157
};
156158

157159
enum StringTypeTag {

c2rust-transpile/src/c_ast/conversion.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -947,6 +947,16 @@ impl ConversionContext {
947947
self.processed_nodes.insert(new_id, OTHER_TYPE);
948948
}
949949

950+
TypeTag::TagAutoType if expected_ty & TYPE != 0 => {
951+
let auto_id =
952+
from_value(ty_node.extras[0].clone()).expect("Auto type child not found");
953+
let auto = self.visit_type(auto_id);
954+
955+
let auto_ty = CTypeKind::Auto(auto);
956+
self.add_type(new_id, not_located(auto_ty));
957+
self.processed_nodes.insert(new_id, TYPE);
958+
}
959+
950960
t => panic!(
951961
"Type conversion not implemented for {:?} expecting {:?}",
952962
t, expected_ty

c2rust-transpile/src/c_ast/iterators.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,7 @@ fn immediate_type_children(kind: &CTypeKind) -> Vec<SomeId> {
294294
Decayed(ctype)
295295
| Paren(ctype)
296296
| TypeOf(ctype)
297+
| Auto(ctype)
297298
| Complex(ctype)
298299
| ConstantArray(ctype, _)
299300
| IncompleteArray(ctype) => intos![ctype],

c2rust-transpile/src/c_ast/mod.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -760,6 +760,7 @@ impl TypedAstContext {
760760
CDeclKind::Typedef { typ: ty, .. } => ty.ctype,
761761
_ => panic!("Typedef decl did not point to a typedef"),
762762
},
763+
Auto(ty) => ty,
763764
_ => return typ,
764765
};
765766
self.resolve_type_id(ty)
@@ -778,6 +779,7 @@ impl TypedAstContext {
778779
Decayed(ty) => ty,
779780
TypeOf(ty) => ty,
780781
Paren(ty) => ty,
782+
Auto(ty) => ty,
781783
_ => return typ,
782784
};
783785
self.resolve_type_id_no_typedef(ty)
@@ -2549,6 +2551,9 @@ pub enum CTypeKind {
25492551
SSize,
25502552
PtrDiff,
25512553
WChar,
2554+
2555+
// `__auto_type` with its deduced actual type.
2556+
Auto(CTypeId),
25522557
}
25532558

25542559
impl CTypeKind {
@@ -2678,6 +2683,8 @@ impl CTypeKind {
26782683
Float128 => false,
26792684

26802685
// Non-scalars.
2686+
// TODO: we should investigate if all of these are dead code,
2687+
// and replace them with panics in that case.
26812688
Complex(_) => false,
26822689
Pointer(_) => false,
26832690
Reference(_) => false,
@@ -2700,6 +2707,7 @@ impl CTypeKind {
27002707
Vector(_, _) => false,
27012708
UnhandledSveType => false,
27022709
Atomic(_) => false,
2710+
Auto(_) => false,
27032711
}
27042712
}
27052713

@@ -2787,6 +2795,7 @@ impl CTypeKind {
27872795
SSize => false,
27882796
PtrDiff => false,
27892797
WChar => false,
2798+
Auto(_) => false,
27902799
}
27912800
}
27922801
}

c2rust-transpile/src/convert_type.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,7 @@ impl TypeConverter {
329329
}
330330

331331
CTypeKind::TypeOf(ty) => self.convert(ctxt, ty),
332+
CTypeKind::Auto(ty) => self.convert(ctxt, ty),
332333

333334
ref t => Err(format_err!("Unsupported type {:?}", t).into()),
334335
}

c2rust-transpile/src/translator/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4243,6 +4243,7 @@ impl<'c> Translation<'c> {
42434243
| Reference(CQualTypeId { ctype, .. })
42444244
| BlockPointer(CQualTypeId { ctype, .. })
42454245
| TypeOf(ctype)
4246+
| Auto(ctype)
42464247
| Complex(ctype) => imports.extend(self.imports_for_type(*ctype)),
42474248
Enum(decl_id) | Typedef(decl_id) | Union(decl_id) | Struct(decl_id) => {
42484249
let mut decl_id = *decl_id;

c2rust-transpile/tests/snapshots.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,11 @@ fn test_atomics() {
314314
transpile("atomics.c").run();
315315
}
316316

317+
#[test]
318+
fn test_auto_type() {
319+
transpile("auto_type.c").run();
320+
}
321+
317322
#[test]
318323
fn test_bitfields() {
319324
transpile("bitfields.c").expect_compile_error(true).run();
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
struct bar {
2+
int x;
3+
};
4+
5+
int foo() {
6+
__auto_type x = 42;
7+
__auto_type px = &x;
8+
__auto_type sx = sizeof(x);
9+
__auto_type y = (struct bar) { .x = x };
10+
return y.x;
11+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
---
2+
source: c2rust-transpile/tests/snapshots.rs
3+
expression: cat tests/snapshots/auto_type.2021.rs
4+
---
5+
#![allow(
6+
clippy::missing_safety_doc,
7+
dead_code,
8+
non_camel_case_types,
9+
non_snake_case,
10+
non_upper_case_globals,
11+
unused_assignments,
12+
unused_mut
13+
)]
14+
#![feature(raw_ref_op)]
15+
#[derive(Copy, Clone)]
16+
#[repr(C)]
17+
pub struct bar {
18+
pub x: ::core::ffi::c_int,
19+
}
20+
#[no_mangle]
21+
pub unsafe extern "C" fn foo() -> ::core::ffi::c_int {
22+
let mut x: ::core::ffi::c_int = 42 as ::core::ffi::c_int;
23+
let mut px: *mut ::core::ffi::c_int = &raw mut x;
24+
let mut sx: ::core::ffi::c_ulong =
25+
::core::mem::size_of::<::core::ffi::c_int>() as ::core::ffi::c_ulong;
26+
let mut y: bar = bar {
27+
x: x as ::core::ffi::c_int,
28+
} as bar;
29+
return y.x;
30+
}

0 commit comments

Comments
 (0)