Skip to content

Commit fe14b6d

Browse files
committed
Merge branch 'master' into lambdas
2 parents 3688b37 + 1ce3815 commit fe14b6d

186 files changed

Lines changed: 1702 additions & 1605 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: 46 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -650,6 +650,10 @@ bool Converter::RecordDerivesDefault(const clang::RecordDecl *decl) {
650650
}
651651

652652
for (auto f : decl->fields()) {
653+
if (f->hasInClassInitializer()) {
654+
return false;
655+
}
656+
653657
// Records that contain function pointer do not derive Default
654658
if (auto ptr_ty = f->getType()->getAs<clang::PointerType>()) {
655659
if (ptr_ty->getPointeeType()->isFunctionType()) {
@@ -1062,9 +1066,17 @@ std::string Converter::GetMethodName(const clang::CXXMethodDecl *decl) {
10621066
if (clang::isa<clang::CXXDestructorDecl>(decl)) {
10631067
return kDestructorName;
10641068
}
1069+
if (const char *name = GetCopyOrMoveName(decl);
1070+
name && CanUseCopyOrMoveName(decl, name)) {
1071+
return name;
1072+
}
10651073
if (IsOverloadedMethod(decl)) {
10661074
return GetOverloadedFunctionName(decl);
10671075
}
1076+
if (auto *conversion = clang::dyn_cast<clang::CXXConversionDecl>(decl)) {
1077+
return GetConversionName(
1078+
conversion, GetUnsafeTypeAsString(conversion->getConversionType()));
1079+
}
10681080
return GetNamedDeclAsString(decl);
10691081
}
10701082

@@ -1107,12 +1119,15 @@ std::string Converter::GetSelfMaybeWithMut(const clang::CXXMethodDecl *decl) {
11071119

11081120
std::string Converter::GetCtorName(clang::CXXConstructorDecl *decl) {
11091121
if (decl->isCopyOrMoveConstructor()) {
1122+
if (const char *name = GetCopyOrMoveName(decl);
1123+
CanUseCopyOrMoveName(decl, name)) {
1124+
return name;
1125+
}
11101126
return GetOverloadedFunctionName(decl);
11111127
}
1112-
return GetRecordName(decl->getParent()) +
1113-
(GetNumberOfConvertingCtors(decl->getParent()) != 1
1114-
? std::to_string(GetCtorIndex(decl))
1115-
: "");
1128+
return GetNumberOfConvertingCtors(decl->getParent()) != 1
1129+
? std::format("new_{}", GetCtorIndex(decl))
1130+
: "new";
11161131
}
11171132

11181133
bool Converter::VisitCXXConstructorDecl(clang::CXXConstructorDecl *decl) {
@@ -1332,7 +1347,12 @@ bool Converter::VisitIfStmt(clang::IfStmt *stmt) {
13321347
return false;
13331348
}
13341349
StrCat(keyword::kIf);
1335-
ConvertCondition(stmt->getCond());
1350+
if (auto *cond = clang::dyn_cast<clang::ConstantExpr>(stmt->getCond());
1351+
cond && stmt->isConstexpr()) {
1352+
StrCat(cond->getResultAsAPSInt() != 0 ? keyword::kTrue : keyword::kFalse);
1353+
} else {
1354+
ConvertCondition(stmt->getCond());
1355+
}
13361356
ConvertBody(stmt->getThen());
13371357
if (stmt->hasElseStorage()) {
13381358
StrCat(keyword::kElse);
@@ -3298,7 +3318,7 @@ void Converter::ConvertMemberExpr(clang::MemberExpr *expr) {
32983318
if (auto *method = clang::dyn_cast<clang::CXXMethodDecl>(member);
32993319
method && IsOverloadedMethod(method)) {
33003320
StrCat(token::kDot);
3301-
StrCat(GetOverloadedFunctionName(method));
3321+
StrCat(GetMethodName(method));
33023322
} else if (!name_override.empty()) {
33033323
StrCat(token::kDot, name_override);
33043324
} else if (member->getDeclName().isIdentifier() ||
@@ -3346,6 +3366,7 @@ bool Converter::VisitArrayInitLoopExpr(clang::ArrayInitLoopExpr *expr) {
33463366
}
33473367

33483368
bool Converter::VisitInitListExpr(clang::InitListExpr *expr) {
3369+
auto *syntactic = expr->isSyntacticForm() ? expr : expr->getSyntacticForm();
33493370
if (auto form = expr->getSemanticForm())
33503371
expr = form;
33513372

@@ -3371,6 +3392,13 @@ bool Converter::VisitInitListExpr(clang::InitListExpr *expr) {
33713392
return false;
33723393
}
33733394

3395+
auto *cxx = clang::dyn_cast<clang::CXXRecordDecl>(record);
3396+
if (syntactic->getNumInits() == 0 && !(cxx && cxx->isLambda())) {
3397+
StrCat(GetDefaultAsString(qual_type));
3398+
SetFreshType(qual_type);
3399+
return false;
3400+
}
3401+
33743402
StrCat(GetUnsafeTypeAsString(qual_type));
33753403
PushBrace brace(*this);
33763404
int i = 0;
@@ -4100,18 +4128,6 @@ std::string Converter::GetDefaultAsStringFallback(clang::QualType qual_type) {
41004128
return getTypedLiteral("0.0", ToString(qual_type));
41014129
}
41024130

4103-
if (auto record = qual_type->getAsRecordDecl();
4104-
record && in_const_initializer_) {
4105-
if (auto cxx = clang::dyn_cast<clang::CXXRecordDecl>(record)) {
4106-
ENSURE(GetUserDefinedDefaultConstructor(cxx) == nullptr &&
4107-
"Default initializing globals using default constructor is not "
4108-
"supported");
4109-
}
4110-
Buffer buf(*this);
4111-
EmitDefaultStructLiteral(record);
4112-
return std::move(buf).str();
4113-
}
4114-
41154131
if (auto record = qual_type->getAsRecordDecl()) {
41164132
if (ctx_.getSourceManager().isInSystemHeader(record->getLocation()) &&
41174133
qual_type.isPODType(ctx_)) {
@@ -4138,6 +4154,10 @@ std::string Converter::ConvertVarDefaultInit(clang::QualType qual_type) {
41384154
std::string
41394155
Converter::GetOverloadedFunctionName(const clang::FunctionDecl *decl) {
41404156
auto name = GetFunctionBaseName(decl);
4157+
if (auto *conversion = clang::dyn_cast<clang::CXXConversionDecl>(decl)) {
4158+
name = GetConversionName(
4159+
conversion, GetUnsafeTypeAsString(conversion->getConversionType()));
4160+
}
41414161
if (auto *ctor = clang::dyn_cast<clang::CXXConstructorDecl>(decl);
41424162
ctor && !ctor->getParent()->getIdentifier()) {
41434163
name = GetRecordName(ctor->getParent());
@@ -4207,19 +4227,7 @@ Converter::GetOverloadedFunctionName(const clang::FunctionDecl *decl) {
42074227
}
42084228
}
42094229

4210-
ReplaceAll(name, "[", "arr");
4211-
ReplaceAll(name, "]", "arr");
4212-
ReplaceAll(name, ";", "_");
4213-
ReplaceAll(name, ",", "_");
4214-
name.erase(std::remove_if(name.begin(), name.end(),
4215-
[](char c) {
4216-
return c == '<' || c == '>' || c == ' ' ||
4217-
c == ':' || c == '(' || c == ')' ||
4218-
c == '-';
4219-
}),
4220-
name.end());
4221-
std::replace(name.begin(), name.end(), '*', 'p');
4222-
4230+
ToIdentifier(name);
42234231
return name;
42244232
}
42254233

@@ -4769,8 +4777,13 @@ void Converter::EmitDefaultStructLiteral(const clang::RecordDecl *decl) {
47694777
StrCat(GetRecordName(decl));
47704778
PushBrace brace(*this);
47714779
for (auto *field : decl->fields()) {
4772-
StrCat(GetNamedDeclAsString(field), token::kColon,
4773-
GetDefaultAsString(field->getType()), token::kComma);
4780+
StrCat(GetNamedDeclAsString(field), token::kColon);
4781+
if (auto *init = field->getInClassInitializer()) {
4782+
ConvertVarInit(field->getType(), init);
4783+
} else {
4784+
StrCat(GetDefaultAsString(field->getType()));
4785+
}
4786+
StrCat(token::kComma);
47744787
}
47754788
}
47764789

‎cpp2rust/converter/converter.h‎

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,21 +127,35 @@ class Converter : public clang::RecursiveASTVisitor<Converter> {
127127
virtual const char *CharRustType() const { return "libc::c_char"; }
128128

129129
virtual bool VisitCXXMethodDecl(clang::CXXMethodDecl *decl);
130+
130131
virtual bool ShouldConvertMethod(const clang::CXXMethodDecl *decl);
132+
131133
virtual bool ConvertOutOfLineMethod(clang::CXXMethodDecl *decl);
134+
132135
bool ConvertCXXMethodDecl(clang::CXXMethodDecl *decl);
136+
133137
std::string GetMethodName(const clang::CXXMethodDecl *decl);
138+
134139
virtual std::string GetSelfMaybeWithMut(const clang::CXXMethodDecl *decl);
140+
135141
std::string GetCtorName(clang::CXXConstructorDecl *decl);
142+
136143
virtual void ConvertCXXRecordMethods(clang::CXXRecordDecl *decl);
144+
137145
virtual void ConvertLateInstantiatedMethods(clang::CXXRecordDecl *decl);
146+
138147
virtual std::string DestroyMembers(const clang::CXXRecordDecl *decl);
148+
139149
virtual void EmitScopedDestructor(const clang::VarDecl *decl);
150+
140151
void EmitDeallocation(clang::CXXDeleteExpr *expr,
141152
const std::string &argument_as_string);
153+
142154
virtual void SetUFCSReceiver(clang::Expr *base, bool is_arrow,
143155
const clang::CXXMethodDecl *method);
156+
144157
void ConvertUserOperatorCall(clang::CXXOperatorCallExpr *expr);
158+
145159
virtual std::string GetUFCSName(const clang::CXXMethodDecl *method) const;
146160

147161
virtual bool ThisIsRustPtr() const { return false; }
@@ -419,6 +433,7 @@ class Converter : public clang::RecursiveASTVisitor<Converter> {
419433
VisitUnaryExprOrTypeTraitExpr(clang::UnaryExprOrTypeTraitExpr *expr);
420434

421435
virtual bool VisitTypeTraitExpr(clang::TypeTraitExpr *expr);
436+
422437
virtual bool VisitSizeOfPackExpr(clang::SizeOfPackExpr *expr);
423438

424439
virtual bool VisitOffsetOfExpr(clang::OffsetOfExpr *expr);

‎cpp2rust/converter/converter_lib.cpp‎

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,44 @@ bool IsOverloadedMethod(const clang::CXXMethodDecl *decl) {
288288
}) > 1;
289289
}
290290

291+
const char *GetCopyOrMoveName(const clang::CXXMethodDecl *method) {
292+
if (auto *ctor = clang::dyn_cast<clang::CXXConstructorDecl>(method)) {
293+
if (ctor->isCopyConstructor()) {
294+
return "copy_from";
295+
}
296+
if (ctor->isMoveConstructor()) {
297+
return "move_from";
298+
}
299+
return nullptr;
300+
}
301+
if (method->isCopyAssignmentOperator()) {
302+
return "copy_assign";
303+
}
304+
if (method->isMoveAssignmentOperator()) {
305+
return "move_assign";
306+
}
307+
return nullptr;
308+
}
309+
310+
bool CanUseCopyOrMoveName(const clang::CXXMethodDecl *decl,
311+
const std::string &name) {
312+
const auto *record = decl->getParent();
313+
bool is_unique_member =
314+
std::count_if(record->method_begin(), record->method_end(),
315+
[&name](const clang::CXXMethodDecl *method) {
316+
const char *method_name = GetCopyOrMoveName(method);
317+
return !method->isDeleted() && method_name &&
318+
method_name == name;
319+
}) == 1;
320+
bool is_unique_name =
321+
std::none_of(record->method_begin(), record->method_end(),
322+
[&name](const clang::CXXMethodDecl *method) {
323+
return method->getDeclName().isIdentifier() &&
324+
method->getName() == name;
325+
});
326+
return is_unique_member && is_unique_name;
327+
}
328+
291329
bool IsUserDefinedCopyConstructor(const clang::CXXConstructorDecl *ctor) {
292330
return ctor->isCopyConstructor() && ctor->isUserProvided() &&
293331
IsUserDefinedDecl(ctor);
@@ -1005,6 +1043,38 @@ std::string GetFunctionBaseName(const clang::FunctionDecl *decl) {
10051043
return decl->getNameAsString();
10061044
}
10071045

1046+
void ToIdentifier(std::string &name) {
1047+
ReplaceAll(name, "[", "arr");
1048+
ReplaceAll(name, "]", "arr");
1049+
ReplaceAll(name, ";", "_");
1050+
ReplaceAll(name, ",", "_");
1051+
name.erase(std::remove_if(name.begin(), name.end(),
1052+
[](char c) {
1053+
return c == '<' || c == '>' || c == ' ' ||
1054+
c == ':' || c == '(' || c == ')' ||
1055+
c == '-';
1056+
}),
1057+
name.end());
1058+
std::replace(name.begin(), name.end(), '*', 'p');
1059+
}
1060+
1061+
std::string GetConversionName(const clang::CXXConversionDecl *decl,
1062+
const std::string &rust_type) {
1063+
if (decl->getParent()->isLambda()) {
1064+
return GetFunctionBaseName(decl);
1065+
}
1066+
auto name = "to_" + rust_type;
1067+
ToIdentifier(name);
1068+
const auto *record = decl->getParent();
1069+
bool is_unique_name =
1070+
std::none_of(record->method_begin(), record->method_end(),
1071+
[&name](const clang::CXXMethodDecl *method) {
1072+
return method->getDeclName().isIdentifier() &&
1073+
method->getName() == name;
1074+
});
1075+
return is_unique_name ? name : GetFunctionBaseName(decl);
1076+
}
1077+
10081078
clang::CXXDestructorDecl *
10091079
GetUserDefinedDestructor(const clang::CXXRecordDecl *decl) {
10101080
if (!decl->hasDefinition() || !IsUserDefinedDecl(decl) ||

‎cpp2rust/converter/converter_lib.h‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,11 @@ void ForEachTemplateInstantiatedMethod(
7070

7171
bool IsOverloadedMethod(const clang::CXXMethodDecl *decl);
7272

73+
const char *GetCopyOrMoveName(const clang::CXXMethodDecl *method);
74+
75+
bool CanUseCopyOrMoveName(const clang::CXXMethodDecl *decl,
76+
const std::string &name);
77+
7378
bool IsUserDefinedCopyConstructor(const clang::CXXConstructorDecl *ctor);
7479

7580
bool IsConvertibleCopyOrMoveConstructor(const clang::CXXConstructorDecl *ctor);
@@ -174,6 +179,11 @@ const char *GetOverloadedOperator(const clang::FunctionDecl *decl);
174179

175180
std::string GetFunctionBaseName(const clang::FunctionDecl *decl);
176181

182+
void ToIdentifier(std::string &name);
183+
184+
std::string GetConversionName(const clang::CXXConversionDecl *decl,
185+
const std::string &rust_type);
186+
177187
bool IsImplicitAssignmentCall(const clang::CallExpr *expr);
178188
bool IsUserOperatorCall(const clang::CXXOperatorCallExpr *expr);
179189

‎cpp2rust/converter/models/converter_refcount.cpp‎

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1601,6 +1601,7 @@ void ConverterRefCount::ConvertBinaryOperator(clang::BinaryOperator *expr) {
16011601
}
16021602

16031603
bool ConverterRefCount::VisitInitListExpr(clang::InitListExpr *expr) {
1604+
auto *syntactic = expr->isSyntacticForm() ? expr : expr->getSyntacticForm();
16041605
if (auto form = expr->getSemanticForm())
16051606
expr = form;
16061607

@@ -1626,6 +1627,15 @@ bool ConverterRefCount::VisitInitListExpr(clang::InitListExpr *expr) {
16261627
return false;
16271628
}
16281629

1630+
if (syntactic->getNumInits() == 0) {
1631+
{
1632+
PushConversionKind push(*this, ConversionKind::Unboxed);
1633+
StrCat(GetDefaultAsString(qual_type));
1634+
}
1635+
computed_expr_type_ = ComputedExprType::FreshValue;
1636+
return false;
1637+
}
1638+
16291639
StrCat(GetUnsafeTypeAsString(qual_type));
16301640
{
16311641
PushBrace brace(*this);
@@ -2122,6 +2132,18 @@ std::string ConverterRefCount::GetDefaultAsString(clang::QualType qual_type) {
21222132

21232133
std::string
21242134
ConverterRefCount::GetDefaultAsStringFallback(clang::QualType qual_type) {
2135+
auto canonical = qual_type.getUnqualifiedType().getCanonicalType();
2136+
if (canonical->isBooleanType() ||
2137+
(canonical->isIntegerType() && !canonical->isEnumeralType()) ||
2138+
canonical->isFloatingType()) {
2139+
std::string unboxed;
2140+
{
2141+
PushConversionKind push(*this, ConversionKind::Unboxed);
2142+
unboxed = Converter::GetDefaultAsStringFallback(qual_type);
2143+
}
2144+
return BoxValue(std::move(unboxed));
2145+
}
2146+
21252147
return std::format("<{}>::default()", ToString(qual_type));
21262148
}
21272149

‎docs/src/codegen/types/classes.md‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,9 +90,9 @@ behind pointers, is emitted at the end of the file as an empty
9090

9191
A constructor becomes an associated function named after the class. It opens
9292
with `let mut this = Self { ... }`, one field per member initializer, then runs
93-
the C++ body and returns `this`. Only implicit or defaulted copy and move
94-
constructors are supported: a user-defined one stops the translation, and the
95-
implicit copy is what the `Clone` impl represents.
93+
the C++ body and returns `this`. Copy and move constructors become `copy_from`
94+
and `move_from` (see [Naming](./naming.md)); the `Clone` impl calls `copy_from`
95+
when the copy constructor is user-defined.
9696

9797
Methods take `&self` when `const` and `&mut self` otherwise in the unsafe model.
9898
In the refcount model they always take `&self`, since mutation goes through the

‎docs/src/codegen/types/naming.md‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,8 @@ name unless they are overloaded, in which case the parameter types are appended
2727
(`method_i32`, `method_i32_const`). `operator<` is emitted as `lt`; comparison
2828
operators additionally produce the corresponding trait impls (`PartialOrd`,
2929
`Ord`, `PartialEq`).
30+
31+
Copy and move constructors are named `copy_from` and `move_from`, and copy and
32+
move assignment operators `copy_assign` and `move_assign`, as long as the class
33+
has only one member of that kind and no method already uses the name; otherwise
34+
they get the overloaded form.

‎rules/new/src.cpp‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,5 @@ void f2(void *a0) { return ::operator delete(a0); }
1010
void *f3(std::size_t a0) { return ::operator new[](a0); }
1111

1212
void f4(void *a0) { return ::operator delete[](a0); }
13+
14+
template <typename T1> T1 *f5(T1 *a0) { return std::launder(a0); }

‎rules/new/tgt_refcount.rs‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,7 @@ fn f3(a0: usize) -> AnyPtr {
1818
fn f4(a0: AnyPtr) {
1919
libcc2rs::free_refcount(a0)
2020
}
21+
22+
fn f5<T1>(a0: Ptr<T1>) -> Ptr<T1> {
23+
a0
24+
}

‎rules/new/tgt_unsafe.rs‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,7 @@ unsafe fn f3(a0: usize) -> *mut ::libc::c_void {
1616
unsafe fn f4(a0: *mut ::libc::c_void) {
1717
libcc2rs::free_unsafe(a0)
1818
}
19+
20+
unsafe fn f5<T1>(a0: *mut T1) -> *mut T1 {
21+
a0
22+
}

0 commit comments

Comments
 (0)