Skip to content

Commit b4476f9

Browse files
committed
Merge branch 'master' into in-class-initializer
2 parents f0801a3 + 7a349c9 commit b4476f9

100 files changed

Lines changed: 1450 additions & 792 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: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1102,6 +1102,10 @@ std::string Converter::GetMethodName(const clang::CXXMethodDecl *decl) {
11021102
if (IsOverloadedMethod(decl)) {
11031103
return GetOverloadedFunctionName(decl);
11041104
}
1105+
if (auto *conversion = clang::dyn_cast<clang::CXXConversionDecl>(decl)) {
1106+
return GetConversionName(
1107+
conversion, GetUnsafeTypeAsString(conversion->getConversionType()));
1108+
}
11051109
return GetNamedDeclAsString(decl);
11061110
}
11071111

@@ -1146,10 +1150,9 @@ std::string Converter::GetCtorName(clang::CXXConstructorDecl *decl) {
11461150
if (decl->isCopyOrMoveConstructor()) {
11471151
return GetOverloadedFunctionName(decl);
11481152
}
1149-
return GetRecordName(decl->getParent()) +
1150-
(GetNumberOfConvertingCtors(decl->getParent()) != 1
1151-
? std::to_string(GetCtorIndex(decl))
1152-
: "");
1153+
return GetNumberOfConvertingCtors(decl->getParent()) != 1
1154+
? std::format("new_{}", GetCtorIndex(decl))
1155+
: "new";
11531156
}
11541157

