Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions cpp2rust/converter/converter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -990,6 +990,7 @@ bool Converter::VisitIfStmt(clang::IfStmt *stmt) {
}

bool Converter::VisitWhileStmt(clang::WhileStmt *stmt) {
PushBreakTarget push(break_target_, BreakTarget::Loop);
StrCat("'loop_:");
StrCat(keyword::kWhile);
ConvertCondition(stmt->getCond());
Expand All @@ -1002,6 +1003,7 @@ bool Converter::VisitWhileStmt(clang::WhileStmt *stmt) {
}

bool Converter::VisitDoStmt(clang::DoStmt *stmt) {
PushBreakTarget push(break_target_, BreakTarget::Loop);
StrCat("'loop_:");
StrCat(keyword::kLoop, token::kOpenCurlyBracket);
curr_for_inc_.emplace(nullptr);
Expand All @@ -1016,6 +1018,7 @@ bool Converter::VisitDoStmt(clang::DoStmt *stmt) {
}

bool Converter::VisitForStmt(clang::ForStmt *stmt) {
PushBreakTarget push(break_target_, BreakTarget::Loop);
Convert(stmt->getInit());
StrCat("'loop_:");
StrCat(keyword::kWhile);
Expand Down Expand Up @@ -1055,6 +1058,7 @@ void Converter::ConvertLoopVariable(clang::VarDecl *decl,

void Converter::ConvertForRangeBody(clang::CXXForRangeStmt *stmt,
const clang::VarDecl *map_iter_decl) {
PushBreakTarget push(break_target_, BreakTarget::Loop);
std::optional<ScopedMapIterDecl> skip;
if (map_iter_decl)
skip.emplace(*this, map_iter_decl);
Expand Down Expand Up @@ -1137,7 +1141,7 @@ bool Converter::VisitCXXForRangeStmtIndexBased(clang::CXXForRangeStmt *stmt,

bool Converter::VisitBreakStmt([[maybe_unused]] clang::BreakStmt *stmt) {
StrCat(keyword::kBreak);
if (break_with_explicit_label_) {
if (isSwitchBreak()) {
StrCat("'switch");
}
return false;
Expand Down Expand Up @@ -2644,6 +2648,7 @@ bool Converter::VisitSwitchCase(clang::SwitchCase *stmt) {
}

bool Converter::VisitSwitchStmt(clang::SwitchStmt *stmt) {
PushBreakTarget push(break_target_, BreakTarget::Switch);
StrCat("'switch: {");
StrCat(std::format("let __match_cond = {};", ToString(stmt->getCond())));
StrCat("match __match_cond");
Expand All @@ -2653,7 +2658,6 @@ bool Converter::VisitSwitchStmt(clang::SwitchStmt *stmt) {
auto body = llvm::cast<clang::CompoundStmt>(stmt->getBody());
assert(body);

break_with_explicit_label_ = true;
for (auto it = body->body_begin(), end = body->body_end(); it != end;) {
if (auto switch_case = clang::dyn_cast<clang::SwitchCase>(*it)) {
if (clang::isa<clang::CaseStmt>(switch_case)) {
Expand All @@ -2676,7 +2680,6 @@ bool Converter::VisitSwitchStmt(clang::SwitchStmt *stmt) {
if (!has_default_case) {
StrCat(R"( _ => {})");
}
break_with_explicit_label_ = false;

StrCat("}");
StrCat("}");
Expand Down
22 changes: 21 additions & 1 deletion cpp2rust/converter/converter.h
Original file line number Diff line number Diff line change
Expand Up @@ -463,10 +463,30 @@ class Converter : public clang::RecursiveASTVisitor<Converter> {
clang::ASTContext &ctx_;
clang::FunctionDecl *curr_function_ = nullptr;
bool in_function_formals_ = false;
bool break_with_explicit_label_ = false;
std::stack<clang::Expr *> curr_for_inc_;
std::stack<clang::QualType> curr_init_type_;

enum class BreakTarget { Loop, Switch };
std::stack<BreakTarget> break_target_;

bool isSwitchBreak() const {
return !break_target_.empty() && break_target_.top() == BreakTarget::Switch;
}

class PushBreakTarget {
public:
PushBreakTarget(std::stack<BreakTarget> &stack, BreakTarget target)
: stack_(stack) {
stack_.push(target);
}
~PushBreakTarget() { stack_.pop(); }
PushBreakTarget(const PushBreakTarget &) = delete;
PushBreakTarget &operator=(const PushBreakTarget &) = delete;

private:
std::stack<BreakTarget> &stack_;
};

std::unordered_set<const clang::VarDecl *> map_iter_decls_;

struct ScopedMapIterDecl {
Expand Down
3 changes: 3 additions & 0 deletions tests/lit/lit/formats/Cpp2RustTest.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,9 @@ def fail(str, code = fail_code):
return lit.Test.XFAIL, ''
return fail('cpp2rust failed\n' + err)

if should_not_translate:
return fail('expected translation-fail but cpp2rust succeeded')

expected_file = self.getExpectedFile(filepath, model, fname)
if not os.path.exists(expected_file) and not replace_expected:
return fail('no expected file')
Expand Down
2 changes: 1 addition & 1 deletion tests/unit/out/refcount/switch_for_in_switch_break.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ pub fn for_in_switch_break_0(n: i32) -> i32 {
let i: Value<i32> = Rc::new(RefCell::new(0));
'loop_: while ((*i.borrow()) < 10) {
if ((*i.borrow()) == 3) {
break 'switch;
break;
}
(*r.borrow_mut()) += (*i.borrow());
(*i.borrow_mut()).prefix_inc();
Expand Down
2 changes: 1 addition & 1 deletion tests/unit/out/refcount/switch_for_switch_for_break.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ pub fn for_switch_for_break_0(n: i32) -> i32 {
let j: Value<i32> = Rc::new(RefCell::new(0));
'loop_: while ((*j.borrow()) < 10) {
if ((*j.borrow()) == 2) {
break 'switch;
break;
}
(*r.borrow_mut()) += 1;
(*j.borrow_mut()).prefix_inc();
Expand Down
6 changes: 3 additions & 3 deletions tests/unit/out/refcount/switch_nested.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,15 +32,15 @@ pub fn nested_0(a: i32, b: i32) -> i32 {
}
};
(*r.borrow_mut()) += 1;
break;
break 'switch;
}
v if v == 2 => {
(*r.borrow_mut()) = 2;
break;
break 'switch;
}
_ => {
(*r.borrow_mut()) = -1_i32;
break;
break 'switch;
}
}
};
Expand Down
2 changes: 1 addition & 1 deletion tests/unit/out/refcount/switch_while_in_switch_break.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ pub fn while_in_switch_break_0(n: i32) -> i32 {
let i: Value<i32> = Rc::new(RefCell::new(0));
'loop_: while ((*i.borrow()) < 10) {
if ((*i.borrow()) == 4) {
break 'switch;
break;
}
(*r.borrow_mut()) += (*i.borrow());
(*i.borrow_mut()).prefix_inc();
Expand Down
2 changes: 1 addition & 1 deletion tests/unit/out/unsafe/switch_for_in_switch_break.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ pub unsafe fn for_in_switch_break_0(mut n: i32) -> i32 {
let mut i: i32 = 0;
'loop_: while ((i) < (10)) {
if ((i) == (3)) {
break 'switch;
break;
}
r += i;
i.prefix_inc();
Expand Down
2 changes: 1 addition & 1 deletion tests/unit/out/unsafe/switch_for_switch_for_break.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ pub unsafe fn for_switch_for_break_0(mut n: i32) -> i32 {
let mut j: i32 = 0;
'loop_: while ((j) < (10)) {
if ((j) == (2)) {
break 'switch;
break;
}
r += 1;
j.prefix_inc();
Expand Down
6 changes: 3 additions & 3 deletions tests/unit/out/unsafe/switch_nested.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,15 @@ pub unsafe fn nested_0(mut a: i32, mut b: i32) -> i32 {
}
};
r += 1;
break;
break 'switch;
}
v if v == 2 => {
r = 2;
break;
break 'switch;
}
_ => {
r = -1_i32;
break;
break 'switch;
}
}
};
Expand Down
2 changes: 1 addition & 1 deletion tests/unit/out/unsafe/switch_while_in_switch_break.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ pub unsafe fn while_in_switch_break_0(mut n: i32) -> i32 {
let mut i: i32 = 0;
'loop_: while ((i) < (10)) {
if ((i) == (4)) {
break 'switch;
break;
}
r += i;
i.prefix_inc();
Expand Down
1 change: 0 additions & 1 deletion tests/unit/switch_for_in_switch_break.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
// panic
#include <cassert>

int for_in_switch_break(int n) {
Expand Down
1 change: 0 additions & 1 deletion tests/unit/switch_for_switch_for_break.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
// panic
#include <cassert>

int for_switch_for_break(int n) {
Expand Down
1 change: 0 additions & 1 deletion tests/unit/switch_nested.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
// no-compile
#include <cassert>

int nested(int a, int b) {
Expand Down
1 change: 0 additions & 1 deletion tests/unit/switch_while_in_switch_break.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
// panic
#include <cassert>

int while_in_switch_break(int n) {
Expand Down
Loading