Skip to content

Commit 4edfb45

Browse files
authored
Map default initializer of translated type (#111)
1 parent 2668652 commit 4edfb45

13 files changed

Lines changed: 103 additions & 78 deletions

File tree

cpp2rust/converter/converter.cpp

Lines changed: 53 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -3015,12 +3015,64 @@ bool Converter::VisitCXXStdInitializerListExpr(
30153015
return false;
30163016
}
30173017

3018+
std::string Converter::GetArrayDefaultAsString(clang::QualType qual_type) {
3019+
if (auto *array_type = clang::dyn_cast<clang::ConstantArrayType>(qual_type)) {
3020+
auto size_as_string = GetNumAsString(array_type->getSize());
3021+
auto element_type = array_type->getElementType();
3022+
auto element_type_as_string = GetDefaultAsString(element_type);
3023+
return std::format("[{}; {}]", element_type_as_string,
3024+
size_as_string.c_str());
3025+
}
3026+
if (auto *array_type =
3027+
clang::dyn_cast<clang::IncompleteArrayType>(qual_type)) {
3028+
return GetDefaultAsString(array_type->getElementType());
3029+
}
3030+
if (Mapper::ToString(qual_type).contains("std::array")) {
3031+
assert(GetTemplateArgs(qual_type).has_value());
3032+
auto template_args = *GetTemplateArgs(qual_type);
3033+
assert(template_args.size() == 2);
3034+
auto array_size = template_args[1];
3035+
unsigned size = 0;
3036+
switch (array_size.getKind()) {
3037+
case clang::TemplateArgument::Expression: {
3038+
auto array_size_expr = array_size.getAsExpr();
3039+
assert(array_size_expr && !array_size_expr->isValueDependent());
3040+
clang::Expr::EvalResult result;
3041+
ENSURE(array_size_expr->EvaluateAsInt(result, ctx_));
3042+
size = result.Val.getInt().getZExtValue();
3043+
break;
3044+
}
3045+
case clang::TemplateArgument::Integral: {
3046+
size = array_size.getAsIntegral().getZExtValue();
3047+
break;
3048+
}
3049+
default:
3050+
assert(0 && "Unsupported array size kind");
3051+
break;
3052+
}
3053+
return std::format(
3054+
"std::array::from_fn::<_, {}, _>(|_| Default::default()).to_vec()",
3055+
size);
3056+
}
3057+
return {};
3058+
}
3059+
30183060
std::string Converter::GetDefaultAsString(clang::QualType qual_type) {
30193061
if (IsVaListType(qual_type)) {
30203062
computed_expr_type_ = ComputedExprType::FreshValue;
30213063
return "VaList::default()";
30223064
}
30233065

3066+
if (auto arr = GetArrayDefaultAsString(qual_type); !arr.empty()) {
3067+
computed_expr_type_ = ComputedExprType::FreshValue;
3068+
return arr;
3069+
}
3070+
3071+
if (auto init = Mapper::MapInitializer(qual_type); !init.empty()) {
3072+
computed_expr_type_ = ComputedExprType::FreshValue;
3073+
return init;
3074+
}
3075+
30243076
if (qual_type->isPointerType()) {
30253077
auto pointee = qual_type->getPointeeType();
30263078
if (pointee->isFunctionType()) {
@@ -3032,54 +3084,7 @@ std::string Converter::GetDefaultAsString(clang::QualType qual_type) {
30323084
}
30333085

30343086
computed_expr_type_ = ComputedExprType::FreshValue;
3035-
3036-
if (auto *array_type = clang::dyn_cast<clang::ConstantArrayType>(qual_type)) {
3037-
auto size_as_string = GetNumAsString(array_type->getSize());
3038-
auto element_type = array_type->getElementType();
3039-
auto element_type_as_string = GetDefaultAsString(element_type);
3040-
return std::format("[{}; {}]", element_type_as_string,
3041-
size_as_string.c_str());
3042-
} else if (auto *array_type =
3043-
clang::dyn_cast<clang::IncompleteArrayType>(qual_type)) {
3044-
return GetDefaultAsString(array_type->getElementType());
3045-
} else {
3046-
auto qual_type_str = Mapper::ToString(qual_type);
3047-
if (qual_type_str == "struct std::pair") {
3048-
auto template_args = *GetTemplateArgs(qual_type);
3049-
auto first_type = template_args[0].getAsType();
3050-
auto second_type = template_args[1].getAsType();
3051-
return std::format("({}, {})", GetDefaultAsString(first_type),
3052-
GetDefaultAsString(second_type));
3053-
} else if (qual_type_str.contains("std::array")) {
3054-
assert(GetTemplateArgs(qual_type).has_value());
3055-
auto template_args = *GetTemplateArgs(qual_type);
3056-
assert(template_args.size() == 2);
3057-
auto array_size = template_args[1];
3058-
unsigned size = 0;
3059-
switch (array_size.getKind()) {
3060-
case clang::TemplateArgument::Expression: {
3061-
auto array_size_expr = array_size.getAsExpr();
3062-
assert(array_size_expr && !array_size_expr->isValueDependent());
3063-
clang::Expr::EvalResult result;
3064-
ENSURE(array_size_expr->EvaluateAsInt(result, ctx_));
3065-
size = result.Val.getInt().getZExtValue();
3066-
break;
3067-
}
3068-
case clang::TemplateArgument::Integral: {
3069-
size = array_size.getAsIntegral().getZExtValue();
3070-
break;
3071-
}
3072-
default:
3073-
assert(0 && "Unsupported array size kind");
3074-
break;
3075-
}
3076-
return std::format(
3077-
"std::array::from_fn::<_, {}, _>(|_| Default::default()).to_vec()",
3078-
size);
3079-
} else {
3080-
return GetDefaultAsStringFallback(qual_type);
3081-
}
3082-
}
3087+
return GetDefaultAsStringFallback(qual_type);
30833088
}
30843089

30853090
std::string Converter::GetDefaultAsStringFallback(clang::QualType qual_type) {

cpp2rust/converter/converter.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -403,6 +403,8 @@ class Converter : public clang::RecursiveASTVisitor<Converter> {
403403

404404
virtual std::string GetDefaultAsString(clang::QualType qual_type);
405405

406+
virtual std::string GetArrayDefaultAsString(clang::QualType qual_type);
407+
406408
virtual std::string GetDefaultAsStringFallback(clang::QualType qual_type);
407409

408410
virtual std::string ConvertVarDefaultInit(clang::QualType qual_type);

cpp2rust/converter/mapper.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -634,6 +634,18 @@ std::string Map(clang::QualType qual_type) {
634634
return {};
635635
}
636636

637+
std::string MapInitializer(clang::QualType qual_type) {
638+
auto type_str = ToString(qual_type);
639+
auto [rule, subs] = search(types_, type_str, GetTypeMapKey(type_str));
640+
if (rule && !rule->initializer.empty()) {
641+
for (auto &ty : subs) {
642+
ty = mapTypeStringRecursive(ty);
643+
}
644+
return instantiateTgt(subs, rule->initializer);
645+
}
646+
return {};
647+
}
648+
637649
bool MapsToPointer(clang::QualType qual_type) {
638650
auto rule = search(qual_type);
639651
return rule && rule->type_info.is_pointer();

cpp2rust/converter/mapper.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ bool Contains(clang::QualType qual_type);
2828
bool Contains(const clang::Expr *expr);
2929

3030
std::string Map(clang::QualType qual_type);
31+
std::string MapInitializer(clang::QualType qual_type);
3132
const TranslationRule::ExprRule *GetExprRule(const clang::Expr *expr);
3233
std::string MapFunctionName(const clang::FunctionDecl *decl);
3334
std::string InstantiateTemplate(const clang::Expr *expr, unsigned n);

cpp2rust/converter/models/converter_refcount.cpp

Lines changed: 25 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1623,11 +1623,36 @@ bool ConverterRefCount::VisitCXXDefaultArgExpr(clang::CXXDefaultArgExpr *expr) {
16231623
return Converter::VisitCXXDefaultArgExpr(expr);
16241624
}
16251625

1626+
std::string
1627+
ConverterRefCount::GetArrayDefaultAsString(clang::QualType qual_type) {
1628+
if (auto *array_type = clang::dyn_cast<clang::ConstantArrayType>(qual_type)) {
1629+
const auto &size = array_type->getSize();
1630+
auto size_as_string = GetNumAsString(size);
1631+
auto element_type = array_type->getElementType();
1632+
PushConversionKind push(*this, ConversionKind::Unboxed);
1633+
auto element_type_as_string = ToString(element_type);
1634+
auto default_as_string = GetDefaultAsString(element_type);
1635+
return std::format("(0..{}).map(|_| {}).collect::<Box<[{}]>>()",
1636+
size_as_string.c_str(), default_as_string,
1637+
element_type_as_string);
1638+
}
1639+
return Converter::GetArrayDefaultAsString(qual_type);
1640+
}
1641+
16261642
std::string ConverterRefCount::GetDefaultAsString(clang::QualType qual_type) {
16271643
if (IsVaListType(qual_type)) {
16281644
return BoxValue("VaList::default()");
16291645
}
16301646

1647+
if (auto arr = GetArrayDefaultAsString(qual_type); !arr.empty()) {
1648+
return BoxValue(std::move(arr));
1649+
}
1650+
1651+
if (auto init = Mapper::MapInitializer(qual_type); !init.empty()) {
1652+
computed_expr_type_ = ComputedExprType::FreshValue;
1653+
return BoxValue(std::move(init));
1654+
}
1655+
16311656
std::string ret;
16321657
if (qual_type->isPointerType()) {
16331658
auto pointee_type = qual_type->getPointeeType();
@@ -1641,26 +1666,6 @@ std::string ConverterRefCount::GetDefaultAsString(clang::QualType qual_type) {
16411666
ret = std::format("Ptr::<{}>::null()", ConvertPointeeType(qual_type));
16421667
}
16431668
}
1644-
} else if (auto *array_type =
1645-
clang::dyn_cast<clang::ConstantArrayType>(qual_type)) {
1646-
const auto &size = array_type->getSize();
1647-
auto size_as_string = GetNumAsString(size);
1648-
auto element_type = array_type->getElementType();
1649-
PushConversionKind push(*this, ConversionKind::Unboxed);
1650-
auto element_type_as_string = ToString(element_type);
1651-
auto default_as_string = GetDefaultAsString(element_type);
1652-
ret = std::format("(0..{}).map(|_| {}).collect::<Box<[{}]>>()",
1653-
size_as_string.c_str(), default_as_string,
1654-
element_type_as_string);
1655-
} else if (Mapper::ToString(qual_type) == "struct std::pair") {
1656-
auto template_args = *GetTemplateArgs(qual_type);
1657-
auto first_type = template_args[0].getAsType();
1658-
auto second_type = template_args[1].getAsType();
1659-
ret = std::format("(Rc::new(RefCell::new({})), Rc::new(RefCell::new({})))",
1660-
GetDefaultAsString(first_type),
1661-
GetDefaultAsString(second_type));
1662-
} else if (Mapper::ToString(qual_type).contains("std::array")) {
1663-
ret = Converter::GetDefaultAsString(qual_type);
16641669
} else {
16651670
return Converter::GetDefaultAsString(qual_type);
16661671
}

cpp2rust/converter/models/converter_refcount.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,8 @@ class ConverterRefCount final : public Converter {
124124

125125
std::string GetDefaultAsString(clang::QualType qual_type) override;
126126

127+
std::string GetArrayDefaultAsString(clang::QualType qual_type) override;
128+
127129
void ConvertEqualsNullPtr(clang::Expr *expr) override;
128130

129131
std::string GetDefaultAsStringFallback(clang::QualType qual_type) override;

rules/pair/ir_unsafe.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -459,7 +459,7 @@
459459
}
460460
},
461461
"t1": {
462-
"init": "(T1::default(), T2::default())",
462+
"init": "<(T1, T2)>::default()",
463463
"type": "(T1, T2)"
464464
}
465465
}

rules/pair/tgt_unsafe.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ struct T1;
88
struct T2;
99

1010
fn types() {
11-
let t1: (T1, T2) = (T1::default(), T2::default());
11+
let t1: (T1, T2) = <(T1, T2)>::default();
1212
}
1313

1414
unsafe fn f1<T1, T2>(a0: (T1, T2)) -> T2 {

rules/stdio/ir_unsafe.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -756,7 +756,7 @@
756756
}
757757
},
758758
"t1": {
759-
"init": "Default::default()",
759+
"init": "std::ptr::null_mut()",
760760
"type": "*mut ::std::fs::File",
761761
"is_unsafe_pointer": true
762762
}

rules/stdio/tgt_unsafe.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use libcc2rs::*;
55
use std::io::prelude::*;
66

77
fn types() -> Result<(), Box<dyn std::error::Error>> {
8-
let t1: *mut ::std::fs::File = Default::default();
8+
let t1: *mut ::std::fs::File = std::ptr::null_mut();
99
Ok(())
1010
}
1111

0 commit comments

Comments
 (0)