11551158
bool Converter::VisitCXXConstructorDecl(clang::CXXConstructorDecl *decl) {
@@ -1369,7 +1372,12 @@ bool Converter::VisitIfStmt(clang::IfStmt *stmt) {
13691372
return false;
13701373
}
13711374
StrCat(keyword::kIf);
1372-
ConvertCondition(stmt->getCond());
1375+
if (auto *cond = clang::dyn_cast<clang::ConstantExpr>(stmt->getCond());
1376+
cond && stmt->isConstexpr()) {
1377+
StrCat(cond->getResultAsAPSInt() != 0 ? keyword::kTrue : keyword::kFalse);
1378+
} else {
1379+
ConvertCondition(stmt->getCond());
1380+
}
13731381
ConvertBody(stmt->getThen());
13741382
if (stmt->hasElseStorage()) {
13751383
StrCat(keyword::kElse);
@@ -4074,6 +4082,10 @@ std::string Converter::ConvertVarDefaultInit(clang::QualType qual_type) {
40744082
std::string
40754083
Converter::GetOverloadedFunctionName(const clang::FunctionDecl *decl) {
40764084
auto name = GetFunctionBaseName(decl);
4085+
if (auto *conversion = clang::dyn_cast<clang::CXXConversionDecl>(decl)) {
4086+
name = GetConversionName(
4087+
conversion, GetUnsafeTypeAsString(conversion->getConversionType()));
4088+
}
40774089
if (auto *ctor = clang::dyn_cast<clang::CXXConstructorDecl>(decl);
40784090
ctor && !ctor->getParent()->getIdentifier()) {
40794091
name = GetRecordName(ctor->getParent());
@@ -4143,19 +4155,7 @@ Converter::GetOverloadedFunctionName(const clang::FunctionDecl *decl) {
41434155
}
41444156
}
41454157

4146-
ReplaceAll(name, "[", "arr");
4147-
ReplaceAll(name, "]", "arr");
4148-
ReplaceAll(name, ";", "_");
4149-
ReplaceAll(name, ",", "_");
4150-
name.erase(std::remove_if(name.begin(), name.end(),
4151-
[](char c) {
4152-
return c == '<' || c == '>' || c == ' ' ||
4153-
c == ':' || c == '(' || c == ')' ||
4154-
c == '-';
4155-
}),
4156-
name.end());
4157-
std::replace(name.begin(), name.end(), '*', 'p');
4158-
4158+
ToIdentifier(name);
41594159
return name;
41604160
}
41614161

‎cpp2rust/converter/converter.h‎

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

134134
virtual bool VisitCXXMethodDecl(clang::CXXMethodDecl *decl);
135+
135136
virtual bool ShouldConvertMethod(const clang::CXXMethodDecl *decl);
137+
136138
virtual bool ConvertOutOfLineMethod(clang::CXXMethodDecl *decl);
139+
137140
bool ConvertCXXMethodDecl(clang::CXXMethodDecl *decl);
141+
138142
std::string GetMethodName(const clang::CXXMethodDecl *decl);
143+
139144
virtual std::string GetSelfMaybeWithMut(const clang::CXXMethodDecl *decl);
145+
140146
std::string GetCtorName(clang::CXXConstructorDecl *decl);
147+
141148
virtual void ConvertCXXRecordMethods(clang::CXXRecordDecl *decl);
149+
142150
virtual void ConvertLateInstantiatedMethods(clang::CXXRecordDecl *decl);
151+
143152
virtual std::string DestroyMembers(const clang::CXXRecordDecl *decl);
153+
144154
virtual void EmitScopedDestructor(const clang::VarDecl *decl);
155+
145156
void EmitDeallocation(clang::CXXDeleteExpr *expr,
146157
const std::string &argument_as_string);
158+
147159
virtual void SetUFCSReceiver(clang::Expr *base, bool is_arrow,
148160
const clang::CXXMethodDecl *method);
161+
149162
void ConvertUserOperatorCall(clang::CXXOperatorCallExpr *expr);
163+
150164
virtual std::string GetUFCSName(const clang::CXXMethodDecl *method) const;
151165

152166
virtual bool ThisIsRustPtr() const { return false; }
@@ -424,6 +438,7 @@ class Converter : public clang::RecursiveASTVisitor<Converter> {
424438
VisitUnaryExprOrTypeTraitExpr(clang::UnaryExprOrTypeTraitExpr *expr);
425439

426440
virtual bool VisitTypeTraitExpr(clang::TypeTraitExpr *expr);
441+
427442
virtual bool VisitSizeOfPackExpr(clang::SizeOfPackExpr *expr);
428443

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

‎cpp2rust/converter/converter_lib.cpp‎

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -942,6 +942,35 @@ std::string GetFunctionBaseName(const clang::FunctionDecl *decl) {
942942
return decl->getNameAsString();
943943
}
944944

945+
void ToIdentifier(std::string &name) {
946+
ReplaceAll(name, "[", "arr");
947+
ReplaceAll(name, "]", "arr");
948+
ReplaceAll(name, ";", "_");
949+
ReplaceAll(name, ",", "_");
950+
name.erase(std::remove_if(name.begin(), name.end(),
951+
[](char c) {
952+
return c == '<' || c == '>' || c == ' ' ||
953+
c == ':' || c == '(' || c == ')' ||
954+
c == '-';
955+
}),
956+
name.end());
957+
std::replace(name.begin(), name.end(), '*', 'p');
958+
}
959+
960+
std::string GetConversionName(const clang::CXXConversionDecl *decl,
961+
const std::string &rust_type) {
962+
auto name = "to_" + rust_type;
963+
ToIdentifier(name);
964+
const auto *record = decl->getParent();
965+
bool is_unique_name =
966+
std::none_of(record->method_begin(), record->method_end(),
967+
[&name](const clang::CXXMethodDecl *method) {
968+
return method->getDeclName().isIdentifier() &&
969+
method->getName() == name;
970+
});
971+
return is_unique_name ? name : GetFunctionBaseName(decl);
972+
}
973+
945974
clang::CXXDestructorDecl *
946975
GetUserDefinedDestructor(const clang::CXXRecordDecl *decl) {
947976
if (!decl->hasDefinition() || !IsUserDefinedDecl(decl) ||

‎cpp2rust/converter/converter_lib.h‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,11 @@ const char *GetOverloadedOperator(const clang::FunctionDecl *decl);
165165

166166
std::string GetFunctionBaseName(const clang::FunctionDecl *decl);
167167

168+
void ToIdentifier(std::string &name);
169+
170+
std::string GetConversionName(const clang::CXXConversionDecl *decl,
171+
const std::string &rust_type);
172+
168173
bool IsImplicitAssignmentCall(const clang::CallExpr *expr);
169174
bool IsUserOperatorCall(const clang::CXXOperatorCallExpr *expr);
170175

‎cpp2rust/converter/models/converter_refcount.cpp‎

Lines changed: 33 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -215,62 +215,6 @@ bool ConverterRefCount::VisitReferenceType(clang::ReferenceType *type) {
215215
return false;
216216
}
217217

218-
std::string ConverterRefCount::BuildFnAdapter(
219-
const clang::FunctionDecl *src_fn,
220-
const clang::FunctionProtoType *src_proto,
221-
const clang::FunctionProtoType *target_proto) {
222-
223-
// UB: Incompatible arity
224-
if (src_proto->getNumParams() != target_proto->getNumParams()) {
225-
return "None";
226-
}
227-
228-
PushConversionKind push(*this, ConversionKind::Unboxed);
229-
230-
// Build adapter signature: |a0: T0, a1: T1, ...| -> Tr
231-
std::string closure = "(|";
232-
for (unsigned i = 0; i < target_proto->getNumParams(); ++i) {
233-
closure +=
234-
std::format("a{}: {},", i, ToString(target_proto->getParamType(i)));
235-
}
236-
closure += '|';
237-
if (!target_proto->getReturnType()->isVoidType()) {
238-
closure += std::format(" -> {} ", ToString(target_proto->getReturnType()));
239-
}
240-
closure += "{ ";
241-
242-
// Build adapter body: src_fn(convert(a0), convert(a1), ...)
243-
closure += Mapper::MapFunctionName(src_fn) + '(';
244-
for (unsigned i = 0; i < src_proto->getNumParams(); ++i) {
245-
auto src_pty = src_proto->getParamType(i);
246-
auto tgt_pty = target_proto->getParamType(i);
247-
if (ToString(src_pty) == ToString(tgt_pty)) {
248-
closure += std::format("a{}", i);
249-
} else if (src_pty->isPointerType() && tgt_pty->isPointerType()) {
250-
if (tgt_pty->isVoidPointerType()) {
251-
closure += std::format("a{}.reinterpret_cast::<{}>()", i,
252-
ConvertPointeeType(src_pty));
253-
} else if (src_pty->isVoidPointerType()) {
254-
closure += std::format("a{}.to_any()", i);
255-
} else if (tgt_pty->getPointeeType()->isCharType()) {
256-
closure += std::format("a{}.reinterpret_cast::<{}>()", i,
257-
ConvertPointeeType(src_pty));
258-
} else if (src_pty->getPointeeType()->isCharType()) {
259-
closure += std::format("a{}.reinterpret_cast::<{}>()", i,
260-
ConvertPointeeType(src_pty));
261-
}
262-
} else {
263-
// UB: Incompatible types
264-
return "None";
265-
}
266-
closure += ", ";
267-
}
268-
closure += ") })";
269-
270-
return std::format("Some({} as {})", closure,
271-
ConvertFunctionPointerType(target_proto));
272-
}
273-
274218
std::string ConverterRefCount::ConvertFunctionPointerType(
275219
const clang::FunctionProtoType *proto, FnProtoType kind) {
276220
PushConversionKind push(*this, ConversionKind::Unboxed);
@@ -1390,9 +1334,8 @@ bool ConverterRefCount::VisitImplicitCastExpr(clang::ImplicitCastExpr *expr) {
13901334
}
13911335

13921336
void ConverterRefCount::EmitFnPtrCall(clang::Expr *callee) {
1393-
StrCat("(*");
13941337
Convert(callee);
1395-
StrCat(')');
1338+
StrCat(".call");
13961339
}
13971340

13981341
void ConverterRefCount::ConvertFunctionToFunctionPointer(
@@ -1423,25 +1366,8 @@ bool ConverterRefCount::VisitFunctionPointerCast(
14231366
expr->getType()->isFunctionPointerType()) {
14241367
auto target_proto =
14251368
expr->getType()->getPointeeType()->getAs<clang::FunctionProtoType>();
1426-
auto src_proto = expr->getSubExpr()
1427-
->getType()
1428-
->getPointeeType()
1429-
->getAs<clang::FunctionProtoType>();
1430-
auto fn_type = ConvertFunctionPointerType(target_proto);
1431-
1432-
std::string adapter = "None";
1433-
// Only accept direct references to the casted function. Otherwise the
1434-
// closure would be capturing and would not coerce into a fn pointer.
1435-
if (auto *decl_ref = clang::dyn_cast<clang::DeclRefExpr>(
1436-
expr->getSubExpr()->IgnoreImplicit())) {
1437-
if (auto *fn_decl =
1438-
clang::dyn_cast<clang::FunctionDecl>(decl_ref->getDecl())) {
1439-
adapter = BuildFnAdapter(fn_decl, src_proto, target_proto);
1440-
}
1441-
}
1442-
1443-
StrCat(std::format("{}.cast::<{}>({})", ToString(expr->getSubExpr()),
1444-
fn_type, adapter));
1369+
StrCat(std::format("{}.cast::<{}>()", ToString(expr->getSubExpr()),
1370+
ConvertFunctionPointerType(target_proto)));
14451371
} else if (expr->getSubExpr()->getType()->isFunctionPointerType() ||
14461372
expr->getType()->isVoidPointerType()) {
14471373
Convert(expr->getSubExpr());
@@ -1456,6 +1382,7 @@ bool ConverterRefCount::VisitFunctionPointerCast(
14561382
} else {
14571383
assert(0 && "Unhandled function pointer cast");
14581384
}
1385+
computed_expr_type_ = ComputedExprType::FreshPointer;
14591386
return false;
14601387
}
14611388

@@ -2263,11 +2190,40 @@ std::string ConverterRefCount::ConvertVarInitValue(clang::QualType qual_type,
22632190
return std::format("({} as {})", ConvertFreshPointer(expr),
22642191
ToString(qual_type));
22652192
}
2193+
if (qual_type->isFunctionPointerType()) {
2194+
return ConvertFnPtrValue(qual_type, expr);
2195+
}
22662196
return ConvertFreshPointer(expr);
22672197
}
22682198
return ConvertFreshRValue(expr, qual_type);
22692199
}
22702200

2201+
std::string ConverterRefCount::ConvertFnPtrValue(clang::QualType qual_type,
2202+
clang::Expr *expr) {
2203+
auto base = ConvertFreshPointer(expr);
2204+
2205+
// `qual_type` (the expected fn pointer type) and `expr`'s own fn pointer
2206+
// type may differ in spelling only because the translation maps two
2207+
// typedefs of the same C type to distinct Rust types (e.g. size_t vs
2208+
// unsigned long) -- FnPtr::cast handles this (and any other cast)
2209+
// automatically, so just insert it whenever the two differ.
2210+
auto target_proto =
2211+
qual_type->getPointeeType()->getAs<clang::FunctionProtoType>();
2212+
if (!target_proto || !expr->getType()->isFunctionPointerType()) {
2213+
return base;
2214+
}
2215+
auto src_proto =
2216+
expr->getType()->getPointeeType()->getAs<clang::FunctionProtoType>();
2217+
if (!src_proto) {
2218+
return base;
2219+
}
2220+
auto fn_type = ConvertFunctionPointerType(target_proto);
2221+
if (ConvertFunctionPointerType(src_proto) == fn_type) {
2222+
return base;
2223+
}
2224+
return std::format("{}.cast::<{}>()", base, fn_type);
2225+
}
2226+
22712227
void ConverterRefCount::ConvertVarInit(clang::QualType qual_type,
22722228
clang::Expr *expr) {
22732229
bool is_ref = qual_type->isReferenceType();

‎cpp2rust/converter/models/converter_refcount.h‎

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -277,9 +277,12 @@ class ConverterRefCount final : public Converter {
277277
const char *GetPointerDerefSuffix(clang::QualType pointee_type);
278278
const char *GetPointerDerefPrefix(clang::QualType pointee_type) override;
279279

280-
std::string BuildFnAdapter(const clang::FunctionDecl *src_fn,
281-
const clang::FunctionProtoType *src_proto,
282-
const clang::FunctionProtoType *target_proto);
280+
// Converts `expr` for use where a `qual_type` function pointer is
281+
// expected, inserting a `.cast()` if `expr`'s own fn pointer type differs
282+
// from `qual_type` -- e.g. because the two describe the same C function
283+
// pointer type through different typedefs that the translation maps to
284+
// distinct Rust types (`size_t` vs `unsigned long`).
285+
std::string ConvertFnPtrValue(clang::QualType qual_type, clang::Expr *expr);
283286

284287
void EmitSetOrAssign(clang::Expr *lhs, std::string_view rhs);
285288

0 commit comments

Comments
 (0)