Skip to content

Commit f1ce30d

Browse files
committed
Merge branch 'master' into fn-ptr
2 parents 83e8868 + 2340d75 commit f1ce30d

136 files changed

Lines changed: 5674 additions & 1333 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.

.github/workflows/format.yml

Lines changed: 2 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,13 @@ jobs:
1111
format:
1212
runs-on: ubuntu-latest
1313
permissions:
14-
contents: write
14+
contents: read
1515

1616
steps:
1717
- name: Checkout code
1818
uses: actions/checkout@v6
1919

20-
- name: Setup LLVM 22
20+
- name: Setup LLVM
2121
uses: ZhongRuoyu/setup-llvm@v0
2222
with:
2323
llvm-version: 22
@@ -34,28 +34,6 @@ jobs:
3434
toolchain: nightly
3535
components: rustfmt, clippy, rustc-dev
3636

37-
- name: Apply C++ formatting fixes
38-
run: find cpp2rust tests -name '*.cpp' -o -name '*.h' -o -name '*.c' | xargs clang-format -i
39-
40-
- name: Apply Rust lint fixes
41-
run: |
42-
cargo clippy --fix --allow-dirty --manifest-path rules/Cargo.toml --all-targets
43-
cargo +nightly clippy --fix --allow-dirty --manifest-path rule-preprocessor/Cargo.toml --all-targets
44-
cargo clippy --fix --allow-dirty --manifest-path libcc2rs/Cargo.toml --all-targets
45-
46-
- name: Apply Rust formatting fixes
47-
run: |
48-
cargo fmt --manifest-path rules/Cargo.toml
49-
cargo fmt --manifest-path rule-preprocessor/Cargo.toml
50-
cargo fmt --manifest-path libcc2rs/Cargo.toml
51-
find tests -name '*.rs' -print0 | xargs -0 rustfmt
52-
53-
- name: Commit auto-fixes
54-
if: github.ref != 'refs/heads/master'
55-
uses: stefanzweifel/git-auto-commit-action@v5
56-
with:
57-
commit_message: "Automatically apply formatting and lint fixes"
58-
5937
- name: Check C++ formatting
6038
run: find cpp2rust tests -name '*.cpp' -o -name '*.h' -o -name '*.c' | xargs clang-format --dry-run --Werror
6139

CMakeLists.txt

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,10 @@ add_custom_target("check-libcc2rs"
117117
)
118118

119119
add_custom_target("check-unit"
120-
COMMAND "python3"
120+
COMMAND ${CMAKE_COMMAND} -E env
121+
"CC=${CMAKE_C_COMPILER}"
122+
"CXX=${CMAKE_CXX_COMPILER}"
123+
"python3"
121124
"${PROJECT_SOURCE_DIR}/tests/lit/lit.py"
122125
${LIT_FLAGS}
123126
"${PROJECT_SOURCE_DIR}/tests/unit"
@@ -127,7 +130,10 @@ add_custom_target("check-unit"
127130
)
128131

129132
add_custom_target("check-benchmarks"
130-
COMMAND "python3"
133+
COMMAND ${CMAKE_COMMAND} -E env
134+
"CC=${CMAKE_C_COMPILER}"
135+
"CXX=${CMAKE_CXX_COMPILER}"
136+
"python3"
131137
"${PROJECT_SOURCE_DIR}/tests/lit/lit.py"
132138
${LIT_FLAGS}
133139
"${PROJECT_SOURCE_DIR}/tests/benchmarks"
@@ -152,3 +158,7 @@ add_custom_target("check-rules"
152158
DEPENDS install-rust-toolchain
153159
USES_TERMINAL
154160
)
161+
162+
add_custom_target("check-all"
163+
DEPENDS check-libcc2rs check-rules check-unit check-benchmarks
164+
)

cpp2rust/converter/converter.cpp

Lines changed: 123 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -519,9 +519,11 @@ bool IsPointerType(clang::QualType qual_type) {
519519
->getCanonicalTypeInternal()));
520520
}
521521

