|
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" |
@@ -1059,7 +1060,10 @@ void Converter::ConvertLoopVariable(clang::VarDecl *decl, |
1059 | 1060 | StrCat(std::format(".as_mut_ptr().add({})", loop_var_name)); |
1060 | 1061 | } |
1061 | 1062 | } else { |
1062 | | - Convert(range_init); |
| 1063 | + { |
| 1064 | + PushExplicitAutoref autoref(*this, /*is_mut=*/false); |
| 1065 | + Convert(range_init); |
| 1066 | + } |
1063 | 1067 | StrCat(std::format("[{}]", loop_var_name)); |
1064 | 1068 | StrCat(".clone()"); |
1065 | 1069 | } |
@@ -2218,19 +2222,25 @@ void Converter::EmitStmtExprTail(clang::Expr *tail) { Convert(tail); } |
2218 | 2222 | bool Converter::VisitConditionalOperator(clang::ConditionalOperator *expr) { |
2219 | 2223 | StrCat(keyword::kIf); |
2220 | 2224 | ConvertCondition(expr->getCond()); |
| 2225 | + bool branch_is_addr = |
| 2226 | + expr->isLValue() && !isRValue() && !expr->getType()->isFunctionType(); |
2221 | 2227 | { |
2222 | 2228 | PushBrace then_brace(*this); |
2223 | | - if (expr->isLValue() && !isRValue() && !expr->getType()->isFunctionType()) { |
| 2229 | + if (branch_is_addr) { |
2224 | 2230 | StrCat(token::kRef, keyword_mut_); |
2225 | 2231 | } |
| 2232 | + PushExplicitAutoref no_autoref(*this, branch_is_addr ? std::nullopt |
| 2233 | + : autoref_mut_); |
2226 | 2234 | Convert(expr->getTrueExpr()); |
2227 | 2235 | } |
2228 | 2236 | StrCat(keyword::kElse); |
2229 | 2237 | { |
2230 | 2238 | PushBrace else_brace(*this); |
2231 | | - if (expr->isLValue() && !isRValue() && !expr->getType()->isFunctionType()) { |
| 2239 | + if (branch_is_addr) { |
2232 | 2240 | StrCat(token::kRef, keyword_mut_); |
2233 | 2241 | } |
| 2242 | + PushExplicitAutoref no_autoref(*this, branch_is_addr ? std::nullopt |
| 2243 | + : autoref_mut_); |
2234 | 2244 | Convert(expr->getFalseExpr()); |
2235 | 2245 | } |
2236 | 2246 | return false; |
@@ -2285,11 +2295,7 @@ bool Converter::VisitDeclRefExpr(clang::DeclRefExpr *expr) { |
2285 | 2295 |
|
2286 | 2296 | if (decl->getType()->getAs<clang::ReferenceType>() && !isAddrOf() && |
2287 | 2297 | !map_iter_decls_.contains(clang::dyn_cast<clang::VarDecl>(decl))) { |
2288 | | - { |
2289 | | - PushParen paren(*this); |
2290 | | - StrCat(GetPointerDerefPrefix(decl->getType().getNonReferenceType()), |
2291 | | - std::move(str)); |
2292 | | - } |
| 2298 | + EmitDeref(std::move(str), decl->getType().getNonReferenceType()); |
2293 | 2299 | SetValueFreshness(expr->getType()); |
2294 | 2300 | return false; |
2295 | 2301 | } |
@@ -2362,9 +2368,11 @@ bool Converter::ConvertCXXOperatorCallExpr(clang::CXXOperatorCallExpr *expr) { |
2362 | 2368 | Convert(expr->getArg(0)); |
2363 | 2369 | } |
2364 | 2370 | break; |
2365 | | - case clang::OverloadedOperatorKind::OO_Subscript: |
| 2371 | + case clang::OverloadedOperatorKind::OO_Subscript: { |
| 2372 | + PushExplicitAutoref autoref(*this, IsMutatingCall(expr)); |
2366 | 2373 | ConvertArraySubscript(expr->getArg(0), expr->getArg(1), expr->getType()); |
2367 | 2374 | break; |
| 2375 | + } |
2368 | 2376 | case clang::OverloadedOperatorKind::OO_LessLess: |
2369 | 2377 | if (IsCallToOstream(expr)) { |
2370 | 2378 | ConvertCallToOstream(expr); |
@@ -2430,8 +2438,7 @@ bool Converter::VisitMemberExpr(clang::MemberExpr *expr) { |
2430 | 2438 | } |
2431 | 2439 |
|
2432 | 2440 | if (!isAddrOf() && member->getType()->isReferenceType()) { |
2433 | | - PushParen paren(*this); |
2434 | | - StrCat(GetPointerDerefPrefix(member->getType().getNonReferenceType()), str); |
| 2441 | + EmitDeref(std::move(str), member->getType().getNonReferenceType()); |
2435 | 2442 | return false; |
2436 | 2443 | } |
2437 | 2444 |
|
@@ -3200,10 +3207,14 @@ void Converter::ConvertPointerOffset(clang::Expr *base, clang::Expr *idx, |
3200 | 3207 |
|
3201 | 3208 | void Converter::ConvertArraySubscript(clang::Expr *base, clang::Expr *idx, |
3202 | 3209 | clang::QualType type) { |
3203 | | - Convert(base->IgnoreImplicit()); |
3204 | 3210 | if (IsUniquePtr(base->getType())) { |
| 3211 | + PushExplicitAutoref no_autoref(*this, std::nullopt); |
| 3212 | + Convert(base->IgnoreImplicit()); |
3205 | 3213 | StrCat(".as_mut().unwrap()"); |
| 3214 | + } else { |
| 3215 | + Convert(base->IgnoreImplicit()); |
3206 | 3216 | } |
| 3217 | + PushExplicitAutoref no_autoref(*this, std::nullopt); |
3207 | 3218 | PushBracket bracket(*this); |
3208 | 3219 | { |
3209 | 3220 | PushParen paren(*this); |
@@ -3509,11 +3520,19 @@ void Converter::ConvertAddrOf(clang::Expr *expr, clang::QualType pointer_type) { |
3509 | 3520 | } |
3510 | 3521 | } |
3511 | 3522 |
|
| 3523 | +void Converter::EmitDeref(std::string inner, clang::QualType pointee_type) { |
| 3524 | + auto wrap = std::exchange(autoref_mut_, std::nullopt); |
| 3525 | + PushParen outer(*this, wrap.has_value()); |
| 3526 | + if (wrap) { |
| 3527 | + StrCat(*wrap ? "&mut" : "&"); |
| 3528 | + } |
| 3529 | + PushParen paren(*this); |
| 3530 | + StrCat(GetPointerDerefPrefix(pointee_type), std::move(inner)); |
| 3531 | +} |
| 3532 | + |
3512 | 3533 | void Converter::ConvertDeref(clang::Expr *expr) { |
3513 | 3534 | if (!isAddrOf()) { |
3514 | | - PushParen paren(*this); |
3515 | | - StrCat(GetPointerDerefPrefix(expr->getType()->getPointeeType()), |
3516 | | - ToString(expr)); |
| 3535 | + EmitDeref(ToString(expr), expr->getType()->getPointeeType()); |
3517 | 3536 | } else { |
3518 | 3537 | Convert(expr); |
3519 | 3538 | } |
|
0 commit comments