|
9 | 9 | #include <llvm/Support/ConvertUTF.h> |
10 | 10 |
|
11 | 11 | #include <format> |
| 12 | +#include <utility> |
12 | 13 |
|
13 | 14 | #include "compiler.h" |
14 | 15 | #include "converter/converter_lib.h" |
@@ -1060,7 +1061,7 @@ void Converter::ConvertLoopVariable(clang::VarDecl *decl, |
1060 | 1061 | } |
1061 | 1062 | } else { |
1062 | 1063 | { |
1063 | | - PushAutorefReceiver autoref(*this, /*is_mut=*/false); |
| 1064 | + PushExplicitAutoref autoref(*this, /*is_mut=*/false); |
1064 | 1065 | Convert(range_init); |
1065 | 1066 | } |
1066 | 1067 | StrCat(std::format("[{}]", loop_var_name)); |
@@ -2224,20 +2225,22 @@ bool Converter::VisitConditionalOperator(clang::ConditionalOperator *expr) { |
2224 | 2225 | bool branch_is_addr = |
2225 | 2226 | expr->isLValue() && !isRValue() && !expr->getType()->isFunctionType(); |
2226 | 2227 | { |
2227 | | - PushBrace then_brace(*this); |
| 2228 | + PushBrace brace(*this); |
2228 | 2229 | if (branch_is_addr) { |
2229 | 2230 | StrCat(token::kRef, keyword_mut_); |
2230 | | - autoref_receiver_ = false; |
2231 | 2231 | } |
| 2232 | + PushExplicitAutoref no_autoref(*this, branch_is_addr ? std::optional<bool>{} |
| 2233 | + : autoref_mut_); |
2232 | 2234 | Convert(expr->getTrueExpr()); |
2233 | 2235 | } |
2234 | 2236 | StrCat(keyword::kElse); |
2235 | 2237 | { |
2236 | | - PushBrace else_brace(*this); |
| 2238 | + PushBrace brace(*this); |
2237 | 2239 | if (branch_is_addr) { |
2238 | 2240 | StrCat(token::kRef, keyword_mut_); |
2239 | | - autoref_receiver_ = false; |
2240 | 2241 | } |
| 2242 | + PushExplicitAutoref no_autoref(*this, branch_is_addr ? std::optional<bool>{} |
| 2243 | + : autoref_mut_); |
2241 | 2244 | Convert(expr->getFalseExpr()); |
2242 | 2245 | } |
2243 | 2246 | return false; |
@@ -2292,8 +2295,7 @@ bool Converter::VisitDeclRefExpr(clang::DeclRefExpr *expr) { |
2292 | 2295 |
|
2293 | 2296 | if (decl->getType()->getAs<clang::ReferenceType>() && !isAddrOf() && |
2294 | 2297 | !map_iter_decls_.contains(clang::dyn_cast<clang::VarDecl>(decl))) { |
2295 | | - EmitMaybeWrappedDeref(std::move(str), |
2296 | | - decl->getType().getNonReferenceType()); |
| 2298 | + EmitDeref(std::move(str), decl->getType().getNonReferenceType()); |
2297 | 2299 | SetValueFreshness(expr->getType()); |
2298 | 2300 | return false; |
2299 | 2301 | } |
@@ -2373,7 +2375,7 @@ bool Converter::ConvertCXXOperatorCallExpr(clang::CXXOperatorCallExpr *expr) { |
2373 | 2375 | is_mut = !method->isConst(); |
2374 | 2376 | } |
2375 | 2377 | } |
2376 | | - PushAutorefReceiver autoref(*this, is_mut); |
| 2378 | + PushExplicitAutoref autoref(*this, is_mut); |
2377 | 2379 | ConvertArraySubscript(expr->getArg(0), expr->getArg(1), expr->getType()); |
2378 | 2380 | break; |
2379 | 2381 | } |
@@ -2442,8 +2444,7 @@ bool Converter::VisitMemberExpr(clang::MemberExpr *expr) { |
2442 | 2444 | } |
2443 | 2445 |
|
2444 | 2446 | if (!isAddrOf() && member->getType()->isReferenceType()) { |
2445 | | - EmitMaybeWrappedDeref(std::move(str), |
2446 | | - member->getType().getNonReferenceType()); |
| 2447 | + EmitDeref(std::move(str), member->getType().getNonReferenceType()); |
2447 | 2448 | return false; |
2448 | 2449 | } |
2449 | 2450 |
|
@@ -2471,19 +2472,18 @@ void Converter::ConvertMemberExpr(clang::MemberExpr *expr) { |
2471 | 2472 | auto *base = expr->getBase(); |
2472 | 2473 | bool base_is_this = clang::isa<clang::CXXThisExpr>(base->IgnoreCasts()); |
2473 | 2474 | PushExprKind push(*this, isLValue() ? ExprKind::LValue : ExprKind::RValue); |
2474 | | - std::optional<PushAutorefReceiver> autoref; |
2475 | | - if (auto *method = clang::dyn_cast<clang::CXXMethodDecl>(member); |
2476 | | - method && !method->isStatic() && isCallee() && !base_is_this) { |
2477 | | - autoref.emplace(*this, !method->isConst()); |
2478 | | - } |
| 2475 | + auto *method = clang::dyn_cast<clang::CXXMethodDecl>(member); |
| 2476 | + PushExplicitAutoref autoref(*this, method && !method->isStatic() && |
| 2477 | + isCallee() && !base_is_this |
| 2478 | + ? std::optional{!method->isConst()} |
| 2479 | + : autoref_mut_); |
2479 | 2480 | if (expr->isArrow() && !base_is_this) { |
2480 | 2481 | ConvertArrow(base); |
2481 | 2482 | } else { |
2482 | 2483 | Convert(base); |
2483 | 2484 | } |
2484 | 2485 |
|
2485 | | - if (auto *method = clang::dyn_cast<clang::CXXMethodDecl>(member); |
2486 | | - method && IsOverloadedMethod(method)) { |
| 2486 | + if (method && IsOverloadedMethod(method)) { |
2487 | 2487 | StrCat(token::kDot); |
2488 | 2488 | StrCat(GetOverloadedFunctionName(method)); |
2489 | 2489 | } else { |
@@ -3217,15 +3217,14 @@ void Converter::ConvertPointerOffset(clang::Expr *base, clang::Expr *idx, |
3217 | 3217 |
|
3218 | 3218 | void Converter::ConvertArraySubscript(clang::Expr *base, clang::Expr *idx, |
3219 | 3219 | clang::QualType type) { |
3220 | | - bool is_unique_ptr = IsUniquePtr(base->getType()); |
3221 | | - if (is_unique_ptr) { |
3222 | | - autoref_receiver_ = false; |
3223 | | - } |
3224 | | - Convert(base->IgnoreImplicit()); |
3225 | | - if (is_unique_ptr) { |
| 3220 | + if (IsUniquePtr(base->getType())) { |
| 3221 | + PushExplicitAutoref no_autoref(*this, std::nullopt); |
| 3222 | + Convert(base->IgnoreImplicit()); |
3226 | 3223 | StrCat(".as_mut().unwrap()"); |
| 3224 | + } else { |
| 3225 | + Convert(base->IgnoreImplicit()); |
3227 | 3226 | } |
3228 | | - autoref_receiver_ = false; |
| 3227 | + PushExplicitAutoref no_autoref(*this, std::nullopt); |
3229 | 3228 | PushBracket bracket(*this); |
3230 | 3229 | { |
3231 | 3230 | PushParen paren(*this); |
@@ -3531,26 +3530,19 @@ void Converter::ConvertAddrOf(clang::Expr *expr, clang::QualType pointer_type) { |
3531 | 3530 | } |
3532 | 3531 | } |
3533 | 3532 |
|
3534 | | -void Converter::EmitMaybeWrappedDeref(std::string inner, |
3535 | | - clang::QualType pointee_type) { |
3536 | | - bool wrap = autoref_receiver_; |
3537 | | - bool wrap_mut = autoref_receiver_mut_; |
3538 | | - autoref_receiver_ = false; |
| 3533 | +void Converter::EmitDeref(std::string inner, clang::QualType pointee_type) { |
| 3534 | + auto wrap = std::exchange(autoref_mut_, std::nullopt); |
| 3535 | + PushParen outer(*this, wrap.has_value()); |
3539 | 3536 | if (wrap) { |
3540 | | - StrCat("(", wrap_mut ? "&mut " : "&"); |
3541 | | - } |
3542 | | - { |
3543 | | - PushParen paren(*this); |
3544 | | - StrCat(GetPointerDerefPrefix(pointee_type), std::move(inner)); |
3545 | | - } |
3546 | | - if (wrap) { |
3547 | | - StrCat(")"); |
| 3537 | + StrCat(*wrap ? "&mut" : "&"); |
3548 | 3538 | } |
| 3539 | + PushParen paren(*this); |
| 3540 | + StrCat(GetPointerDerefPrefix(pointee_type), std::move(inner)); |
3549 | 3541 | } |
3550 | 3542 |
|
3551 | 3543 | void Converter::ConvertDeref(clang::Expr *expr) { |
3552 | 3544 | if (!isAddrOf()) { |
3553 | | - EmitMaybeWrappedDeref(ToString(expr), expr->getType()->getPointeeType()); |
| 3545 | + EmitDeref(ToString(expr), expr->getType()->getPointeeType()); |
3554 | 3546 | } else { |
3555 | 3547 | Convert(expr); |
3556 | 3548 | } |
|
0 commit comments