522-
bool Converter::RecordDerivesDefault(const clang::CXXRecordDecl *decl) {
523-
if (GetUserDefinedDefaultConstructor(decl)) {
524-
return false;
522+
bool Converter::RecordDerivesDefault(const clang::RecordDecl *decl) {
523+
if (auto cxx_decl = clang::dyn_cast<clang::CXXRecordDecl>(decl)) {
524+
if (GetUserDefinedDefaultConstructor(cxx_decl)) {
525+
return false;
526+
}
525527
}
526528

527529
for (auto f : decl->fields()) {
@@ -546,7 +548,7 @@ bool Converter::RecordDerivesDefault(const clang::CXXRecordDecl *decl) {
546548
return true;
547549
}
548550

549-
static bool recordDerivesCopy(const clang::CXXRecordDecl *decl) {
551+
static bool recordDerivesCopy(const clang::RecordDecl *decl) {
550552
for (auto f : decl->fields()) {
551553
// Records that contain std::vector, std::array, std::string or anything
552554
// that is translated to Vec<>, do not derive Copy
@@ -569,8 +571,8 @@ static bool recordDerivesCopy(const clang::CXXRecordDecl *decl) {
569571
}
570572
}
571573

572-
// Look recursively into fields that are CXXRecordDecl
573-
if (auto field_record = f->getType()->getAsCXXRecordDecl()) {
574+
// Look recursively into fields that are RecordDecl
575+
if (auto field_record = f->getType()->getAsRecordDecl()) {
574576
if (!recordDerivesCopy(field_record)) {
575577
return false;
576578
}
@@ -580,6 +582,109 @@ static bool recordDerivesCopy(const clang::CXXRecordDecl *decl) {
580582
return true;
581583
}
582584

585+
bool Converter::VisitRecordDecl(clang::RecordDecl *decl) {
586+
decl->dumpColor();
587+
588+
// VisitCXXRecordDecl already visited the record
589+
if (clang::isa<clang::CXXRecordDecl>(decl)) {
590+
return true;
591+
}
592+
593+
if (!decl->isCompleteDefinition()) {
594+
return false;
595+
}
596+
597+
if (!record_decls_.insert(GetID(decl)).second) {
598+
return false;
599+
}
600+
601+
Mapper::AddRuleForUserDefinedType(decl);
602+
EmitRustStruct(decl);
603+
604+
return false;
605+
}
606+
607+
void Converter::EmitRustStruct(clang::RecordDecl *decl) {
608+
// Enums and static variables. In rust they live outside the record
609+
for (auto *d : decl->decls()) {
610+
if (auto *enum_decl = llvm::dyn_cast<clang::EnumDecl>(d)) {
611+
VisitEnumDecl(enum_decl);
612+
}
613+
if (auto *var_decl = clang::dyn_cast<clang::VarDecl>(d)) {
614+
VisitVarDecl(var_decl);
615+
}
616+
}
617+
618+
// Inner records. In rust they live outside the record
619+
for (auto *d : decl->decls()) {
620+
if (auto *nested = clang::dyn_cast<clang::RecordDecl>(d)) {
621+
if (!nested->isImplicit()) {
622+
inner_structs_[GetID(nested)] = GetRecordName(nested);
623+
if (auto *cxx = clang::dyn_cast<clang::CXXRecordDecl>(nested)) {
624+
VisitCXXRecordDecl(cxx);
625+
} else {
626+
VisitRecordDecl(nested);
627+
}
628+
}
629+
}
630+
}
631+
632+
// Derived traits
633+
StrCat("#[derive(");
634+
for (auto *attr : GetStructAttributes(decl)) {
635+
StrCat(attr, ",");
636+
}
637+
StrCat(")]");
638+
639+
// Fields
640+
auto access = clang::dyn_cast<clang::CXXRecordDecl>(decl)
641+
? AccessSpecifierAsString(decl->getAccess())
642+
: keyword::kPub;
643+
StrCat(access, keyword::kStruct, GetRecordName(decl),
644+
token::kOpenCurlyBracket);
645+
for (auto *field : decl->fields()) {
646+
VisitFieldDecl(field);
647+
}
648+
StrCat(token::kCloseCurlyBracket);
649+
650+
// C++ method decls
651+
if (auto *cxx = clang::dyn_cast<clang::CXXRecordDecl>(decl)) {
652+
auto struct_name = GetRecordName(cxx);
653+
654+
ConvertCXXMethodDecls(
655+
cxx, std::string(keyword::kImpl) + ' ' + struct_name,
656+
[](const auto *method) {
657+
return !method->isImplicit() &&
658+
!(method->getDefinition() &&
659+
method->getDefinition()->isDefaulted()) &&
660+
(method->isThisDeclarationADefinition() ||
661+
clang::isa<clang::CXXConstructorDecl>(method)) &&
662+
!method->isVirtual() &&
663+
!clang::isa<clang::CXXDestructorDecl>(method);
664+
});
665+
666+
if (cxx->bases_begin() != cxx->bases_end()) {
667+
ConvertCXXMethodDecls(
668+
cxx,
669+
std::format("{} impl {} for {}", keyword_unsafe_,
670+
GetUnsafeTypeAsString(cxx->bases_begin()->getType()),
671+
struct_name),
672+
[](const auto *method) {
673+
return !method->isImplicit() && method->isVirtual();
674+
});
675+
}
676+
}
677+
678+
// Traits
679+
if (auto *cxx = clang::dyn_cast<clang::CXXRecordDecl>(decl)) {
680+
AddOrdTrait(cxx);
681+
AddCloneTrait(cxx);
682+
AddDropTrait(cxx);
683+
AddDefaultTrait(cxx);
684+
}
685+
AddByteReprTrait(decl);
686+
}
687+
583688
bool Converter::VisitCXXRecordDecl(clang::CXXRecordDecl *decl) {
584689
if (clang::isa<clang::ClassTemplateSpecializationDecl>(decl)) {
585690
materializeTemplateSpecialization(decl);
@@ -623,74 +728,7 @@ bool Converter::VisitCXXRecordDecl(clang::CXXRecordDecl *decl) {
623728
}
624729
}
625730

626-
auto struct_name = GetRecordName(decl);
627-
628-
// First visit the nested enums
629-
for (auto d : decl->decls()) {
630-
if (auto enum_decl = llvm::dyn_cast<clang::EnumDecl>(d)) {
631-
VisitEnumDecl(enum_decl);
632-
}
633-
}
634-
635-
for (auto *decl : decl->decls()) {
636-
if (auto var_decl = clang::dyn_cast<clang::VarDecl>(decl)) {
637-
VisitVarDecl(var_decl);
638-
}
639-
}
640-
641-
auto nested = GetNestedStructs(decl);
642-
for (auto *record_decl : nested) {
643-
auto ID = GetID(record_decl);
644-
inner_structs_[ID] = GetRecordName(record_decl);
645-
VisitCXXRecordDecl(record_decl);
646-
}
647-
648-
StrCat(token::kHash, token::kOpenBracket, "derive", token::kOpenParen);
649-
bool derives_default = RecordDerivesDefault(decl);
650-
651-
for (auto *struct_attr : GetStructAttributes(decl, derives_default)) {
652-
StrCat(struct_attr, token::kComma);
653-
}
654-
StrCat(token::kCloseParen, token::kCloseBracket);
655-
656-
auto access_specifier = decl->getAccess();
657-
StrCat(AccessSpecifierAsString(access_specifier), keyword::kStruct,
658-
struct_name, token::kOpenCurlyBracket);
659-
for (auto *field : decl->fields()) {
660-
VisitFieldDecl(field);
661-
}
662-
StrCat(token::kCloseCurlyBracket);
663-
664-
ConvertCXXMethodDecls(
665-
decl, std::string(keyword::kImpl) + ' ' + struct_name,
666-
[](const auto *method) {
667-
return !method->isImplicit() &&
668-
!(method->getDefinition() &&
669-
method->getDefinition()->isDefaulted()) &&
670-
(method->isThisDeclarationADefinition() ||
671-
clang::isa<clang::CXXConstructorDecl>(method)) &&
672-
!method->isVirtual() &&
673-
!clang::isa<clang::CXXDestructorDecl>(method);
674-
});
675-
676-
AddOrdTrait(decl);
677-
AddCloneTrait(decl);
678-
AddDropTrait(decl);
679-
if (!derives_default) {
680-
AddDefaultTrait(decl);
681-
}
682-
AddByteReprTrait(decl);
683-
684-
if (decl->bases_begin() != decl->bases_end()) {
685-
ConvertCXXMethodDecls(
686-
decl,
687-
std::format("{} impl {} for {}", keyword_unsafe_,
688-
GetUnsafeTypeAsString(decl->bases_begin()->getType()),
689-
struct_name),
690-
[](const auto *method) {
691-
return !method->isImplicit() && method->isVirtual();
692-
});
693-
}
731+
EmitRustStruct(decl);
694732
} else {
695733
// FIXME: improve error handling
696734
assert(0 && "unsupported union");
@@ -2797,15 +2835,18 @@ std::string Converter::GetRecordName(const clang::NamedDecl *decl) const {
27972835
}
27982836

27992837
std::vector<const char *>
2800-
Converter::GetStructAttributes(const clang::CXXRecordDecl *decl,
2801-
bool &out_impl_default) {
2838+
Converter::GetStructAttributes(const clang::RecordDecl *decl) {
28022839
std::vector<const char *> struct_attrs = {};
28032840

28042841
if (recordDerivesCopy(decl)) {
28052842
struct_attrs.emplace_back("Copy");
28062843
}
28072844

2808-
if (!decl->defaultedCopyConstructorIsDeleted()) {
2845+
if (auto cxx_decl = clang::dyn_cast<clang::CXXRecordDecl>(decl)) {
2846+
if (!cxx_decl->defaultedCopyConstructorIsDeleted()) {
2847+
struct_attrs.emplace_back("Clone");
2848+
}
2849+
} else /* RecordDecl */ {
28092850
struct_attrs.emplace_back("Clone");
28102851
}
28112852

@@ -3106,11 +3147,14 @@ void Converter::AddCloneTrait(const clang::CXXRecordDecl *decl) {}
31063147
void Converter::AddDropTrait(const clang::CXXRecordDecl *decl) {}
31073148

31083149
void Converter::AddDefaultTrait(const clang::CXXRecordDecl *decl) {
3150+
if (RecordDerivesDefault(decl)) {
3151+
return;
3152+
}
31093153
auto struct_name = GetRecordName(decl);
31103154
StrCat(std::format("impl Default for {}", struct_name),
31113155
token::kOpenCurlyBracket, "fn default() -> Self",
31123156
token::kOpenCurlyBracket);
3113-
if (auto default_ctor = GetUserDefinedDefaultConstructor(decl)) {
3157+
if (auto *default_ctor = GetUserDefinedDefaultConstructor(decl)) {
31143158
StrCat(keyword_unsafe_, token::kOpenCurlyBracket);
31153159
Convert(clang::CXXConstructExpr::Create(
31163160
ctx_, ctx_.getCanonicalTagType(decl), clang::SourceLocation(),
@@ -3133,7 +3177,7 @@ void Converter::AddDefaultTrait(const clang::CXXRecordDecl *decl) {
31333177
StrCat(token::kCloseCurlyBracket, token::kCloseCurlyBracket);
31343178
}
31353179

3136-
void Converter::AddByteReprTrait(const clang::CXXRecordDecl *decl) {}
3180+
void Converter::AddByteReprTrait(const clang::RecordDecl *decl) {}
31373181

31383182
void Converter::ConvertUnsignedArithBinaryOperator(clang::BinaryOperator *op,
31393183
clang::Expr *expr) {

cpp2rust/converter/converter.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,12 @@ class Converter : public clang::RecursiveASTVisitor<Converter> {
9595

9696
virtual bool ConvertLambdaVarDecl(clang::VarDecl *decl);
9797

98+
bool VisitRecordDecl(clang::RecordDecl *decl);
99+
98100
virtual bool VisitCXXRecordDecl(clang::CXXRecordDecl *decl);
99101

102+
void EmitRustStruct(clang::RecordDecl *decl);
103+
100104
virtual bool VisitCXXMethodDecl(clang::CXXMethodDecl *decl);
101105
virtual std::string GetSelfMaybeWithMut(const clang::CXXMethodDecl *decl);
102106

@@ -355,7 +359,7 @@ class Converter : public clang::RecursiveASTVisitor<Converter> {
355359
virtual std::string GetRecordName(const clang::NamedDecl *decl) const;
356360

357361
virtual std::vector<const char *>
358-
GetStructAttributes(const clang::CXXRecordDecl *decl, bool &out_impl_default);
362+
GetStructAttributes(const clang::RecordDecl *decl);
359363

360364
virtual std::string GetUnsafeTypeAsString(clang::QualType qual_type) const;
361365

@@ -410,7 +414,7 @@ class Converter : public clang::RecursiveASTVisitor<Converter> {
410414

411415
virtual void AddDefaultTrait(const clang::CXXRecordDecl *decl);
412416

413-
virtual void AddByteReprTrait(const clang::CXXRecordDecl *decl);
417+
virtual void AddByteReprTrait(const clang::RecordDecl *decl);
414418

415419
virtual void
416420
ConvertUnsignedArithBinaryOperator(clang::BinaryOperator *binary_operator,
@@ -453,7 +457,7 @@ class Converter : public clang::RecursiveASTVisitor<Converter> {
453457

454458
virtual bool IsReferenceType(const clang::Expr *expr) const;
455459

456-
virtual bool RecordDerivesDefault(const clang::CXXRecordDecl *decl);
460+
virtual bool RecordDerivesDefault(const clang::RecordDecl *decl);
457461

458462
bool ShouldReplaceWithMappedBody(clang::DeclRefExpr *expr) const;
459463

0 commit comments

Comments
 (0)