Skip to content

Commit 2e76b75

Browse files
authored
1 parent 8f677b7 commit 2e76b75

1 file changed

Lines changed: 32 additions & 14 deletions

File tree

cpp2rust/converter/converter.cpp

Lines changed: 32 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3479,14 +3479,9 @@ std::string Converter::GetUnsafeTypeAsString(clang::QualType qual_type) const {
34793479

34803480
void Converter::ConvertVarInit(clang::QualType qual_type, clang::Expr *expr) {
34813481
if (qual_type->isReferenceType() && !IsReferenceType(expr)) {
3482-
if (IsGlobalVar(expr)) {
3483-
StrCat("&raw");
3484-
StrCat(IsMut(qual_type) ? keyword_mut_ : keyword::kConst);
3485-
} else {
3486-
StrCat(token::kRef);
3487-
if (IsMut(qual_type)) {
3488-
StrCat(keyword_mut_);
3489-
}
3482+
StrCat(token::kRef);
3483+
if (IsMut(qual_type)) {
3484+
StrCat(keyword_mut_);
34903485
}
34913486
}
34923487
if (qual_type->isFunctionPointerType()) {
@@ -4179,12 +4174,35 @@ std::string Converter::ConvertIRFragment(
41794174
auto all_args = BuildUnifiedArgs(expr, args, num_args);
41804175

41814176
std::string result;
4182-
for (auto &frag : fragments) {
4183-
if (auto *t = std::get_if<TextFragment>(&frag)) {
4184-
result += t->text;
4185-
} else if (auto *g = std::get_if<GenericFragment>(&frag)) {
4177+
for (size_t i = 0; i < fragments.size(); ++i) {
4178+
const auto &frag = fragments[i];
4179+
if (const auto *t = std::get_if<TextFragment>(&frag)) {
4180+
std::string text = t->text;
4181+
// If this text fragment ends with a lone '&' (reference operator, not
4182+
// '&&' or '&mut') and the immediately following fragment is a placeholder
4183+
// for a global variable, upgrade '&' to '&raw const' or '&raw mut' to
4184+
// comply with Rust 2024's ban on shared references to mutable statics.
4185+
if (!text.empty() && text.back() == '&' &&
4186+
(text.size() < 2 || text[text.size() - 2] != '&') &&
4187+
i + 1 < fragments.size()) {
4188+
if (const auto *next_ph =
4189+
std::get_if<PlaceholderFragment>(&fragments[i + 1])) {
4190+
auto next_idx = next_ph->n;
4191+
if (next_idx < all_args.size() && IsGlobalVar(all_args[next_idx])) {
4192+
const auto *decl_ref = clang::dyn_cast<clang::DeclRefExpr>(
4193+
all_args[next_idx]->IgnoreImplicit());
4194+
bool is_const =
4195+
decl_ref &&
4196+
decl_ref->getDecl()->getType().isConstQualified();
4197+
text.pop_back(); // remove '&'
4198+
text += is_const ? "&raw const " : std::string("&raw") + keyword_mut_;
4199+
}
4200+
}
4201+
}
4202+
result += text;
4203+
} else if (const auto *g = std::get_if<GenericFragment>(&frag)) {
41864204
result += Mapper::InstantiateTemplate(GetCalleeOrExpr(expr), g->n);
4187-
} else if (auto *ph = std::get_if<PlaceholderFragment>(&frag)) {
4205+
} else if (const auto *ph = std::get_if<PlaceholderFragment>(&frag)) {
41884206
auto arg_idx = ph->n;
41894207
assert(arg_idx < all_args.size());
41904208
auto *arg = all_args[arg_idx];
@@ -4204,7 +4222,7 @@ std::string Converter::ConvertIRFragment(
42044222
.is_index_base = ph->is_index_base,
42054223
};
42064224
result += ConvertPlaceholder(expr, arg, ph_ctx);
4207-
} else if (auto *mc =
4225+
} else if (const auto *mc =
42084226
std::get_if<std::unique_ptr<MethodCallFragment>>(&frag)) {
42094227
result += ConvertMappedMethodCall(expr, **mc, args, num_args, ctx);
42104228
}

0 commit comments

Comments
 (0)