Skip to content

Commit f6b377f

Browse files
committed
Track current break target using a stack
1 parent 2340d75 commit f6b377f

2 files changed

Lines changed: 27 additions & 4 deletions

File tree

cpp2rust/converter/converter.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -990,6 +990,7 @@ bool Converter::VisitIfStmt(clang::IfStmt *stmt) {
990990
}
991991

992992
bool Converter::VisitWhileStmt(clang::WhileStmt *stmt) {
993+
PushBreakTarget push(break_target_, BreakTarget::Loop);
993994
StrCat("'loop_:");
994995
StrCat(keyword::kWhile);
995996
ConvertCondition(stmt->getCond());
@@ -1002,6 +1003,7 @@ bool Converter::VisitWhileStmt(clang::WhileStmt *stmt) {
10021003
}
10031004

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

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

10561059
void Converter::ConvertForRangeBody(clang::CXXForRangeStmt *stmt,
10571060
const clang::VarDecl *map_iter_decl) {
1061+
PushBreakTarget push(break_target_, BreakTarget::Loop);
10581062
std::optional<ScopedMapIterDecl> skip;
10591063
if (map_iter_decl)
10601064
skip.emplace(*this, map_iter_decl);
@@ -1137,7 +1141,7 @@ bool Converter::VisitCXXForRangeStmtIndexBased(clang::CXXForRangeStmt *stmt,
11371141

11381142
bool Converter::VisitBreakStmt([[maybe_unused]] clang::BreakStmt *stmt) {
11391143
StrCat(keyword::kBreak);
1140-
if (break_with_explicit_label_) {
1144+
if (isSwitchBreak()) {
11411145
StrCat("'switch");
11421146
}
11431147
return false;
@@ -2644,6 +2648,7 @@ bool Converter::VisitSwitchCase(clang::SwitchCase *stmt) {
26442648
}
26452649

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

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

26812684
StrCat("}");
26822685
StrCat("}");

cpp2rust/converter/converter.h

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -463,10 +463,30 @@ class Converter : public clang::RecursiveASTVisitor<Converter> {
463463
clang::ASTContext &ctx_;
464464
clang::FunctionDecl *curr_function_ = nullptr;
465465
bool in_function_formals_ = false;
466-
bool break_with_explicit_label_ = false;
467466
std::stack<clang::Expr *> curr_for_inc_;
468467
std::stack<clang::QualType> curr_init_type_;
469468

469+
enum class BreakTarget { Loop, Switch };
470+
std::stack<BreakTarget> break_target_;
471+
472+
bool isSwitchBreak() const {
473+
return !break_target_.empty() && break_target_.top() == BreakTarget::Switch;
474+
}
475+
476+
class PushBreakTarget {
477+
public:
478+
PushBreakTarget(std::stack<BreakTarget> &stack, BreakTarget target)
479+
: stack_(stack) {
480+
stack_.push(target);
481+
}
482+
~PushBreakTarget() { stack_.pop(); }
483+
PushBreakTarget(const PushBreakTarget &) = delete;
484+
PushBreakTarget &operator=(const PushBreakTarget &) = delete;
485+
486+
private:
487+
std::stack<BreakTarget> &stack_;
488+
};
489+
470490
std::unordered_set<const clang::VarDecl *> map_iter_decls_;
471491

472492
struct ScopedMapIterDecl {

0 commit comments

Comments
 (0)