Skip to content

Commit 1320b16

Browse files
committed
Index through specializations that have the same arguments
1 parent 0889705 commit 1320b16

5 files changed

Lines changed: 27 additions & 18 deletions

File tree

‎cpp2rust/converter/converter.cpp‎

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1978,7 +1978,8 @@ void Converter::ConvertLambdaCall(clang::CallExpr *expr,
19781978
if (lambda->isGenericLambda()) {
19791979
auto call_operator = expr->getDirectCallee();
19801980
auto proto = call_operator->getType()->castAs<clang::FunctionProtoType>();
1981-
StrCat(std::format(".spec::<{}>()", ConvertFunctionPointerType(proto)));
1981+
StrCat(std::format(".spec::<{}>({})", ConvertFunctionPointerType(proto),
1982+
GetLambdaSpecializationIndex(call_operator)));
19821983
}
19831984
StrCat(".call");
19841985
}
@@ -3963,13 +3964,7 @@ bool Converter::VisitLambdaExpr(clang::LambdaExpr *expr) {
39633964
}
39643965
}
39653966
StrCat(token::kComma);
3966-
std::unordered_set<std::string> signatures;
39673967
ForEachLambdaCallOperator(decl, [&](clang::CXXMethodDecl *call_operator) {
3968-
auto proto = call_operator->getType()->castAs<clang::FunctionProtoType>();
3969-
if (!signatures.insert(ConvertFunctionPointerType(proto)).second) {
3970-
llvm::report_fatal_error("generic lambda with two specializations of "
3971-
"the same signature is not supported");
3972-
}
39733968
ConvertLambdaClosure(decl, call_operator);
39743969
StrCat(token::kComma);
39753970
});

‎cpp2rust/converter/converter_lib.cpp‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1210,6 +1210,22 @@ AsLambdaCallOperator(const clang::CXXConversionDecl *conversion) {
12101210
return found;
12111211
}
12121212

1213+
unsigned
1214+
GetLambdaSpecializationIndex(const clang::FunctionDecl *call_operator) {
1215+
std::optional<unsigned> index;
1216+
unsigned i = 0;
1217+
ForEachLambdaCallOperator(
1218+
clang::cast<clang::CXXMethodDecl>(call_operator)->getParent(),
1219+
[&](const clang::CXXMethodDecl *op) {
1220+
if (op->getCanonicalDecl() == call_operator->getCanonicalDecl()) {
1221+
index = i;
1222+
}
1223+
++i;
1224+
});
1225+
assert(index);
1226+
return *index;
1227+
}
1228+
12131229
const clang::LambdaCapture *AsLambdaCapture(const clang::FieldDecl *field) {
12141230
auto decl = clang::dyn_cast<clang::CXXRecordDecl>(field->getParent());
12151231
if (!decl || !decl->isLambda()) {

‎cpp2rust/converter/converter_lib.h‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,8 @@ void ForEachLambdaCallOperator(
221221
clang::CXXMethodDecl *
222222
AsLambdaCallOperator(const clang::CXXConversionDecl *conversion);
223223

224+
unsigned GetLambdaSpecializationIndex(const clang::FunctionDecl *call_operator);
225+
224226
const clang::LambdaCapture *AsLambdaCapture(const clang::FieldDecl *field);
225227

226228
bool IsLambdaCopyOrMoveConstructor(const clang::CXXConstructorDecl *ctor);

‎cpp2rust/converter/models/converter_refcount.cpp‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1579,10 +1579,10 @@ void ConverterRefCount::ConvertLambdaToFunctionPointer(
15791579
StrCat(ConvertFreshRValue(lambda));
15801580
auto decl = AsLambdaClass(lambda->getType());
15811581
if (decl->isGenericLambda()) {
1582-
auto proto = conversion->getConversionType()
1583-
->getPointeeType()
1584-
->castAs<clang::FunctionProtoType>();
1585-
StrCat(std::format(".spec::<{}>()", ConvertFunctionPointerType(proto)));
1582+
auto call_operator = AsLambdaCallOperator(conversion);
1583+
auto proto = call_operator->getType()->castAs<clang::FunctionProtoType>();
1584+
StrCat(std::format(".spec::<{}>({})", ConvertFunctionPointerType(proto),
1585+
GetLambdaSpecializationIndex(call_operator)));
15861586
}
15871587
}
15881588

‎libcc2rs/src/fn_ptr.rs‎

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -458,14 +458,10 @@ impl FnPtr<Generic> {
458458
}
459459
}
460460

461-
pub fn spec<U: FnSig>(&self) -> FnPtr<U> {
461+
pub fn spec<U: FnSig>(&self, index: usize) -> FnPtr<U> {
462462
assert!(!self.is_null(), "ub: null fn pointer call");
463-
self.original
464-
.as_ref()
465-
.unwrap()
466-
.specializations()
467-
.iter()
468-
.find_map(|spec| spec.downcast_ref::<FnPtr<U>>())
463+
self.original.as_ref().unwrap().specializations()[index]
464+
.downcast_ref::<FnPtr<U>>()
469465
.expect("ub: calling through incompatible fn pointer type")
470466
.clone()
471467
}

0 commit comments

Comments
 (0)