Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
65123bc
Delete iterator rules
lucic71 Oct 16, 2026
bba5320
Add rules for iterator category
lucic71 Oct 16, 2026
8d7aadd
Use T1, T2, etc
lucic71 Oct 16, 2026
e2ea802
Add shim and rules for iterator category
lucic71 Oct 16, 2026
f00823d
Use random accsess iterator for vector
lucic71 Oct 16, 2026
eaeb89f
Implement iterator category for raw pointers
lucic71 Oct 16, 2026
56f386e
Update tests
lucic71 Oct 16, 2026
0345a42
Switch algorithm rules to iterators
lucic71 Oct 16, 2026
79a508f
Add shims in project
lucic71 Oct 16, 2026
1b8552c
Update tests
lucic71 Oct 16, 2026
631cf7a
Assert that all src generics are used in the tgt
lucic71 Oct 16, 2026
4c45ece
Delete EnableIf handler
lucic71 Oct 16, 2026
2691d1b
Fix iterator category rules
lucic71 Oct 16, 2026
56c9cb9
Update tests
lucic71 Oct 16, 2026
78b99b8
Add rule for ptrdiff
lucic71 Oct 16, 2026
fcc2bae
Update tests
lucic71 Oct 16, 2026
adda4ea
Add conversion between const/non-const iterators
lucic71 Oct 16, 2026
37d82a3
Don't key dependend and user defined decls
lucic71 Oct 16, 2026
ff7603d
Fix conversion between iterators
lucic71 Oct 16, 2026
88cd675
Change translation for std::map
lucic71 Oct 16, 2026
d6d13b2
Update tests
lucic71 Oct 16, 2026
a388145
Update tests
lucic71 Oct 16, 2026
a3d015b
format
lucic71 Oct 16, 2026
f985c98
Drop get strongest iterator category
lucic71 Oct 16, 2026
0d55e4c
Add rvalue ref overloads
lucic71 Oct 16, 2026
770f07e
Remove PushSuppressIteratorClone
lucic71 Oct 16, 2026
099c97b
Update tests
lucic71 Oct 16, 2026
0aa5c08
Use unordered_set
lucic71 Oct 16, 2026
4dd4bb1
Stop spelling translated names in the code
lucic71 Oct 16, 2026
837078f
Add back fill and unique
lucic71 Oct 16, 2026
31bf58f
Fix std::fill
lucic71 Oct 16, 2026
18fd12f
Add rules for overloaded map::erase
lucic71 Oct 16, 2026
342ab3b
Drop declares object from index
lucic71 Oct 16, 2026
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
3 changes: 3 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,9 @@ file(GLOB_RECURSE rule_preprocessor_sources
file(GLOB_RECURSE libcc2rs_sources CONFIGURE_DEPENDS
${PROJECT_SOURCE_DIR}/libcc2rs/src/*.rs
${PROJECT_SOURCE_DIR}/libcc2rs-macros/src/*.rs)
file(GLOB rule_shim_sources CONFIGURE_DEPENDS
${PROJECT_SOURCE_DIR}/rules/*/shim.rs)
list(APPEND libcc2rs_sources ${rule_shim_sources})
list(APPEND libcc2rs_sources
${PROJECT_SOURCE_DIR}/libcc2rs/Cargo.toml
${PROJECT_SOURCE_DIR}/libcc2rs-macros/Cargo.toml)
Expand Down
34 changes: 2 additions & 32 deletions cpp2rust/converter/converter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -793,21 +793,6 @@ bool Converter::RecordHasCopyableFields(const clang::RecordDecl *decl) {
return false;
}
for (auto f : decl->fields()) {
// Records that contain std::vector, std::array, std::string or anything
// that is translated to Vec<>, do not derive Copy
auto mapped = Mapper::Map(*this, f->getType());
if (mapped.starts_with("Vec<")) {
return false;
}

if (IsUniquePtr(f->getType())) {
return false;
}

if (mapped.starts_with("BTreeMap<")) {
return false;
}

if (auto ptr_ty = f->getType()->getAs<clang::PointerType>()) {
if (ptr_ty->getPointeeType()->isFunctionType()) {
if (!FunctionPointerImplementsCopy()) {
Expand Down Expand Up @@ -1575,7 +1560,7 @@ bool Converter::VisitCXXForRangeStmtMap(clang::CXXForRangeStmt *stmt) {
StrCat("'loop_:");
auto map_type = Mapper::Map(*this, stmt->getRangeInit()->getType());
StrCat(keyword::kFor, GetNamedDeclAsString(begin), keyword::kIn,
"UnsafeMapIterator::begin(&");
"UnsafeMap::range(&");
Convert(stmt->getRangeInit());
StrCat(std::format(" as *const {})", map_type));
{
Expand Down Expand Up @@ -3362,9 +3347,6 @@ bool Converter::ConvertCXXOperatorCallExpr(clang::CXXOperatorCallExpr *expr) {
case clang::OverloadedOperatorKind::OO_Arrow:
if (IsUniquePtr(expr->getArg(0)->getType())) {
ConvertUniquePtrDeref(expr);
} else if (GetStrongestIteratorCategory(ctx_, expr->getArg(0)->getType()) ==
IteratorCategory::Bidirectional) {
Convert(expr->getArg(0));
} else if (expr->getOperator() == clang::OverloadedOperatorKind::OO_Star) {
PushParen paren(*this);
StrCat(token::kStar);
Expand Down Expand Up @@ -3914,8 +3896,6 @@ void Converter::ConvertCXXConstructExprArgs(clang::CXXConstructExpr *expr) {
}

bool Converter::VisitCXXConstructExpr(clang::CXXConstructExpr *expr) {
PushSuppressIteratorClone push(*this, expr);

if (expr->isElidable()) {
Convert(expr->getArg(0));
return false;
Expand All @@ -3938,11 +3918,9 @@ bool Converter::VisitCXXConstructExpr(clang::CXXConstructExpr *expr) {
return false;
}
if (IsPassThroughConstructor(ctor)) {
// Take suppress before recursing into the child.
bool suppress = PushSuppressIteratorClone::take(*this);
Convert(expr->getArg(0));
if ((ctor->isCopyConstructor() || IsDefaultedMoveConstructor(ctor)) &&
!suppress && !TypeIsCopyable(expr->getType())) {
!TypeIsCopyable(expr->getType())) {
StrCat(".clone()");
SetFreshType(expr->getType());
}
Expand Down Expand Up @@ -5452,14 +5430,6 @@ void Converter::ConvertConstructFromArgs(clang::QualType type,
std::string Converter::AccessLValueObject(clang::MemberExpr *member) {
auto *object = member->getBase();
auto type = object->getType();
if (member->isArrow()) {
auto *op =
clang::dyn_cast<clang::CXXOperatorCallExpr>(object->IgnoreImplicit());
if (op && GetStrongestIteratorCategory(ctx_, op->getArg(0)->getType()) ==
IteratorCategory::Bidirectional) {
return ToString(object);
}
}
if (type->isPointerType() ||
(IsReferenceType(object) && clang::isa<clang::CallExpr>(object))) {
return std::format("({}{})", GetPointerDerefPrefix(type->getPointeeType()),
Expand Down
36 changes: 0 additions & 36 deletions cpp2rust/converter/converter.h
Original file line number Diff line number Diff line change
Expand Up @@ -841,7 +841,6 @@ class Converter : public clang::RecursiveASTVisitor<Converter> {
std::string ufcs_receiver_;
bool in_const_initializer_ = false;
std::optional<bool> autoref_mut_;
bool suppress_iterator_clone_ = false;

struct PushExplicitAutoref {
Converter &c;
Expand All @@ -853,41 +852,6 @@ class Converter : public clang::RecursiveASTVisitor<Converter> {
~PushExplicitAutoref() { c.autoref_mut_ = prev; }
};

struct PushSuppressIteratorClone {
Converter &c;
bool prev;
PushSuppressIteratorClone(Converter &c, clang::CXXConstructExpr *expr)
: c(c), prev(c.suppress_iterator_clone_) {
auto *ctor = expr->getConstructor();
if (!ctor->isCopyOrMoveConstructor() &&
ctor->isConvertingConstructor(/*AllowExplicit=*/false) &&
ctor->getNumParams() == 1 && IsIteratorType(expr->getType())) {
c.suppress_iterator_clone_ = true;
}
}
~PushSuppressIteratorClone() { c.suppress_iterator_clone_ = prev; }
PushSuppressIteratorClone(const PushSuppressIteratorClone &) = delete;
PushSuppressIteratorClone &
operator=(const PushSuppressIteratorClone &) = delete;

static bool take(Converter &c) {
return std::exchange(c.suppress_iterator_clone_, false);
}

private:
static bool IsIteratorType(clang::QualType qt) {
if (auto *record = qt->getAsCXXRecordDecl()) {
for (auto *d : record->decls()) {
if (auto *tnd = llvm::dyn_cast<clang::TypedefNameDecl>(d)) {
if (tnd->getName() == "iterator_category")
return true;
}
}
}
return false;
}
};

struct PushConstInitializer {
Converter &c;
bool prev;
Expand Down
22 changes: 1 addition & 21 deletions cpp2rust/converter/converter_lib.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1892,7 +1892,7 @@ clang::Expr *GetCallee(clang::CallExpr *expr) {
}

bool HasReceiver(clang::Expr *expr) {
if (clang::isa<clang::CXXMemberCallExpr>(expr))
if (clang::isa<clang::CXXMemberCallExpr, clang::MemberExpr>(expr))
return true;
if (auto *opcall = clang::dyn_cast<clang::CXXOperatorCallExpr>(expr)) {
if (auto *callee = opcall->getCalleeDecl()) {
Expand Down Expand Up @@ -1920,26 +1920,6 @@ std::optional<clang::QualType> GetParamImplicitConvertTarget(clang::Expr *expr,
return fn->getParamDecl(param_idx)->getType().getNonReferenceType();
}

std::optional<IteratorCategory>
GetStrongestIteratorCategory(clang::ASTContext &ctx, clang::QualType type) {
type = type.getNonReferenceType().getUnqualifiedType();
if (!Mapper::Contains(ctx, type)) {
return std::nullopt;
}
if (RuleRegistry::MapsToRefcountPointer(ctx, type)) {
return IteratorCategory::Contiguous;
}
auto mapped = Mapper::Map(ctx, type);
if (mapped.empty()) {
return std::nullopt;
}
if (mapped.starts_with("RefcountMapIter<") ||
mapped.starts_with("UnsafeMapIterator<")) {
return IteratorCategory::Bidirectional;
}
return std::nullopt;
}

std::string GetClassName(clang::QualType type) {
if (auto *record = type->getAsCXXRecordDecl())
return record->getQualifiedNameAsString();
Expand Down
11 changes: 0 additions & 11 deletions cpp2rust/converter/converter_lib.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,17 +28,6 @@ class Sema;

namespace cpp2rust {

// Order matters: each category is a superset of the previous one.
// Use >= to check "at least this capable".
enum class IteratorCategory {
Forward,
Bidirectional,
RandomAccess,
Contiguous,
};

std::optional<IteratorCategory>
GetStrongestIteratorCategory(clang::ASTContext &ctx, clang::QualType type);
bool IsBuiltinConstantP(const clang::Expr *expr);

bool IsGlobalVar(const clang::VarDecl *decl);
Expand Down
32 changes: 6 additions & 26 deletions cpp2rust/converter/models/converter_refcount.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,8 @@ static bool IsFieldOfVectorElem(const clang::MemberExpr *expr) {
}

static bool IsPointerType(clang::ASTContext &ctx, clang::QualType type) {
return type->isPointerType() || GetStrongestIteratorCategory(ctx, type) ==
IteratorCategory::Contiguous;
return type->isPointerType() ||
RuleRegistry::MapsToRefcountPointer(ctx, type);
}

void ConverterRefCount::PendingDeref::set(std::string str, bool fresh) {
Expand Down Expand Up @@ -2279,7 +2279,7 @@ bool ConverterRefCount::VisitCXXForRangeStmtMap(clang::CXXForRangeStmt *stmt) {
auto begin_name = GetNamedDeclAsString(begin);

StrCat("'loop_:");
StrCat(keyword::kFor, begin_name, keyword::kIn, "RefcountMapIter::begin(",
StrCat(keyword::kFor, begin_name, keyword::kIn, "Map::range(",
ConvertObject(stmt->getRangeInit()), ')');
PushBrace brace(*this);

Expand Down Expand Up @@ -2375,7 +2375,6 @@ bool ConverterRefCount::VisitCXXConstructExpr(clang::CXXConstructExpr *expr) {
getConversionKind() != ConversionKind::Unboxed;
PushConversionKind push(*this, boxed_array ? ConversionKind::Pointee
: ConversionKind::Unboxed);
PushSuppressIteratorClone push_suppress(*this, expr);

if (auto str = GetMappedAsString(expr, expr->getArgs(), expr->getNumArgs());
!str.empty()) {
Expand Down Expand Up @@ -2408,9 +2407,7 @@ bool ConverterRefCount::VisitCXXConstructExpr(clang::CXXConstructExpr *expr) {

if (ctor->isCopyOrMoveConstructor() &&
!IsConvertibleCopyOrMoveConstructor(ctor)) {
StrCat(PushSuppressIteratorClone::take(*this)
? ConvertRValue(expr->getArg(0))
: ConvertFreshRValue(expr->getArg(0)));
StrCat(ConvertFreshRValue(expr->getArg(0)));
return false;
}

Expand Down Expand Up @@ -2848,12 +2845,6 @@ bool ConverterRefCount::ConvertCXXOperatorCallExpr(
break;
}

if (GetStrongestIteratorCategory(ctx_, expr->getArg(0)->getType()) ==
IteratorCategory::Bidirectional) {
Convert(expr->getArg(0));
break;
}

{
bool deref = !isAddrOf();
PushParen paren(*this, deref);
Expand Down Expand Up @@ -3314,7 +3305,8 @@ void ConverterRefCount::ConvertArrow(clang::Expr *expr) {
bool is_overloaded_arrow =
op && op->getOperator() == clang::OverloadedOperatorKind::OO_Arrow;

if (!is_overloaded_arrow || IsUserOperatorCall(op)) {
if (!is_overloaded_arrow || IsUserOperatorCall(op) ||
RuleRegistry::ReturnsPointer(ctx_, expr)) {
auto pointee_type = expr->getType()->getPointeeType();
// Virtual methods, which take &mut self, are called through PtrDyn.
if (auto *record = pointee_type->getAsRecordDecl();
Expand All @@ -3333,12 +3325,6 @@ void ConverterRefCount::ConvertArrow(clang::Expr *expr) {
return;
}

if (GetStrongestIteratorCategory(ctx_, op->getArg(0)->getType()) ==
IteratorCategory::Bidirectional) {
Convert(op->getArg(0));
return;
}

Convert(expr);
}

Expand All @@ -3348,12 +3334,6 @@ std::string ConverterRefCount::AccessLValueObject(clang::MemberExpr *member) {

bool is_mut = method && !method->isConst();
if (member->isArrow()) {
auto *op =
clang::dyn_cast<clang::CXXOperatorCallExpr>(object->IgnoreImplicit());
if (op && GetStrongestIteratorCategory(ctx_, op->getArg(0)->getType()) ==
IteratorCategory::Bidirectional) {
return ConvertRValue(op->getArg(0));
}
auto str = is_mut ? ConvertLValue(object) : ConvertRValue(object);
auto pointee_type = object->getType()->getPointeeType();
return DerefPtrExpr(str, pointee_type);
Expand Down
24 changes: 0 additions & 24 deletions cpp2rust/converter/rules/decls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,30 +77,6 @@ const clang::Expr *GetMacroMemberBase(const clang::SourceManager &sm,
}
}

clang::QualType EnableIfSameType(const clang::Decl *rule) {
auto tmpl = llvm::dyn_cast<clang::TemplateDecl>(rule);
if (!tmpl) {
return {};
}
for (auto param : *tmpl->getTemplateParameters()) {
auto type_param = llvm::dyn_cast<clang::TemplateTypeParmDecl>(param);
if (!type_param || type_param->getIdentifier() ||
!type_param->hasDefaultArgument()) {
continue;
}
auto same = type_param->getDefaultArgument()
.getArgument()
.getAsType()
->getAs<clang::TemplateSpecializationType>();
if (!same || !same->isTypeAlias() ||
same->getTemplateName().getAsTemplateDecl()->getName() != "SameAs") {
continue;
}
return same->template_arguments()[1].getAsType();
}
return {};
}

std::optional<std::vector<clang::TemplateArgument>>
DeduceFromType(clang::Sema &sema, clang::TemplateParameterList *params,
clang::QualType pattern, clang::QualType actual) {
Expand Down
2 changes: 0 additions & 2 deletions cpp2rust/converter/rules/decls.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,6 @@ const clang::Expr *GetReturned(const clang::FunctionDecl *rule);
const clang::Expr *GetMacroMemberBase(const clang::SourceManager &sm,
const clang::MemberExpr *member);

clang::QualType EnableIfSameType(const clang::Decl *rule);

std::optional<std::vector<clang::TemplateArgument>>
DeduceFromType(clang::Sema &sema, clang::TemplateParameterList *params,
clang::QualType pattern, clang::QualType actual);
Expand Down
4 changes: 0 additions & 4 deletions cpp2rust/converter/rules/expr_matcher.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -155,10 +155,6 @@ std::vector<clang::Expr *> getOperands(clang::ASTContext &ctx,
auto base =
const_cast<clang::Expr *>(macro_base ? macro_base : member->getBase())
->IgnoreParenImpCasts();
if (auto arrow = llvm::dyn_cast<clang::CXXOperatorCallExpr>(base);
arrow && arrow->getOperator() == clang::OO_Arrow) {
base = arrow->getArg(0);
}
operands.push_back(getObject(ctx, base));
}
while (!operands.empty() &&
Expand Down
Loading
Loading