Skip to content

Commit 45aefe8

Browse files
authored
Merge branch 'master' into new-lambda-shapes
2 parents 87e68ef + 2a57d76 commit 45aefe8

172 files changed

Lines changed: 3500 additions & 622 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: 148 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -268,12 +268,15 @@ bool Converter::VisitConstantArrayType(clang::ConstantArrayType *type) {
268268
bool Converter::VisitIncompleteArrayType(clang::IncompleteArrayType *type) {
269269
StrCat('[');
270270
Convert(type->getElementType());
271-
StrCat(']');
271+
StrCat("; 0]");
272272
return false;
273273
}
274274

275275
bool Converter::VisitReferenceType(clang::ReferenceType *type) {
276276
auto pointee_type = type->getPointeeType();
277+
if (pointee_type->isFunctionType()) {
278+
return Convert(ctx_.getPointerType(pointee_type));
279+
}
277280
StrCat(pointee_type.isConstQualified() ? "*const" : "*mut");
278281
return Convert(pointee_type);
279282
}
@@ -429,6 +432,12 @@ void Converter::ConvertFunctionBody(clang::FunctionDecl *decl) {
429432
return;
430433
}
431434
auto compound = clang::dyn_cast<clang::CompoundStmt>(decl->getBody());
435+
if (decl->isMain() && compound &&
436+
(compound->body_empty() ||
437+
!clang::isa<clang::ReturnStmt>(compound->body_back()))) {
438+
StrCat('0');
439+
return;
440+
}
432441
if (!compound || compound->body_empty()) {
433442
return;
434443
}
@@ -596,6 +605,14 @@ void Converter::EmitScopedDestructor(const clang::VarDecl *decl) {
596605
return;
597606
}
598607
auto type = decl->getType();
608+
if (auto lambda = AsLambdaClass(type);
609+
lambda && LambdaNeedsDestruction(lambda)) {
610+
StrCat(token::kSemiColon,
611+
std::format("let _dtor_{0} = ScopedDestructorUnsafe::new(&raw mut "
612+
"{0}, |__f| __f.destroy())",
613+
GetNamedDeclAsString(decl)));
614+
return;
615+
}
599616
if (type->isReferenceType() || type->isArrayType() ||
600617
!TypeNeedsDestruction(type)) {
601618
return;
@@ -981,7 +998,7 @@ void Converter::DefineImplicitMembers(clang::CXXRecordDecl *decl) {
981998
}
982999
if (ctor->isMoveConstructor() && !ctor->isUserProvided() &&
9831000
!ctor->doesThisDeclarationHaveABody() && !ctor->isDeleted() &&
984-
!HasDefaultedCopyConstructor(decl)) {
1001+
(decl->isLambda() || !HasDefaultedCopyConstructor(decl))) {
9851002
sema_->DefineImplicitMoveConstructor(decl->getLocation(), ctor);
9861003
}
9871004
}
@@ -1134,8 +1151,7 @@ bool Converter::VisitCXXConstructorDecl(clang::CXXConstructorDecl *decl) {
11341151
}
11351152
PushCurrFunction push_fn(*this, decl);
11361153

1137-
if (decl->isCopyOrMoveConstructor() &&
1138-
!decl->doesThisDeclarationHaveABody()) {
1154+
if (decl->isCopyOrMoveConstructor() && !decl->hasBody()) {
11391155
return false;
11401156
}
11411157

@@ -1338,7 +1354,8 @@ bool Converter::VisitCompoundStmt(clang::CompoundStmt *stmt) {
13381354

13391355
bool Converter::VisitDeclStmt(clang::DeclStmt *stmt) {
13401356
for (auto *decl : stmt->decls()) {
1341-
if (clang::isa<clang::TagDecl>(decl)) {
1357+
auto *var = clang::dyn_cast<clang::VarDecl>(decl);
1358+
if (clang::isa<clang::TagDecl>(decl) || (var && var->isStaticLocal())) {
13421359
Buffer buf(*this);
13431360
Convert(decl);
13441361
hoisted_records_ += std::move(buf).str();
@@ -1382,13 +1399,15 @@ bool Converter::VisitIfStmt(clang::IfStmt *stmt) {
13821399
stmt->setInit(init);
13831400
return false;
13841401
}
1385-
StrCat(keyword::kIf);
1386-
if (auto *cond = clang::dyn_cast<clang::ConstantExpr>(stmt->getCond());
1387-
cond && stmt->isConstexpr()) {
1388-
StrCat(cond->getResultAsAPSInt() != 0 ? keyword::kTrue : keyword::kFalse);
1389-
} else {
1390-
ConvertCondition(stmt->getCond());
1402+
if (bool taken = false;
1403+
!stmt->getConditionVariable() && !stmt->isConsteval() &&
1404+
!stmt->getCond()->isValueDependent() &&
1405+
stmt->getCond()->EvaluateAsBooleanCondition(taken, ctx_)) {
1406+
ConvertBody(taken ? stmt->getThen() : stmt->getElse());
1407+
return false;
13911408
}
1409+
StrCat(keyword::kIf);
1410+
ConvertCondition(stmt->getCond());
13921411
ConvertBody(stmt->getThen());
13931412
if (stmt->hasElseStorage()) {
13941413
StrCat(keyword::kElse);
@@ -2406,6 +2425,37 @@ Converter::GetCodeUnitArrayLiteral(const clang::StringLiteral *expr) {
24062425
return out;
24072426
}
24082427

2428+
std::string Converter::GetSourceFileAsString(clang::QualType type) {
2429+
return std::format("concat!(file!(), \"\\0\").as_ptr() as {}",
2430+
ToString(type));
2431+
}
2432+
2433+
bool Converter::VisitSourceLocExpr(clang::SourceLocExpr *expr) {
2434+
switch (expr->getIdentKind()) {
2435+
case clang::SourceLocIdentKind::Line:
2436+
StrCat(std::format("line!() as {}", ToString(expr->getType())));
2437+
computed_expr_type_ = ComputedExprType::FreshValue;
2438+
return false;
2439+
case clang::SourceLocIdentKind::File:
2440+
StrCat(GetSourceFileAsString(expr->getType()));
2441+
computed_expr_type_ = ComputedExprType::FreshPointer;
2442+
return false;
2443+
case clang::SourceLocIdentKind::Function: {
2444+
auto value = expr->EvaluateInContext(ctx_, nullptr);
2445+
auto *str = clang::cast<clang::StringLiteral>(
2446+
value.getLValueBase().get<const clang::Expr *>());
2447+
Convert(clang::ImplicitCastExpr::Create(
2448+
ctx_, expr->getType(), clang::CK_ArrayToPointerDecay,
2449+
const_cast<clang::StringLiteral *>(str), nullptr, clang::VK_PRValue,
2450+
clang::FPOptionsOverride()));
2451+
return false;
2452+
}
2453+
default:
2454+
assert(0 && "unsupported SourceLocExpr");
2455+
return false;
2456+
}
2457+
}
2458+
24092459
bool Converter::VisitStringLiteral(clang::StringLiteral *expr) {
24102460
if (IsCodeUnitStringLiteral(expr)) {
24112461
StrCat(GetCodeUnitArrayLiteral(expr));
@@ -3264,6 +3314,11 @@ bool Converter::VisitMemberExpr(clang::MemberExpr *expr) {
32643314
ConvertDeclRefValue(expr, member);
32653315
return false;
32663316
}
3317+
if (auto field = clang::dyn_cast<clang::FieldDecl>(member);
3318+
field && AsLambdaCapture(field)) {
3319+
ConvertDeclRefValue(expr, member);
3320+
return false;
3321+
}
32673322
if (auto *method = clang::dyn_cast<clang::CXXMethodDecl>(member);
32683323
method && IsMethodOnPtr(method) && !Mapper::Contains(ctx_, expr)) {
32693324
SetUFCSReceiver(expr->getBase(), expr->isArrow(), method);
@@ -3433,6 +3488,11 @@ bool Converter::VisitInitListExpr(clang::InitListExpr *expr) {
34333488
if (auto form = expr->getSemanticForm())
34343489
expr = form;
34353490

3491+
if (expr->isTransparent()) {
3492+
Convert(expr->getInit(0));
3493+
return false;
3494+
}
3495+
34363496
auto qual_type = expr->getType();
34373497
if (qual_type->isScalarType()) {
34383498
assert(expr->getNumInits() < 2 && "Excess elements in scalar initializer");
@@ -3710,6 +3770,12 @@ bool Converter::VisitCXXConstructExpr(clang::CXXConstructExpr *expr) {
37103770
}
37113771

37123772
auto *ctor = expr->getConstructor();
3773+
if (IsLambdaCopyOrMoveConstructor(ctor)) {
3774+
Convert(expr->getArg(0));
3775+
StrCat(std::format(".{}()", GetCopyOrMoveName(ctor)));
3776+
SetFreshType(expr->getType());
3777+
return false;
3778+
}
37133779
if (IsPassThroughConstructor(ctor)) {
37143780
// Take suppress before recursing into the child.
37153781
bool suppress = PushSuppressIteratorClone::take(*this);
@@ -3875,6 +3941,12 @@ bool Converter::VisitLambdaExpr(clang::LambdaExpr *expr) {
38753941
}
38763942
StrCat(token::kComma);
38773943
ConvertLambdaClosure(decl);
3944+
ConvertLambdaCopyAndMove(decl);
3945+
if (LambdaNeedsDestruction(decl)) {
3946+
StrCat(token::kComma, "destroy", token::kAssign);
3947+
PushBrace destroy(*this);
3948+
StrCat(DestroyMembers(decl));
3949+
}
38783950
computed_expr_type_ = ComputedExprType::FreshValue;
38793951
return false;
38803952
}
@@ -3918,6 +3990,25 @@ void Converter::ConvertLambdaClosure(const clang::CXXRecordDecl *decl) {
39183990
ConvertFunctionBody(curr_function_);
39193991
}
39203992

3993+
void Converter::ConvertLambdaCopyAndMove(clang::CXXRecordDecl *decl) {
3994+
DefineImplicitMembers(decl);
3995+
for (auto ctor : decl->ctors()) {
3996+
if (!ctor->isCopyOrMoveConstructor() || ctor->isDeleted()) {
3997+
continue;
3998+
}
3999+
StrCat(token::kComma, GetCopyOrMoveName(ctor));
4000+
PushBrace brace(*this);
4001+
PushCurrFunction push_fn(*this, ctor);
4002+
for (auto init : ctor->inits()) {
4003+
assert(init->isMemberInitializer());
4004+
auto field = init->getMember();
4005+
StrCat(GetNamedDeclAsString(field), token::kColon);
4006+
ConvertVarInit(field->getType(), init->getInit());
4007+
StrCat(token::kComma);
4008+
}
4009+
}
4010+
}
4011+
39214012
bool Converter::VisitImplicitValueInitExpr(clang::ImplicitValueInitExpr *expr) {
39224013
if (auto arr_ty = clang::dyn_cast<clang::ArrayType>(
39234014
expr->getType()->getCanonicalTypeInternal().getTypePtr())) {
@@ -4082,9 +4173,8 @@ std::string Converter::GetArrayDefaultAsString(clang::QualType qual_type) {
40824173
return std::format("[{}; {}]", element_type_as_string,
40834174
size_as_string.c_str());
40844175
}
4085-
if (auto *array_type =
4086-
clang::dyn_cast<clang::IncompleteArrayType>(qual_type)) {
4087-
return GetDefaultAsString(array_type->getElementType());
4176+
if (clang::isa<clang::IncompleteArrayType>(qual_type)) {
4177+
return "[]";
40884178
}
40894179
if (Printer::ToString(ctx_, qual_type).contains("std::array")) {
40904180
assert(GetTemplateArgs(qual_type).has_value());
@@ -4268,6 +4358,12 @@ std::string Converter::GetUnsafeTypeAsString(clang::QualType qual_type) const {
42684358
}
42694359

42704360
void Converter::ConvertVarInit(clang::QualType qual_type, clang::Expr *expr) {
4361+
if (qual_type->isFunctionReferenceType()) {
4362+
PushExprKind push(*this, ExprKind::AddrOf);
4363+
PushInitType init_type(*this, qual_type);
4364+
Convert(expr);
4365+
return;
4366+
}
42714367
if (qual_type->isReferenceType() && !IsReferenceType(expr)) {
42724368
if (llvm::isa<clang::MaterializeTemporaryExpr>(expr->IgnoreImpCasts())) {
42734369
StrCat(EmitMaterializedTempBinding(qual_type, expr));
@@ -4612,6 +4708,32 @@ std::string Converter::GetComparisonCall(const clang::FunctionDecl *op,
46124708
arg(0, lhs), arg(1, rhs));
46134709
}
46144710

4711+
std::string Converter::GetComparisonBool(const clang::FunctionDecl *op,
4712+
const clang::CXXRecordDecl *decl,
4713+
std::string_view lhs,
4714+
std::string_view rhs) {
4715+
auto call = GetComparisonCall(op, decl, lhs, rhs);
4716+
auto ret = op->getReturnType();
4717+
if (ret->isBooleanType()) {
4718+
return call;
4719+
}
4720+
if (ret->isIntegerType()) {
4721+
return std::format("(({}) != 0)", call);
4722+
}
4723+
const auto *record = ret->getAsCXXRecordDecl();
4724+
assert(record && "unsupported comparison operator return type");
4725+
for (const auto *found : record->getVisibleConversionFunctions()) {
4726+
const auto *conversion = clang::dyn_cast<clang::CXXConversionDecl>(found);
4727+
if (conversion && conversion->getConversionType()->isBooleanType()) {
4728+
return std::format("{{ let __cmp = &{}; {}::{}({}) }}", call,
4729+
GetUFCSName(conversion), GetMethodName(conversion),
4730+
GetComparisonReceiver(conversion, record, "__cmp"));
4731+
}
4732+
}
4733+
assert(0 && "comparison operator result has no conversion to bool");
4734+
return call;
4735+
}
4736+
46154737
std::string
46164738
Converter::GetComparisonReferenceArg(const clang::CXXRecordDecl *decl,
46174739
std::string_view value) {
@@ -4639,19 +4761,19 @@ void Converter::ConvertOrdAndPartialOrdTraits(const clang::CXXRecordDecl *decl,
46394761
cmp_body = std::format("if {} {{ std::cmp::Ordering::Less }} else if {} {{ "
46404762
"std::cmp::Ordering::Greater }} else {{ "
46414763
"std::cmp::Ordering::Equal }}",
4642-
GetComparisonCall(lt, decl, "self", "other"),
4643-
GetComparisonCall(lt, decl, "other", "self"));
4764+
GetComparisonBool(lt, decl, "self", "other"),
4765+
GetComparisonBool(lt, decl, "other", "self"));
46444766
}
46454767

46464768
if (eq) {
4647-
eq_body = GetComparisonCall(eq, decl, "self", "other");
4769+
eq_body = GetComparisonBool(eq, decl, "self", "other");
46484770
} else if (cmp) {
46494771
eq_body = std::format("{} == std::cmp::Ordering::Equal",
46504772
GetComparisonCall(cmp, decl, "self", "other"));
46514773
} else {
46524774
eq_body = std::format("!({}) && !({})",
4653-
GetComparisonCall(lt, decl, "self", "other"),
4654-
GetComparisonCall(lt, decl, "other", "self"));
4775+
GetComparisonBool(lt, decl, "self", "other"),
4776+
GetComparisonBool(lt, decl, "other", "self"));
46554777
}
46564778

46574779
ConvertOrdAndPartialOrdTraitsBase(cmp_body, eq_body, GetRecordName(decl));
@@ -4666,6 +4788,10 @@ void Converter::AddOrdTrait(const clang::CXXRecordDecl *decl) {
46664788
fn->getDescribedFunctionTemplate() || !IsSameTypeComparison(fn, decl)) {
46674789
return;
46684790
}
4791+
if (fn->getOverloadedOperator() == clang::OO_Spaceship &&
4792+
!ctx_.CompCategories.lookupInfoForType(fn->getReturnType())) {
4793+
return;
4794+
}
46694795
switch (fn->getOverloadedOperator()) {
46704796
case clang::OO_EqualEqual:
46714797
eq = fn;
@@ -4967,9 +5093,9 @@ std::string Converter::ConvertPlaceholder(clang::Expr *expr, clang::Expr *arg,
49675093
}
49685094

49695095
if (ph_ctx.declared_in_rule_as_rust_ptr && arg->getType()->isArrayType()) {
4970-
return std::format(
4971-
"({} as {})", ConvertFreshPointer(arg),
4972-
Mapper::GetParamType(ctx_, GetCalleeOrExpr(expr), ph_ctx.arg_idx));
5096+
auto elem = ctx_.getAsArrayType(arg->getType())->getElementType();
5097+
return std::format("({} as {})", ConvertFreshPointer(arg),
5098+
ToStringBase(ctx_.getPointerType(elem)));
49735099
}
49745100

49755101
if (ph_ctx.needs_materialization()) {

‎cpp2rust/converter/converter.h‎

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -382,6 +382,10 @@ class Converter : public clang::RecursiveASTVisitor<Converter> {
382382
uint64_t pad_nulls = 0) const;
383383
virtual bool VisitStringLiteral(clang::StringLiteral *expr);
384384

385+
bool VisitSourceLocExpr(clang::SourceLocExpr *expr);
386+
387+
virtual std::string GetSourceFileAsString(clang::QualType type);
388+
385389
virtual bool VisitCXXBoolLiteralExpr(clang::CXXBoolLiteralExpr *expr);
386390

387391
bool VisitCXXNoexceptExpr(clang::CXXNoexceptExpr *expr);
@@ -477,6 +481,8 @@ class Converter : public clang::RecursiveASTVisitor<Converter> {
477481

478482
void ConvertLambdaClosure(const clang::CXXRecordDecl *decl);
479483

484+
virtual void ConvertLambdaCopyAndMove(clang::CXXRecordDecl *decl);
485+
480486
virtual bool VisitImplicitValueInitExpr(clang::ImplicitValueInitExpr *expr);
481487
virtual bool VisitCXXScalarValueInitExpr(clang::CXXScalarValueInitExpr *expr);
482488

@@ -499,6 +505,10 @@ class Converter : public clang::RecursiveASTVisitor<Converter> {
499505
return true;
500506
}
501507

508+
bool TraverseExplicitInstantiationDecl(clang::ExplicitInstantiationDecl *) {
509+
return true;
510+
}
511+
502512
virtual bool
503513
VisitCXXStdInitializerListExpr(clang::CXXStdInitializerListExpr *expr);
504514

@@ -672,6 +682,10 @@ class Converter : public clang::RecursiveASTVisitor<Converter> {
672682
const clang::CXXRecordDecl *decl,
673683
std::string_view lhs, std::string_view rhs);
674684

685+
std::string GetComparisonBool(const clang::FunctionDecl *op,
686+
const clang::CXXRecordDecl *decl,
687+
std::string_view lhs, std::string_view rhs);
688+
675689
virtual std::string
676690
GetComparisonReferenceArg(const clang::CXXRecordDecl *decl,
677691
std::string_view value);

0 commit comments

Comments
 (0)