Skip to content

Commit 3151130

Browse files
committed
Merge branch 'master' into remaining-iterator
2 parents 4ca6ef0 + d3f3288 commit 3151130

99 files changed

Lines changed: 894 additions & 1153 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎cpp2rust/converter/converter.cpp‎

Lines changed: 34 additions & 143 deletions
Original file line numberDiff line numberDiff line change
@@ -723,9 +723,8 @@ bool Converter::TypeDerivesDefault(clang::QualType qual_type) {
723723
return false;
724724
}
725725

726-
// Types that need a custom array initializer (e.g., std::array, which is
727-
// translated to Vec)
728-
if (!GetArrayDefaultAsString(qual_type).empty()) {
726+
auto *cxx_record = qual_type->getAsCXXRecordDecl();
727+
if (IsStdDecl(cxx_record, "array") || IsStdDecl(cxx_record, "basic_string")) {
729728
return false;
730729
}
731730

@@ -1373,6 +1372,9 @@ bool Converter::VisitDeclStmt(clang::DeclStmt *stmt) {
13731372
hoisted_records_ += std::move(buf).str();
13741373
continue;
13751374
}
1375+
if (var && IsAliasOfInit(ctx_, var)) {
1376+
continue;
1377+
}
13761378
if (var && var->isImplicit()) {
13771379
VisitVarDecl(var);
13781380
} else {
@@ -1488,112 +1490,25 @@ bool Converter::VisitForStmt(clang::ForStmt *stmt) {
14881490
return false;
14891491
}
14901492

1491-
void Converter::ConvertLoopVariable(clang::VarDecl *decl,
1492-
clang::Expr *range_init) {
1493-
auto loop_var_type = decl->getType();
1494-
auto loop_var_name = GetNamedDeclAsString(decl);
1495-
1496-
if (loop_var_type->isReferenceType()) {
1497-
auto pointee_type = loop_var_type->getPointeeType();
1498-
Convert(range_init);
1499-
if (pointee_type.isConstQualified()) {
1500-
StrCat(std::format(".as_ptr().add({})", loop_var_name));
1501-
} else {
1502-
StrCat(std::format(".as_mut_ptr().add({})", loop_var_name));
1503-
}
1504-
} else {
1505-
{
1506-
PushExplicitAutoref autoref(*this, /*is_mut=*/false);
1507-
Convert(range_init);
1508-
}
1509-
StrCat(std::format("[{}]", loop_var_name));
1510-
StrCat(".clone()");
1511-
}
1512-
}
1513-
1514-
void Converter::ConvertForRangeBody(clang::CXXForRangeStmt *stmt) {
1515-
PushBreakTarget push(break_target_, BreakTarget::Loop);
1516-
curr_for_inc_.emplace_back(nullptr);
1517-
ConvertBodyStmts(stmt->getBody());
1518-
curr_for_inc_.pop_back();
1519-
}
1520-
15211493
bool Converter::VisitCXXForRangeStmt(clang::CXXForRangeStmt *stmt) {
1522-
auto range_init_type = stmt->getRangeInit()->getType();
1523-
1524-
if (!Mapper::Contains(ctx_, range_init_type.getUnqualifiedType())) {
1525-
// FIXME: improve error handling
1526-
log() << "for range stmts only for types in std namespace\n";
1527-
}
1528-
1529-
log() << "GetClassName: " << GetClassName(range_init_type) << '\n';
1530-
1531-
if (GetClassName(range_init_type) == "std::map") {
1532-
return VisitCXXForRangeStmtMap(stmt);
1533-
}
1534-
if (GetClassName(range_init_type) == "std::basic_string") {
1535-
return VisitCXXForRangeStmtString(stmt);
1536-
}
1537-
return VisitCXXForRangeStmtVector(stmt);
1538-
}
1539-
1540-
bool Converter::VisitCXXForRangeStmtMap(clang::CXXForRangeStmt *stmt) {
1541-
auto begin =
1542-
llvm::cast<clang::VarDecl>(stmt->getBeginStmt()->getSingleDecl());
1543-
1494+
PushBreakTarget push(break_target_, BreakTarget::Loop);
1495+
Convert(stmt->getInit());
1496+
Convert(stmt->getRangeStmt());
1497+
auto *begin =
1498+
clang::cast<clang::VarDecl>(stmt->getBeginStmt()->getSingleDecl());
1499+
auto *end = clang::cast<clang::VarDecl>(stmt->getEndStmt()->getSingleDecl());
1500+
begin->setDeclName(stmt->getLoopVariable()->getDeclName());
15441501
StrCat("'loop_:");
1545-
auto map_type = Mapper::Map(*this, stmt->getRangeInit()->getType());
15461502
StrCat(keyword::kFor, GetNamedDeclAsString(begin), keyword::kIn,
1547-
"UnsafeMap::range(&");
1548-
Convert(stmt->getRangeInit());
1549-
StrCat(std::format(" as *const {})", map_type));
1503+
"IterRange::new(", ConvertFreshRValue(begin->getInit()), token::kComma,
1504+
ConvertFreshRValue(end->getInit()), ')');
15501505
{
15511506
PushBrace brace(*this);
1507+
curr_for_inc_.emplace_back(nullptr);
15521508
Convert(stmt->getLoopVarStmt());
1553-
ConvertForRangeBody(stmt);
1554-
}
1555-
1556-
return false;
1557-
}
1558-
1559-
bool Converter::VisitCXXForRangeStmtString(clang::CXXForRangeStmt *stmt) {
1560-
return VisitCXXForRangeStmtIndexBased(stmt, "len()-1");
1561-
}
1562-
1563-
bool Converter::VisitCXXForRangeStmtVector(clang::CXXForRangeStmt *stmt) {
1564-
return VisitCXXForRangeStmtIndexBased(stmt, "len()");
1565-
}
1566-
1567-
bool Converter::VisitCXXForRangeStmtIndexBased(clang::CXXForRangeStmt *stmt,
1568-
const char *len_suffix) {
1569-
auto *loop_var = stmt->getLoopVariable();
1570-
auto loop_var_name = GetNamedDeclAsString(loop_var);
1571-
1572-
StrCat("'loop_:");
1573-
StrCat(keyword::kFor, loop_var_name, keyword::kIn, "0..");
1574-
{
1575-
PushParen range(*this);
1576-
Convert(stmt->getRangeInit());
1577-
StrCat(token::kDot, len_suffix);
1578-
}
1579-
{
1580-
PushBrace body(*this);
1581-
StrCat(keyword::kLet);
1582-
1583-
auto loop_var_type = loop_var->getType();
1584-
if (!loop_var_type.isConstQualified()) {
1585-
StrCat(keyword_mut_);
1586-
}
1587-
1588-
StrCat(loop_var_name);
1589-
StrCat(token::kAssign);
1590-
1591-
ConvertLoopVariable(loop_var, stmt->getRangeInit());
1592-
1593-
StrCat(token::kSemiColon);
1594-
ConvertForRangeBody(stmt);
1509+
ConvertBodyStmts(stmt->getBody());
1510+
curr_for_inc_.pop_back();
15951511
}
1596-
15971512
return false;
15981513
}
15991514

@@ -3269,6 +3184,11 @@ bool Converter::VisitDeclRefExpr(clang::DeclRefExpr *expr) {
32693184
Convert(init);
32703185
return false;
32713186
}
3187+
if (auto var = clang::dyn_cast<clang::VarDecl>(expr->getDecl());
3188+
var && IsAliasOfInit(ctx_, var)) {
3189+
Convert(var->getInit());
3190+
return false;
3191+
}
32723192
ConvertDeclRefValue(expr, expr->getDecl());
32733193
return false;
32743194
}
@@ -3613,22 +3533,20 @@ bool Converter::VisitInitListExpr(clang::InitListExpr *expr) {
36133533
}
36143534
} else if (qual_type->isRecordType()) {
36153535
const auto *record = qual_type->getAsRecordDecl();
3616-
if (record->getQualifiedNameAsString() == "std::array") {
3617-
if (auto init = clang::dyn_cast<clang::InitListExpr>(expr->getInit(0))) {
3618-
StrCat("vec!");
3619-
VisitInitListExpr(init);
3620-
} else {
3621-
StrCat(GetArrayDefaultAsString(qual_type));
3622-
}
3536+
if (syntactic->getNumInits() == 0) {
3537+
StrCat(GetDefaultAsString(qual_type));
36233538
SetFreshType(qual_type);
36243539
return false;
36253540
}
36263541

3627-
if (syntactic->getNumInits() == 0) {
3628-
StrCat(GetDefaultAsString(qual_type));
3542+
if (auto str =
3543+
GetMappedAsString(expr, expr->getInits(), expr->getNumInits());
3544+
!str.empty()) {
3545+
StrCat(str);
36293546
SetFreshType(qual_type);
36303547
return false;
36313548
}
3549+
assert(IsUserDefinedDecl(record) && "aggregate list without a rule");
36323550

36333551
StrCat(GetUnsafeTypeAsString(qual_type));
36343552
PushBrace brace(*this);
@@ -4258,11 +4176,11 @@ bool Converter::VisitClassTemplateDecl(clang::ClassTemplateDecl *decl) {
42584176

42594177
bool Converter::VisitCXXStdInitializerListExpr(
42604178
clang::CXXStdInitializerListExpr *expr) {
4261-
if (expr->getSubExpr()->getType()->isArrayType()) {
4262-
// Arrays become Vec's
4263-
StrCat("vec!");
4264-
}
4265-
Convert(expr->getSubExpr());
4179+
auto *backing = expr->getSubExpr();
4180+
auto str = GetMappedAsString(expr, &backing, 1);
4181+
ENSURE(!str.empty());
4182+
StrCat(str);
4183+
SetFreshType(expr->getType());
42664184
return false;
42674185
}
42684186

@@ -4283,33 +4201,6 @@ std::string Converter::GetArrayDefaultAsString(clang::QualType qual_type) {
42834201
if (clang::isa<clang::IncompleteArrayType>(qual_type)) {
42844202
return "[]";
42854203
}
4286-
if (IsStdDecl(qual_type->getAsCXXRecordDecl(), "array")) {
4287-
assert(GetTemplateArgs(qual_type).has_value());
4288-
auto template_args = *GetTemplateArgs(qual_type);
4289-
assert(template_args.size() == 2);
4290-
auto array_size = template_args[1];
4291-
unsigned size = 0;
4292-
switch (array_size.getKind()) {
4293-
case clang::TemplateArgument::Expression: {
4294-
auto array_size_expr = array_size.getAsExpr();
4295-
assert(array_size_expr && !array_size_expr->isValueDependent());
4296-
clang::Expr::EvalResult result;
4297-
ENSURE(array_size_expr->EvaluateAsInt(result, ctx_));
4298-
size = result.Val.getInt().getZExtValue();
4299-
break;
4300-
}
4301-
case clang::TemplateArgument::Integral: {
4302-
size = array_size.getAsIntegral().getZExtValue();
4303-
break;
4304-
}
4305-
default:
4306-
assert(0 && "Unsupported array size kind");
4307-
break;
4308-
}
4309-
return std::format(
4310-
"std::array::from_fn::<_, {}, _>(|_| Default::default()).to_vec()",
4311-
size);
4312-
}
43134204
return {};
43144205
}
43154206

‎cpp2rust/converter/converter.h‎

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -223,17 +223,6 @@ class Converter : public clang::RecursiveASTVisitor<Converter> {
223223

224224
virtual bool VisitCXXForRangeStmt(clang::CXXForRangeStmt *stmt);
225225

226-
virtual bool VisitCXXForRangeStmtMap(clang::CXXForRangeStmt *stmt);
227-
228-
virtual bool VisitCXXForRangeStmtVector(clang::CXXForRangeStmt *stmt);
229-
230-
virtual bool VisitCXXForRangeStmtString(clang::CXXForRangeStmt *stmt);
231-
232-
bool VisitCXXForRangeStmtIndexBased(clang::CXXForRangeStmt *stmt,
233-
const char *len_suffix);
234-
235-
void ConvertForRangeBody(clang::CXXForRangeStmt *stmt);
236-
237226
virtual bool VisitBreakStmt(clang::BreakStmt *stmt);
238227

239228
virtual bool VisitContinueStmt(clang::ContinueStmt *stmt);
@@ -750,9 +739,6 @@ class Converter : public clang::RecursiveASTVisitor<Converter> {
750739
virtual void ConvertCast(clang::QualType qual_type,
751740
int line = __builtin_LINE());
752741

753-
virtual void ConvertLoopVariable(clang::VarDecl *decl,
754-
clang::Expr *range_init);
755-
756742
virtual bool ConvertCXXOperatorCallExpr(clang::CXXOperatorCallExpr *expr);
757743

758744
std::string GetMappedAsString(clang::Expr *expr, clang::Expr **args = nullptr,

‎cpp2rust/converter/converter_lib.cpp‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1920,10 +1920,10 @@ std::optional<clang::QualType> GetParamImplicitConvertTarget(clang::Expr *expr,
19201920
return fn->getParamDecl(param_idx)->getType().getNonReferenceType();
19211921
}
19221922

1923-
std::string GetClassName(clang::QualType type) {
1924-
if (auto *record = type->getAsCXXRecordDecl())
1925-
return record->getQualifiedNameAsString();
1926-
return {};
1923+
bool IsAliasOfInit(clang::ASTContext &ctx, const clang::VarDecl *var) {
1924+
auto *init = var->getInit();
1925+
return var->isImplicit() && var->getType()->isReferenceType() && init &&
1926+
init->isGLValue() && !init->HasSideEffects(ctx);
19271927
}
19281928

19291929
bool IsVaListType(clang::QualType type) {

‎cpp2rust/converter/converter_lib.h‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -321,10 +321,10 @@ clang::Expr *BuildInitExpr(clang::Sema &sema, clang::QualType type,
321321
llvm::ArrayRef<clang::Expr *> args,
322322
clang::SourceLocation loc);
323323

324-
std::string GetClassName(clang::QualType type);
325-
326324
bool IsVaListType(clang::QualType type);
327325

326+
bool IsAliasOfInit(clang::ASTContext &ctx, const clang::VarDecl *var);
327+
328328
bool NeedsImplicitScalarCast(clang::ASTContext &ctx, clang::QualType from,
329329
clang::QualType to);
330330

‎cpp2rust/converter/models/boxed_vars.cpp‎

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,17 @@ class AddressTakenVisitor
9595
: public clang::RecursiveASTVisitor<AddressTakenVisitor> {
9696
public:
9797
AddressTakenVisitor(clang::ASTContext &ctx,
98-
std::unordered_set<const clang::VarDecl *> &vars)
99-
: ctx_(ctx), address_taken_(vars) {}
98+
std::unordered_set<const clang::VarDecl *> &vars,
99+
std::unordered_set<const clang::VarDecl *> &iterators)
100+
: ctx_(ctx), address_taken_(vars), range_iterators_(iterators) {}
101+
102+
bool VisitCXXForRangeStmt(clang::CXXForRangeStmt *stmt) {
103+
if (auto *begin = stmt->getBeginStmt()) {
104+
range_iterators_.insert(
105+
clang::cast<clang::VarDecl>(begin->getSingleDecl()));
106+
}
107+
return true;
108+
}
100109

101110
bool shouldVisitTemplateInstantiations() const { return true; }
102111

@@ -249,18 +258,20 @@ class AddressTakenVisitor
249258

250259
clang::ASTContext &ctx_;
251260
std::unordered_set<const clang::VarDecl *> &address_taken_;
261+
std::unordered_set<const clang::VarDecl *> &range_iterators_;
252262
// The references to variables that only access their value.
253263
std::unordered_set<const clang::DeclRefExpr *> value_uses_;
254264
};
255265
} // namespace
256266

257267
BoxedVars::BoxedVars(clang::ASTContext &ctx) : ctx_(ctx) {
258-
AddressTakenVisitor(ctx, address_taken_)
268+
AddressTakenVisitor(ctx, address_taken_, range_iterators_)
259269
.TraverseDecl(ctx.getTranslationUnitDecl());
260270
}
261271

262272
bool BoxedVars::contains(const clang::VarDecl *decl) const {
263-
return !CanUnbox(ctx_, decl) || address_taken_.contains(decl);
273+
return !range_iterators_.contains(decl) &&
274+
(!CanUnbox(ctx_, decl) || address_taken_.contains(decl));
264275
}
265276

266277
namespace {

‎cpp2rust/converter/models/boxed_vars.h‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ class BoxedVars {
2828
private:
2929
clang::ASTContext &ctx_;
3030
std::unordered_set<const clang::VarDecl *> address_taken_;
31+
std::unordered_set<const clang::VarDecl *> range_iterators_;
3132
};
3233

3334
// The reads of the value of variables in a returned expression that are the

0 commit comments

Comments
 (0)