Skip to content

Commit 38f0ddb

Browse files
committed
Merge branch 'master' into 18-union-list-init
2 parents 0819f61 + f19aca1 commit 38f0ddb

50 files changed

Lines changed: 721 additions & 364 deletions

Some content is hidden

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

‎CMakeLists.txt‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ find_program(CLANG_FORMAT NAMES clang-format-22 clang-format)
9090
find_program(RUFF NAMES ruff)
9191

9292
file(GLOB_RECURSE ALL_CXX_SOURCES
93-
cpp2rust/*.cpp cpp2rust/*.h tests/*.cpp tests/*.c)
93+
cpp2rust/*.cpp cpp2rust/*.h rules/*.cpp rules/*.c rules/*.h tests/*.cpp tests/*.c)
9494

9595
set(PYTHON_SOURCES ${PROJECT_SOURCE_DIR}/tests/lit/lit/formats/Cpp2RustTest.py)
9696

‎cpp2rust/converter/converter.cpp‎

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ std::unordered_map<std::string, std::string> Converter::inner_structs_;
3030
std::unordered_set<std::string> Converter::decl_ids_;
3131
std::unordered_set<std::string> Converter::globals_;
3232
std::vector<std::string> Converter::global_inits_;
33-
std::unordered_set<std::string> Converter::abstract_structs_;
3433
Converter::RecordIndex Converter::record_decls_;
3534
std::map<std::string, Converter::DeferredBlock> Converter::virtual_methods_;
3635

@@ -318,7 +317,7 @@ bool Converter::VisitPointerType(clang::PointerType *type) {
318317
auto pointee_type = type->getPointeeType();
319318
StrCat(pointee_type.isConstQualified() ? "*const" : "*mut");
320319
if (pointee_type->isRecordType() &&
321-
abstract_structs_.contains(GetID(pointee_type->getAsRecordDecl()))) {
320+
IsAbstractUserClass(pointee_type->getAsRecordDecl())) {
322321
StrCat(keyword::kDyn);
323322
}
324323
return Convert(pointee_type);
@@ -1364,7 +1363,11 @@ bool Converter::VisitDeclStmt(clang::DeclStmt *stmt) {
13641363
hoisted_records_ += std::move(buf).str();
13651364
continue;
13661365
}
1367-
Convert(decl);
1366+
if (var && var->isImplicit()) {
1367+
VisitVarDecl(var);
1368+
} else {
1369+
Convert(decl);
1370+
}
13681371
StrCat(token::kSemiColon);
13691372
}
13701373
return false;
@@ -2279,8 +2282,13 @@ std::optional<Converter::TempMaterializationCtx>
22792282
Converter::ConvertCallExpr(clang::CallExpr *expr) {
22802283
auto *callee = expr->getCallee();
22812284

2282-
if (auto fn = Printer::ToString(ctx_, callee);
2283-
fn.starts_with("int printf") || fn.starts_with("int fprintf")) {
2285+
auto fn = Printer::ToString(ctx_, callee);
2286+
bool is_printf = fn.starts_with("int printf");
2287+
bool is_fprintf = fn.starts_with("int fprintf");
2288+
unsigned format_arg = is_fprintf ? 1 : 0;
2289+
if ((is_printf || is_fprintf) &&
2290+
clang::isa<clang::StringLiteral>(
2291+
expr->getArg(format_arg)->IgnoreImplicit())) {
22842292
ConvertPrintf(expr);
22852293
} else if (IsTransparentStdCall(expr)) {
22862294
Convert(expr->getArg(0));
@@ -4637,7 +4645,6 @@ pub fn main() {{
46374645
}
46384646

46394647
void Converter::ConvertAbstractClass(clang::CXXRecordDecl *decl) {
4640-
ENSURE(abstract_structs_.insert(GetID(decl)).second);
46414648
auto trait_name = GetRecordName(decl);
46424649
auto access_specifier_as_string = AccessSpecifierAsString(decl->getAccess());
46434650
auto signature = std::format("{} {} trait {}", access_specifier_as_string,

‎cpp2rust/converter/converter.h‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -952,7 +952,6 @@ class Converter : public clang::RecursiveASTVisitor<Converter> {
952952
};
953953

954954
static std::unordered_set<std::string> decl_ids_;
955-
static std::unordered_set<std::string> abstract_structs_;
956955

957956
class RecordIndex {
958957
public:

‎cpp2rust/converter/converter_lib.cpp‎

Lines changed: 42 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ static const char rust_keywords[][12] = {
7575
"safe",
7676
// Standard library keywords
7777
"vec",
78+
"Err",
7879
};
7980

8081
namespace cpp2rust {
@@ -301,6 +302,13 @@ bool IsUserDefinedDecl(const clang::Decl *decl) {
301302
!src_mgr.isInSystemMacro(src_loc);
302303
}
303304

305+
bool IsAbstractUserClass(const clang::RecordDecl *decl) {
306+
auto cxx = llvm::dyn_cast<clang::CXXRecordDecl>(decl);
307+
auto definition = cxx ? cxx->getDefinition() : nullptr;
308+
return definition && IsUserDefinedDecl(definition) &&
309+
definition->isAbstract();
310+
}
311+
304312
bool RefersToUserDefinedDecl(const clang::Expr *expr) {
305313
expr = expr->IgnoreParenImpCasts();
306314
const clang::Decl *decl = nullptr;
@@ -912,6 +920,23 @@ static size_t GetDeclId(const clang::NamedDecl *decl, bool internal) {
912920
return type_mapping.try_emplace(key, type_mapping.size()).first->second;
913921
}
914922

923+
void EscapeRustKeyword(std::string &name) {
924+
if (!name.empty() &&
925+
std::ranges::all_of(name, [](char c) { return c == '_'; })) {
926+
name += '_';
927+
}
928+
for (auto &keyword : rust_keywords) {
929+
if (!name.starts_with(keyword))
930+
continue;
931+
932+
auto suffix = std::string_view(name).substr(strlen(keyword));
933+
if (std::ranges::all_of(suffix, [](char c) { return c == '_'; })) {
934+
name += '_';
935+
break;
936+
}
937+
}
938+
}
939+
915940
std::string GetNamedDeclAsString(const clang::NamedDecl *decl) {
916941
auto name = decl->getDeclName().isIdentifier() ? decl->getName().str()
917942
: decl->getNameAsString();
@@ -927,13 +952,24 @@ std::string GetNamedDeclAsString(const clang::NamedDecl *decl) {
927952
}
928953
}
929954

955+
auto *anonymous_record_var = clang::dyn_cast<clang::VarDecl>(decl);
956+
if (anonymous_record_var) {
957+
auto *record = anonymous_record_var->getType()->getAsRecordDecl();
958+
if (clang::isa<clang::ParmVarDecl>(decl) || !record ||
959+
record->getIdentifier()) {
960+
anonymous_record_var = nullptr;
961+
}
962+
}
963+
930964
// Anonymous record or enum
931-
if (name.empty() && (clang::isa<clang::RecordDecl>(decl) ||
932-
clang::isa<clang::FieldDecl>(decl) ||
933-
clang::isa<clang::EnumDecl>(decl))) {
965+
if (name.empty() &&
966+
(clang::isa<clang::RecordDecl>(decl) ||
967+
clang::isa<clang::FieldDecl>(decl) || anonymous_record_var ||
968+
clang::isa<clang::EnumDecl>(decl))) {
934969
const clang::NamedDecl *target = decl;
935-
if (auto *field = clang::dyn_cast<clang::FieldDecl>(decl)) {
936-
if (auto *record = field->getType()->getAsRecordDecl();
970+
if (clang::isa<clang::FieldDecl, clang::VarDecl>(decl)) {
971+
auto type = clang::cast<clang::ValueDecl>(decl)->getType();
972+
if (auto *record = type->getAsRecordDecl();
937973
record && !record->getIdentifier()) {
938974
target = record;
939975
}
@@ -962,24 +998,7 @@ std::string GetNamedDeclAsString(const clang::NamedDecl *decl) {
962998
name += std::to_string(*id);
963999
}
9641000

965-
// transform decl names that are rust keywords:
966-
// keyword -> keyword_
967-
// keyword_ -> keyword__
968-
// etc
969-
if (!name.empty() &&
970-
std::ranges::all_of(name, [](char c) { return c == '_'; })) {
971-
name += '_';
972-
}
973-
for (auto &keyword : rust_keywords) {
974-
if (!name.starts_with(keyword))
975-
continue;
976-
977-
auto suffix = std::string_view(name).substr(strlen(keyword));
978-
if (std::ranges::all_of(suffix, [](char c) { return c == '_'; })) {
979-
name += '_';
980-
break;
981-
}
982-
}
1001+
EscapeRustKeyword(name);
9831002

9841003
if (name.empty()) {
9851004
auto *pdecl = llvm::dyn_cast<clang::ParmVarDecl>(decl);

‎cpp2rust/converter/converter_lib.h‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ bool IsCodeUnitStringLiteral(const clang::StringLiteral *expr);
6666

6767
bool IsUserDefinedDecl(const clang::Decl *decl);
6868

69+
bool IsAbstractUserClass(const clang::RecordDecl *decl);
70+
6971
bool RefersToUserDefinedDecl(const clang::Expr *expr);
7072

7173
bool IsUnsignedArithOp(const clang::BinaryOperator *expr);
@@ -180,6 +182,8 @@ unsigned GetArraySize(clang::QualType array_type);
180182
std::string GetID(const clang::Decl *decl);
181183
std::string GetMethodID(const clang::CXXMethodDecl *decl);
182184

185+
void EscapeRustKeyword(std::string &name);
186+
183187
std::string GetNamedDeclAsString(const clang::NamedDecl *decl);
184188

185189
std::string DisambiguateAnonymousTag(const clang::TagDecl *tag);

‎cpp2rust/converter/models/converter_refcount.cpp‎

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -341,7 +341,7 @@ bool ConverterRefCount::VisitPointerType(clang::PointerType *type) {
341341
PushConversionKind push2(*this, ConversionKind::FullRefCount,
342342
pointee_is_array);
343343
if (pointee_type->isRecordType() &&
344-
abstract_structs_.contains(GetID(pointee_type->getAsRecordDecl()))) {
344+
IsAbstractUserClass(pointee_type->getAsRecordDecl())) {
345345
StrCat("PtrDyn<dyn");
346346
} else {
347347
StrCat("Ptr<");
@@ -1252,16 +1252,8 @@ static std::vector<const char *> printf2fmt(std::string &format) {
12521252
void ConverterRefCount::ConvertPrintf(clang::CallExpr *expr) {
12531253
bool is_fprintf =
12541254
Printer::ToString(ctx_, expr->getCallee()).starts_with("int fprintf");
1255-
std::string format;
1256-
if (auto *str = clang::dyn_cast<clang::StringLiteral>(
1257-
expr->getArg(is_fprintf)->IgnoreImplicit())) {
1258-
format = GetEscapedStringLiteral(str);
1259-
} else {
1260-
llvm::errs() << "Unknown fprintf format: ";
1261-
expr->getArg(1)->dump();
1262-
llvm::errs() << '\n';
1263-
exit(1);
1264-
}
1255+
auto format = GetEscapedStringLiteral(clang::cast<clang::StringLiteral>(
1256+
expr->getArg(is_fprintf)->IgnoreImplicit()));
12651257
bool ends_newline = format.ends_with("\\n\"");
12661258

12671259
auto fd = is_fprintf ? Printer::ToString(ctx_, expr->getArg(0)) : "stdout";
@@ -1507,7 +1499,7 @@ bool ConverterRefCount::VisitImplicitCastExpr(clang::ImplicitCastExpr *expr) {
15071499
auto ptype = clang::dyn_cast<clang::PointerType>(expr->getType());
15081500
auto pointee_type = ptype->getPointeeType()->getAsCXXRecordDecl();
15091501

1510-
if (pointee_type && abstract_structs_.contains(GetID(pointee_type))) {
1502+
if (pointee_type && IsAbstractUserClass(pointee_type)) {
15111503
PushConversionKind push(*this, ConversionKind::Unboxed);
15121504
StrCat(std::format("{}.to_dyn::<{}>(|w| w)",
15131505
ToString(sub_expr->IgnoreCasts()),
@@ -3237,7 +3229,7 @@ void ConverterRefCount::ConvertArrow(clang::Expr *expr) {
32373229
auto pointee_type = expr->getType()->getPointeeType();
32383230
// Virtual methods, which take &mut self, are called through PtrDyn.
32393231
if (auto *record = pointee_type->getAsRecordDecl();
3240-
isLValue() && record && abstract_structs_.contains(GetID(record))) {
3232+
isLValue() && record && IsAbstractUserClass(record)) {
32413233
StrCat(std::format("(*{}.upgrade().deref_mut())", ToString(expr)));
32423234
SetValueFreshness(pointee_type);
32433235
return;

‎cpp2rust/converter/printer.cpp‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ std::string ToRustName(std::string name) {
116116
if (stem == "Ptr" || stem == "Value" || stem == "Box") {
117117
name += '_';
118118
}
119+
EscapeRustKeyword(name);
119120
return name;
120121
}
121122

‎rules/algorithm/src.cpp‎

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,7 @@ template <class T1, class T2> T1 f3(T1 first, T1 last, const T2 &value) {
1919
return std::find(first, last, value);
2020
}
2121

22-
template <typename T1, typename T2>
23-
void f6(T1 first, T1 last, T2 comp) {
22+
template <typename T1, typename T2> void f6(T1 first, T1 last, T2 comp) {
2423
return std::stable_sort(first, last, comp);
2524
}
2625

@@ -48,8 +47,7 @@ std::ostream_iterator<char> f13(std::string::iterator a0,
4847
return std::copy(a0, a1, a2);
4948
}
5049

51-
template <typename T1, typename T2>
52-
void f14(T1 *first, T1 *last, T2 comp) {
50+
template <typename T1, typename T2> void f14(T1 *first, T1 *last, T2 comp) {
5351
return std::stable_sort(first, last, comp);
5452
}
5553

‎rules/array/src.cpp‎

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,7 @@
33

44
#include <array>
55

6-
template <typename T1, std::size_t T2>
7-
using t1 = std::array<T1, T2>;
6+
template <typename T1, std::size_t T2> using t1 = std::array<T1, T2>;
87

98
template <typename T1, std::size_t T2>
109
using t2 = typename std::array<T1, T2>::size_type;

‎rules/assert/src.c‎

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,4 @@
33

44
#include <assert.h>
55

6-
bool f1(bool condition) {
7-
return cpp2rust_assert_fail(condition);
8-
}
6+
bool f1(bool condition) { return cpp2rust_assert_fail(condition); }

0 commit comments

Comments
 (0)