Skip to content
4 changes: 2 additions & 2 deletions cpp2rust/converter/converter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2434,8 +2434,8 @@ void Converter::ConvertIntegralToBooleanCast(clang::ImplicitCastExpr *expr) {
bool Converter::IsCastRedundantInRust(clang::Expr *expr,
clang::QualType target_type) {
auto target = GetUnsafeTypeAsString(target_type);
if (const auto *rule = RuleRegistry::GetExprRule(ctx_, expr)) {
return rule->return_type.type == target;
if (RuleRegistry::GetExprRule(ctx_, expr)) {
return Trim(Mapper::GetReturnType(*this, expr)) == target;
}
return GetUnsafeTypeAsString(expr->getType()) == target;
}
Expand Down
37 changes: 34 additions & 3 deletions cpp2rust/converter/rules/expr_matcher.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,28 @@ MatchResult matchFunction(clang::Sema &sema, const clang::Expr *use,
return llvm::ArrayRef<clang::TemplateArgument>();
}

bool constructsReturnType(const clang::Expr *returned, clang::QualType ret,
const ResolvedDecl &usage_decl) {
auto list =
llvm::dyn_cast<clang::InitListExpr>(RuleDecls::SkipImplicit(returned));
if (!list || list->getType()->isRecordType()) {
return false;
}
auto record = ret->getAsCXXRecordDecl();
if (!record) {
return false;
}
if (auto decl = std::get_if<const clang::Decl *>(&usage_decl)) {
auto ctor = llvm::dyn_cast<clang::CXXConstructorDecl>(*decl);
return ctor &&
ctor->getParent()->getCanonicalDecl() == record->getCanonicalDecl();
}
if (auto aggregate = std::get_if<AggregateUsage>(&usage_decl)) {
return RuleKeys::GetTypeKey(ret) == aggregate->type;
}
return false;
}

MatchResult matchTemplate(clang::Sema &sema, const clang::Expr *use,
const ResolvedDecl &usage_decl,
clang::FunctionTemplateDecl *rule) {
Expand All @@ -355,16 +377,25 @@ MatchResult matchTemplate(clang::Sema &sema, const clang::Expr *use,
}
if (std::holds_alternative<AggregateUsage>(usage_decl)) {
auto returned = RuleDecls::GetReturned(rule->getTemplatedDecl());
if (getResolvedDecl(ctx, returned, /*must_resolve=*/false) != usage_decl) {
if (getResolvedDecl(ctx, returned, /*must_resolve=*/false) != usage_decl &&
!constructsReturnType(returned, specialization->getReturnType(),
usage_decl)) {
return std::nullopt;
}
checkCallable(sema, use, rule->getTemplatedDecl());
return specialization->getTemplateSpecializationArgs()->asArray();
}
auto returned =
substituteSpecializationInRuleTmpl(sema, rule, specialization);
if (!returned ||
getResolvedDecl(ctx, returned, /*must_resolve=*/true) != usage_decl) {
if (!returned) {
return std::nullopt;
}
if (constructsReturnType(returned, specialization->getReturnType(),
usage_decl)) {
checkCallable(sema, use, rule->getTemplatedDecl());
return specialization->getTemplateSpecializationArgs()->asArray();
}
if (getResolvedDecl(ctx, returned, /*must_resolve=*/true) != usage_decl) {
return std::nullopt;
}
checkCallable(sema, use, rule->getTemplatedDecl());
Expand Down
5 changes: 4 additions & 1 deletion cpp2rust/converter/rules/registry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -410,7 +410,10 @@ Matcher::Match<TranslationRule::TypeRule> Search(clang::ASTContext &ctx,
}
auto bindings = getBindings(match.rule_decl->decl, match.match.args);
if (auto generic = match.rule_decl->rule.generic) {
return Search(ctx, bindings.at(generic - 1).getAsType());
if (auto bound = Search(ctx, bindings.at(generic - 1).getAsType());
bound.first) {
return bound;
}
}
return {&match.rule_decl->rule, std::move(bindings)};
}
Expand Down
15 changes: 13 additions & 2 deletions cpp2rust/converter/rules/rule_keys.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ const clang::Decl *getParent(clang::QualType type) {
spec->getTemplateName().getAsTemplateDecl())) {
return tmpl->getCanonicalDecl();
}
return nullptr;
}
auto record = type->getAsCXXRecordDecl();
if (!record) {
Expand Down Expand Up @@ -137,6 +136,10 @@ std::optional<ExprKey> GetExprKey(clang::ASTContext &ctx,
rewritten->getOperator()));
}
if (auto cast = llvm::dyn_cast<clang::ExplicitCastExpr>(expr)) {
if (auto key = getConstructorKey(getParent(cast->getSubExpr()->getType()));
key && cast->isTypeDependent()) {
return key;
}
return GetExprKey(ctx, cast->getSubExpr());
}
if (auto construct = llvm::dyn_cast<clang::CXXConstructExpr>(expr)) {
Expand All @@ -147,6 +150,9 @@ std::optional<ExprKey> GetExprKey(clang::ASTContext &ctx,
return getConstructorKey(getParent(construct->getTypeAsWritten()));
}
if (auto call = llvm::dyn_cast<clang::CallExpr>(expr)) {
if (llvm::isa<clang::CXXMemberCallExpr>(call)) {
return GetExprKey(ctx, call->getCallee());
}
if (auto callee = call->getDirectCallee()) {
return GetDeclKey(callee);
}
Expand All @@ -172,7 +178,9 @@ std::optional<ExprKey> GetExprKey(clang::ASTContext &ctx,
sm, ctx.getLangOpts());
return Unqualified{clang::DeclarationName(&ctx.Idents.get(macro))};
}
return GetDeclKey(member->getMemberDecl());
return getMemberKey(
getParent(member->getBase()->IgnoreImpCasts()->getType()),
member->getMemberDecl()->getDeclName());
}
if (auto ref = llvm::dyn_cast<clang::DeclRefExpr>(expr)) {
return GetDeclKey(ref->getDecl());
Expand Down Expand Up @@ -226,6 +234,9 @@ std::vector<ExprKey> GetExprKeys(clang::ASTContext &ctx,
return keys;
}
auto key = GetExprKey(ctx, returned);
if (!key && llvm::isa<clang::InitListExpr>(returned)) {
key = getConstructorKey(getParent(rule->getAsFunction()->getReturnType()));
}
assert(key && "expression rule has no key");
return {*key};
}
Expand Down
5 changes: 5 additions & 0 deletions cpp2rust/rule_preprocessing/cpp_rule_indexer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,11 @@ void IndexRuleFile(clang::ASTContext &ctx, const std::string &dir_name,
if (key.empty()) {
key = ClassOfParameters(decl);
}
if (auto returned = RuleExpr(decl);
key.empty() && returned &&
llvm::isa<clang::InitListExpr>(returned->IgnoreImplicit())) {
key = ClassOf(decl->getAsFunction()->getReturnType());
}
bool any_class = key.empty() && llvm::isa<clang::TemplateDecl>(decl);
if (any_class) {
key = RulesLoader::kAnyClassKey;
Expand Down
12 changes: 12 additions & 0 deletions rules/atomic/src.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// Copyright (c) 2022-present INESC-ID.
// Distributed under the MIT license that can be found in the LICENSE file.

#include <atomic>

template <typename T1> using t1 = std::atomic<T1>;

template <typename T1> std::atomic<T1> f1() { return {}; }

template <typename T1> T1 f2(const std::atomic<T1> &a0) {
return static_cast<T1>(a0);
}
16 changes: 16 additions & 0 deletions rules/atomic/tgt_unsafe.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// Copyright (c) 2022-present INESC-ID.
// Distributed under the MIT license that can be found in the LICENSE file.

// TODO: use proper atomic translation

fn t1<T1: Default>() -> T1 {
T1::default()
}

unsafe fn f1<T1: Default>() -> T1 {
T1::default()
}

unsafe fn f2<T1>(a0: T1) -> T1 {
a0
}
13 changes: 13 additions & 0 deletions tests/unit/atomic.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#include <atomic>
#include <cassert>

struct Counter {
int n;
};

int main() {
std::atomic<Counter> a{};
Counter v = a;
assert(v.n == 0);
return 0;
}
25 changes: 25 additions & 0 deletions tests/unit/out/refcount/atomic.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
extern crate libcc2rs;
use libcc2rs::*;
use std::cell::RefCell;
use std::collections::BTreeMap;
use std::io::prelude::*;
use std::io::{Read, Seek, Write};
use std::os::fd::AsFd;
use std::rc::{Rc, Weak};
#[derive(Clone, Record, ByteRepr, VaArg, FnPtrArg, Default)]
#[byte_size(4)]
pub struct Counter {
#[offset(0)]
pub n: i32,
}
pub fn main() {
__cpp2rust_init_globals();
std::process::exit(main_0());
}
fn main_0() -> i32 {
let a: Value<Counter> = Rc::new(RefCell::new(Counter::default()));
let mut v: Counter = (*a.borrow()).clone();
assert!((v.n == 0));
return 0;
}
pub fn __cpp2rust_init_globals() {}
26 changes: 26 additions & 0 deletions tests/unit/out/unsafe/atomic.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
extern crate libc;
use libc::*;
extern crate libcc2rs;
use libcc2rs::*;
use std::collections::BTreeMap;
use std::io::{Read, Seek, Write};
use std::os::fd::{AsFd, FromRawFd, IntoRawFd};
use std::rc::Rc;
#[repr(C)]
#[derive(Copy, Clone, VaArg, FnPtrArg, Default)]
pub struct Counter {
pub n: i32,
}
pub fn main() {
unsafe {
__cpp2rust_init_globals();
std::process::exit(main_0() as i32);
}
}
unsafe fn main_0() -> i32 {
let mut a: Counter = Counter::default();
let mut v: Counter = a;
assert!(((v.n) == (0)));
return 0;
}
pub unsafe fn __cpp2rust_init_globals() {}
Loading