diff --git a/cpp2rust/converter/converter.cpp b/cpp2rust/converter/converter.cpp index 0f6f48d..6870ce9 100644 --- a/cpp2rust/converter/converter.cpp +++ b/cpp2rust/converter/converter.cpp @@ -130,17 +130,20 @@ bool Converter::VisitRecordType(clang::RecordType *type) { auto *decl = type->getDecl(); if (auto lambda = clang::dyn_cast(decl)) { if (lambda->isLambda()) { - auto call_op = lambda->getLambdaCallOperator(); - StrCat("Rcparameters()) { - StrCat(std::format("{},", ToStringBase(p->getType()))); - } - StrCat(")"); - if (!call_op->getReturnType()->isVoidType()) { - StrCat("->"); - StrCat(ToStringBase(call_op->getReturnType())); + if (in_function_formals_) { + auto call_op = lambda->getLambdaCallOperator(); + StrCat("impl Fn("); + for (auto p : call_op->parameters()) { + StrCat(std::format("{},", ToStringBase(p->getType()))); + } + StrCat(")"); + if (!call_op->getReturnType()->isVoidType()) { + StrCat("->"); + StrCat(ToStringBase(call_op->getReturnType())); + } + } else { + StrCat("_"); } - StrCat(">"); return false; } } @@ -226,7 +229,7 @@ void Converter::ConvertFunctionPointerType(clang::PointerType *type) { auto proto = type->getPointeeType()->getAs(); assert(proto && "Type should be a function prototype"); - StrCat("Rcparam_types()) { StrCat(std::format("{},", ToString(p_ty))); } @@ -383,9 +386,15 @@ bool Converter::ConvertVarDeclSkipInit(clang::VarDecl *decl) { return false; } StrCat(AccessSpecifierAsString(decl->getAccess()), keyword::kStatic); + if (!qual_type.isConstQualified()) { + StrCat(keyword_mut_); + } ENSURE(decl_ids_.insert(GetID(decl)).second); } else if (decl->isStaticLocal()) { StrCat(keyword::kStatic); + if (!qual_type.isConstQualified()) { + StrCat(keyword_mut_); + } } else if (decl->isLocalVarDecl()) { StrCat(keyword::kLet); } @@ -417,6 +426,9 @@ bool Converter::ConvertVarDeclSkipInit(clang::VarDecl *decl) { } bool Converter::ConvertLambdaVarDecl(clang::VarDecl *decl) { + if (decl->getType()->isFunctionPointerType()) { + return false; + } if (decl->hasInit()) { if (clang::isa( decl->getInit()->IgnoreUnlessSpelledInSource())) { @@ -1362,6 +1374,31 @@ bool Converter::VisitCallExpr(clang::CallExpr *expr) { return false; } +void Converter::EmitFnPtrCall(clang::Expr *callee) { + StrCat(token::kOpenParen); + Convert(callee); + StrCat(").unwrap()"); +} + +void Converter::EmitFnAsValue(const clang::FunctionDecl *fn_decl) { + StrCat(std::format("Some({})", Mapper::GetFnRefName(fn_decl))); +} + +std::string Converter::GetPointeeRustType(clang::QualType ptr_type) { + auto pointee = ptr_type->getPointeeType(); + if (pointee->isIntegerType()) { + return ToString(pointee); + } + auto str = ToString(ptr_type); + while (!str.empty() && std::isspace(str.back())) { + str.pop_back(); + } + if (str.starts_with("Ptr<") && str.ends_with(">")) { + return str.substr(4, str.size() - 5); + } + return ToString(pointee); +} + void Converter::ConvertGenericCallExpr(clang::CallExpr *expr) { clang::Expr *callee = expr->getCallee(); auto convert_param_ty = [&](clang::QualType param_type, clang::Expr *expr) { @@ -1384,7 +1421,8 @@ void Converter::ConvertGenericCallExpr(clang::CallExpr *expr) { StrCat(token::kOpenParen); StrCat(keyword_unsafe_); StrCat(token::kOpenCurlyBracket); - const auto *function = expr->getCalleeDecl()->getAsFunction(); + const auto *function = + expr->getCalleeDecl() ? expr->getCalleeDecl()->getAsFunction() : nullptr; const clang::FunctionProtoType *proto = nullptr; if (!function) { @@ -1432,7 +1470,12 @@ void Converter::ConvertGenericCallExpr(clang::CallExpr *expr) { } } - Convert(callee); + if (proto && !function) { + EmitFnPtrCall(callee); + } else { + PushExprKind push(*this, ExprKind::RValue); + Convert(StripFunctionPointerDecay(callee)); + } StrCat(token::kOpenParen); for (unsigned i = 0; i < num_named_params && i < num_args; ++i) { auto *arg = expr->getArg(i + arg_begin); @@ -1648,7 +1691,11 @@ bool Converter::VisitImplicitCastExpr(clang::ImplicitCastExpr *expr) { break; } case clang::CastKind::CK_FunctionToPointerDecay: - case clang::CastKind::CK_BuiltinFnToFnPtr: + case clang::CastKind::CK_BuiltinFnToFnPtr: { + PushExprKind push(*this, ExprKind::AddrOf); + Convert(sub_expr); + break; + } case clang::CastKind::CK_ConstructorConversion: case clang::CastKind::CK_DerivedToBase: Convert(sub_expr); @@ -1663,7 +1710,11 @@ bool Converter::VisitImplicitCastExpr(clang::ImplicitCastExpr *expr) { ConvertEqualsNullPtr(sub_expr); break; case clang::CastKind::CK_NullToPointer: - StrCat(keyword_default_); + if (type->isFunctionPointerType()) { + StrCat("None"); + } else { + StrCat(keyword_default_); + } computed_expr_type_ = ComputedExprType::FreshPointer; break; default: @@ -1708,6 +1759,17 @@ bool Converter::VisitExplicitCastExpr(clang::ExplicitCastExpr *expr) { if (expr->getType() == sub_expr->getType()) { return Convert(sub_expr); } + if (type->isFunctionPointerType() || + sub_expr->getType()->isFunctionPointerType()) { + StrCat("std::mem::transmute::<"); + Convert(sub_expr->getType()); + StrCat(","); + Convert(type); + StrCat(">("); + Convert(sub_expr); + StrCat(")"); + return false; + } StrCat(token::kOpenParen); Convert(sub_expr); if (auto *unary_oper = clang::dyn_cast(sub_expr); @@ -1934,12 +1996,12 @@ bool Converter::VisitConditionalOperator(clang::ConditionalOperator *expr) { StrCat(keyword::kIf); Convert(expr->getCond()); StrCat(token::kOpenCurlyBracket); - if (expr->isLValue() && !isRValue()) { + if (expr->isLValue() && !isRValue() && !expr->getType()->isFunctionType()) { StrCat(token::kRef, keyword_mut_); } Convert(expr->getTrueExpr()); StrCat(token::kCloseCurlyBracket, keyword::kElse, token::kOpenCurlyBracket); - if (expr->isLValue() && !isRValue()) { + if (expr->isLValue() && !isRValue() && !expr->getType()->isFunctionType()) { StrCat(token::kRef, keyword_mut_); } Convert(expr->getFalseExpr()); @@ -1956,7 +2018,8 @@ std::string Converter::ConvertDeclRefExpr(clang::DeclRefExpr *expr) { } auto *decl = expr->getDecl(); - if (Mapper::Contains(expr)) { + if (!(clang::isa(decl) && isAddrOf()) && + Mapper::Contains(expr)) { return GetMappedAsString(expr); } else if (auto *function = decl->getAsFunction()) { if (auto method = clang::dyn_cast(function)) { @@ -1993,35 +2056,23 @@ bool Converter::VisitDeclRefExpr(clang::DeclRefExpr *expr) { return false; } - if (auto function = clang::dyn_cast(decl)) { + if (auto *fn_decl = clang::dyn_cast(decl)) { if (isAddrOf()) { - // Wrap unsafe function in safe closure because the Fn trait only accepts - // safe functions - std::string arguments; - for (unsigned i = 0; i < function->getNumParams(); i++) { - arguments += (i ? ", a" : "a") + std::to_string(i); - } - StrCat("Rc::new", token::kOpenParen); - StrCat(std::format("|{}|", arguments)); - StrCat(keyword_unsafe_, token::kOpenCurlyBracket); - StrCat(str); - StrCat(token::kOpenParen); - StrCat(arguments); - StrCat(token::kCloseParen); - StrCat(token::kCloseCurlyBracket); - StrCat(token::kCloseParen); + EmitFnAsValue(fn_decl); return false; } } if (auto var_decl = clang::dyn_cast(decl)) { - if (auto init = var_decl->getInit()) { - if (auto lambda = clang::dyn_cast( - init->IgnoreUnlessSpelledInSource())) { - StrCat(token::kOpenParen); - VisitLambdaExpr(lambda); - StrCat(token::kCloseParen); - return false; + if (!var_decl->getType()->isFunctionPointerType()) { + if (auto init = var_decl->getInit()) { + if (auto lambda = clang::dyn_cast( + init->IgnoreUnlessSpelledInSource())) { + StrCat(token::kOpenParen); + VisitLambdaExpr(lambda); + StrCat(token::kCloseParen); + return false; + } } } } @@ -2480,6 +2531,9 @@ bool Converter::VisitCXXDefaultArgExpr(clang::CXXDefaultArgExpr *expr) { } bool Converter::VisitLambdaExpr(clang::LambdaExpr *expr) { + if (isAddrOf() && expr->capture_size() == 0) { + StrCat("Some"); + } StrCat(token::kOpenParen); StrCat("|"); for (auto p : expr->getLambdaClass()->getLambdaCallOperator()->parameters()) { @@ -2609,15 +2663,7 @@ bool Converter::VisitCXXStdInitializerListExpr( std::string Converter::GetFunctionPointerDefaultAsString(clang::QualType qual_type) { - std::string ret; - auto proto = qual_type->getPointeeType()->getAs(); - assert(proto); - ret = "Rc::new(|"; - for (unsigned i = 0; i < proto->getNumParams(); i++) { - ret += "_,"; - } - ret += R"(| { panic!("ub: uninit function pointer") }))"; - return ret; + return "None"; } std::string Converter::GetDefaultAsString(clang::QualType qual_type) { @@ -2679,18 +2725,18 @@ std::string Converter::GetDefaultAsString(clang::QualType qual_type) { } std::string Converter::GetDefaultAsStringFallback(clang::QualType qual_type) { - static llvm::DenseMap default_for_type = { - {clang::BuiltinType::Char_U, "0_u8"}, - {clang::BuiltinType::SChar, "0_i8"}, - {clang::BuiltinType::UChar, "0_u8"}, - }; - qual_type = qual_type.getUnqualifiedType().getCanonicalType(); - if (auto builtin = qual_type->getAs()) { - auto it = default_for_type.find(builtin->getKind()); - if (it != default_for_type.end()) { - return it->second; - } + + if (qual_type->isBooleanType()) { + return "false"; + } + + if (qual_type->isIntegerType() && !qual_type->isEnumeralType()) { + return std::format("0_{}", ToString(qual_type)); + } + + if (qual_type->isFloatingType()) { + return std::format("0.0_{}", ToString(qual_type)); } return std::format("<{}>::default()", ToString(qual_type)); @@ -2771,6 +2817,16 @@ void Converter::ConvertVarInit(clang::QualType qual_type, clang::Expr *expr) { StrCat(keyword_mut_); } } + if (qual_type->isFunctionPointerType()) { + if (auto *lambda = clang::dyn_cast( + expr->IgnoreUnlessSpelledInSource())) { + PushExprKind push(*this, ExprKind::AddrOf); + curr_init_type_.push(qual_type); + VisitLambdaExpr(lambda); + curr_init_type_.pop(); + return; + } + } auto *ignore_casts = expr->IgnoreCasts(); // FIXME: this looks very complicated if (auto *ctor = clang::dyn_cast(ignore_casts); @@ -2816,7 +2872,8 @@ void Converter::ConvertUnsignedArithOperand(clang::Expr *expr, void Converter::ConvertEqualsNullPtr(clang::Expr *expr) { StrCat("("); Convert(expr); - if (IsUniquePtr(expr->getType())) { + if (IsUniquePtr(expr->getType()) || + expr->getType()->isFunctionPointerType()) { StrCat(").is_none()"); } else { StrCat(").is_null()"); @@ -3201,6 +3258,8 @@ void Converter::PlaceholderCtx::dump() const { std::string Converter::ConvertPlaceholder(clang::Expr *expr, clang::Expr *arg, const PlaceholderCtx &ph_ctx) { + arg = StripFunctionPointerDecay(arg); + if (ph_ctx.needs_materialization()) { auto materialized = ph_ctx.materialize_ctx->GetOrMaterialize( static_cast(ph_ctx.materialize_idx), diff --git a/cpp2rust/converter/converter.h b/cpp2rust/converter/converter.h index 899cc96..7494a99 100644 --- a/cpp2rust/converter/converter.h +++ b/cpp2rust/converter/converter.h @@ -199,6 +199,12 @@ class Converter : public clang::RecursiveASTVisitor { void ConvertGenericCallExpr(clang::CallExpr *expr); + virtual void EmitFnPtrCall(clang::Expr *callee); + + virtual void EmitFnAsValue(const clang::FunctionDecl *fn_decl); + + std::string GetPointeeRustType(clang::QualType ptr_type); + virtual void ConvertPrintf(clang::CallExpr *expr); void ConvertVAArgCall(clang::CallExpr *expr); @@ -332,7 +338,8 @@ class Converter : public clang::RecursiveASTVisitor { virtual bool Convert(clang::Stmt *stmt); virtual bool Convert(clang::Expr *expr); - std::string GetFunctionPointerDefaultAsString(clang::QualType qual_type); + virtual std::string + GetFunctionPointerDefaultAsString(clang::QualType qual_type); virtual std::string GetDefaultAsString(clang::QualType qual_type); diff --git a/cpp2rust/converter/converter_lib.cpp b/cpp2rust/converter/converter_lib.cpp index ba3899a..26624a0 100644 --- a/cpp2rust/converter/converter_lib.cpp +++ b/cpp2rust/converter/converter_lib.cpp @@ -320,24 +320,35 @@ const char *AccessSpecifierAsString(clang::AccessSpecifier spec) { } clang::QualType GetReturnTypeOfFunction(const clang::CallExpr *expr) { - auto decl = expr->getCalleeDecl(); - if (decl->getAsFunction()) { - return decl->getAsFunction()->getReturnType().getCanonicalType(); + if (auto *decl = expr->getCalleeDecl()) { + if (auto *fn = decl->getAsFunction()) { + return fn->getReturnType().getCanonicalType(); + } } - auto callee_ty = - expr->getCallee()->getType().getDesugaredType(decl->getASTContext()); - if (auto ptr_ty = callee_ty->getAs()) { - return ptr_ty->getPointeeType() - ->getAs() - ->getReturnType() - .getCanonicalType(); + auto callee_ty = expr->getCallee()->getType(); + if (auto *ptr_ty = callee_ty->getAs()) { + if (auto *fn_ty = + ptr_ty->getPointeeType()->getAs()) { + return fn_ty->getReturnType().getCanonicalType(); + } } assert(0 && "Unhandled function prototype"); return {}; } +clang::Expr *StripFunctionPointerDecay(clang::Expr *expr) { + if (auto *ice = clang::dyn_cast(expr)) { + auto ck = ice->getCastKind(); + if (ck == clang::CK_FunctionToPointerDecay || + ck == clang::CK_BuiltinFnToFnPtr) { + return ice->getSubExpr(); + } + } + return expr; +} + std::string GetOverloadedOperator(const clang::FunctionDecl *decl) { switch (decl->getOverloadedOperator()) { case clang::OO_Less: diff --git a/cpp2rust/converter/converter_lib.h b/cpp2rust/converter/converter_lib.h index c0d2a65..68c2704 100644 --- a/cpp2rust/converter/converter_lib.h +++ b/cpp2rust/converter/converter_lib.h @@ -91,6 +91,8 @@ template llvm::SmallString<16> GetNumAsString(const T &num) { clang::QualType GetReturnTypeOfFunction(const clang::CallExpr *expr); +clang::Expr *StripFunctionPointerDecay(clang::Expr *expr); + std::string GetOverloadedOperator(const clang::FunctionDecl *decl); bool IsOverloadedComparisonOperator(const clang::CXXMethodDecl *decl); diff --git a/cpp2rust/converter/mapper.cpp b/cpp2rust/converter/mapper.cpp index 478e3c5..8ba1d59 100644 --- a/cpp2rust/converter/mapper.cpp +++ b/cpp2rust/converter/mapper.cpp @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -560,6 +561,17 @@ std::string normalizeTranslationRule(std::string rule) { return rule; } +std::string GetRulePathForFunction(const clang::FunctionDecl *decl, + const std::string &model_suffix) { + assert(decl); + auto it = exprs_.find(ToString(decl)); + if (it == exprs_.end()) { + return ""; + } + auto &tgt = it->second; + return std::format("rules::{}_{}::{}", tgt.module, model_suffix, tgt.name); +} + } // namespace bool Contains(clang::QualType qual_type) { @@ -575,6 +587,21 @@ const TranslationRule::ExprTgt *GetExprTgt(const clang::Expr *expr) { return nullptr; } +std::string GetFnRefName(const clang::FunctionDecl *decl) { + assert(decl); + if (model_ == Model::kRefCount) { + auto refcount_path = GetRulePathForFunction(decl, "tgt_refcount"); + if (!refcount_path.empty()) { + return refcount_path; + } + } + auto unsafe_path = GetRulePathForFunction(decl, "tgt_unsafe"); + if (!unsafe_path.empty()) { + return unsafe_path; + } + return GetNamedDeclAsString(decl->getCanonicalDecl()); +} + std::string InstantiateTemplate(const clang::Expr *expr, const std::string &text) { auto it = search(expr); diff --git a/cpp2rust/converter/mapper.h b/cpp2rust/converter/mapper.h index 14de180..c8ed73f 100644 --- a/cpp2rust/converter/mapper.h +++ b/cpp2rust/converter/mapper.h @@ -19,6 +19,7 @@ bool Contains(const clang::Expr *expr); std::string Map(clang::QualType qual_type); const TranslationRule::ExprTgt *GetExprTgt(const clang::Expr *expr); +std::string GetFnRefName(const clang::FunctionDecl *decl); std::string InstantiateTemplate(const clang::Expr *expr, const std::string &text); bool ReturnsPointer(const clang::Expr *expr); diff --git a/cpp2rust/converter/models/converter_refcount.cpp b/cpp2rust/converter/models/converter_refcount.cpp index 6c58987..0a57c26 100644 --- a/cpp2rust/converter/models/converter_refcount.cpp +++ b/cpp2rust/converter/models/converter_refcount.cpp @@ -165,10 +165,77 @@ bool ConverterRefCount::VisitLValueReferenceType( return false; } +std::string ConverterRefCount::BuildFnAdapter( + const clang::FunctionDecl *src_fn, + const clang::FunctionProtoType *src_proto, + const clang::FunctionProtoType *target_proto) { + + // UB: Incompatible arity + if (src_proto->getNumParams() != target_proto->getNumParams()) { + return "None"; + } + + PushConversionKind push(*this, ConversionKind::Unboxed); + + // Build adapter signature: |a0: T0, a1: T1, ...| -> Tr + std::string closure = "(|"; + for (unsigned i = 0; i < target_proto->getNumParams(); ++i) { + closure += + std::format("a{}: {},", i, ToString(target_proto->getParamType(i))); + } + closure += "|"; + if (!target_proto->getReturnType()->isVoidType()) { + closure += std::format(" -> {} ", ToString(target_proto->getReturnType())); + } + closure += "{ "; + + // Build adapter body: src_fn(convert(a0), convert(a1), ...) + closure += Mapper::GetFnRefName(src_fn) + "("; + for (unsigned i = 0; i < src_proto->getNumParams(); ++i) { + auto src_pty = src_proto->getParamType(i); + auto tgt_pty = target_proto->getParamType(i); + if (ToString(src_pty) == ToString(tgt_pty)) { + closure += std::format("a{}", i); + } else if (src_pty->isPointerType() && tgt_pty->isPointerType()) { + if (tgt_pty->isVoidPointerType()) { + closure += std::format("a{}.cast::<{}>().unwrap()", i, + GetPointeeRustType(src_pty)); + } else if (src_pty->isVoidPointerType()) { + closure += std::format("a{}.to_any()", i); + } else if (tgt_pty->getPointeeType()->isCharType()) { + closure += std::format("a{}.reinterpret_cast::<{}>()", i, + GetPointeeRustType(src_pty)); + } else if (src_pty->getPointeeType()->isCharType()) { + closure += std::format("a{}.reinterpret_cast::()", i); + } + } else { + // UB: Incompatible types + return "None"; + } + closure += ", "; + } + closure += ") })"; + + return std::format("Some({} as {})", closure, GetFnTypeString(target_proto)); +} + +std::string +ConverterRefCount::GetFnTypeString(const clang::FunctionProtoType *proto) { + PushConversionKind push(*this, ConversionKind::Unboxed); + std::string result = "fn("; + for (auto p_ty : proto->param_types()) { + result += ToString(p_ty) + ","; + } + result += ")"; + if (!proto->getReturnType()->isVoidType()) { + result += std::format(" -> {}", ToString(proto->getReturnType())); + } + return result; +} + bool ConverterRefCount::VisitPointerType(clang::PointerType *type) { - if (type->getPointeeType()->getAs()) { - PushConversionKind push(*this, ConversionKind::Unboxed); - ConvertFunctionPointerType(type); + if (auto proto = type->getPointeeType()->getAs()) { + StrCat(std::format("FnPtr<{}>", GetFnTypeString(proto))); return false; } @@ -560,17 +627,18 @@ bool ConverterRefCount::VisitDeclRefExpr(clang::DeclRefExpr *expr) { } } - if (Mapper::Contains(expr)) { + auto str = ConvertDeclRefExpr(expr); + auto decl = expr->getDecl(); + + if (!(clang::isa(decl) && isAddrOf()) && + Mapper::Contains(expr)) { StrCat(GetMappedAsString(expr)); return false; } - auto str = ConvertDeclRefExpr(expr); - auto decl = expr->getDecl(); - - if (clang::isa(decl)) { + if (auto *fn_decl = clang::dyn_cast(decl)) { if (isAddrOf()) { - StrCat(std::format("Rc::new({})", str)); + EmitFnAsValue(fn_decl); } else { StrCat(str); } @@ -951,9 +1019,86 @@ bool ConverterRefCount::VisitImplicitCastExpr(clang::ImplicitCastExpr *expr) { } } + if (expr->getCastKind() == clang::CastKind::CK_NullToPointer && + expr->getType()->isFunctionPointerType()) { + StrCat("FnPtr::null()"); + computed_expr_type_ = ComputedExprType::FreshPointer; + return false; + } + return Converter::VisitImplicitCastExpr(expr); } +void ConverterRefCount::EmitFnPtrCall(clang::Expr *callee) { + StrCat("(*"); + Convert(callee); + StrCat(")"); +} + +void ConverterRefCount::EmitFnAsValue(const clang::FunctionDecl *fn_decl) { + StrCat(std::format( + "fn_ptr!({}, {})", Mapper::GetFnRefName(fn_decl), + GetFnTypeString(fn_decl->getType()->getAs()))); +} + +std::string ConverterRefCount::GetFunctionPointerDefaultAsString( + clang::QualType qual_type) { + return "FnPtr::null()"; +} + +void ConverterRefCount::ConvertEqualsNullPtr(clang::Expr *expr) { + StrCat("("); + Convert(expr); + StrCat(").is_null()"); +} + +bool ConverterRefCount::VisitFunctionPointerCast( + clang::ExplicitCastExpr *expr) { + if (expr->getType()->isFunctionPointerType() || + expr->getSubExpr()->getType()->isFunctionPointerType()) { + if (expr->getSubExpr()->getType()->isFunctionPointerType() && + expr->getType()->isFunctionPointerType()) { + auto target_proto = + expr->getType()->getPointeeType()->getAs(); + auto src_proto = expr->getSubExpr() + ->getType() + ->getPointeeType() + ->getAs(); + auto fn_type = GetFnTypeString(target_proto); + + std::string adapter = "None"; + // Only accept direct references to the casted function. Otherwise the + // closure would be capturing and would not coerce into a fn pointer. + if (auto *decl_ref = clang::dyn_cast( + expr->getSubExpr()->IgnoreImplicit())) { + if (auto *fn_decl = + clang::dyn_cast(decl_ref->getDecl())) { + adapter = BuildFnAdapter(fn_decl, src_proto, target_proto); + } + } + + StrCat(std::format("{}.cast::<{}>({})", ToString(expr->getSubExpr()), + fn_type, adapter)); + } else if (expr->getSubExpr()->getType()->isFunctionPointerType() || + expr->getType()->isVoidPointerType()) { + Convert(expr->getSubExpr()); + StrCat(".to_any()"); + } else if (expr->getSubExpr()->getType()->isVoidPointerType() || + expr->getType()->isFunctionPointerType()) { + auto target_proto = + expr->getType()->getPointeeType()->getAs(); + auto fn_type = GetFnTypeString(target_proto); + StrCat(std::format("{}.cast_fn::<{}>().expect(\"ub:wrong fn type\")", + ToString(expr->getSubExpr()), fn_type)); + } else { + assert(0 && "Unhandled function pointer cast"); + } + return false; + } + + return true; +} + bool ConverterRefCount::VisitExplicitCastExpr(clang::ExplicitCastExpr *expr) { if (expr->getTypeAsWritten()->isVoidType()) { return false; @@ -968,7 +1113,9 @@ bool ConverterRefCount::VisitExplicitCastExpr(clang::ExplicitCastExpr *expr) { return false; case clang::Stmt::CStyleCastExprClass: case clang::Stmt::CXXStaticCastExprClass: - if (expr->getSubExpr()->getType()->isVoidPointerType()) { + if (!VisitFunctionPointerCast(expr)) { + return false; + } else if (expr->getSubExpr()->getType()->isVoidPointerType()) { Convert(expr->getSubExpr()); PushConversionKind push(*this, ConversionKind::Unboxed); StrCat(std::format(".cast::<{}>().expect(\"ub:wrong type\")", @@ -1477,9 +1624,13 @@ void ConverterRefCount::ConvertVarInit(clang::QualType qual_type, { Buffer buf(*this); PushConversionKind push(*this, ConversionKind::Unboxed); - StrCat("Rc::new("); - VisitLambdaExpr(lambda); - StrCat(")"); + if (qual_type->isFunctionPointerType() && lambda->capture_size() == 0) { + StrCat("FnPtr::new(("); + VisitLambdaExpr(lambda); + StrCat("), 0)"); + } else { + VisitLambdaExpr(lambda); + } str = std::move(buf).str(); } StrCat(BoxValue(std::move(str))); diff --git a/cpp2rust/converter/models/converter_refcount.h b/cpp2rust/converter/models/converter_refcount.h index 8102590..cb9f3d8 100644 --- a/cpp2rust/converter/models/converter_refcount.h +++ b/cpp2rust/converter/models/converter_refcount.h @@ -59,12 +59,18 @@ class ConverterRefCount final : public Converter { void ConvertPrintf(clang::CallExpr *expr) override; + void EmitFnPtrCall(clang::Expr *callee) override; + + void EmitFnAsValue(const clang::FunctionDecl *fn_decl) override; + bool VisitCallExpr(clang::CallExpr *expr) override; bool VisitStringLiteral(clang::StringLiteral *expr) override; bool VisitImplicitCastExpr(clang::ImplicitCastExpr *expr) override; + bool VisitFunctionPointerCast(clang::ExplicitCastExpr *expr); + bool VisitExplicitCastExpr(clang::ExplicitCastExpr *expr) override; bool VisitBinaryOperator(clang::BinaryOperator *expr) override; @@ -103,6 +109,11 @@ class ConverterRefCount final : public Converter { std::string GetDefaultAsString(clang::QualType qual_type) override; + std::string + GetFunctionPointerDefaultAsString(clang::QualType qual_type) override; + + void ConvertEqualsNullPtr(clang::Expr *expr) override; + std::string GetDefaultAsStringFallback(clang::QualType qual_type) override; std::string ConvertVarDefaultInit(clang::QualType qual_type) override; @@ -171,6 +182,11 @@ class ConverterRefCount final : public Converter { const char *GetPointerDerefSuffix(clang::QualType pointee_type); const char *GetPointerDerefPrefix(clang::QualType pointee_type) override; + std::string GetFnTypeString(const clang::FunctionProtoType *proto); + std::string BuildFnAdapter(const clang::FunctionDecl *src_fn, + const clang::FunctionProtoType *src_proto, + const clang::FunctionProtoType *target_proto); + void EmitSetOrAssign(clang::Expr *lhs, std::string_view rhs); // Wraps a pointer expression with deref prefix/suffix: e.g. diff --git a/cpp2rust/converter/translation_rule.cpp b/cpp2rust/converter/translation_rule.cpp index 6350a21..2adaa07 100644 --- a/cpp2rust/converter/translation_rule.cpp +++ b/cpp2rust/converter/translation_rule.cpp @@ -320,7 +320,7 @@ RuleMap LoadTgtFromIR(const std::filesystem::path &json_path) { Rule rule; if (name[0] == 'f') { rule.tgt = ParseExprTgtJSON(*obj); - std::get(rule.tgt).validate(json_path.string() + ":" + name); + std::get(rule.tgt).name = name; } else if (name[0] == 't') { rule.tgt = ParseTypeTgtJSON(*obj); } else { @@ -462,6 +462,8 @@ void ExprTgt::validate(const std::string &context) const { ValidateConsecutiveKeys(params, 'a', 0, context + " params"); ValidateConsecutiveKeys(generics, 'T', 1, context + " generics"); assert(!body.empty() && "ExprTgt body must not be empty"); + assert(!name.empty() && "ExprTgt name must not be empty"); + assert(!module.empty() && "ExprTgt module must not be empty"); } std::vector Load(const std::filesystem::path &path, Model model) { @@ -484,11 +486,17 @@ std::vector Load(const std::filesystem::path &path, Model model) { } for (auto &[name, src_rule] : src_rules) { rules.at(name).src = std::move(src_rule.src); + if (auto *expr_tgt = std::get_if(&rules.at(name).tgt)) { + expr_tgt->module = dir.filename().string(); + } } std::vector result; for (auto &[name, rule] : rules) { assert(!rule.src.empty() && "Rule loaded from IR but has no src"); + if (auto *expr_tgt = std::get_if(&rule.tgt)) { + expr_tgt->validate(path.string() + ":" + name); + } result.push_back(std::move(rule)); } return result; diff --git a/cpp2rust/converter/translation_rule.h b/cpp2rust/converter/translation_rule.h index 566dd90..2d63c8f 100644 --- a/cpp2rust/converter/translation_rule.h +++ b/cpp2rust/converter/translation_rule.h @@ -61,6 +61,8 @@ struct TypeInfo { }; struct ExprTgt { + std::string name; + std::string module; std::unordered_map params; // "a0" -> TypeInfo TypeInfo return_type; std::unordered_map> diff --git a/libcc2rs/src/fn_ptr.rs b/libcc2rs/src/fn_ptr.rs new file mode 100644 index 0000000..07a5f0d --- /dev/null +++ b/libcc2rs/src/fn_ptr.rs @@ -0,0 +1,172 @@ +// Copyright (c) 2022-present INESC-ID. +// Distributed under the MIT license that can be found in the LICENSE file. + +#[macro_export] +macro_rules! fn_ptr { + ($f:expr, $ty:ty) => { + $crate::FnPtr::new($f as $ty, $f as *const () as usize) + }; +} + +use std::any::{Any, TypeId}; +use std::marker::PhantomData; +use std::ops::Deref; +use std::rc::Rc; + +use crate::rc::{AnyPtr, ErasedPtr}; +use crate::reinterpret::ByteRepr; + +#[derive(Clone)] +pub(crate) struct FnState { + addr: usize, + cast_history: Vec>>, +} + +pub struct FnPtr { + state: Option>, + // FnPtr does not use T, hence wrap in PhantomData + _marker: PhantomData, +} + +impl FnPtr { + #[inline] + pub fn null() -> Self { + FnPtr { + state: None, + _marker: PhantomData, + } + } + + #[inline] + pub fn is_null(&self) -> bool { + self.state.is_none() + } +} + +impl FnPtr { + pub fn new(f: T, addr: usize) -> Self { + FnPtr { + state: Some(Rc::new(FnState { + addr, + cast_history: vec![Some(Rc::new(f))], + })), + _marker: PhantomData, + } + } + + pub fn cast(&self, adapter: Option) -> FnPtr { + let state = self.state.as_ref().expect("ub: null fn pointer cast"); + + for (i, entry) in state.cast_history.iter().enumerate() { + if let Some(ref rc) = entry { + if (*rc).as_ref().type_id() == TypeId::of::() { + return FnPtr { + state: Some(Rc::new(FnState { + addr: state.addr, + cast_history: state.cast_history[..=i].to_vec(), + })), + _marker: PhantomData, + }; + } + } + } + + let mut new_stack = state.cast_history.clone(); + new_stack.push(adapter.map(|a| Rc::new(a) as Rc)); + + FnPtr { + state: Some(Rc::new(FnState { + addr: state.addr, + cast_history: new_stack, + })), + _marker: PhantomData, + } + } +} + +impl Deref for FnPtr { + type Target = T; + fn deref(&self) -> &T { + let state = self.state.as_ref().expect("ub: null fn pointer call"); + let entry = state + .cast_history + .last() + .expect("empty fn pointer cast_history"); + match entry { + Some(rc) => rc + .downcast_ref::() + .expect("ub: fn pointer type mismatch"), + None => panic!("ub: calling through incompatible fn pointer type"), + } + } +} + +impl Clone for FnPtr { + fn clone(&self) -> Self { + FnPtr { + state: self.state.clone(), + _marker: PhantomData, + } + } +} + +impl Default for FnPtr { + fn default() -> Self { + Self::null() + } +} + +impl PartialEq for FnPtr { + fn eq(&self, other: &Self) -> bool { + match (&self.state, &other.state) { + (None, None) => true, + (Some(a), Some(b)) => a.addr == b.addr, + _ => false, + } + } +} + +impl Eq for FnPtr {} + +impl std::fmt::Debug for FnPtr { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match &self.state { + None => write!(f, "FnPtr(null)"), + Some(s) => write!(f, "FnPtr(0x{:x})", s.addr), + } + } +} + +impl ByteRepr for FnPtr {} + +impl ErasedPtr for FnPtr { + fn pointee_type_id(&self) -> TypeId { + TypeId::of::() + } + fn memcpy(&self, _src: &dyn ErasedPtr, _len: usize) { + panic!("memcpy not supported on fn pointer"); + } + fn as_any(&self) -> &dyn Any { + self + } + fn equals(&self, other: &dyn ErasedPtr) -> Option { + if self.pointee_type_id() != other.pointee_type_id() { + return None; + } + other.as_any().downcast_ref::>().map(|o| self == o) + } +} + +impl FnPtr { + pub fn to_any(&self) -> AnyPtr { + AnyPtr { + ptr: Rc::new(self.clone()), + } + } +} + +impl AnyPtr { + pub fn cast_fn(&self) -> Option> { + self.ptr.as_any().downcast_ref::>().cloned() + } +} diff --git a/libcc2rs/src/lib.rs b/libcc2rs/src/lib.rs index 42eb411..1271b94 100644 --- a/libcc2rs/src/lib.rs +++ b/libcc2rs/src/lib.rs @@ -7,6 +7,9 @@ pub use reinterpret::ByteRepr; mod rc; pub use rc::*; +mod fn_ptr; +pub use fn_ptr::FnPtr; + mod inc; pub use inc::*; diff --git a/libcc2rs/src/rc.rs b/libcc2rs/src/rc.rs index eb197ee..75c2606 100644 --- a/libcc2rs/src/rc.rs +++ b/libcc2rs/src/rc.rs @@ -1004,7 +1004,7 @@ impl Ptr { } } -trait ErasedPtr: std::any::Any { +pub(crate) trait ErasedPtr: std::any::Any { fn pointee_type_id(&self) -> std::any::TypeId; fn memcpy(&self, src: &dyn ErasedPtr, len: usize); fn as_any(&self) -> &dyn std::any::Any; @@ -1013,7 +1013,7 @@ trait ErasedPtr: std::any::Any { impl ErasedPtr for Ptr where - T: Clone + ByteRepr + 'static, + T: ByteRepr + 'static, Ptr: PartialEq, { fn pointee_type_id(&self) -> std::any::TypeId { @@ -1024,35 +1024,13 @@ where if self.pointee_type_id() != src.pointee_type_id() { panic!("memcpy: type mismatch"); } - let src_ptr = src .as_any() .downcast_ref::>() .expect("memcpy: downcast to Ptr failed"); - - let elem = std::mem::size_of::(); - - if len == elem { - self.write(src_ptr.read()); - return; - } - - if elem != 0 && len.is_multiple_of(elem) { - let mut dst = self.clone(); - let mut src_it = src_ptr.clone(); - for _ in 0..(len / elem) { - dst.write(src_it.read()); - dst += 1; - src_it += 1; - } - - return; - } - - panic!( - "memcpy: len {} not compatible with element size {}", - len, elem - ); + let dst_bytes: Ptr = self.reinterpret_cast(); + let src_bytes: Ptr = src_ptr.reinterpret_cast(); + dst_bytes.memcpy(&src_bytes, len); } fn as_any(&self) -> &dyn std::any::Any { @@ -1074,10 +1052,10 @@ where #[derive(Clone)] pub struct AnyPtr { - ptr: Rc, + pub(crate) ptr: Rc, } -impl Ptr { +impl Ptr { pub fn to_any(&self) -> AnyPtr { AnyPtr { ptr: Rc::new(self.clone()), @@ -1093,6 +1071,11 @@ impl Default for AnyPtr { impl AnyPtr { pub fn cast(&self) -> Option> { + if let Some(p) = self.ptr.as_any().downcast_ref::>() { + if p.is_null() { + return Some(Ptr::::null()); + } + } self.ptr.as_any().downcast_ref::>().cloned() } diff --git a/rules/src/lib.rs b/rules/src/lib.rs index 9efa064..44df340 100644 --- a/rules/src/lib.rs +++ b/rules/src/lib.rs @@ -3,3 +3,4 @@ #![allow(warnings)] mod modules; +pub use modules::*; diff --git a/rules/stdio/ir_unsafe.json b/rules/stdio/ir_unsafe.json index 81d8f44..8b55e1c 100644 --- a/rules/stdio/ir_unsafe.json +++ b/rules/stdio/ir_unsafe.json @@ -618,7 +618,7 @@ "multi_statement": true, "params": { "a0": { - "type": "*mut u8", + "type": "*mut ::libc::c_void", "is_unsafe_pointer": true }, "a1": { @@ -797,7 +797,7 @@ "multi_statement": true, "params": { "a0": { - "type": "*mut u8", + "type": "*const ::libc::c_void", "is_unsafe_pointer": true }, "a1": { diff --git a/rules/stdio/tgt_refcount.rs b/rules/stdio/tgt_refcount.rs index ea7174f..a36d31a 100644 --- a/rules/stdio/tgt_refcount.rs +++ b/rules/stdio/tgt_refcount.rs @@ -55,7 +55,7 @@ fn f4(a0: &mut ::std::fs::File, a1: i64, a2: i32) -> i32 { } } -fn f5(a0: AnyPtr, a1: u64, a2: u64, a3: Ptr<::std::fs::File>) -> u64 { +pub fn f5(a0: AnyPtr, a1: u64, a2: u64, a3: Ptr<::std::fs::File>) -> u64 { let total = a1.saturating_mul(a2) as usize; let mut dst = a0 .cast::() @@ -92,7 +92,7 @@ fn f5(a0: AnyPtr, a1: u64, a2: u64, a3: Ptr<::std::fs::File>) -> u64 { (read_bytes / a1 as usize) as u64 } -fn f6(a0: AnyPtr, a1: u64, a2: u64, a3: Ptr<::std::fs::File>) -> u64 { +pub fn f6(a0: AnyPtr, a1: u64, a2: u64, a3: Ptr<::std::fs::File>) -> u64 { let total = a1.saturating_mul(a2) as usize; let mut src = a0 .cast::() diff --git a/rules/stdio/tgt_unsafe.rs b/rules/stdio/tgt_unsafe.rs index adc0565..d0bf882 100644 --- a/rules/stdio/tgt_unsafe.rs +++ b/rules/stdio/tgt_unsafe.rs @@ -65,7 +65,7 @@ unsafe fn f4(a0: *mut ::std::fs::File, a1: i64, a2: i32) -> i32 { } } -unsafe fn f5(a0: *mut u8, a1: u64, a2: u64, a3: *mut ::std::fs::File) -> u64 { +pub unsafe fn f5(a0: *mut ::libc::c_void, a1: u64, a2: u64, a3: *mut ::std::fs::File) -> u64 { let total = a1.saturating_mul(a2) as usize; let mut dst = a0 as *mut u8; @@ -97,7 +97,7 @@ unsafe fn f5(a0: *mut u8, a1: u64, a2: u64, a3: *mut ::std::fs::File) -> u64 { (read_bytes / a1 as usize) as u64 } -unsafe fn f6(a0: *mut u8, a1: u64, a2: u64, a3: *mut ::std::fs::File) -> u64 { +pub unsafe fn f6(a0: *const ::libc::c_void, a1: u64, a2: u64, a3: *mut ::std::fs::File) -> u64 { let total = a1.saturating_mul(a2) as usize; let mut src = a0 as *mut u8; diff --git a/tests/benchmarks/out/unsafe/bfs.rs b/tests/benchmarks/out/unsafe/bfs.rs index ae9be6f..956d754 100644 --- a/tests/benchmarks/out/unsafe/bfs.rs +++ b/tests/benchmarks/out/unsafe/bfs.rs @@ -62,7 +62,7 @@ pub unsafe fn BFS_0(graph: *const Graph, mut start_vertex: u32) -> *mut u32 { let mut Q: Queue = Queue { elems: Box::leak( (0..((*graph).V as u64)) - .map(|_| ::default()) + .map(|_| 0_u32) .collect::>(), ) .as_mut_ptr(), @@ -72,13 +72,13 @@ pub unsafe fn BFS_0(graph: *const Graph, mut start_vertex: u32) -> *mut u32 { }; let mut visited: *mut bool = Box::leak( (0..((*graph).V as u64)) - .map(|_| ::default()) + .map(|_| false) .collect::>(), ) .as_mut_ptr(); let mut pred: *mut u32 = Box::leak( (0..((*graph).V as u64)) - .map(|_| ::default()) + .map(|_| 0_u32) .collect::>(), ) .as_mut_ptr(); diff --git a/tests/lit/lit/formats/Cpp2RustTest.py b/tests/lit/lit/formats/Cpp2RustTest.py index 292eedc..5fafe0c 100644 --- a/tests/lit/lit/formats/Cpp2RustTest.py +++ b/tests/lit/lit/formats/Cpp2RustTest.py @@ -7,21 +7,29 @@ import difflib, os, re, shutil, random import tomli -def read_rust_version(): - toolchain_path = os.path.join(os.path.dirname(__file__), - '../../../../libcc2rs/rust-toolchain.toml') - with open(toolchain_path, 'rb') as f: - return tomli.load(f)['toolchain']['channel'] - class Cpp2RustTest(TestFormat): def __init__(self): self.regex_xfail = re.compile(r"//\s*XFAIL:\s*(.*)") self.regex_panic = re.compile(r"//\s*panic\s*(?::\s*(.*))?$", re.MULTILINE) self.regex_nocompile = re.compile(r"//\s*no-compile\s*(?::\s*(.*))?$", re.MULTILINE) self.regex_nondet_result = re.compile(r"//\s*nondet-result\s*(?::\s*(.*))?$", re.MULTILINE) - self.rust_version = read_rust_version() + self.rust_version = self.readRustVersion() os.environ['RUSTFLAGS'] = '-Awarnings -A dangerous-implicit-autorefs' + def readRustVersion(self): + toolchain_path = os.path.join(os.path.dirname(__file__), + '../../../../libcc2rs/rust-toolchain.toml') + with open(toolchain_path, 'rb') as f: + return tomli.load(f)['toolchain']['channel'] + + def cargoEnv(self): + return dict(os.environ, CARGO_TARGET_DIR=os.path.abspath(self.sharedTargetDir())) + + def sharedTargetDir(self): + return os.path.abspath(os.path.join( + os.path.dirname(__file__), + '../../../../build/tmp/cargo-target')) + def updateExpected(self, generated, expected_path): os.makedirs(os.path.dirname(expected_path), exist_ok=True) with open(expected_path, 'w') as f: @@ -120,24 +128,32 @@ def fail(str, code = fail_code): fromfile='expected', tofile='generated')) return fail('different output\n' + diff) + pkg_name = "test_" + re.sub(r'[^a-zA-Z0-9_]', '_', + os.path.basename(tmp_dir)) + # Check if we can compile the rust file with open(tmp_dir + "/rust-toolchain.toml", 'w') as f: f.write(f'[toolchain]\nchannel = "{self.rust_version}"\n') with open(tmp_dir + "/Cargo.toml", 'w') as f: f.write(f""" [package] -name = "test" +name = "{pkg_name}" version = "0.1.0" edition = "2021" rust-version = "{self.rust_version}" +[[bin]] +name = "{pkg_name}" +path = "src/main.rs" + [dependencies] libc = "0.2.169" libcc2rs = {{ path = "../../../libcc2rs" }} +rules = {{ path = "../../../rules" }} """) cmd = ['cargo', 'build', '--release', '--quiet'] - _, err, returncode = lit.util.executeCommand(cmd, tmp_dir) + _, err, returncode = lit.util.executeCommand(cmd, tmp_dir, env=self.cargoEnv()) if should_not_compile: if returncode != 0: shutil.rmtree(tmp_dir, True) @@ -146,7 +162,7 @@ def fail(str, code = fail_code): if returncode != 0: return fail('cargo failed\n' + err) - rust_bin = tmp_dir + "/target/release/test" + rust_bin = os.path.join(self.sharedTargetDir(), "release", pkg_name) if not skip_run: if should_panic: diff --git a/tests/ub/out/refcount/dangling-prvalue-as-lvalue.rs b/tests/ub/out/refcount/dangling-prvalue-as-lvalue.rs index c5ffd85..fd03296 100644 --- a/tests/ub/out/refcount/dangling-prvalue-as-lvalue.rs +++ b/tests/ub/out/refcount/dangling-prvalue-as-lvalue.rs @@ -17,7 +17,7 @@ fn main_0() -> i32 { let v: Value> = Rc::new(RefCell::new(vec![1, 2])); let b: Ptr = ({ let _a: Ptr = (v.as_pointer() as Ptr); - Rc::new(foo_0)(_a) + foo_0(_a) }); (*v.borrow_mut()).clear(); return (b.read()); diff --git a/tests/ub/out/refcount/ub1.rs b/tests/ub/out/refcount/ub1.rs index 0b4feef..e525fce 100644 --- a/tests/ub/out/refcount/ub1.rs +++ b/tests/ub/out/refcount/ub1.rs @@ -16,6 +16,6 @@ pub fn main() { std::process::exit(main_0()); } fn main_0() -> i32 { - let x: Ptr = ({ Rc::new(dangling_0)() }); + let x: Ptr = ({ dangling_0() }); return (x.read()); } diff --git a/tests/ub/out/unsafe/dangling-prvalue-as-lvalue.rs b/tests/ub/out/unsafe/dangling-prvalue-as-lvalue.rs index 11ddb63..eeaa1d9 100644 --- a/tests/ub/out/unsafe/dangling-prvalue-as-lvalue.rs +++ b/tests/ub/out/unsafe/dangling-prvalue-as-lvalue.rs @@ -19,7 +19,7 @@ unsafe fn main_0() -> i32 { let mut v: Vec = vec![1, 2]; let b: *const i32 = (unsafe { let _a: *const i32 = &(*v.as_mut_ptr()) as *const i32; - Rc::new(|a0| unsafe { foo_0(a0) })(_a) + foo_0(_a) }); v.clear(); return (*b); diff --git a/tests/ub/out/unsafe/ub1.rs b/tests/ub/out/unsafe/ub1.rs index bc49a90..002d9c7 100644 --- a/tests/ub/out/unsafe/ub1.rs +++ b/tests/ub/out/unsafe/ub1.rs @@ -18,6 +18,6 @@ pub fn main() { } } unsafe fn main_0() -> i32 { - let x: *mut i32 = (unsafe { Rc::new(|| unsafe { dangling_0() })() }); + let x: *mut i32 = (unsafe { dangling_0() }); return (*x); } diff --git a/tests/ub/out/unsafe/ub10.rs b/tests/ub/out/unsafe/ub10.rs index 14ba0ea..f684d12 100644 --- a/tests/ub/out/unsafe/ub10.rs +++ b/tests/ub/out/unsafe/ub10.rs @@ -13,12 +13,8 @@ pub fn main() { } } unsafe fn main_0() -> i32 { - let mut arr: *mut i32 = Box::leak( - (0..10_u64) - .map(|_| ::default()) - .collect::>(), - ) - .as_mut_ptr(); + let mut arr: *mut i32 = + Box::leak((0..10_u64).map(|_| 0_i32).collect::>()).as_mut_ptr(); let mut ptr: *mut i32 = arr.offset((1) as isize); let mut out: i32 = (*ptr); diff --git a/tests/ub/out/unsafe/ub14.rs b/tests/ub/out/unsafe/ub14.rs index 491de59..61c8958 100644 --- a/tests/ub/out/unsafe/ub14.rs +++ b/tests/ub/out/unsafe/ub14.rs @@ -13,12 +13,8 @@ pub fn main() { } } unsafe fn main_0() -> i32 { - let mut arr1: *mut i32 = Box::leak( - (0..100_u64) - .map(|_| ::default()) - .collect::>(), - ) - .as_mut_ptr(); + let mut arr1: *mut i32 = + Box::leak((0..100_u64).map(|_| 0_i32).collect::>()).as_mut_ptr(); (*arr1.offset((100) as isize)) = 1; ::std::mem::drop(Box::from_raw(::std::slice::from_raw_parts_mut( diff --git a/tests/ub/out/unsafe/ub15.rs b/tests/ub/out/unsafe/ub15.rs index dc08aa1..669d188 100644 --- a/tests/ub/out/unsafe/ub15.rs +++ b/tests/ub/out/unsafe/ub15.rs @@ -13,12 +13,8 @@ pub fn main() { } } unsafe fn main_0() -> i32 { - let mut arr: *mut i32 = Box::leak( - (0..15_u64) - .map(|_| ::default()) - .collect::>(), - ) - .as_mut_ptr(); + let mut arr: *mut i32 = + Box::leak((0..15_u64).map(|_| 0_i32).collect::>()).as_mut_ptr(); let mut ptr: *mut i32 = arr.offset((15) as isize); let mut out: i32 = (*ptr); diff --git a/tests/ub/out/unsafe/ub16.rs b/tests/ub/out/unsafe/ub16.rs index a53d884..a4c801e 100644 --- a/tests/ub/out/unsafe/ub16.rs +++ b/tests/ub/out/unsafe/ub16.rs @@ -16,12 +16,8 @@ pub fn main() { } } unsafe fn main_0() -> i32 { - let mut p1: *mut i32 = Box::leak( - (0..10_u64) - .map(|_| ::default()) - .collect::>(), - ) - .as_mut_ptr(); + let mut p1: *mut i32 = + Box::leak((0..10_u64).map(|_| 0_i32).collect::>()).as_mut_ptr(); let mut out: i32 = (*(unsafe { let _a: *mut i32 = (&mut (*p1.offset((1) as isize)) as *mut i32); foo_0(_a) diff --git a/tests/ub/out/unsafe/ub20.rs b/tests/ub/out/unsafe/ub20.rs index 8517a69..053b353 100644 --- a/tests/ub/out/unsafe/ub20.rs +++ b/tests/ub/out/unsafe/ub20.rs @@ -16,12 +16,8 @@ pub fn main() { } } unsafe fn main_0() -> i32 { - let mut x: *mut i32 = Box::leak( - (0..10_u64) - .map(|_| ::default()) - .collect::>(), - ) - .as_mut_ptr(); + let mut x: *mut i32 = + Box::leak((0..10_u64).map(|_| 0_i32).collect::>()).as_mut_ptr(); (unsafe { let _single: *mut i32 = x; foo_0(_single) diff --git a/tests/ub/out/unsafe/ub9.rs b/tests/ub/out/unsafe/ub9.rs index f2136e7..8f57418 100644 --- a/tests/ub/out/unsafe/ub9.rs +++ b/tests/ub/out/unsafe/ub9.rs @@ -13,12 +13,8 @@ pub fn main() { } } unsafe fn main_0() -> i32 { - let mut arr: *mut i32 = Box::leak( - (0..10_u64) - .map(|_| ::default()) - .collect::>(), - ) - .as_mut_ptr(); + let mut arr: *mut i32 = + Box::leak((0..10_u64).map(|_| 0_i32).collect::>()).as_mut_ptr(); let mut out: i32 = (*arr.offset((10) as isize)); ::std::mem::drop(Box::from_raw(::std::slice::from_raw_parts_mut( diff --git a/tests/unit/Cargo.toml b/tests/unit/Cargo.toml deleted file mode 100644 index a8618fe..0000000 --- a/tests/unit/Cargo.toml +++ /dev/null @@ -1,14 +0,0 @@ -[package] -name = "rs" -version = "0.1.0" -edition = "2021" - -[dependencies] -libc = "0.2.153" -libcc2rs = { path = "../../../libcc2rs" } - -# Any project that uses rust-analyzer with the rustc_private -# crates must set [package.metadata.rust-analyzer] rustc_private=true to use it. - -[package.metadata.rust-analyzer] -rustc_private=true diff --git a/tests/unit/fn_ptr.cpp b/tests/unit/fn_ptr.cpp new file mode 100644 index 0000000..c7c9c7e --- /dev/null +++ b/tests/unit/fn_ptr.cpp @@ -0,0 +1,21 @@ +#include + +typedef int (*foo_t)(void *); + +int my_foo(void *p) { return *static_cast(p); } + +int foo(foo_t fn, int *pi) { return fn(pi); } + +int main() { + foo_t fn = nullptr; + assert(fn == nullptr); + assert(fn != my_foo); + + fn = my_foo; + assert(fn != nullptr); + assert(fn == my_foo); + + int a = 10; + assert(foo(fn, &a) == a); + return 0; +} diff --git a/tests/unit/fn_ptr_array.cpp b/tests/unit/fn_ptr_array.cpp new file mode 100644 index 0000000..f7521fa --- /dev/null +++ b/tests/unit/fn_ptr_array.cpp @@ -0,0 +1,21 @@ +#include + +typedef int (*op_t)(int, int); + +int add(int a, int b) { return a + b; } +int sub(int a, int b) { return a - b; } +int mul(int a, int b) { return a * b; } + +int main() { + op_t ops[3] = {add, sub, mul}; + + assert(ops[0](2, 3) == 5); + assert(ops[1](7, 4) == 3); + assert(ops[2](6, 5) == 30); + + assert(ops[0] != nullptr); + assert(ops[0] == add); + assert(ops[0] != sub); + + return 0; +} diff --git a/tests/unit/fn_ptr_as_condition.cpp b/tests/unit/fn_ptr_as_condition.cpp new file mode 100644 index 0000000..5817f7e --- /dev/null +++ b/tests/unit/fn_ptr_as_condition.cpp @@ -0,0 +1,33 @@ +#include + +typedef void (*callback_t)(int *); + +void double_it(int *x) { *x *= 2; } + +void maybe_call(callback_t cb, int *x) { + if (cb) { + cb(x); + } +} + +int main() { + int a = 5; + maybe_call(double_it, &a); + assert(a == 10); + + int b = 5; + maybe_call(nullptr, &b); + assert(b == 5); + + callback_t fn = nullptr; + if (!fn) { + fn = double_it; + } + int c = 3; + if (fn) { + fn(&c); + } + assert(c == 6); + + return 0; +} diff --git a/tests/unit/fn_ptr_cast.cpp b/tests/unit/fn_ptr_cast.cpp new file mode 100644 index 0000000..d825b05 --- /dev/null +++ b/tests/unit/fn_ptr_cast.cpp @@ -0,0 +1,56 @@ +#include + +typedef void (*generic_fn)(void); +typedef int (*int_fn)(int); + +int double_it(int x) { return x * 2; } + +void test_roundtrip() { + int_fn fn = double_it; + assert(fn(5) == 10); + + generic_fn gfn = (generic_fn)fn; + assert(gfn != nullptr); + + int_fn fn2 = (int_fn)gfn; + assert(fn2(5) == 10); + assert(fn2 == fn); +} + +void test_double_cast() { + int_fn fn = double_it; + int_fn fn2 = (int_fn)(generic_fn)fn; + assert(fn2(5) == 10); + assert(fn2 == fn); +} + +struct Command { + void *data; +}; + +void test_void_ptr_to_fn() { + Command cmd; + cmd.data = (void *)double_it; + + int_fn fn = (int_fn)cmd.data; + assert(fn(5) == 10); +} + +typedef int (*generic_int_fn)(void *, int); + +int add_offset(int *base, int offset) { return *base + offset; } + +void test_call_through_cast() { + generic_int_fn gfn = (generic_int_fn)add_offset; + int val = 100; + int result = gfn(&val, 42); + assert(result == 142); +} + +int main() { + test_roundtrip(); + test_double_cast(); + test_void_ptr_to_fn(); + test_call_through_cast(); + return 0; +} diff --git a/tests/unit/fn_ptr_conditional.cpp b/tests/unit/fn_ptr_conditional.cpp new file mode 100644 index 0000000..d1b4c83 --- /dev/null +++ b/tests/unit/fn_ptr_conditional.cpp @@ -0,0 +1,25 @@ +#include + +typedef int (*op_t)(int); + +int inc(int x) { return x + 1; } +int dec(int x) { return x - 1; } +int identity(int x) { return x; } + +op_t pick(int mode) { return mode > 0 ? inc : mode < 0 ? dec : identity; } + +int apply(op_t fn, int x) { + op_t actual = fn ? fn : identity; + return actual(x); +} + +int main() { + assert(pick(1)(10) == 11); + assert(pick(-1)(10) == 9); + assert(pick(0)(10) == 10); + + assert(apply(inc, 5) == 6); + assert(apply(nullptr, 5) == 5); + + return 0; +} diff --git a/tests/unit/fn_ptr_default_arg.cpp b/tests/unit/fn_ptr_default_arg.cpp new file mode 100644 index 0000000..c5e0f55 --- /dev/null +++ b/tests/unit/fn_ptr_default_arg.cpp @@ -0,0 +1,23 @@ +#include + +typedef int (*transform_t)(int); + +int identity(int x) { return x; } + +int apply(int x, transform_t fn = nullptr) { + if (fn) { + return fn(x); + } + return x; +} + +int main() { + assert(apply(5) == 5); + assert(apply(5, nullptr) == 5); + assert(apply(5, identity) == 5); + + transform_t negate = [](int x) { return -x; }; + assert(apply(5, negate) == -5); + + return 0; +} diff --git a/tests/unit/fn_ptr_global.cpp b/tests/unit/fn_ptr_global.cpp new file mode 100644 index 0000000..5ff3082 --- /dev/null +++ b/tests/unit/fn_ptr_global.cpp @@ -0,0 +1,36 @@ +#include + +typedef int (*op_t)(int); + +int double_it(int x) { return x * 2; } +int triple_it(int x) { return x * 3; } + +static op_t g_op = nullptr; + +void set_op(op_t fn) { g_op = fn; } + +int call_op(int x) { + if (g_op) { + return g_op(x); + } + return x; +} + +int main() { + assert(call_op(5) == 5); + + set_op(double_it); + assert(g_op != nullptr); + assert(g_op == double_it); + assert(call_op(5) == 10); + + set_op(triple_it); + assert(g_op == triple_it); + assert(call_op(5) == 15); + + set_op(nullptr); + assert(g_op == nullptr); + assert(call_op(5) == 5); + + return 0; +} diff --git a/tests/unit/fn_ptr_reassign.cpp b/tests/unit/fn_ptr_reassign.cpp new file mode 100644 index 0000000..b8dc48f --- /dev/null +++ b/tests/unit/fn_ptr_reassign.cpp @@ -0,0 +1,27 @@ +#include + +typedef int (*op_t)(int, int); + +int add(int a, int b) { return a + b; } +int sub(int a, int b) { return a - b; } +int mul(int a, int b) { return a * b; } + +int main() { + op_t fn = add; + assert(fn(3, 4) == 7); + + fn = sub; + assert(fn(10, 3) == 7); + + fn = mul; + assert(fn(6, 7) == 42); + + fn = nullptr; + assert(fn == nullptr); + + fn = add; + assert(fn != nullptr); + assert(fn(1, 1) == 2); + + return 0; +} diff --git a/tests/unit/fn_ptr_return.cpp b/tests/unit/fn_ptr_return.cpp new file mode 100644 index 0000000..6e57093 --- /dev/null +++ b/tests/unit/fn_ptr_return.cpp @@ -0,0 +1,27 @@ +#include + +typedef int (*op_t)(int); + +int inc(int x) { return x + 1; } +int dec(int x) { return x - 1; } + +op_t pick(int choose_inc) { + if (choose_inc) { + return inc; + } + return dec; +} + +int main() { + op_t f = pick(1); + assert(f != nullptr); + assert(f == inc); + assert(f(10) == 11); + + op_t g = pick(0); + assert(g == dec); + assert(g(10) == 9); + + assert(f != g); + return 0; +} diff --git a/tests/unit/fn_ptr_stable_sort.cpp b/tests/unit/fn_ptr_stable_sort.cpp new file mode 100644 index 0000000..8361b5a --- /dev/null +++ b/tests/unit/fn_ptr_stable_sort.cpp @@ -0,0 +1,25 @@ +#include +#include +#include + +struct Item { + int key; + int value; +}; + +static bool Compare(const Item &a, const Item &b) { return a.key < b.key; } + +int main() { + std::vector v; + v.push_back({3, 30}); + v.push_back({1, 10}); + v.push_back({2, 20}); + + std::stable_sort(v.begin(), v.end(), Compare); + + assert(v[0].key == 1); + assert(v[1].key == 2); + assert(v[2].key == 3); + + return 0; +} diff --git a/tests/unit/fn_ptr_stdlib_compare.cpp b/tests/unit/fn_ptr_stdlib_compare.cpp new file mode 100644 index 0000000..6bb8b55 --- /dev/null +++ b/tests/unit/fn_ptr_stdlib_compare.cpp @@ -0,0 +1,23 @@ +#include +#include +#include + +typedef size_t (*fread_t)(void *, size_t, size_t, FILE *); + +typedef size_t (*fread_alternative_t)(char *, size_t, size_t, void *); + +size_t my_alternative_fread(char *p, size_t n, size_t m, void *f) { return 22; } + +int main() { + fread_t fn1 = fread; + assert(fn1 == fread); + assert(fn1 != nullptr); + + fread_alternative_t fn2 = (fread_alternative_t)fread; + assert(fn1 == (fread_t)fn2); + + fread_t f3 = (fread_t)my_alternative_fread; + assert((*f3)(nullptr, 0, 0, nullptr) == 22); + + return 0; +} diff --git a/tests/unit/fn_ptr_struct.cpp b/tests/unit/fn_ptr_struct.cpp new file mode 100644 index 0000000..55216e7 --- /dev/null +++ b/tests/unit/fn_ptr_struct.cpp @@ -0,0 +1,26 @@ +#include + +typedef int (*handler_t)(int); + +struct Handler { + int tag; + handler_t cb; +}; + +int double_it(int x) { return x * 2; } +int negate(int x) { return -x; } + +int main() { + Handler h1 = {1, double_it}; + Handler h2 = {2, negate}; + + assert(h1.cb != nullptr); + assert(h1.cb(5) == 10); + assert(h2.cb(7) == -7); + + h1.cb = negate; + assert(h1.cb(3) == -3); + assert(h1.cb == h2.cb); + + return 0; +} diff --git a/tests/unit/fn_ptr_void_return.cpp b/tests/unit/fn_ptr_void_return.cpp new file mode 100644 index 0000000..3ae221a --- /dev/null +++ b/tests/unit/fn_ptr_void_return.cpp @@ -0,0 +1,25 @@ +#include + +typedef void (*action_t)(int *); + +void negate(int *x) { *x = -*x; } +void zero_out(int *x) { *x = 0; } + +void run(action_t fn, int *x) { fn(x); } + +int main() { + int a = 42; + run(negate, &a); + assert(a == -42); + + run(zero_out, &a); + assert(a == 0); + + action_t fn = negate; + assert(fn != nullptr); + int b = 10; + fn(&b); + assert(b == -10); + + return 0; +} diff --git a/tests/unit/fn_ptr_vtable.cpp b/tests/unit/fn_ptr_vtable.cpp new file mode 100644 index 0000000..8d318a5 --- /dev/null +++ b/tests/unit/fn_ptr_vtable.cpp @@ -0,0 +1,41 @@ +#include + +typedef void *(*create_fn)(int); +typedef int (*get_fn)(void *); +typedef void (*destroy_fn)(void *); + +struct Vtable { + create_fn create; + get_fn get; + destroy_fn destroy; +}; + +static int storage; + +void *int_create(int val) { + storage = val; + return &storage; +} + +int int_get(void *p) { return *(int *)p; } + +void int_destroy(void *p) { *(int *)p = 0; } + +int main() { + Vtable vt = {int_create, int_get, int_destroy}; + + assert(vt.create != nullptr); + assert(vt.get != nullptr); + assert(vt.destroy != nullptr); + + void *obj = vt.create(42); + assert(vt.get(obj) == 42); + + vt.destroy(obj); + assert(storage == 0); + + vt.get = nullptr; + assert(vt.get == nullptr); + + return 0; +} diff --git a/tests/unit/lambda_capture_pass.cpp b/tests/unit/lambda_capture_pass.cpp new file mode 100644 index 0000000..439b128 --- /dev/null +++ b/tests/unit/lambda_capture_pass.cpp @@ -0,0 +1,19 @@ +#include + +template int apply(F fn, int x) { return fn(x); } + +int main() { + int base = 10; + + auto add_base = [&base](int x) { return x + base; }; + assert(apply(add_base, 5) == 15); + + base = 100; + assert(apply(add_base, 5) == 105); + + int factor = 3; + auto scale = [factor](int x) { return x * factor; }; + assert(apply(scale, 4) == 12); + + return 0; +} diff --git a/tests/unit/lambda_nested.cpp b/tests/unit/lambda_nested.cpp new file mode 100644 index 0000000..f7f26e9 --- /dev/null +++ b/tests/unit/lambda_nested.cpp @@ -0,0 +1,17 @@ +#include + +int main() { + int x = 10; + + auto outer = [&x](int y) { + auto inner = [&x, y](int z) { return x + y + z; }; + return inner(1); + }; + + assert(outer(20) == 31); + + x = 100; + assert(outer(20) == 121); + + return 0; +} diff --git a/tests/unit/out/refcount/complex_function.rs b/tests/unit/out/refcount/complex_function.rs index 7a7c203..2d778ae 100644 --- a/tests/unit/out/refcount/complex_function.rs +++ b/tests/unit/out/refcount/complex_function.rs @@ -133,11 +133,11 @@ fn main_0() -> i32 { let r1: Ptr = x1.as_pointer(); let r2: Ptr = ({ let _x: Ptr = x1.as_pointer(); - Rc::new(bar_2)(_x) + bar_2(_x) }); let r3: Ptr = ({ let _x: Ptr = (r1).clone(); - Rc::new(bar_2)(_x) + bar_2(_x) }); let __rhs = (*x1.borrow()); { @@ -403,7 +403,7 @@ fn main_0() -> i32 { .deref()) .v .as_pointer()); - Rc::new(ptr_1)(_x) + ptr_1(_x) }) .clone(); let __tmp = __ptr.read() + 1; @@ -436,7 +436,7 @@ fn main_0() -> i32 { .deref()) .v .as_pointer()); - Rc::new(ptr_1)(_x) + ptr_1(_x) }); let ptr3: Value> = Rc::new(RefCell::new( ({ @@ -450,7 +450,7 @@ fn main_0() -> i32 { .deref()) .v .as_pointer()); - Rc::new(ptr_1)(_x) + ptr_1(_x) }), )); let vptr: Value = Rc::new(RefCell::new( @@ -481,7 +481,7 @@ fn main_0() -> i32 { .deref()) .v .as_pointer(); - Rc::new(bar_2)(_x) + bar_2(_x) }), )); ({ @@ -495,7 +495,7 @@ fn main_0() -> i32 { .deref()) .v .as_pointer(); - Rc::new(bar_2)(_x) + bar_2(_x) }) .with_mut(|__v| __v.postfix_inc()); return (((({ diff --git a/tests/unit/out/refcount/fn_ptr.rs b/tests/unit/out/refcount/fn_ptr.rs new file mode 100644 index 0000000..34753e3 --- /dev/null +++ b/tests/unit/out/refcount/fn_ptr.rs @@ -0,0 +1,48 @@ +extern crate libcc2rs; +use libcc2rs::*; +use std::cell::RefCell; +use std::collections::BTreeMap; +use std::io::prelude::*; +use std::io::Seek; +use std::io::{Read, Write}; +use std::os::fd::AsFd; +use std::rc::{Rc, Weak}; +pub fn my_foo_0(p: AnyPtr) -> i32 { + let p: Value = Rc::new(RefCell::new(p)); + return ((*p.borrow()).cast::().expect("ub:wrong type").read()); +} +pub fn foo_1(fn_: FnPtr i32>, pi: Ptr) -> i32 { + let fn_: Value i32>> = Rc::new(RefCell::new(fn_)); + let pi: Value> = Rc::new(RefCell::new(pi)); + return ({ + let _arg0: AnyPtr = ((*pi.borrow()).clone() as Ptr).to_any(); + (*(*fn_.borrow()))(_arg0) + }); +} +pub fn main() { + std::process::exit(main_0()); +} +fn main_0() -> i32 { + let fn_: Value i32>> = Rc::new(RefCell::new(FnPtr::null())); + assert!((*fn_.borrow()).is_null()); + assert!({ + let _lhs = (*fn_.borrow()).clone(); + _lhs != fn_ptr!(my_foo_0, fn(AnyPtr) -> i32) + }); + (*fn_.borrow_mut()) = fn_ptr!(my_foo_0, fn(AnyPtr) -> i32); + assert!(!((*fn_.borrow()).is_null())); + assert!({ + let _lhs = (*fn_.borrow()).clone(); + _lhs == fn_ptr!(my_foo_0, fn(AnyPtr) -> i32) + }); + let a: Value = Rc::new(RefCell::new(10)); + assert!({ + let _lhs = ({ + let _fn: FnPtr i32> = (*fn_.borrow()).clone(); + let _pi: Ptr = (a.as_pointer()); + foo_1(_fn, _pi) + }); + _lhs == (*a.borrow()) + }); + return 0; +} diff --git a/tests/unit/out/refcount/fn_ptr_array.rs b/tests/unit/out/refcount/fn_ptr_array.rs new file mode 100644 index 0000000..e524cc7 --- /dev/null +++ b/tests/unit/out/refcount/fn_ptr_array.rs @@ -0,0 +1,59 @@ +extern crate libcc2rs; +use libcc2rs::*; +use std::cell::RefCell; +use std::collections::BTreeMap; +use std::io::prelude::*; +use std::io::Seek; +use std::io::{Read, Write}; +use std::os::fd::AsFd; +use std::rc::{Rc, Weak}; +pub fn add_0(a: i32, b: i32) -> i32 { + let a: Value = Rc::new(RefCell::new(a)); + let b: Value = Rc::new(RefCell::new(b)); + return ((*a.borrow()) + (*b.borrow())); +} +pub fn sub_1(a: i32, b: i32) -> i32 { + let a: Value = Rc::new(RefCell::new(a)); + let b: Value = Rc::new(RefCell::new(b)); + return ((*a.borrow()) - (*b.borrow())); +} +pub fn mul_2(a: i32, b: i32) -> i32 { + let a: Value = Rc::new(RefCell::new(a)); + let b: Value = Rc::new(RefCell::new(b)); + return ((*a.borrow()) * (*b.borrow())); +} +pub fn main() { + std::process::exit(main_0()); +} +fn main_0() -> i32 { + let ops: Value i32>]>> = Rc::new(RefCell::new(Box::new([ + fn_ptr!(add_0, fn(i32, i32) -> i32), + fn_ptr!(sub_1, fn(i32, i32) -> i32), + fn_ptr!(mul_2, fn(i32, i32) -> i32), + ]))); + assert!( + (({ + let _arg0: i32 = 2; + let _arg1: i32 = 3; + (*(*ops.borrow())[(0) as usize])(_arg0, _arg1) + }) == 5) + ); + assert!( + (({ + let _arg0: i32 = 7; + let _arg1: i32 = 4; + (*(*ops.borrow())[(1) as usize])(_arg0, _arg1) + }) == 3) + ); + assert!( + (({ + let _arg0: i32 = 6; + let _arg1: i32 = 5; + (*(*ops.borrow())[(2) as usize])(_arg0, _arg1) + }) == 30) + ); + assert!(!(((*ops.borrow())[(0) as usize]).is_null())); + assert!(((*ops.borrow())[(0) as usize] == fn_ptr!(add_0, fn(i32, i32) -> i32))); + assert!(((*ops.borrow())[(0) as usize] != fn_ptr!(sub_1, fn(i32, i32) -> i32))); + return 0; +} diff --git a/tests/unit/out/refcount/fn_ptr_as_condition.rs b/tests/unit/out/refcount/fn_ptr_as_condition.rs new file mode 100644 index 0000000..5afb76c --- /dev/null +++ b/tests/unit/out/refcount/fn_ptr_as_condition.rs @@ -0,0 +1,59 @@ +extern crate libcc2rs; +use libcc2rs::*; +use std::cell::RefCell; +use std::collections::BTreeMap; +use std::io::prelude::*; +use std::io::Seek; +use std::io::{Read, Write}; +use std::os::fd::AsFd; +use std::rc::{Rc, Weak}; +pub fn double_it_0(x: Ptr) { + let x: Value> = Rc::new(RefCell::new(x)); + { + let __ptr = (*x.borrow()).clone(); + let __tmp = __ptr.read() * 2; + __ptr.write(__tmp) + }; +} +pub fn maybe_call_1(cb: FnPtr)>, x: Ptr) { + let cb: Value)>> = Rc::new(RefCell::new(cb)); + let x: Value> = Rc::new(RefCell::new(x)); + if !(*cb.borrow()).is_null() { + ({ + let _arg0: Ptr = (*x.borrow()).clone(); + (*(*cb.borrow()))(_arg0) + }); + } +} +pub fn main() { + std::process::exit(main_0()); +} +fn main_0() -> i32 { + let a: Value = Rc::new(RefCell::new(5)); + ({ + let _cb: FnPtr)> = fn_ptr!(double_it_0, fn(Ptr::)); + let _x: Ptr = (a.as_pointer()); + maybe_call_1(_cb, _x) + }); + assert!(((*a.borrow()) == 10)); + let b: Value = Rc::new(RefCell::new(5)); + ({ + let _cb: FnPtr)> = FnPtr::null(); + let _x: Ptr = (b.as_pointer()); + maybe_call_1(_cb, _x) + }); + assert!(((*b.borrow()) == 5)); + let fn_: Value)>> = Rc::new(RefCell::new(FnPtr::null())); + if !!(*fn_.borrow()).is_null() { + (*fn_.borrow_mut()) = (fn_ptr!(double_it_0, fn(Ptr::))).clone(); + } + let c: Value = Rc::new(RefCell::new(3)); + if !(*fn_.borrow()).is_null() { + ({ + let _arg0: Ptr = (c.as_pointer()); + (*(*fn_.borrow()))(_arg0) + }); + } + assert!(((*c.borrow()) == 6)); + return 0; +} diff --git a/tests/unit/out/refcount/fn_ptr_cast.rs b/tests/unit/out/refcount/fn_ptr_cast.rs new file mode 100644 index 0000000..400cf44 --- /dev/null +++ b/tests/unit/out/refcount/fn_ptr_cast.rs @@ -0,0 +1,123 @@ +extern crate libcc2rs; +use libcc2rs::*; +use std::cell::RefCell; +use std::collections::BTreeMap; +use std::io::prelude::*; +use std::io::Seek; +use std::io::{Read, Write}; +use std::os::fd::AsFd; +use std::rc::{Rc, Weak}; +pub fn double_it_0(x: i32) -> i32 { + let x: Value = Rc::new(RefCell::new(x)); + return ((*x.borrow()) * 2); +} +pub fn test_roundtrip_1() { + let fn_: Value i32>> = + Rc::new(RefCell::new(fn_ptr!(double_it_0, fn(i32) -> i32))); + assert!( + (({ + let _arg0: i32 = 5; + (*(*fn_.borrow()))(_arg0) + }) == 10) + ); + let gfn: Value> = + Rc::new(RefCell::new(((*fn_.borrow()).cast::(None)).clone())); + assert!(!((*gfn.borrow()).is_null())); + let fn2: Value i32>> = Rc::new(RefCell::new( + ((*gfn.borrow()).cast:: i32>(None)).clone(), + )); + assert!( + (({ + let _arg0: i32 = 5; + (*(*fn2.borrow()))(_arg0) + }) == 10) + ); + assert!({ + let _lhs = (*fn2.borrow()).clone(); + _lhs == (*fn_.borrow()).clone() + }); +} +pub fn test_double_cast_2() { + let fn_: Value i32>> = + Rc::new(RefCell::new(fn_ptr!(double_it_0, fn(i32) -> i32))); + let fn2: Value i32>> = Rc::new(RefCell::new( + ((*fn_.borrow()) + .cast::(None) + .cast:: i32>(None)) + .clone(), + )); + assert!( + (({ + let _arg0: i32 = 5; + (*(*fn2.borrow()))(_arg0) + }) == 10) + ); + assert!({ + let _lhs = (*fn2.borrow()).clone(); + _lhs == (*fn_.borrow()).clone() + }); +} +#[derive(Default)] +pub struct Command { + pub data: Value, +} +impl Clone for Command { + fn clone(&self) -> Self { + let mut this = Self { + data: Rc::new(RefCell::new((*self.data.borrow()).clone())), + }; + this + } +} +impl ByteRepr for Command {} +pub fn test_void_ptr_to_fn_3() { + let cmd: Value = Rc::new(RefCell::new(::default())); + (*(*cmd.borrow()).data.borrow_mut()) = fn_ptr!(double_it_0, fn(i32) -> i32).to_any(); + let fn_: Value i32>> = Rc::new(RefCell::new( + ((*(*cmd.borrow()).data.borrow()) + .cast_fn:: i32>() + .expect("ub:wrong fn type")) + .clone(), + )); + assert!( + (({ + let _arg0: i32 = 5; + (*(*fn_.borrow()))(_arg0) + }) == 10) + ); +} +pub fn add_offset_4(base: Ptr, offset: i32) -> i32 { + let base: Value> = Rc::new(RefCell::new(base)); + let offset: Value = Rc::new(RefCell::new(offset)); + return { + let _lhs = ((*base.borrow()).read()); + _lhs + (*offset.borrow()) + }; +} +pub fn test_call_through_cast_5() { + let gfn: Value i32>> = Rc::new(RefCell::new( + fn_ptr!(add_offset_4, fn(Ptr::, i32) -> i32).cast:: i32>(Some( + (|a0: AnyPtr, a1: i32| -> i32 { add_offset_4(a0.cast::().unwrap(), a1) }) + as fn(AnyPtr, i32) -> i32, + )), + )); + let val: Value = Rc::new(RefCell::new(100)); + let result: Value = Rc::new(RefCell::new( + ({ + let _arg0: AnyPtr = ((val.as_pointer()) as Ptr).to_any(); + let _arg1: i32 = 42; + (*(*gfn.borrow()))(_arg0, _arg1) + }), + )); + assert!(((*result.borrow()) == 142)); +} +pub fn main() { + std::process::exit(main_0()); +} +fn main_0() -> i32 { + ({ test_roundtrip_1() }); + ({ test_double_cast_2() }); + ({ test_void_ptr_to_fn_3() }); + ({ test_call_through_cast_5() }); + return 0; +} diff --git a/tests/unit/out/refcount/fn_ptr_conditional.rs b/tests/unit/out/refcount/fn_ptr_conditional.rs new file mode 100644 index 0000000..8868479 --- /dev/null +++ b/tests/unit/out/refcount/fn_ptr_conditional.rs @@ -0,0 +1,94 @@ +extern crate libcc2rs; +use libcc2rs::*; +use std::cell::RefCell; +use std::collections::BTreeMap; +use std::io::prelude::*; +use std::io::Seek; +use std::io::{Read, Write}; +use std::os::fd::AsFd; +use std::rc::{Rc, Weak}; +pub fn inc_0(x: i32) -> i32 { + let x: Value = Rc::new(RefCell::new(x)); + return ((*x.borrow()) + 1); +} +pub fn dec_1(x: i32) -> i32 { + let x: Value = Rc::new(RefCell::new(x)); + return ((*x.borrow()) - 1); +} +pub fn identity_2(x: i32) -> i32 { + let x: Value = Rc::new(RefCell::new(x)); + return (*x.borrow()); +} +pub fn pick_3(mode: i32) -> FnPtr i32> { + let mode: Value = Rc::new(RefCell::new(mode)); + return if ((*mode.borrow()) > 0) { + fn_ptr!(inc_0, fn(i32) -> i32) + } else { + if ((*mode.borrow()) < 0) { + fn_ptr!(dec_1, fn(i32) -> i32) + } else { + fn_ptr!(identity_2, fn(i32) -> i32) + } + }; +} +pub fn apply_4(fn_: FnPtr i32>, x: i32) -> i32 { + let fn_: Value i32>> = Rc::new(RefCell::new(fn_)); + let x: Value = Rc::new(RefCell::new(x)); + let actual: Value i32>> = + Rc::new(RefCell::new(if !(*fn_.borrow()).is_null() { + (*fn_.borrow()).clone() + } else { + fn_ptr!(identity_2, fn(i32) -> i32) + })); + return ({ + let _arg0: i32 = (*x.borrow()); + (*(*actual.borrow()))(_arg0) + }); +} +pub fn main() { + std::process::exit(main_0()); +} +fn main_0() -> i32 { + assert!( + (({ + let _arg0: i32 = 10; + (*({ + let _mode: i32 = 1; + pick_3(_mode) + }))(_arg0) + }) == 11) + ); + assert!( + (({ + let _arg0: i32 = 10; + (*({ + let _mode: i32 = -1_i32; + pick_3(_mode) + }))(_arg0) + }) == 9) + ); + assert!( + (({ + let _arg0: i32 = 10; + (*({ + let _mode: i32 = 0; + pick_3(_mode) + }))(_arg0) + }) == 10) + ); + assert!( + (({ + let _fn: FnPtr i32> = fn_ptr!(inc_0, fn(i32) -> i32); + let _x: i32 = 5; + apply_4(_fn, _x) + }) == 6) + ); + assert!( + (({ + let _fn: FnPtr i32> = FnPtr::null(); + let _x: i32 = 5; + apply_4(_fn, _x) + }) == 5) + ); + return 0; +} diff --git a/tests/unit/out/refcount/fn_ptr_default_arg.rs b/tests/unit/out/refcount/fn_ptr_default_arg.rs new file mode 100644 index 0000000..0c598b6 --- /dev/null +++ b/tests/unit/out/refcount/fn_ptr_default_arg.rs @@ -0,0 +1,65 @@ +extern crate libcc2rs; +use libcc2rs::*; +use std::cell::RefCell; +use std::collections::BTreeMap; +use std::io::prelude::*; +use std::io::Seek; +use std::io::{Read, Write}; +use std::os::fd::AsFd; +use std::rc::{Rc, Weak}; +pub fn identity_0(x: i32) -> i32 { + let x: Value = Rc::new(RefCell::new(x)); + return (*x.borrow()); +} +pub fn apply_1(x: i32, fn_: Option i32>>) -> i32 { + let x: Value = Rc::new(RefCell::new(x)); + let fn_: Value i32>> = Rc::new(RefCell::new(fn_.unwrap_or(FnPtr::null()))); + if !(*fn_.borrow()).is_null() { + return ({ + let _arg0: i32 = (*x.borrow()); + (*(*fn_.borrow()))(_arg0) + }); + } + return (*x.borrow()); +} +pub fn main() { + std::process::exit(main_0()); +} +fn main_0() -> i32 { + assert!( + (({ + let _x: i32 = 5; + let _fn: FnPtr i32> = Default::default(); + apply_1(_x, Some(_fn)) + }) == 5) + ); + assert!( + (({ + let _x: i32 = 5; + let _fn: FnPtr i32> = FnPtr::null(); + apply_1(_x, Some(_fn)) + }) == 5) + ); + assert!( + (({ + let _x: i32 = 5; + let _fn: FnPtr i32> = fn_ptr!(identity_0, fn(i32) -> i32); + apply_1(_x, Some(_fn)) + }) == 5) + ); + let negate: Value i32>> = Rc::new(RefCell::new(FnPtr::new( + (|x: i32| { + let x: Value = Rc::new(RefCell::new(x)); + return -(*x.borrow()); + }), + 0, + ))); + assert!( + (({ + let _x: i32 = 5; + let _fn: FnPtr i32> = (*negate.borrow()).clone(); + apply_1(_x, Some(_fn)) + }) == -5_i32) + ); + return 0; +} diff --git a/tests/unit/out/refcount/fn_ptr_global.rs b/tests/unit/out/refcount/fn_ptr_global.rs new file mode 100644 index 0000000..94b7d34 --- /dev/null +++ b/tests/unit/out/refcount/fn_ptr_global.rs @@ -0,0 +1,86 @@ +extern crate libcc2rs; +use libcc2rs::*; +use std::cell::RefCell; +use std::collections::BTreeMap; +use std::io::prelude::*; +use std::io::Seek; +use std::io::{Read, Write}; +use std::os::fd::AsFd; +use std::rc::{Rc, Weak}; +pub fn double_it_0(x: i32) -> i32 { + let x: Value = Rc::new(RefCell::new(x)); + return ((*x.borrow()) * 2); +} +pub fn triple_it_1(x: i32) -> i32 { + let x: Value = Rc::new(RefCell::new(x)); + return ((*x.borrow()) * 3); +} +thread_local!( + pub static g_op: Value i32>> = Rc::new(RefCell::new(FnPtr::null())); +); +pub fn set_op_2(fn_: FnPtr i32>) { + let fn_: Value i32>> = Rc::new(RefCell::new(fn_)); + (*g_op.with(Value::clone).borrow_mut()) = (*fn_.borrow()).clone(); +} +pub fn call_op_3(x: i32) -> i32 { + let x: Value = Rc::new(RefCell::new(x)); + if !(*g_op.with(Value::clone).borrow()).is_null() { + return ({ + let _arg0: i32 = (*x.borrow()); + (*(*g_op.with(Value::clone).borrow()))(_arg0) + }); + } + return (*x.borrow()); +} +pub fn main() { + std::process::exit(main_0()); +} +fn main_0() -> i32 { + assert!( + (({ + let _x: i32 = 5; + call_op_3(_x) + }) == 5) + ); + ({ + let _fn: FnPtr i32> = fn_ptr!(double_it_0, fn(i32) -> i32); + set_op_2(_fn) + }); + assert!(!((*g_op.with(Value::clone).borrow()).is_null())); + assert!({ + let _lhs = (*g_op.with(Value::clone).borrow()).clone(); + _lhs == fn_ptr!(double_it_0, fn(i32) -> i32) + }); + assert!( + (({ + let _x: i32 = 5; + call_op_3(_x) + }) == 10) + ); + ({ + let _fn: FnPtr i32> = fn_ptr!(triple_it_1, fn(i32) -> i32); + set_op_2(_fn) + }); + assert!({ + let _lhs = (*g_op.with(Value::clone).borrow()).clone(); + _lhs == fn_ptr!(triple_it_1, fn(i32) -> i32) + }); + assert!( + (({ + let _x: i32 = 5; + call_op_3(_x) + }) == 15) + ); + ({ + let _fn: FnPtr i32> = FnPtr::null(); + set_op_2(_fn) + }); + assert!((*g_op.with(Value::clone).borrow()).is_null()); + assert!( + (({ + let _x: i32 = 5; + call_op_3(_x) + }) == 5) + ); + return 0; +} diff --git a/tests/unit/out/refcount/fn_ptr_reassign.rs b/tests/unit/out/refcount/fn_ptr_reassign.rs new file mode 100644 index 0000000..c8c47f6 --- /dev/null +++ b/tests/unit/out/refcount/fn_ptr_reassign.rs @@ -0,0 +1,66 @@ +extern crate libcc2rs; +use libcc2rs::*; +use std::cell::RefCell; +use std::collections::BTreeMap; +use std::io::prelude::*; +use std::io::Seek; +use std::io::{Read, Write}; +use std::os::fd::AsFd; +use std::rc::{Rc, Weak}; +pub fn add_0(a: i32, b: i32) -> i32 { + let a: Value = Rc::new(RefCell::new(a)); + let b: Value = Rc::new(RefCell::new(b)); + return ((*a.borrow()) + (*b.borrow())); +} +pub fn sub_1(a: i32, b: i32) -> i32 { + let a: Value = Rc::new(RefCell::new(a)); + let b: Value = Rc::new(RefCell::new(b)); + return ((*a.borrow()) - (*b.borrow())); +} +pub fn mul_2(a: i32, b: i32) -> i32 { + let a: Value = Rc::new(RefCell::new(a)); + let b: Value = Rc::new(RefCell::new(b)); + return ((*a.borrow()) * (*b.borrow())); +} +pub fn main() { + std::process::exit(main_0()); +} +fn main_0() -> i32 { + let fn_: Value i32>> = + Rc::new(RefCell::new(fn_ptr!(add_0, fn(i32, i32) -> i32))); + assert!( + (({ + let _arg0: i32 = 3; + let _arg1: i32 = 4; + (*(*fn_.borrow()))(_arg0, _arg1) + }) == 7) + ); + (*fn_.borrow_mut()) = fn_ptr!(sub_1, fn(i32, i32) -> i32); + assert!( + (({ + let _arg0: i32 = 10; + let _arg1: i32 = 3; + (*(*fn_.borrow()))(_arg0, _arg1) + }) == 7) + ); + (*fn_.borrow_mut()) = fn_ptr!(mul_2, fn(i32, i32) -> i32); + assert!( + (({ + let _arg0: i32 = 6; + let _arg1: i32 = 7; + (*(*fn_.borrow()))(_arg0, _arg1) + }) == 42) + ); + (*fn_.borrow_mut()) = FnPtr::null(); + assert!((*fn_.borrow()).is_null()); + (*fn_.borrow_mut()) = fn_ptr!(add_0, fn(i32, i32) -> i32); + assert!(!((*fn_.borrow()).is_null())); + assert!( + (({ + let _arg0: i32 = 1; + let _arg1: i32 = 1; + (*(*fn_.borrow()))(_arg0, _arg1) + }) == 2) + ); + return 0; +} diff --git a/tests/unit/out/refcount/fn_ptr_return.rs b/tests/unit/out/refcount/fn_ptr_return.rs new file mode 100644 index 0000000..b80f7c1 --- /dev/null +++ b/tests/unit/out/refcount/fn_ptr_return.rs @@ -0,0 +1,67 @@ +extern crate libcc2rs; +use libcc2rs::*; +use std::cell::RefCell; +use std::collections::BTreeMap; +use std::io::prelude::*; +use std::io::Seek; +use std::io::{Read, Write}; +use std::os::fd::AsFd; +use std::rc::{Rc, Weak}; +pub fn inc_0(x: i32) -> i32 { + let x: Value = Rc::new(RefCell::new(x)); + return ((*x.borrow()) + 1); +} +pub fn dec_1(x: i32) -> i32 { + let x: Value = Rc::new(RefCell::new(x)); + return ((*x.borrow()) - 1); +} +pub fn pick_2(choose_inc: i32) -> FnPtr i32> { + let choose_inc: Value = Rc::new(RefCell::new(choose_inc)); + if ((*choose_inc.borrow()) != 0) { + return fn_ptr!(inc_0, fn(i32) -> i32); + } + return fn_ptr!(dec_1, fn(i32) -> i32); +} +pub fn main() { + std::process::exit(main_0()); +} +fn main_0() -> i32 { + let f: Value i32>> = Rc::new(RefCell::new( + ({ + let _choose_inc: i32 = 1; + pick_2(_choose_inc) + }), + )); + assert!(!((*f.borrow()).is_null())); + assert!({ + let _lhs = (*f.borrow()).clone(); + _lhs == fn_ptr!(inc_0, fn(i32) -> i32) + }); + assert!( + (({ + let _arg0: i32 = 10; + (*(*f.borrow()))(_arg0) + }) == 11) + ); + let g: Value i32>> = Rc::new(RefCell::new( + ({ + let _choose_inc: i32 = 0; + pick_2(_choose_inc) + }), + )); + assert!({ + let _lhs = (*g.borrow()).clone(); + _lhs == fn_ptr!(dec_1, fn(i32) -> i32) + }); + assert!( + (({ + let _arg0: i32 = 10; + (*(*g.borrow()))(_arg0) + }) == 9) + ); + assert!({ + let _lhs = (*f.borrow()).clone(); + _lhs != (*g.borrow()).clone() + }); + return 0; +} diff --git a/tests/unit/out/refcount/fn_ptr_stable_sort.rs b/tests/unit/out/refcount/fn_ptr_stable_sort.rs new file mode 100644 index 0000000..2770c95 --- /dev/null +++ b/tests/unit/out/refcount/fn_ptr_stable_sort.rs @@ -0,0 +1,80 @@ +extern crate libcc2rs; +use libcc2rs::*; +use std::cell::RefCell; +use std::collections::BTreeMap; +use std::io::prelude::*; +use std::io::Seek; +use std::io::{Read, Write}; +use std::os::fd::AsFd; +use std::rc::{Rc, Weak}; +#[derive(Default)] +pub struct Item { + pub key: Value, + pub value: Value, +} +impl Clone for Item { + fn clone(&self) -> Self { + let mut this = Self { + key: Rc::new(RefCell::new((*self.key.borrow()))), + value: Rc::new(RefCell::new((*self.value.borrow()))), + }; + this + } +} +impl ByteRepr for Item {} +pub fn Compare_0(a: Ptr, b: Ptr) -> bool { + return { + let _lhs = (*(*a.upgrade().deref()).key.borrow()); + _lhs < (*(*b.upgrade().deref()).key.borrow()) + }; +} +pub fn main() { + std::process::exit(main_0()); +} +fn main_0() -> i32 { + let v: Value> = Rc::new(RefCell::new(Vec::new())); + (*v.borrow_mut()).push(Item { + key: Rc::new(RefCell::new(3)), + value: Rc::new(RefCell::new(30)), + }); + (*v.borrow_mut()).push(Item { + key: Rc::new(RefCell::new(1)), + value: Rc::new(RefCell::new(10)), + }); + (*v.borrow_mut()).push(Item { + key: Rc::new(RefCell::new(2)), + value: Rc::new(RefCell::new(20)), + }); + (v.as_pointer() as Ptr).sort_with_cmp( + (v.as_pointer() as Ptr).to_end().get_offset(), + Compare_0, + ); + assert!( + ((*(*(v.as_pointer() as Ptr) + .offset(0_u64 as isize) + .upgrade() + .deref()) + .key + .borrow()) + == 1) + ); + assert!( + ((*(*(v.as_pointer() as Ptr) + .offset(1_u64 as isize) + .upgrade() + .deref()) + .key + .borrow()) + == 2) + ); + assert!( + ((*(*(v.as_pointer() as Ptr) + .offset(2_u64 as isize) + .upgrade() + .deref()) + .key + .borrow()) + == 3) + ); + return 0; +} diff --git a/tests/unit/out/refcount/fn_ptr_stdlib_compare.rs b/tests/unit/out/refcount/fn_ptr_stdlib_compare.rs new file mode 100644 index 0000000..178f035 --- /dev/null +++ b/tests/unit/out/refcount/fn_ptr_stdlib_compare.rs @@ -0,0 +1,77 @@ +extern crate libcc2rs; +use libcc2rs::*; +use std::cell::RefCell; +use std::collections::BTreeMap; +use std::io::prelude::*; +use std::io::Seek; +use std::io::{Read, Write}; +use std::os::fd::AsFd; +use std::rc::{Rc, Weak}; +pub fn my_alternative_fread_0(p: Ptr, n: u64, m: u64, f: AnyPtr) -> u64 { + let p: Value> = Rc::new(RefCell::new(p)); + let n: Value = Rc::new(RefCell::new(n)); + let m: Value = Rc::new(RefCell::new(m)); + let f: Value = Rc::new(RefCell::new(f)); + return 22_u64; +} +pub fn main() { + std::process::exit(main_0()); +} +fn main_0() -> i32 { + let fn1: Value) -> u64>> = + Rc::new(RefCell::new(fn_ptr!( + rules::stdio_tgt_refcount::f5, + fn(AnyPtr, u64, u64, Ptr<::std::fs::File>) -> u64 + ))); + assert!({ + let _lhs = (*fn1.borrow()).clone(); + _lhs == fn_ptr!( + rules::stdio_tgt_refcount::f5, + fn(AnyPtr, u64, u64, Ptr<::std::fs::File>) -> u64 + ) + }); + assert!(!((*fn1.borrow()).is_null())); + let fn2: Value, u64, u64, AnyPtr) -> u64>> = Rc::new(RefCell::new( + fn_ptr!( + rules::stdio_tgt_refcount::f5, + fn(AnyPtr, u64, u64, Ptr<::std::fs::File>) -> u64 + ) + .cast::, u64, u64, AnyPtr) -> u64>(Some( + (|a0: Ptr, a1: u64, a2: u64, a3: AnyPtr| -> u64 { + rules::stdio_tgt_refcount::f5( + a0.to_any(), + a1, + a2, + a3.cast::<::std::fs::File>().unwrap(), + ) + }) as fn(Ptr, u64, u64, AnyPtr) -> u64, + )), + )); + assert!({ + let _lhs = (*fn1.borrow()).clone(); + _lhs == ((*fn2.borrow()).cast::) -> u64>(None)) + .clone() + }); + let f3: Value) -> u64>> = + Rc::new(RefCell::new( + fn_ptr!( + my_alternative_fread_0, + fn(Ptr::, u64, u64, AnyPtr) -> u64 + ) + .cast::) -> u64>(Some( + (|a0: AnyPtr, a1: u64, a2: u64, a3: Ptr<::std::fs::File>| -> u64 { + my_alternative_fread_0(a0.cast::().unwrap(), a1, a2, a3.to_any()) + }) as fn(AnyPtr, u64, u64, Ptr<::std::fs::File>) -> u64, + )), + )); + assert!( + (({ + let _arg0: AnyPtr = Default::default(); + let _arg1: u64 = 0_u64; + let _arg2: u64 = 0_u64; + let _arg3: Ptr<::std::fs::File> = Default::default(); + (*(*f3.borrow()))(_arg0, _arg1, _arg2, _arg3) + }) == 22_u64) + ); + return 0; +} diff --git a/tests/unit/out/refcount/fn_ptr_struct.rs b/tests/unit/out/refcount/fn_ptr_struct.rs new file mode 100644 index 0000000..0d34f1d --- /dev/null +++ b/tests/unit/out/refcount/fn_ptr_struct.rs @@ -0,0 +1,78 @@ +extern crate libcc2rs; +use libcc2rs::*; +use std::cell::RefCell; +use std::collections::BTreeMap; +use std::io::prelude::*; +use std::io::Seek; +use std::io::{Read, Write}; +use std::os::fd::AsFd; +use std::rc::{Rc, Weak}; +#[derive()] +pub struct Handler { + pub tag: Value, + pub cb: Value i32>>, +} +impl Clone for Handler { + fn clone(&self) -> Self { + let mut this = Self { + tag: Rc::new(RefCell::new((*self.tag.borrow()))), + cb: Rc::new(RefCell::new((*self.cb.borrow()).clone())), + }; + this + } +} +impl Default for Handler { + fn default() -> Self { + Handler { + tag: >::default(), + cb: Rc::new(RefCell::new(FnPtr::null())), + } + } +} +impl ByteRepr for Handler {} +pub fn double_it_0(x: i32) -> i32 { + let x: Value = Rc::new(RefCell::new(x)); + return ((*x.borrow()) * 2); +} +pub fn negate_1(x: i32) -> i32 { + let x: Value = Rc::new(RefCell::new(x)); + return -(*x.borrow()); +} +pub fn main() { + std::process::exit(main_0()); +} +fn main_0() -> i32 { + let h1: Value = Rc::new(RefCell::new(Handler { + tag: Rc::new(RefCell::new(1)), + cb: Rc::new(RefCell::new(fn_ptr!(double_it_0, fn(i32) -> i32))), + })); + let h2: Value = Rc::new(RefCell::new(Handler { + tag: Rc::new(RefCell::new(2)), + cb: Rc::new(RefCell::new(fn_ptr!(negate_1, fn(i32) -> i32))), + })); + assert!(!((*(*h1.borrow()).cb.borrow()).is_null())); + assert!( + (({ + let _arg0: i32 = 5; + (*(*(*h1.borrow()).cb.borrow()))(_arg0) + }) == 10) + ); + assert!( + (({ + let _arg0: i32 = 7; + (*(*(*h2.borrow()).cb.borrow()))(_arg0) + }) == -7_i32) + ); + (*(*h1.borrow()).cb.borrow_mut()) = fn_ptr!(negate_1, fn(i32) -> i32); + assert!( + (({ + let _arg0: i32 = 3; + (*(*(*h1.borrow()).cb.borrow()))(_arg0) + }) == -3_i32) + ); + assert!({ + let _lhs = (*(*h1.borrow()).cb.borrow()).clone(); + _lhs == (*(*h2.borrow()).cb.borrow()).clone() + }); + return 0; +} diff --git a/tests/unit/out/refcount/fn_ptr_void_return.rs b/tests/unit/out/refcount/fn_ptr_void_return.rs new file mode 100644 index 0000000..dc49639 --- /dev/null +++ b/tests/unit/out/refcount/fn_ptr_void_return.rs @@ -0,0 +1,53 @@ +extern crate libcc2rs; +use libcc2rs::*; +use std::cell::RefCell; +use std::collections::BTreeMap; +use std::io::prelude::*; +use std::io::Seek; +use std::io::{Read, Write}; +use std::os::fd::AsFd; +use std::rc::{Rc, Weak}; +pub fn negate_0(x: Ptr) { + let x: Value> = Rc::new(RefCell::new(x)); + let __rhs = -((*x.borrow()).read()); + (*x.borrow()).write(__rhs); +} +pub fn zero_out_1(x: Ptr) { + let x: Value> = Rc::new(RefCell::new(x)); + (*x.borrow()).write(0); +} +pub fn run_2(fn_: FnPtr)>, x: Ptr) { + let fn_: Value)>> = Rc::new(RefCell::new(fn_)); + let x: Value> = Rc::new(RefCell::new(x)); + ({ + let _arg0: Ptr = (*x.borrow()).clone(); + (*(*fn_.borrow()))(_arg0) + }); +} +pub fn main() { + std::process::exit(main_0()); +} +fn main_0() -> i32 { + let a: Value = Rc::new(RefCell::new(42)); + ({ + let _fn: FnPtr)> = fn_ptr!(negate_0, fn(Ptr::)); + let _x: Ptr = (a.as_pointer()); + run_2(_fn, _x) + }); + assert!(((*a.borrow()) == -42_i32)); + ({ + let _fn: FnPtr)> = fn_ptr!(zero_out_1, fn(Ptr::)); + let _x: Ptr = (a.as_pointer()); + run_2(_fn, _x) + }); + assert!(((*a.borrow()) == 0)); + let fn_: Value)>> = Rc::new(RefCell::new(fn_ptr!(negate_0, fn(Ptr::)))); + assert!(!((*fn_.borrow()).is_null())); + let b: Value = Rc::new(RefCell::new(10)); + ({ + let _arg0: Ptr = (b.as_pointer()); + (*(*fn_.borrow()))(_arg0) + }); + assert!(((*b.borrow()) == -10_i32)); + return 0; +} diff --git a/tests/unit/out/refcount/fn_ptr_vtable.rs b/tests/unit/out/refcount/fn_ptr_vtable.rs new file mode 100644 index 0000000..b8e80be --- /dev/null +++ b/tests/unit/out/refcount/fn_ptr_vtable.rs @@ -0,0 +1,86 @@ +extern crate libcc2rs; +use libcc2rs::*; +use std::cell::RefCell; +use std::collections::BTreeMap; +use std::io::prelude::*; +use std::io::Seek; +use std::io::{Read, Write}; +use std::os::fd::AsFd; +use std::rc::{Rc, Weak}; +#[derive()] +pub struct Vtable { + pub create: Value AnyPtr>>, + pub get: Value i32>>, + pub destroy: Value>, +} +impl Clone for Vtable { + fn clone(&self) -> Self { + let mut this = Self { + create: Rc::new(RefCell::new((*self.create.borrow()).clone())), + get: Rc::new(RefCell::new((*self.get.borrow()).clone())), + destroy: Rc::new(RefCell::new((*self.destroy.borrow()).clone())), + }; + this + } +} +impl Default for Vtable { + fn default() -> Self { + Vtable { + create: Rc::new(RefCell::new(FnPtr::null())), + get: Rc::new(RefCell::new(FnPtr::null())), + destroy: Rc::new(RefCell::new(FnPtr::null())), + } + } +} +impl ByteRepr for Vtable {} +thread_local!( + pub static storage: Value = >::default(); +); +pub fn int_create_0(val: i32) -> AnyPtr { + let val: Value = Rc::new(RefCell::new(val)); + (*storage.with(Value::clone).borrow_mut()) = (*val.borrow()); + return ((storage.with(Value::clone).as_pointer()) as Ptr).to_any(); +} +pub fn int_get_1(p: AnyPtr) -> i32 { + let p: Value = Rc::new(RefCell::new(p)); + return ((*p.borrow()).cast::().expect("ub:wrong type").read()); +} +pub fn int_destroy_2(p: AnyPtr) { + let p: Value = Rc::new(RefCell::new(p)); + (*p.borrow()).cast::().expect("ub:wrong type").write(0); +} +pub fn main() { + std::process::exit(main_0()); +} +fn main_0() -> i32 { + let vt: Value = Rc::new(RefCell::new(Vtable { + create: Rc::new(RefCell::new( + (fn_ptr!(int_create_0, fn(i32) -> AnyPtr)).clone(), + )), + get: Rc::new(RefCell::new(fn_ptr!(int_get_1, fn(AnyPtr) -> i32))), + destroy: Rc::new(RefCell::new(fn_ptr!(int_destroy_2, fn(AnyPtr)))), + })); + assert!(!((*(*vt.borrow()).create.borrow()).is_null())); + assert!(!((*(*vt.borrow()).get.borrow()).is_null())); + assert!(!((*(*vt.borrow()).destroy.borrow()).is_null())); + let obj: Value = Rc::new(RefCell::new( + ({ + let _arg0: i32 = 42; + (*(*(*vt.borrow()).create.borrow()))(_arg0) + }), + )); + assert!( + (({ + let _arg0: AnyPtr = (*obj.borrow()).clone(); + (*(*(*vt.borrow()).get.borrow()))(_arg0) + }) == 42) + ); + ({ + let _arg0: AnyPtr = (*obj.borrow()).clone(); + (*(*(*vt.borrow()).destroy.borrow()))(_arg0) + }); + assert!(((*storage.with(Value::clone).borrow()) == 0)); + (*(*vt.borrow()).get.borrow_mut()) = FnPtr::null(); + assert!((*(*vt.borrow()).get.borrow()).is_null()); + return 0; +} diff --git a/tests/unit/out/refcount/lambda_capture_local.rs b/tests/unit/out/refcount/lambda_capture_local.rs new file mode 100644 index 0000000..5b4a525 --- /dev/null +++ b/tests/unit/out/refcount/lambda_capture_local.rs @@ -0,0 +1,74 @@ +extern crate libcc2rs; +use libcc2rs::*; +use std::cell::RefCell; +use std::collections::BTreeMap; +use std::io::prelude::*; +use std::io::Seek; +use std::io::{Read, Write}; +use std::os::fd::AsFd; +use std::rc::{Rc, Weak}; +pub fn main() { + std::process::exit(main_0()); +} +fn main_0() -> i32 { + let base: Value = Rc::new(RefCell::new(10)); + let factor: Value = Rc::new(RefCell::new(3)); + let add_base: Value i32>> = Rc::new(RefCell::new(Rc::new( + (|x: i32| { + let x: Value = Rc::new(RefCell::new(x)); + return ((*x.borrow()) + (*base.borrow())); + }), + ))); + let scale: Value i32>> = Rc::new(RefCell::new(Rc::new( + (|x: i32| { + let x: Value = Rc::new(RefCell::new(x)); + return ((*x.borrow()) * (*factor.borrow())); + }), + ))); + assert!( + (({ + let _x: i32 = 5; + (*add_base.borrow())(_x) + }) == 15) + ); + assert!( + (({ + let _x: i32 = 4; + (*scale.borrow())(_x) + }) == 12) + ); + (*base.borrow_mut()) = 100; + assert!( + (({ + let _x: i32 = 5; + (*add_base.borrow())(_x) + }) == 105) + ); + assert!( + (({ + let _x: i32 = 4; + (*scale.borrow())(_x) + }) == 12) + ); + let sum: Value = Rc::new(RefCell::new(0)); + let accumulate: Value> = Rc::new(RefCell::new(Rc::new( + (|x: i32| { + let x: Value = Rc::new(RefCell::new(x)); + (*sum.borrow_mut()) += (*x.borrow()); + }), + ))); + ({ + let _x: i32 = 1; + (*accumulate.borrow())(_x) + }); + ({ + let _x: i32 = 2; + (*accumulate.borrow())(_x) + }); + ({ + let _x: i32 = 3; + (*accumulate.borrow())(_x) + }); + assert!(((*sum.borrow()) == 6)); + return 0; +} diff --git a/tests/unit/out/refcount/lambda_capture_pass.rs b/tests/unit/out/refcount/lambda_capture_pass.rs new file mode 100644 index 0000000..d7e0865 --- /dev/null +++ b/tests/unit/out/refcount/lambda_capture_pass.rs @@ -0,0 +1,69 @@ +extern crate libcc2rs; +use libcc2rs::*; +use std::cell::RefCell; +use std::collections::BTreeMap; +use std::io::prelude::*; +use std::io::Seek; +use std::io::{Read, Write}; +use std::os::fd::AsFd; +use std::rc::{Rc, Weak}; +pub fn apply_0(fn_: impl Fn(i32) -> i32, x: i32) -> i32 { + let fn_: Value<_> = Rc::new(RefCell::new(fn_)); + let x: Value = Rc::new(RefCell::new(x)); + return ({ + let _x: i32 = (*x.borrow()); + (*fn_.borrow())(_x) + }) + .clone(); +} +pub fn apply_1(fn_: impl Fn(i32) -> i32, x: i32) -> i32 { + let fn_: Value<_> = Rc::new(RefCell::new(fn_)); + let x: Value = Rc::new(RefCell::new(x)); + return ({ + let _x: i32 = (*x.borrow()); + (*fn_.borrow())(_x) + }) + .clone(); +} +pub fn main() { + std::process::exit(main_0()); +} +fn main_0() -> i32 { + let base: Value = Rc::new(RefCell::new(10)); + let add_base: Value<_> = Rc::new(RefCell::new( + (|x: i32| { + let x: Value = Rc::new(RefCell::new(x)); + return ((*x.borrow()) + (*base.borrow())); + }), + )); + assert!( + (({ + let _fn: _ = (*add_base.borrow()).clone(); + let _x: i32 = 5; + apply_0(_fn, _x) + }) == 15) + ); + (*base.borrow_mut()) = 100; + assert!( + (({ + let _fn: _ = (*add_base.borrow()).clone(); + let _x: i32 = 5; + apply_0(_fn, _x) + }) == 105) + ); + let factor: Value = Rc::new(RefCell::new(3)); + let scale: Value<_> = Rc::new(RefCell::new( + (|x: i32| { + let x: Value = Rc::new(RefCell::new(x)); + return ((*x.borrow()) * (*factor.borrow())); + }), + )); + assert!( + (({ + let _fn: _ = (*scale.borrow()).clone(); + let _x: i32 = 4; + apply_1(_fn, _x) + }) == 12) + ); + return 0; +} diff --git a/tests/unit/out/refcount/lambda_nested.rs b/tests/unit/out/refcount/lambda_nested.rs new file mode 100644 index 0000000..d562d80 --- /dev/null +++ b/tests/unit/out/refcount/lambda_nested.rs @@ -0,0 +1,45 @@ +extern crate libcc2rs; +use libcc2rs::*; +use std::cell::RefCell; +use std::collections::BTreeMap; +use std::io::prelude::*; +use std::io::Seek; +use std::io::{Read, Write}; +use std::os::fd::AsFd; +use std::rc::{Rc, Weak}; +pub fn main() { + std::process::exit(main_0()); +} +fn main_0() -> i32 { + let x: Value = Rc::new(RefCell::new(10)); + let outer: Value<_> = Rc::new(RefCell::new( + (|y: i32| { + let y: Value = Rc::new(RefCell::new(y)); + let inner: Value<_> = Rc::new(RefCell::new( + (|z: i32| { + let z: Value = Rc::new(RefCell::new(z)); + return (((*x.borrow()) + (*y.borrow())) + (*z.borrow())); + }), + )); + return ({ + let _z: i32 = 1; + (*inner.borrow())(_z) + }) + .clone(); + }), + )); + assert!( + (({ + let _y: i32 = 20; + (*outer.borrow())(_y) + }) == 31) + ); + (*x.borrow_mut()) = 100; + assert!( + (({ + let _y: i32 = 20; + (*outer.borrow())(_y) + }) == 121) + ); + return 0; +} diff --git a/tests/unit/out/refcount/lambda_nocapture.rs b/tests/unit/out/refcount/lambda_nocapture.rs new file mode 100644 index 0000000..6936dc8 --- /dev/null +++ b/tests/unit/out/refcount/lambda_nocapture.rs @@ -0,0 +1,74 @@ +extern crate libcc2rs; +use libcc2rs::*; +use std::cell::RefCell; +use std::collections::BTreeMap; +use std::io::prelude::*; +use std::io::Seek; +use std::io::{Read, Write}; +use std::os::fd::AsFd; +use std::rc::{Rc, Weak}; +pub fn call_0(f: Option i32>, a: i32, b: i32) -> i32 { + let f: Value i32>> = Rc::new(RefCell::new(f)); + let a: Value = Rc::new(RefCell::new(a)); + let b: Value = Rc::new(RefCell::new(b)); + return ({ + let _arg0: i32 = (*a.borrow()); + let _arg1: i32 = (*b.borrow()); + (*f.borrow()).unwrap()(_arg0, _arg1) + }); +} +pub fn main() { + std::process::exit(main_0()); +} +fn main_0() -> i32 { + let add: Value i32>> = Rc::new(RefCell::new(Some(|a: i32, b: i32| { + let a: Value = Rc::new(RefCell::new(a)); + let b: Value = Rc::new(RefCell::new(b)); + return ((*a.borrow()) + (*b.borrow())); + }))); + let sub: Value i32>> = Rc::new(RefCell::new(Some(|a: i32, b: i32| { + let a: Value = Rc::new(RefCell::new(a)); + let b: Value = Rc::new(RefCell::new(b)); + return ((*a.borrow()) - (*b.borrow())); + }))); + assert!(!((*add.borrow()).is_none())); + assert!({ + let _lhs = (*add.borrow()).clone(); + _lhs != (*sub.borrow()).clone() + }); + assert!( + (({ + let _arg0: i32 = 2; + let _arg1: i32 = 3; + (*add.borrow()).unwrap()(_arg0, _arg1) + }) == 5) + ); + assert!( + (({ + let _arg0: i32 = 10; + let _arg1: i32 = 4; + (*sub.borrow()).unwrap()(_arg0, _arg1) + }) == 6) + ); + assert!( + (({ + let _f: Option i32> = (*add.borrow()).clone(); + let _a: i32 = 7; + let _b: i32 = 8; + call_0(_f, _a, _b) + }) == 15) + ); + assert!( + (({ + let _f: Option i32> = Some(|a: i32, b: i32| { + let a: Value = Rc::new(RefCell::new(a)); + let b: Value = Rc::new(RefCell::new(b)); + return ((*a.borrow()) * (*b.borrow())); + }); + let _a: i32 = 6; + let _b: i32 = 7; + call_0(_f, _a, _b) + }) == 42) + ); + return 0; +} diff --git a/tests/unit/out/refcount/no_direct_callee.rs b/tests/unit/out/refcount/no_direct_callee.rs index a01b00d..6b81f98 100644 --- a/tests/unit/out/refcount/no_direct_callee.rs +++ b/tests/unit/out/refcount/no_direct_callee.rs @@ -10,9 +10,9 @@ use std::rc::{Rc, Weak}; pub fn test1_0() -> bool { return false; } -pub fn test_1(fn_: Rc bool>) -> i32 { - let fn_: Value bool>> = Rc::new(RefCell::new(fn_)); - if !({ (*fn_.borrow())() }) { +pub fn test_1(fn_: FnPtr bool>) -> i32 { + let fn_: Value bool>> = Rc::new(RefCell::new(fn_)); + if !({ (*(*fn_.borrow()))() }) { return 1; } return 0; @@ -22,7 +22,7 @@ pub fn main() { } fn main_0() -> i32 { return ({ - let _fn: Rc bool> = Rc::new(test1_0); + let _fn: FnPtr bool> = fn_ptr!(test1_0, fn() -> bool); test_1(_fn) }); } diff --git a/tests/unit/out/refcount/printfs.rs b/tests/unit/out/refcount/printfs.rs index df5ffa6..a661f37 100644 --- a/tests/unit/out/refcount/printfs.rs +++ b/tests/unit/out/refcount/printfs.rs @@ -44,7 +44,7 @@ fn main_0() -> i32 { .to_c_string_iterator() .chain(std::iter::once(0)) .collect::>(); - Rc::new(fn_0)(_v) + fn_0(_v) }) )) .as_pointer() as Ptr) @@ -53,7 +53,7 @@ fn main_0() -> i32 { "{}", (({ let _v: Ptr> = s.as_pointer(); - Rc::new(fn2_1)(_v) + fn2_1(_v) }) .to_strong() .as_pointer() as Ptr) diff --git a/tests/unit/out/refcount/prvalue-as-lvalue.rs b/tests/unit/out/refcount/prvalue-as-lvalue.rs index a8926cc..610c6ba 100644 --- a/tests/unit/out/refcount/prvalue-as-lvalue.rs +++ b/tests/unit/out/refcount/prvalue-as-lvalue.rs @@ -18,7 +18,7 @@ fn main_0() -> i32 { let pa: Value> = Rc::new(RefCell::new((a.as_pointer()))); let b: Ptr = ({ let _a: Ptr = (*pa.borrow()).clone(); - Rc::new(foo_0)(_a) + foo_0(_a) }); return (b.read()); } diff --git a/tests/unit/out/refcount/ref_calls.rs b/tests/unit/out/refcount/ref_calls.rs index 41dbbfd..f9e604f 100644 --- a/tests/unit/out/refcount/ref_calls.rs +++ b/tests/unit/out/refcount/ref_calls.rs @@ -27,7 +27,7 @@ fn main_0() -> i32 { )); let z: Ptr = ({ let _x: Ptr = x.as_pointer(); - Rc::new(foo_1)(_x) + foo_1(_x) }); return { let _lhs = { diff --git a/tests/unit/out/unsafe/06_new_array.rs b/tests/unit/out/unsafe/06_new_array.rs index cdb76f9..d7bb799 100644 --- a/tests/unit/out/unsafe/06_new_array.rs +++ b/tests/unit/out/unsafe/06_new_array.rs @@ -13,8 +13,7 @@ pub fn main() { } } unsafe fn main_0() -> i32 { - let mut e: *mut i32 = - Box::leak((0..2_u64).map(|_| ::default()).collect::>()).as_mut_ptr(); + let mut e: *mut i32 = Box::leak((0..2_u64).map(|_| 0_i32).collect::>()).as_mut_ptr(); (*e.offset((0) as isize)) = 6; (*e.offset((1) as isize)) = 7; diff --git a/tests/unit/out/unsafe/clone_vs_move.rs b/tests/unit/out/unsafe/clone_vs_move.rs index c19f9ec..d0fcde2 100644 --- a/tests/unit/out/unsafe/clone_vs_move.rs +++ b/tests/unit/out/unsafe/clone_vs_move.rs @@ -22,10 +22,10 @@ pub struct Foo { impl Default for Foo { fn default() -> Self { Foo { - x: ::default(), + x: 0_i32, y: <*mut i32>::default(), z: Default::default(), - a: [::default(); 3], + a: [0_i32; 3], bar: ::default(), } } diff --git a/tests/unit/out/unsafe/complex_function.rs b/tests/unit/out/unsafe/complex_function.rs index 5d741ea..5707ff9 100644 --- a/tests/unit/out/unsafe/complex_function.rs +++ b/tests/unit/out/unsafe/complex_function.rs @@ -90,11 +90,11 @@ unsafe fn main_0() -> i32 { let r1: *mut i32 = &mut x1 as *mut i32; let r2: *mut i32 = (unsafe { let _x: *mut i32 = &mut x1 as *mut i32; - Rc::new(|a0| unsafe { bar_2(a0) })(_x) + bar_2(_x) }); let r3: *mut i32 = (unsafe { let _x: *mut i32 = r1; - Rc::new(|a0| unsafe { bar_2(a0) })(_x) + bar_2(_x) }); (*r2) += x1; (*r3) += (*r1); @@ -230,12 +230,12 @@ unsafe fn main_0() -> i32 { let mut pref: *mut i32 = (unsafe { let _x: *mut i32 = &mut (*(unsafe { (*(unsafe { (*(unsafe { d.get() })).get() })).get() })).v as *mut i32; - Rc::new(|a0| unsafe { bar_2(a0) })(_x) + bar_2(_x) }); (*(unsafe { let _x: *mut i32 = &mut (*(unsafe { (*(unsafe { (*(unsafe { d.get() })).get() })).get() })).v as *mut i32; - Rc::new(|a0| unsafe { bar_2(a0) })(_x) + bar_2(_x) })) .postfix_inc(); return (((*(unsafe { diff --git a/tests/unit/out/unsafe/default.rs b/tests/unit/out/unsafe/default.rs index 6868377..952ccd8 100644 --- a/tests/unit/out/unsafe/default.rs +++ b/tests/unit/out/unsafe/default.rs @@ -22,7 +22,7 @@ impl Default for Pointers { x2: Default::default(), x3: [Default::default(); 5], x4: [Default::default(); 10], - x5: ::default(), + x5: 0_i32, } } } diff --git a/tests/unit/out/unsafe/fn_ptr.rs b/tests/unit/out/unsafe/fn_ptr.rs new file mode 100644 index 0000000..60ce303 --- /dev/null +++ b/tests/unit/out/unsafe/fn_ptr.rs @@ -0,0 +1,43 @@ +extern crate libc; +use libc::*; +extern crate libcc2rs; +use libcc2rs::*; +use std::collections::BTreeMap; +use std::io::Seek; +use std::io::{Read, Write}; +use std::os::fd::{AsFd, FromRawFd, IntoRawFd}; +use std::rc::Rc; +pub unsafe fn my_foo_0(mut p: *mut ::libc::c_void) -> i32 { + return (*(p as *mut i32)); +} +pub unsafe fn foo_1( + mut fn_: Option i32>, + mut pi: *mut i32, +) -> i32 { + return (unsafe { + let _arg0: *mut ::libc::c_void = (pi as *mut i32 as *mut ::libc::c_void); + (fn_).unwrap()(_arg0) + }); +} +pub fn main() { + unsafe { + std::process::exit(main_0() as i32); + } +} +unsafe fn main_0() -> i32 { + let mut fn_: Option i32> = None; + assert!((fn_).is_none()); + assert!(((fn_) != (Some(my_foo_0)))); + fn_ = Some(my_foo_0); + assert!(!((fn_).is_none())); + assert!(((fn_) == (Some(my_foo_0)))); + let mut a: i32 = 10; + assert!( + ((unsafe { + let _fn: Option i32> = fn_; + let _pi: *mut i32 = (&mut a as *mut i32); + foo_1(_fn, _pi) + }) == (a)) + ); + return 0; +} diff --git a/tests/unit/out/unsafe/fn_ptr_array.rs b/tests/unit/out/unsafe/fn_ptr_array.rs new file mode 100644 index 0000000..1e22470 --- /dev/null +++ b/tests/unit/out/unsafe/fn_ptr_array.rs @@ -0,0 +1,51 @@ +extern crate libc; +use libc::*; +extern crate libcc2rs; +use libcc2rs::*; +use std::collections::BTreeMap; +use std::io::Seek; +use std::io::{Read, Write}; +use std::os::fd::{AsFd, FromRawFd, IntoRawFd}; +use std::rc::Rc; +pub unsafe fn add_0(mut a: i32, mut b: i32) -> i32 { + return ((a) + (b)); +} +pub unsafe fn sub_1(mut a: i32, mut b: i32) -> i32 { + return ((a) - (b)); +} +pub unsafe fn mul_2(mut a: i32, mut b: i32) -> i32 { + return ((a) * (b)); +} +pub fn main() { + unsafe { + std::process::exit(main_0() as i32); + } +} +unsafe fn main_0() -> i32 { + let mut ops: [Option i32>; 3] = [Some(add_0), Some(sub_1), Some(mul_2)]; + assert!( + ((unsafe { + let _arg0: i32 = 2; + let _arg1: i32 = 3; + (ops[(0) as usize]).unwrap()(_arg0, _arg1) + }) == (5)) + ); + assert!( + ((unsafe { + let _arg0: i32 = 7; + let _arg1: i32 = 4; + (ops[(1) as usize]).unwrap()(_arg0, _arg1) + }) == (3)) + ); + assert!( + ((unsafe { + let _arg0: i32 = 6; + let _arg1: i32 = 5; + (ops[(2) as usize]).unwrap()(_arg0, _arg1) + }) == (30)) + ); + assert!(!((ops[(0) as usize]).is_none())); + assert!(((ops[(0) as usize]) == (Some(add_0)))); + assert!(((ops[(0) as usize]) != (Some(sub_1)))); + return 0; +} diff --git a/tests/unit/out/unsafe/fn_ptr_as_condition.rs b/tests/unit/out/unsafe/fn_ptr_as_condition.rs new file mode 100644 index 0000000..7669fb3 --- /dev/null +++ b/tests/unit/out/unsafe/fn_ptr_as_condition.rs @@ -0,0 +1,54 @@ +extern crate libc; +use libc::*; +extern crate libcc2rs; +use libcc2rs::*; +use std::collections::BTreeMap; +use std::io::Seek; +use std::io::{Read, Write}; +use std::os::fd::{AsFd, FromRawFd, IntoRawFd}; +use std::rc::Rc; +pub unsafe fn double_it_0(mut x: *mut i32) { + (*x) *= 2; +} +pub unsafe fn maybe_call_1(mut cb: Option, mut x: *mut i32) { + if !(cb).is_none() { + (unsafe { + let _arg0: *mut i32 = x; + (cb).unwrap()(_arg0) + }); + } +} +pub fn main() { + unsafe { + std::process::exit(main_0() as i32); + } +} +unsafe fn main_0() -> i32 { + let mut a: i32 = 5; + (unsafe { + let _cb: Option = Some(double_it_0); + let _x: *mut i32 = (&mut a as *mut i32); + maybe_call_1(_cb, _x) + }); + assert!(((a) == (10))); + let mut b: i32 = 5; + (unsafe { + let _cb: Option = None; + let _x: *mut i32 = (&mut b as *mut i32); + maybe_call_1(_cb, _x) + }); + assert!(((b) == (5))); + let mut fn_: Option = None; + if !!(fn_).is_none() { + fn_ = Some(double_it_0); + } + let mut c: i32 = 3; + if !(fn_).is_none() { + (unsafe { + let _arg0: *mut i32 = (&mut c as *mut i32); + (fn_).unwrap()(_arg0) + }); + } + assert!(((c) == (6))); + return 0; +} diff --git a/tests/unit/out/unsafe/fn_ptr_cast.rs b/tests/unit/out/unsafe/fn_ptr_cast.rs new file mode 100644 index 0000000..9fce4e7 --- /dev/null +++ b/tests/unit/out/unsafe/fn_ptr_cast.rs @@ -0,0 +1,94 @@ +extern crate libc; +use libc::*; +extern crate libcc2rs; +use libcc2rs::*; +use std::collections::BTreeMap; +use std::io::Seek; +use std::io::{Read, Write}; +use std::os::fd::{AsFd, FromRawFd, IntoRawFd}; +use std::rc::Rc; +pub unsafe fn double_it_0(mut x: i32) -> i32 { + return ((x) * (2)); +} +pub unsafe fn test_roundtrip_1() { + let mut fn_: Option i32> = Some(double_it_0); + assert!( + ((unsafe { + let _arg0: i32 = 5; + (fn_).unwrap()(_arg0) + }) == (10)) + ); + let mut gfn: Option = + std::mem::transmute:: i32>, Option>(fn_); + assert!(!((gfn).is_none())); + let mut fn2: Option i32> = + std::mem::transmute::, Option i32>>(gfn); + assert!( + ((unsafe { + let _arg0: i32 = 5; + (fn2).unwrap()(_arg0) + }) == (10)) + ); + assert!(((fn2) == (fn_))); +} +pub unsafe fn test_double_cast_2() { + let mut fn_: Option i32> = Some(double_it_0); + let mut fn2: Option i32> = + std::mem::transmute::, Option i32>>( + std::mem::transmute:: i32>, Option>(fn_), + ); + assert!( + ((unsafe { + let _arg0: i32 = 5; + (fn2).unwrap()(_arg0) + }) == (10)) + ); + assert!(((fn2) == (fn_))); +} +#[derive(Copy, Clone, Default)] +pub struct Command { + pub data: *mut ::libc::c_void, +} +pub unsafe fn test_void_ptr_to_fn_3() { + let mut cmd: Command = ::default(); + cmd.data = std::mem::transmute:: i32>, *mut ::libc::c_void>(Some( + double_it_0, + )); + let mut fn_: Option i32> = + std::mem::transmute::<*mut ::libc::c_void, Option i32>>(cmd.data); + assert!( + ((unsafe { + let _arg0: i32 = 5; + (fn_).unwrap()(_arg0) + }) == (10)) + ); +} +pub unsafe fn add_offset_4(mut base: *mut i32, mut offset: i32) -> i32 { + return ((*base) + (offset)); +} +pub unsafe fn test_call_through_cast_5() { + let mut gfn: Option i32> = std::mem::transmute::< + Option i32>, + Option i32>, + >(Some(add_offset_4)); + let mut val: i32 = 100; + let mut result: i32 = (unsafe { + let _arg0: *mut ::libc::c_void = + ((&mut val as *mut i32) as *mut i32 as *mut ::libc::c_void); + let _arg1: i32 = 42; + (gfn).unwrap()(_arg0, _arg1) + }); + assert!(((result) == (142))); +} +pub fn main() { + unsafe { + std::process::exit(main_0() as i32); + } +} +unsafe fn main_0() -> i32 { + (unsafe { test_roundtrip_1() }); + (unsafe { test_double_cast_2() }); + (unsafe { test_void_ptr_to_fn_3() }); + (unsafe { test_call_through_cast_5() }); + return 0; +} diff --git a/tests/unit/out/unsafe/fn_ptr_conditional.rs b/tests/unit/out/unsafe/fn_ptr_conditional.rs new file mode 100644 index 0000000..0694a0b --- /dev/null +++ b/tests/unit/out/unsafe/fn_ptr_conditional.rs @@ -0,0 +1,92 @@ +extern crate libc; +use libc::*; +extern crate libcc2rs; +use libcc2rs::*; +use std::collections::BTreeMap; +use std::io::Seek; +use std::io::{Read, Write}; +use std::os::fd::{AsFd, FromRawFd, IntoRawFd}; +use std::rc::Rc; +pub unsafe fn inc_0(mut x: i32) -> i32 { + return ((x) + (1)); +} +pub unsafe fn dec_1(mut x: i32) -> i32 { + return ((x) - (1)); +} +pub unsafe fn identity_2(mut x: i32) -> i32 { + return x; +} +pub unsafe fn pick_3(mut mode: i32) -> Option i32> { + return if ((mode) > (0)) { + Some(inc_0) + } else { + if ((mode) < (0)) { + Some(dec_1) + } else { + Some(identity_2) + } + }; +} +pub unsafe fn apply_4(mut fn_: Option i32>, mut x: i32) -> i32 { + let mut actual: Option i32> = if !(fn_).is_none() { + fn_ + } else { + Some(identity_2) + }; + return (unsafe { + let _arg0: i32 = x; + (actual).unwrap()(_arg0) + }); +} +pub fn main() { + unsafe { + std::process::exit(main_0() as i32); + } +} +unsafe fn main_0() -> i32 { + assert!( + ((unsafe { + let _arg0: i32 = 10; + (unsafe { + let _mode: i32 = 1; + pick_3(_mode) + }) + .unwrap()(_arg0) + }) == (11)) + ); + assert!( + ((unsafe { + let _arg0: i32 = 10; + (unsafe { + let _mode: i32 = -1_i32; + pick_3(_mode) + }) + .unwrap()(_arg0) + }) == (9)) + ); + assert!( + ((unsafe { + let _arg0: i32 = 10; + (unsafe { + let _mode: i32 = 0; + pick_3(_mode) + }) + .unwrap()(_arg0) + }) == (10)) + ); + assert!( + ((unsafe { + let _fn: Option i32> = Some(inc_0); + let _x: i32 = 5; + apply_4(_fn, _x) + }) == (6)) + ); + assert!( + ((unsafe { + let _fn: Option i32> = None; + let _x: i32 = 5; + apply_4(_fn, _x) + }) == (5)) + ); + return 0; +} diff --git a/tests/unit/out/unsafe/fn_ptr_default_arg.rs b/tests/unit/out/unsafe/fn_ptr_default_arg.rs new file mode 100644 index 0000000..86287ca --- /dev/null +++ b/tests/unit/out/unsafe/fn_ptr_default_arg.rs @@ -0,0 +1,61 @@ +extern crate libc; +use libc::*; +extern crate libcc2rs; +use libcc2rs::*; +use std::collections::BTreeMap; +use std::io::Seek; +use std::io::{Read, Write}; +use std::os::fd::{AsFd, FromRawFd, IntoRawFd}; +use std::rc::Rc; +pub unsafe fn identity_0(mut x: i32) -> i32 { + return x; +} +pub unsafe fn apply_1(mut x: i32, mut fn_: Option i32>>) -> i32 { + let mut fn_: Option i32> = fn_.unwrap_or(None); + if !(fn_).is_none() { + return (unsafe { + let _arg0: i32 = x; + (fn_).unwrap()(_arg0) + }); + } + return x; +} +pub fn main() { + unsafe { + std::process::exit(main_0() as i32); + } +} +unsafe fn main_0() -> i32 { + assert!( + ((unsafe { + let _x: i32 = 5; + let _fn: Option i32> = Default::default(); + apply_1(_x, Some(_fn)) + }) == (5)) + ); + assert!( + ((unsafe { + let _x: i32 = 5; + let _fn: Option i32> = None; + apply_1(_x, Some(_fn)) + }) == (5)) + ); + assert!( + ((unsafe { + let _x: i32 = 5; + let _fn: Option i32> = Some(identity_0); + apply_1(_x, Some(_fn)) + }) == (5)) + ); + let mut negate: Option i32> = Some(|x: i32| { + return -x; + }); + assert!( + ((unsafe { + let _x: i32 = 5; + let _fn: Option i32> = negate; + apply_1(_x, Some(_fn)) + }) == (-5_i32)) + ); + return 0; +} diff --git a/tests/unit/out/unsafe/fn_ptr_global.rs b/tests/unit/out/unsafe/fn_ptr_global.rs new file mode 100644 index 0000000..21dc35b --- /dev/null +++ b/tests/unit/out/unsafe/fn_ptr_global.rs @@ -0,0 +1,76 @@ +extern crate libc; +use libc::*; +extern crate libcc2rs; +use libcc2rs::*; +use std::collections::BTreeMap; +use std::io::Seek; +use std::io::{Read, Write}; +use std::os::fd::{AsFd, FromRawFd, IntoRawFd}; +use std::rc::Rc; +pub unsafe fn double_it_0(mut x: i32) -> i32 { + return ((x) * (2)); +} +pub unsafe fn triple_it_1(mut x: i32) -> i32 { + return ((x) * (3)); +} +pub static mut g_op: Option i32> = None; +pub unsafe fn set_op_2(mut fn_: Option i32>) { + g_op = fn_; +} +pub unsafe fn call_op_3(mut x: i32) -> i32 { + if !(g_op).is_none() { + return (unsafe { + let _arg0: i32 = x; + (g_op).unwrap()(_arg0) + }); + } + return x; +} +pub fn main() { + unsafe { + std::process::exit(main_0() as i32); + } +} +unsafe fn main_0() -> i32 { + assert!( + ((unsafe { + let _x: i32 = 5; + call_op_3(_x) + }) == (5)) + ); + (unsafe { + let _fn: Option i32> = Some(double_it_0); + set_op_2(_fn) + }); + assert!(!((g_op).is_none())); + assert!(((g_op) == (Some(double_it_0)))); + assert!( + ((unsafe { + let _x: i32 = 5; + call_op_3(_x) + }) == (10)) + ); + (unsafe { + let _fn: Option i32> = Some(triple_it_1); + set_op_2(_fn) + }); + assert!(((g_op) == (Some(triple_it_1)))); + assert!( + ((unsafe { + let _x: i32 = 5; + call_op_3(_x) + }) == (15)) + ); + (unsafe { + let _fn: Option i32> = None; + set_op_2(_fn) + }); + assert!((g_op).is_none()); + assert!( + ((unsafe { + let _x: i32 = 5; + call_op_3(_x) + }) == (5)) + ); + return 0; +} diff --git a/tests/unit/out/unsafe/fn_ptr_mapped.rs b/tests/unit/out/unsafe/fn_ptr_mapped.rs new file mode 100644 index 0000000..e19a1f5 --- /dev/null +++ b/tests/unit/out/unsafe/fn_ptr_mapped.rs @@ -0,0 +1,45 @@ +extern crate libc; +use libc::*; +extern crate libcc2rs; +use libcc2rs::*; +use std::collections::BTreeMap; +use std::io::Seek; +use std::io::{Read, Write}; +use std::os::fd::{AsFd, FromRawFd, IntoRawFd}; +use std::rc::Rc; +pub unsafe fn foo_0( + mut fn_: Rc u64>, + mut p: *mut ::libc::c_void, + mut size: u64, + mut nmemb: u64, + mut f: *mut ::std::fs::File, +) -> u64 { + return (unsafe { + let _arg0: *mut ::libc::c_void = p; + let _arg1: u64 = size; + let _arg2: u64 = nmemb; + let _arg3: *mut ::std::fs::File = f; + fn_(_arg0, _arg1, _arg2, _arg3) + }); +} +pub fn main() { + unsafe { + std::process::exit(main_0() as i32); + } +} +unsafe fn main_0() -> i32 { + let mut fn_: Rc u64> = + (Rc::new(|a0, a1, a2, a3| unsafe { fread_1(a0, a1, a2, a3) }) + as Rc u64>); + (unsafe { + let _fn: Rc u64> = + Rc::new(|a0, a1, a2, a3| unsafe { fread_1(a0, a1, a2, a3) }); + let _p: *mut ::libc::c_void = Default::default(); + let _size: u64 = 0_u64; + let _nmemb: u64 = 0_u64; + let _f: *mut ::std::fs::File = Default::default(); + foo_0(_fn, _p, _size, _nmemb, _f) + }); + assert!(((fn_) != (Default::default()))); + return 0; +} diff --git a/tests/unit/out/unsafe/fn_ptr_reassign.rs b/tests/unit/out/unsafe/fn_ptr_reassign.rs new file mode 100644 index 0000000..08eed4b --- /dev/null +++ b/tests/unit/out/unsafe/fn_ptr_reassign.rs @@ -0,0 +1,61 @@ +extern crate libc; +use libc::*; +extern crate libcc2rs; +use libcc2rs::*; +use std::collections::BTreeMap; +use std::io::Seek; +use std::io::{Read, Write}; +use std::os::fd::{AsFd, FromRawFd, IntoRawFd}; +use std::rc::Rc; +pub unsafe fn add_0(mut a: i32, mut b: i32) -> i32 { + return ((a) + (b)); +} +pub unsafe fn sub_1(mut a: i32, mut b: i32) -> i32 { + return ((a) - (b)); +} +pub unsafe fn mul_2(mut a: i32, mut b: i32) -> i32 { + return ((a) * (b)); +} +pub fn main() { + unsafe { + std::process::exit(main_0() as i32); + } +} +unsafe fn main_0() -> i32 { + let mut fn_: Option i32> = Some(add_0); + assert!( + ((unsafe { + let _arg0: i32 = 3; + let _arg1: i32 = 4; + (fn_).unwrap()(_arg0, _arg1) + }) == (7)) + ); + fn_ = Some(sub_1); + assert!( + ((unsafe { + let _arg0: i32 = 10; + let _arg1: i32 = 3; + (fn_).unwrap()(_arg0, _arg1) + }) == (7)) + ); + fn_ = Some(mul_2); + assert!( + ((unsafe { + let _arg0: i32 = 6; + let _arg1: i32 = 7; + (fn_).unwrap()(_arg0, _arg1) + }) == (42)) + ); + fn_ = None; + assert!((fn_).is_none()); + fn_ = Some(add_0); + assert!(!((fn_).is_none())); + assert!( + ((unsafe { + let _arg0: i32 = 1; + let _arg1: i32 = 1; + (fn_).unwrap()(_arg0, _arg1) + }) == (2)) + ); + return 0; +} diff --git a/tests/unit/out/unsafe/fn_ptr_return.rs b/tests/unit/out/unsafe/fn_ptr_return.rs new file mode 100644 index 0000000..1cda282 --- /dev/null +++ b/tests/unit/out/unsafe/fn_ptr_return.rs @@ -0,0 +1,53 @@ +extern crate libc; +use libc::*; +extern crate libcc2rs; +use libcc2rs::*; +use std::collections::BTreeMap; +use std::io::Seek; +use std::io::{Read, Write}; +use std::os::fd::{AsFd, FromRawFd, IntoRawFd}; +use std::rc::Rc; +pub unsafe fn inc_0(mut x: i32) -> i32 { + return ((x) + (1)); +} +pub unsafe fn dec_1(mut x: i32) -> i32 { + return ((x) - (1)); +} +pub unsafe fn pick_2(mut choose_inc: i32) -> Option i32> { + if (choose_inc != 0) { + return Some(inc_0); + } + return Some(dec_1); +} +pub fn main() { + unsafe { + std::process::exit(main_0() as i32); + } +} +unsafe fn main_0() -> i32 { + let mut f: Option i32> = (unsafe { + let _choose_inc: i32 = 1; + pick_2(_choose_inc) + }); + assert!(!((f).is_none())); + assert!(((f) == (Some(inc_0)))); + assert!( + ((unsafe { + let _arg0: i32 = 10; + (f).unwrap()(_arg0) + }) == (11)) + ); + let mut g: Option i32> = (unsafe { + let _choose_inc: i32 = 0; + pick_2(_choose_inc) + }); + assert!(((g) == (Some(dec_1)))); + assert!( + ((unsafe { + let _arg0: i32 = 10; + (g).unwrap()(_arg0) + }) == (9)) + ); + assert!(((f) != (g))); + return 0; +} diff --git a/tests/unit/out/unsafe/fn_ptr_stable_sort.rs b/tests/unit/out/unsafe/fn_ptr_stable_sort.rs new file mode 100644 index 0000000..123a880 --- /dev/null +++ b/tests/unit/out/unsafe/fn_ptr_stable_sort.rs @@ -0,0 +1,44 @@ +extern crate libc; +use libc::*; +extern crate libcc2rs; +use libcc2rs::*; +use std::collections::BTreeMap; +use std::io::Seek; +use std::io::{Read, Write}; +use std::os::fd::{AsFd, FromRawFd, IntoRawFd}; +use std::rc::Rc; +#[derive(Copy, Clone, Default)] +pub struct Item { + pub key: i32, + pub value: i32, +} +pub unsafe fn Compare_0(a: *const Item, b: *const Item) -> bool { + return (((*a).key) < ((*b).key)); +} +pub fn main() { + unsafe { + std::process::exit(main_0() as i32); + } +} +unsafe fn main_0() -> i32 { + let mut v: Vec = Vec::new(); + v.push(Item { key: 3, value: 30 }); + v.push(Item { key: 1, value: 10 }); + v.push(Item { key: 2, value: 20 }); + { + let len = v.as_mut_ptr().add(v.len()).offset_from(v.as_mut_ptr()) as usize; + ::std::slice::from_raw_parts_mut(v.as_mut_ptr(), len).sort_by(|x, y| { + if (Compare_0)(x, y) { + std::cmp::Ordering::Less + } else if (Compare_0)(y, x) { + std::cmp::Ordering::Greater + } else { + std::cmp::Ordering::Equal + } + }) + }; + assert!(((v[(0_u64) as usize].key) == (1))); + assert!(((v[(1_u64) as usize].key) == (2))); + assert!(((v[(2_u64) as usize].key) == (3))); + return 0; +} diff --git a/tests/unit/out/unsafe/fn_ptr_stdlib_compare.rs b/tests/unit/out/unsafe/fn_ptr_stdlib_compare.rs new file mode 100644 index 0000000..3ff8e11 --- /dev/null +++ b/tests/unit/out/unsafe/fn_ptr_stdlib_compare.rs @@ -0,0 +1,55 @@ +extern crate libc; +use libc::*; +extern crate libcc2rs; +use libcc2rs::*; +use std::collections::BTreeMap; +use std::io::Seek; +use std::io::{Read, Write}; +use std::os::fd::{AsFd, FromRawFd, IntoRawFd}; +use std::rc::Rc; +pub unsafe fn my_alternative_fread_0( + mut p: *mut u8, + mut n: u64, + mut m: u64, + mut f: *mut ::libc::c_void, +) -> u64 { + return 22_u64; +} +pub fn main() { + unsafe { + std::process::exit(main_0() as i32); + } +} +unsafe fn main_0() -> i32 { + let mut fn1: Option u64> = + Some(rules::stdio_tgt_unsafe::f5); + assert!(((fn1) == (Some(rules::stdio_tgt_unsafe::f5)))); + assert!(!((fn1).is_none())); + let mut fn2: Option u64> = + std::mem::transmute::< + Option u64>, + Option u64>, + >(Some(rules::stdio_tgt_unsafe::f5)); + assert!( + ((fn1) + == (std::mem::transmute::< + Option u64>, + Option u64>, + >(fn2))) + ); + let mut f3: Option u64> = + std::mem::transmute::< + Option u64>, + Option u64>, + >(Some(my_alternative_fread_0)); + assert!( + ((unsafe { + let _arg0: *mut ::libc::c_void = Default::default(); + let _arg1: u64 = 0_u64; + let _arg2: u64 = 0_u64; + let _arg3: *mut ::std::fs::File = Default::default(); + (f3).unwrap()(_arg0, _arg1, _arg2, _arg3) + }) == (22_u64)) + ); + return 0; +} diff --git a/tests/unit/out/unsafe/fn_ptr_struct.rs b/tests/unit/out/unsafe/fn_ptr_struct.rs new file mode 100644 index 0000000..ae9e3a7 --- /dev/null +++ b/tests/unit/out/unsafe/fn_ptr_struct.rs @@ -0,0 +1,65 @@ +extern crate libc; +use libc::*; +extern crate libcc2rs; +use libcc2rs::*; +use std::collections::BTreeMap; +use std::io::Seek; +use std::io::{Read, Write}; +use std::os::fd::{AsFd, FromRawFd, IntoRawFd}; +use std::rc::Rc; +#[derive(Clone)] +pub struct Handler { + pub tag: i32, + pub cb: Option i32>, +} +impl Default for Handler { + fn default() -> Self { + Handler { + tag: 0_i32, + cb: None, + } + } +} +pub unsafe fn double_it_0(mut x: i32) -> i32 { + return ((x) * (2)); +} +pub unsafe fn negate_1(mut x: i32) -> i32 { + return -x; +} +pub fn main() { + unsafe { + std::process::exit(main_0() as i32); + } +} +unsafe fn main_0() -> i32 { + let mut h1: Handler = Handler { + tag: 1, + cb: Some(double_it_0), + }; + let mut h2: Handler = Handler { + tag: 2, + cb: Some(negate_1), + }; + assert!(!((h1.cb).is_none())); + assert!( + ((unsafe { + let _arg0: i32 = 5; + (h1.cb).unwrap()(_arg0) + }) == (10)) + ); + assert!( + ((unsafe { + let _arg0: i32 = 7; + (h2.cb).unwrap()(_arg0) + }) == (-7_i32)) + ); + (h1.cb) = Some(negate_1); + assert!( + ((unsafe { + let _arg0: i32 = 3; + (h1.cb).unwrap()(_arg0) + }) == (-3_i32)) + ); + assert!(((h1.cb) == (h2.cb))); + return 0; +} diff --git a/tests/unit/out/unsafe/fn_ptr_void_return.rs b/tests/unit/out/unsafe/fn_ptr_void_return.rs new file mode 100644 index 0000000..72ab341 --- /dev/null +++ b/tests/unit/out/unsafe/fn_ptr_void_return.rs @@ -0,0 +1,50 @@ +extern crate libc; +use libc::*; +extern crate libcc2rs; +use libcc2rs::*; +use std::collections::BTreeMap; +use std::io::Seek; +use std::io::{Read, Write}; +use std::os::fd::{AsFd, FromRawFd, IntoRawFd}; +use std::rc::Rc; +pub unsafe fn negate_0(mut x: *mut i32) { + (*x) = -(*x); +} +pub unsafe fn zero_out_1(mut x: *mut i32) { + (*x) = 0; +} +pub unsafe fn run_2(mut fn_: Option, mut x: *mut i32) { + (unsafe { + let _arg0: *mut i32 = x; + (fn_).unwrap()(_arg0) + }); +} +pub fn main() { + unsafe { + std::process::exit(main_0() as i32); + } +} +unsafe fn main_0() -> i32 { + let mut a: i32 = 42; + (unsafe { + let _fn: Option = Some(negate_0); + let _x: *mut i32 = (&mut a as *mut i32); + run_2(_fn, _x) + }); + assert!(((a) == (-42_i32))); + (unsafe { + let _fn: Option = Some(zero_out_1); + let _x: *mut i32 = (&mut a as *mut i32); + run_2(_fn, _x) + }); + assert!(((a) == (0))); + let mut fn_: Option = Some(negate_0); + assert!(!((fn_).is_none())); + let mut b: i32 = 10; + (unsafe { + let _arg0: *mut i32 = (&mut b as *mut i32); + (fn_).unwrap()(_arg0) + }); + assert!(((b) == (-10_i32))); + return 0; +} diff --git a/tests/unit/out/unsafe/fn_ptr_vtable.rs b/tests/unit/out/unsafe/fn_ptr_vtable.rs new file mode 100644 index 0000000..48e820e --- /dev/null +++ b/tests/unit/out/unsafe/fn_ptr_vtable.rs @@ -0,0 +1,68 @@ +extern crate libc; +use libc::*; +extern crate libcc2rs; +use libcc2rs::*; +use std::collections::BTreeMap; +use std::io::Seek; +use std::io::{Read, Write}; +use std::os::fd::{AsFd, FromRawFd, IntoRawFd}; +use std::rc::Rc; +#[derive(Clone)] +pub struct Vtable { + pub create: Option *mut ::libc::c_void>, + pub get: Option i32>, + pub destroy: Option, +} +impl Default for Vtable { + fn default() -> Self { + Vtable { + create: None, + get: None, + destroy: None, + } + } +} +pub static mut storage: i32 = 0_i32; +pub unsafe fn int_create_0(mut val: i32) -> *mut ::libc::c_void { + storage = val; + return ((&mut storage as *mut i32) as *mut i32 as *mut ::libc::c_void); +} +pub unsafe fn int_get_1(mut p: *mut ::libc::c_void) -> i32 { + return (*(p as *mut i32)); +} +pub unsafe fn int_destroy_2(mut p: *mut ::libc::c_void) { + (*(p as *mut i32)) = 0; +} +pub fn main() { + unsafe { + std::process::exit(main_0() as i32); + } +} +unsafe fn main_0() -> i32 { + let mut vt: Vtable = Vtable { + create: Some(int_create_0), + get: Some(int_get_1), + destroy: Some(int_destroy_2), + }; + assert!(!((vt.create).is_none())); + assert!(!((vt.get).is_none())); + assert!(!((vt.destroy).is_none())); + let mut obj: *mut ::libc::c_void = (unsafe { + let _arg0: i32 = 42; + (vt.create).unwrap()(_arg0) + }); + assert!( + ((unsafe { + let _arg0: *mut ::libc::c_void = obj; + (vt.get).unwrap()(_arg0) + }) == (42)) + ); + (unsafe { + let _arg0: *mut ::libc::c_void = obj; + (vt.destroy).unwrap()(_arg0) + }); + assert!(((storage) == (0))); + (vt.get) = None; + assert!((vt.get).is_none()); + return 0; +} diff --git a/tests/unit/out/unsafe/init.rs b/tests/unit/out/unsafe/init.rs index 894070b..5e61576 100644 --- a/tests/unit/out/unsafe/init.rs +++ b/tests/unit/out/unsafe/init.rs @@ -20,7 +20,7 @@ pub fn main() { } } unsafe fn main_0() -> i32 { - let mut x: i32 = ::default(); + let mut x: i32 = 0_i32; let mut p: *mut i32 = Default::default(); let g: *mut i32 = &mut x as *mut i32; let mut q: *mut i32 = (&mut x as *mut i32); diff --git a/tests/unit/out/unsafe/init_list.rs b/tests/unit/out/unsafe/init_list.rs index d8e2166..1f6a2b5 100644 --- a/tests/unit/out/unsafe/init_list.rs +++ b/tests/unit/out/unsafe/init_list.rs @@ -15,9 +15,9 @@ pub fn main() { } unsafe fn main_0() -> i32 { let mut i1: i32 = 3; - let mut i2: i32 = ::default(); + let mut i2: i32 = 0_i32; let mut carr1: [i32; 2] = [1, 2]; - let mut carr2: [i32; 3] = [1, ::default(), ::default()]; + let mut carr2: [i32; 3] = [1, 0_i32, 0_i32]; let mut arr: Vec = vec![1, 2, 3]; let mut vec_: Vec = vec![1, 2, 3]; (unsafe { diff --git a/tests/unit/out/unsafe/lambda_capture_local.rs b/tests/unit/out/unsafe/lambda_capture_local.rs new file mode 100644 index 0000000..9e449d6 --- /dev/null +++ b/tests/unit/out/unsafe/lambda_capture_local.rs @@ -0,0 +1,72 @@ +extern crate libc; +use libc::*; +extern crate libcc2rs; +use libcc2rs::*; +use std::collections::BTreeMap; +use std::io::Seek; +use std::io::{Read, Write}; +use std::os::fd::{AsFd, FromRawFd, IntoRawFd}; +use std::rc::Rc; +pub fn main() { + unsafe { + std::process::exit(main_0() as i32); + } +} +unsafe fn main_0() -> i32 { + let mut base: i32 = 10; + let mut factor: i32 = 3; + assert!( + ((unsafe { + let _x: i32 = 5; + (|x: i32| { + return ((x) + (base)); + })(_x) + }) == (15)) + ); + assert!( + ((unsafe { + let _x: i32 = 4; + (|x: i32| { + return ((x) * (factor)); + })(_x) + }) == (12)) + ); + base = 100; + assert!( + ((unsafe { + let _x: i32 = 5; + (|x: i32| { + return ((x) + (base)); + })(_x) + }) == (105)) + ); + assert!( + ((unsafe { + let _x: i32 = 4; + (|x: i32| { + return ((x) * (factor)); + })(_x) + }) == (12)) + ); + let mut sum: i32 = 0; + (unsafe { + let _x: i32 = 1; + (|x: i32| { + sum += x; + })(_x) + }); + (unsafe { + let _x: i32 = 2; + (|x: i32| { + sum += x; + })(_x) + }); + (unsafe { + let _x: i32 = 3; + (|x: i32| { + sum += x; + })(_x) + }); + assert!(((sum) == (6))); + return 0; +} diff --git a/tests/unit/out/unsafe/lambda_capture_pass.rs b/tests/unit/out/unsafe/lambda_capture_pass.rs new file mode 100644 index 0000000..bf1f4fa --- /dev/null +++ b/tests/unit/out/unsafe/lambda_capture_pass.rs @@ -0,0 +1,62 @@ +extern crate libc; +use libc::*; +extern crate libcc2rs; +use libcc2rs::*; +use std::collections::BTreeMap; +use std::io::Seek; +use std::io::{Read, Write}; +use std::os::fd::{AsFd, FromRawFd, IntoRawFd}; +use std::rc::Rc; +pub unsafe fn apply_0(mut fn_: impl Fn(i32) -> i32, mut x: i32) -> i32 { + return (unsafe { + let _x: i32 = x; + fn_(_x) + }); +} +pub unsafe fn apply_1(mut fn_: impl Fn(i32) -> i32, mut x: i32) -> i32 { + return (unsafe { + let _x: i32 = x; + fn_(_x) + }); +} +pub fn main() { + unsafe { + std::process::exit(main_0() as i32); + } +} +unsafe fn main_0() -> i32 { + let mut base: i32 = 10; + assert!( + ((unsafe { + let _fn: _ = (|x: i32| { + return ((x) + (base)); + }) + .clone(); + let _x: i32 = 5; + apply_0(_fn, _x) + }) == (15)) + ); + base = 100; + assert!( + ((unsafe { + let _fn: _ = (|x: i32| { + return ((x) + (base)); + }) + .clone(); + let _x: i32 = 5; + apply_0(_fn, _x) + }) == (105)) + ); + let mut factor: i32 = 3; + assert!( + ((unsafe { + let _fn: _ = (|x: i32| { + return ((x) * (factor)); + }) + .clone(); + let _x: i32 = 4; + apply_1(_fn, _x) + }) == (12)) + ); + return 0; +} diff --git a/tests/unit/out/unsafe/lambda_nested.rs b/tests/unit/out/unsafe/lambda_nested.rs new file mode 100644 index 0000000..542a59d --- /dev/null +++ b/tests/unit/out/unsafe/lambda_nested.rs @@ -0,0 +1,45 @@ +extern crate libc; +use libc::*; +extern crate libcc2rs; +use libcc2rs::*; +use std::collections::BTreeMap; +use std::io::Seek; +use std::io::{Read, Write}; +use std::os::fd::{AsFd, FromRawFd, IntoRawFd}; +use std::rc::Rc; +pub fn main() { + unsafe { + std::process::exit(main_0() as i32); + } +} +unsafe fn main_0() -> i32 { + let mut x: i32 = 10; + assert!( + ((unsafe { + let _y: i32 = 20; + (|y: i32| { + return (unsafe { + let _z: i32 = 1; + (|z: i32| { + return (((x) + (y)) + (z)); + })(_z) + }); + })(_y) + }) == (31)) + ); + x = 100; + assert!( + ((unsafe { + let _y: i32 = 20; + (|y: i32| { + return (unsafe { + let _z: i32 = 1; + (|z: i32| { + return (((x) + (y)) + (z)); + })(_z) + }); + })(_y) + }) == (121)) + ); + return 0; +} diff --git a/tests/unit/out/unsafe/lambda_nocapture.rs b/tests/unit/out/unsafe/lambda_nocapture.rs new file mode 100644 index 0000000..d71ab10 --- /dev/null +++ b/tests/unit/out/unsafe/lambda_nocapture.rs @@ -0,0 +1,64 @@ +extern crate libc; +use libc::*; +extern crate libcc2rs; +use libcc2rs::*; +use std::collections::BTreeMap; +use std::io::Seek; +use std::io::{Read, Write}; +use std::os::fd::{AsFd, FromRawFd, IntoRawFd}; +use std::rc::Rc; +pub unsafe fn call_0(mut f: Option i32>, mut a: i32, mut b: i32) -> i32 { + return (unsafe { + let _arg0: i32 = a; + let _arg1: i32 = b; + (f).unwrap()(_arg0, _arg1) + }); +} +pub fn main() { + unsafe { + std::process::exit(main_0() as i32); + } +} +unsafe fn main_0() -> i32 { + let mut add: Option i32> = Some(|a: i32, b: i32| { + return ((a) + (b)); + }); + let mut sub: Option i32> = Some(|a: i32, b: i32| { + return ((a) - (b)); + }); + assert!(!((add).is_none())); + assert!(((add) != (sub))); + assert!( + ((unsafe { + let _arg0: i32 = 2; + let _arg1: i32 = 3; + (add).unwrap()(_arg0, _arg1) + }) == (5)) + ); + assert!( + ((unsafe { + let _arg0: i32 = 10; + let _arg1: i32 = 4; + (sub).unwrap()(_arg0, _arg1) + }) == (6)) + ); + assert!( + ((unsafe { + let _f: Option i32> = add; + let _a: i32 = 7; + let _b: i32 = 8; + call_0(_f, _a, _b) + }) == (15)) + ); + assert!( + ((unsafe { + let _f: Option i32> = Some(|a: i32, b: i32| { + return ((a) * (b)); + }); + let _a: i32 = 6; + let _b: i32 = 7; + call_0(_f, _a, _b) + }) == (42)) + ); + return 0; +} diff --git a/tests/unit/out/unsafe/memset.rs b/tests/unit/out/unsafe/memset.rs index ec8fd42..284f976 100644 --- a/tests/unit/out/unsafe/memset.rs +++ b/tests/unit/out/unsafe/memset.rs @@ -14,12 +14,8 @@ pub fn main() { } unsafe fn main_0() -> i32 { let N: i32 = 3; - let mut arr: *mut i32 = Box::leak( - (0..(N as u64)) - .map(|_| ::default()) - .collect::>(), - ) - .as_mut_ptr(); + let mut arr: *mut i32 = + Box::leak((0..(N as u64)).map(|_| 0_i32).collect::>()).as_mut_ptr(); { let byte_0 = (arr as *mut i32 as *mut ::libc::c_void) as *mut u8; for offset in 0..(::std::mem::size_of::() as u64 as u64).wrapping_mul((N as u64)) { diff --git a/tests/unit/out/unsafe/new_alloc_array.rs b/tests/unit/out/unsafe/new_alloc_array.rs index 697fe0a..1814e52 100644 --- a/tests/unit/out/unsafe/new_alloc_array.rs +++ b/tests/unit/out/unsafe/new_alloc_array.rs @@ -13,12 +13,8 @@ pub fn main() { } } unsafe fn main_0() -> i32 { - let mut array: *mut i32 = Box::leak( - (0..100_u64) - .map(|_| ::default()) - .collect::>(), - ) - .as_mut_ptr(); + let mut array: *mut i32 = + Box::leak((0..100_u64).map(|_| 0_i32).collect::>()).as_mut_ptr(); { let byte_0 = (array as *mut i32 as *mut ::libc::c_void) as *mut u8; for offset in 0..(::std::mem::size_of::() as u64 as u64).wrapping_mul(100_u64) { diff --git a/tests/unit/out/unsafe/new_array.rs b/tests/unit/out/unsafe/new_array.rs index e2243ee..514fc12 100644 --- a/tests/unit/out/unsafe/new_array.rs +++ b/tests/unit/out/unsafe/new_array.rs @@ -13,12 +13,8 @@ pub fn main() { } } unsafe fn main_0() -> i32 { - let mut array: *mut i32 = Box::leak( - (0..100_u64) - .map(|_| ::default()) - .collect::>(), - ) - .as_mut_ptr(); + let mut array: *mut i32 = + Box::leak((0..100_u64).map(|_| 0_i32).collect::>()).as_mut_ptr(); ::std::mem::drop(Box::from_raw(::std::slice::from_raw_parts_mut( array, diff --git a/tests/unit/out/unsafe/new_array_var_size.rs b/tests/unit/out/unsafe/new_array_var_size.rs index cfdf0c1..f9be614 100644 --- a/tests/unit/out/unsafe/new_array_var_size.rs +++ b/tests/unit/out/unsafe/new_array_var_size.rs @@ -14,24 +14,16 @@ pub fn main() { } unsafe fn main_0() -> i32 { let mut N: i32 = 5; - let mut A: *mut i32 = Box::leak( - (0..(N as u64)) - .map(|_| ::default()) - .collect::>(), - ) - .as_mut_ptr(); + let mut A: *mut i32 = + Box::leak((0..(N as u64)).map(|_| 0_i32).collect::>()).as_mut_ptr(); ::std::mem::drop(Box::from_raw(::std::slice::from_raw_parts_mut( A, libcc2rs::malloc_usable_size(A as *mut ::libc::c_void) / ::std::mem::size_of::(), ))); let N2: *mut i32 = &mut N as *mut i32; - let mut A2: *mut i32 = Box::leak( - (0..((*N2) as u64)) - .map(|_| ::default()) - .collect::>(), - ) - .as_mut_ptr(); + let mut A2: *mut i32 = + Box::leak((0..((*N2) as u64)).map(|_| 0_i32).collect::>()).as_mut_ptr(); ::std::mem::drop(Box::from_raw(::std::slice::from_raw_parts_mut( A2, diff --git a/tests/unit/out/unsafe/no_direct_callee.rs b/tests/unit/out/unsafe/no_direct_callee.rs index 5c962fe..b4eac21 100644 --- a/tests/unit/out/unsafe/no_direct_callee.rs +++ b/tests/unit/out/unsafe/no_direct_callee.rs @@ -10,8 +10,8 @@ use std::rc::Rc; pub unsafe fn test1_0() -> bool { return false; } -pub unsafe fn test_1(mut fn_: Rc bool>) -> i32 { - if !(unsafe { fn_() }) { +pub unsafe fn test_1(mut fn_: Option bool>) -> i32 { + if !(unsafe { (fn_).unwrap()() }) { return 1; } return 0; @@ -23,7 +23,7 @@ pub fn main() { } unsafe fn main_0() -> i32 { return (unsafe { - let _fn: Rc bool> = Rc::new(|| unsafe { test1_0() }); + let _fn: Option bool> = Some(test1_0); test_1(_fn) }); } diff --git a/tests/unit/out/unsafe/pointer_call_offset.rs b/tests/unit/out/unsafe/pointer_call_offset.rs index fdbca43..76f2a3d 100644 --- a/tests/unit/out/unsafe/pointer_call_offset.rs +++ b/tests/unit/out/unsafe/pointer_call_offset.rs @@ -16,12 +16,8 @@ pub fn main() { } } unsafe fn main_0() -> i32 { - let mut p1: *mut i32 = Box::leak( - (0..10_u64) - .map(|_| ::default()) - .collect::>(), - ) - .as_mut_ptr(); + let mut p1: *mut i32 = + Box::leak((0..10_u64).map(|_| 0_i32).collect::>()).as_mut_ptr(); let mut i: u32 = 0_u32; 'loop_: while ((i) < (10_u32)) { (*p1.offset((i) as isize)) = (i as i32); diff --git a/tests/unit/out/unsafe/prvalue-as-lvalue.rs b/tests/unit/out/unsafe/prvalue-as-lvalue.rs index 515e098..4d1040d 100644 --- a/tests/unit/out/unsafe/prvalue-as-lvalue.rs +++ b/tests/unit/out/unsafe/prvalue-as-lvalue.rs @@ -20,7 +20,7 @@ unsafe fn main_0() -> i32 { let mut pa: *mut i32 = (&mut a as *mut i32); let b: *const i32 = (unsafe { let _a: *const i32 = &(*pa) as *const i32; - Rc::new(|a0| unsafe { foo_0(a0) })(_a) + foo_0(_a) }); return (*b); } diff --git a/tests/unit/out/unsafe/random.rs b/tests/unit/out/unsafe/random.rs index 8739723..05efa2b 100644 --- a/tests/unit/out/unsafe/random.rs +++ b/tests/unit/out/unsafe/random.rs @@ -40,9 +40,9 @@ impl Pair { impl Default for Pair { fn default() -> Self { Pair { - x: ::default(), - y: ::default(), - a: [::default(); 5], + x: 0_i32, + y: 0_i32, + a: [0_i32; 5], r: <*mut i32>::default(), p: Default::default(), pair: Default::default(), diff --git a/tests/unit/out/unsafe/ref_calls.rs b/tests/unit/out/unsafe/ref_calls.rs index 0c24b4a..b32c2b2 100644 --- a/tests/unit/out/unsafe/ref_calls.rs +++ b/tests/unit/out/unsafe/ref_calls.rs @@ -26,7 +26,7 @@ unsafe fn main_0() -> i32 { })); let z: *mut i32 = (unsafe { let _x: *mut i32 = &mut x as *mut i32; - Rc::new(|a0| unsafe { foo_1(a0) })(_x) + foo_1(_x) }); return ((((*(unsafe { let _x: *mut i32 = &mut x as *mut i32; diff --git a/tests/unit/out/unsafe/reinterpret_cast_large_array.rs b/tests/unit/out/unsafe/reinterpret_cast_large_array.rs index 6d85d33..d3e0fd8 100644 --- a/tests/unit/out/unsafe/reinterpret_cast_large_array.rs +++ b/tests/unit/out/unsafe/reinterpret_cast_large_array.rs @@ -14,12 +14,8 @@ pub fn main() { } unsafe fn main_0() -> i32 { let N: i32 = 10000; - let mut arr: *mut u32 = Box::leak( - (0..(N as u64)) - .map(|_| ::default()) - .collect::>(), - ) - .as_mut_ptr(); + let mut arr: *mut u32 = + Box::leak((0..(N as u64)).map(|_| 0_u32).collect::>()).as_mut_ptr(); let mut i: i32 = 0; 'loop_: while ((i) < (N)) { (*arr.offset((i) as isize)) = 0_u32; diff --git a/tests/unit/out/unsafe/reinterpret_cast_new_array.rs b/tests/unit/out/unsafe/reinterpret_cast_new_array.rs index 87840ed..3a71d5b 100644 --- a/tests/unit/out/unsafe/reinterpret_cast_new_array.rs +++ b/tests/unit/out/unsafe/reinterpret_cast_new_array.rs @@ -14,7 +14,7 @@ pub fn main() { } unsafe fn main_0() -> i32 { let mut arr: *mut u32 = - Box::leak((0..2_u64).map(|_| ::default()).collect::>()).as_mut_ptr(); + Box::leak((0..2_u64).map(|_| 0_u32).collect::>()).as_mut_ptr(); (*arr.offset((0) as isize)) = 67305985_u32; (*arr.offset((1) as isize)) = 134678021_u32; let mut bytes: *mut u8 = (arr as *mut u8); diff --git a/tests/unit/out/unsafe/static_local.rs b/tests/unit/out/unsafe/static_local.rs index c6fe939..042a700 100644 --- a/tests/unit/out/unsafe/static_local.rs +++ b/tests/unit/out/unsafe/static_local.rs @@ -8,7 +8,7 @@ use std::io::{Read, Write}; use std::os::fd::{AsFd, FromRawFd, IntoRawFd}; use std::rc::Rc; pub unsafe fn foo_0() -> i32 { - static kX1: i32 = 1;; + static mut kX1: i32 = 1;; static kX2: i32 = 2;; kX1 += 1; return ((kX1) + (kX2)); diff --git a/tests/unit/out/unsafe/stdcopy.rs b/tests/unit/out/unsafe/stdcopy.rs index 4c81383..15c5809 100644 --- a/tests/unit/out/unsafe/stdcopy.rs +++ b/tests/unit/out/unsafe/stdcopy.rs @@ -14,7 +14,7 @@ pub fn main() { } unsafe fn main_0() -> i32 { let mut input: [i32; 3] = [1, 2, 3]; - let mut output: [i32; 3] = [::default(); 3]; + let mut output: [i32; 3] = [0_i32; 3]; { let mut outptr = output.as_mut_ptr().clone(); let mut curr = input.as_mut_ptr().clone(); diff --git a/tests/unit/out/unsafe/swap_extended.rs b/tests/unit/out/unsafe/swap_extended.rs index adc9da1..d1e3a3b 100644 --- a/tests/unit/out/unsafe/swap_extended.rs +++ b/tests/unit/out/unsafe/swap_extended.rs @@ -94,7 +94,7 @@ unsafe fn main_0() -> i32 { (*h), ); ::std::mem::drop(Box::from_raw(h)); - let mut i: *mut i32 = Box::leak(Box::new([7, 8, ::default()])).as_mut_ptr(); + let mut i: *mut i32 = Box::leak(Box::new([7, 8, 0_i32])).as_mut_ptr(); write!( std::fs::File::from_raw_fd( std::io::stdout() diff --git a/tests/unit/out/unsafe/unique_ptr.rs b/tests/unit/out/unsafe/unique_ptr.rs index 1db5139..73a1a4b 100644 --- a/tests/unit/out/unsafe/unique_ptr.rs +++ b/tests/unit/out/unsafe/unique_ptr.rs @@ -72,9 +72,7 @@ pub unsafe fn Consume_1(mut safe_ptr: Option>) -> i32 { pub unsafe fn RndStuff_2() { let mut x1: Option> = None; let mut x2: Option> = Some(Box::from_raw(Box::leak( - (0..100_u64) - .map(|_| ::default()) - .collect::>(), + (0..100_u64).map(|_| 0_i32).collect::>(), ))); let mut i: i32 = 0; 'loop_: while ((i) < (100)) { @@ -82,9 +80,7 @@ pub unsafe fn RndStuff_2() { i.prefix_inc(); } x2 = Some(Box::from_raw(Box::leak( - (0..200_u64) - .map(|_| ::default()) - .collect::>(), + (0..200_u64).map(|_| 0_i32).collect::>(), ))); let mut i: i32 = 0; 'loop_: while ((i) < (200)) { diff --git a/tests/unit/out/unsafe/vector2.rs b/tests/unit/out/unsafe/vector2.rs index a62467e..dd5b4d4 100644 --- a/tests/unit/out/unsafe/vector2.rs +++ b/tests/unit/out/unsafe/vector2.rs @@ -9,7 +9,7 @@ use std::os::fd::{AsFd, FromRawFd, IntoRawFd}; use std::rc::Rc; pub unsafe fn fn_0(v: *mut Vec, mut v3: Vec) { (*v).push(20); - let mut x: i32 = ::default(); + let mut x: i32 = 0_i32; let mut v2: Vec = Vec::new(); let mut v4: *mut Vec = (&mut v3 as *mut Vec); v2.push(0); diff --git a/tests/unit/static_local.cpp b/tests/unit/static_local.cpp index 4378e99..acb9117 100644 --- a/tests/unit/static_local.cpp +++ b/tests/unit/static_local.cpp @@ -1,7 +1,6 @@ // Copyright (c) 2022-present INESC-ID. // Distributed under the MIT license that can be found in the LICENSE file. -// no-compile: unsafe int foo() { static int kX1 = 1; static const int kX2 = 2;