Skip to content

Commit 80bda18

Browse files
authored
Add lambda testsuite (#423)
1 parent 7896632 commit 80bda18

38 files changed

Lines changed: 1352 additions & 158 deletions

‎cpp2rust/converter/converter.cpp‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1951,8 +1951,10 @@ Converter::CallInfo Converter::CollectCallInfo(clang::CallExpr *expr) {
19511951
proto = ptr_ty->getPointeeType()->getAs<clang::FunctionProtoType>();
19521952
}
19531953
}
1954-
assert((function || proto) &&
1955-
"Either function decl or function prototype should be known");
1954+
if (!function && !proto) {
1955+
llvm::report_fatal_error(
1956+
"Either function decl or function prototype should be known");
1957+
}
19561958

19571959
unsigned num_args = expr->getNumArgs() - arg_begin;
19581960
unsigned num_named_params =

‎cpp2rust/converter/converter_lib.cpp‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <clang/Basic/SourceManager.h>
1111
#include <clang/Sema/Initialization.h>
1212
#include <clang/Sema/Sema.h>
13+
#include <llvm/Support/ErrorHandling.h>
1314
#include <llvm/Support/Path.h>
1415
#include <llvm/Support/raw_ostream.h>
1516

@@ -769,7 +770,10 @@ std::string GetNamedDeclAsString(const clang::NamedDecl *decl) {
769770

770771
if (name.empty()) {
771772
auto *pdecl = llvm::dyn_cast<clang::ParmVarDecl>(decl);
772-
assert(pdecl && "Unexpected unnamed construct");
773+
if (!pdecl) {
774+
decl->dump();
775+
llvm::report_fatal_error("Unexpected unnamed construct");
776+
}
773777

774778
const auto *fn =
775779
llvm::dyn_cast<clang::FunctionDecl>(pdecl->getDeclContext());

‎tests/unit/lambda_as_field.cpp‎

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// ADDITIONAL_COMPILE_FLAGS: -std=c++23
2+
// no-compile
3+
#include <assert.h>
4+
5+
template <typename F> struct Guard {
6+
F f;
7+
~Guard() { f(); }
8+
};
9+
10+
template <typename F> struct Holder {
11+
F f;
12+
int calls;
13+
int call(int x) {
14+
calls++;
15+
return f(x);
16+
}
17+
};
18+
19+
template <typename T> auto wrap(T fn) {
20+
return [fn](int x) { return fn(x) + 1; };
21+
}
22+
23+
int main() {
24+
int cleaned = 0;
25+
{
26+
Guard g{[&cleaned]() { cleaned++; }};
27+
assert(cleaned == 0);
28+
}
29+
assert(cleaned == 1);
30+
31+
int factor = 3;
32+
Holder h{[factor](int x) { return x * factor; }, 0};
33+
factor = 100;
34+
assert(h.call(2) == 6);
35+
assert(h.call(5) == 15);
36+
assert(h.calls == 2);
37+
38+
auto w = wrap([factor](int x) { return x * factor; });
39+
factor = 7;
40+
assert(w(2) == 201);
41+
42+
auto ww = wrap(w);
43+
assert(ww(2) == 202);
44+
45+
return 0;
46+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// translation-fail
2+
#include <assert.h>
3+
4+
template <typename F> int apply_int(F fn, int x) { return fn(x); }
5+
6+
template <typename F> double apply_double(F fn, double x) { return fn(x); }
7+
8+
template <typename F> int apply_twice(F fn, int x) { return fn(fn(x)); }
9+
10+
int main() {
11+
int factor = 3;
12+
auto scale = [factor](int x) { return x * factor; };
13+
assert(apply_twice(scale, 4) == 36);
14+
15+
assert(apply_int([](int x) { return -x; }, 9) == -9);
16+
17+
auto generic_scale = [factor](auto x) { return x * factor; };
18+
assert(apply_int(generic_scale, 4) == 12);
19+
assert(apply_double(generic_scale, 1.5) == 4.5);
20+
21+
assert(apply_int([](auto x) { return -x; }, 9) == -9);
22+
23+
auto offset = [factor]<typename T>(T x) { return x + factor; };
24+
assert(apply_int(offset, 4) == 7);
25+
assert(apply_double(offset, 1.5) == 4.5);
26+
27+
return 0;
28+
}

‎tests/unit/lambda_basic.cpp‎

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#include <assert.h>
2+
3+
int main() {
4+
auto zero = []() { return 42; };
5+
assert(zero() == 42);
6+
7+
auto one = [](int x) { return x + 1; };
8+
assert(one(1) == 2);
9+
10+
auto three = [](int x, int y, int z) { return x * 100 + y * 10 + z; };
11+
assert(three(1, 2, 3) == 123);
12+
13+
return 0;
14+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
// no-compile: refcount
2+
// panic: unsafe
3+
#include <assert.h>
4+
#include <utility>
5+
6+
struct Counted {
7+
int copies;
8+
int moves;
9+
Counted() : copies(0), moves(0) {}
10+
Counted(const Counted &o) : copies(o.copies + 1), moves(o.moves) {}
11+
Counted(Counted &&o) : copies(o.copies), moves(o.moves + 1) {}
12+
};
13+
14+
int drops = 0;
15+
16+
struct Dropped {
17+
Dropped() {}
18+
Dropped(const Dropped &) {}
19+
Dropped(Dropped &&) {}
20+
~Dropped() { drops++; }
21+
};
22+
23+
int main() {
24+
Counted c;
25+
auto f = [c]() { return c.copies * 10 + c.moves; };
26+
assert(f() == 10);
27+
28+
auto g = f;
29+
assert(g() == 20);
30+
assert(f() == 10);
31+
32+
auto h = std::move(f);
33+
assert(h() == 11);
34+
35+
int returned = [c]() { return c; }().copies;
36+
assert(returned == 2);
37+
38+
Counted arr[2];
39+
auto a = [arr]() { return arr[0].copies + arr[1].copies; };
40+
assert(a() == 2);
41+
42+
auto a2 = a;
43+
assert(a2() == 4);
44+
45+
{
46+
auto m = [d = Dropped()]() {};
47+
auto m2 = std::move(m);
48+
}
49+
assert(drops == 2);
50+
51+
{
52+
auto k = [d = Dropped()]() {};
53+
auto k2 = k;
54+
}
55+
assert(drops == 4);
56+
57+
return 0;
58+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// panic
2+
#include <assert.h>
3+
4+
int main() {
5+
int a = 1;
6+
int b = 2;
7+
int c = 3;
8+
9+
auto by_value = [=](int x) { return a + b + c + x; };
10+
assert(by_value(10) == 16);
11+
a = 100;
12+
assert(by_value(10) == 16);
13+
14+
auto by_ref = [&](int x) { return a + b + c + x; };
15+
assert(by_ref(10) == 115);
16+
b = 200;
17+
assert(by_ref(10) == 313);
18+
19+
auto mixed = [=, &c](int x) {
20+
c += x;
21+
return a + b + c;
22+
};
23+
assert(mixed(1) == 100 + 200 + 4);
24+
assert(c == 4);
25+
26+
return 0;
27+
}

‎tests/unit/lambda_capture_pass.cpp‎

Lines changed: 0 additions & 19 deletions
This file was deleted.

‎tests/unit/lambda_capture_ref.cpp‎

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
// no-compile
2+
#include <assert.h>
3+
#include <stddef.h>
4+
#include <stdint.h>
5+
6+
struct S {
7+
int x;
8+
int y;
9+
};
10+
11+
int main() {
12+
int base = 10;
13+
auto add_base = [&base](int x) { return x + base; };
14+
assert(add_base(5) == 15);
15+
base = 100;
16+
assert(add_base(5) == 105);
17+
18+
S s = {1, 2};
19+
auto sum = [&s]() { return s.x + s.y; };
20+
assert(sum() == 3);
21+
s.x = 50;
22+
assert(sum() == 52);
23+
24+
int counter = 0;
25+
auto bump = [&counter]() { counter++; };
26+
bump();
27+
bump();
28+
assert(counter == 2);
29+
30+
uint16_t arr[4] = {3, 1, 2, 0};
31+
auto swap = [&arr](size_t i, size_t j) {
32+
uint16_t t = arr[j];
33+
arr[j] = arr[i];
34+
arr[i] = t;
35+
};
36+
swap(0, 3);
37+
assert(arr[0] == 0);
38+
assert(arr[3] == 3);
39+
40+
int total = 0;
41+
auto add = [&t = total](int x) { t += x; };
42+
add(2);
43+
add(3);
44+
assert(total == 5);
45+
46+
auto set_y = [&y = s.y](int v) { y = v; };
47+
set_y(9);
48+
assert(s.y == 9);
49+
50+
return 0;
51+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// no-compile: refcount
2+
// panic: unsafe
3+
#include <assert.h>
4+
5+
struct S {
6+
int n;
7+
int twice() const { return n * 2; }
8+
9+
int modify_copy() {
10+
auto f = [*this]() mutable {
11+
n += 10;
12+
return n;
13+
};
14+
int r = f();
15+
return r * 100 + n;
16+
}
17+
18+
int snapshot() {
19+
auto f = [*this]() { return twice(); };
20+
n = 99;
21+
return f();
22+
}
23+
24+
int mixed(int k) {
25+
auto f = [=, *this]() { return n + k; };
26+
n = 0;
27+
return f();
28+
}
29+
};
30+
31+
int main() {
32+
S s = {1};
33+
assert(s.modify_copy() == 1101);
34+
assert(s.n == 1);
35+
36+
assert(s.snapshot() == 2);
37+
assert(s.n == 99);
38+
39+
assert(s.mixed(1) == 100);
40+
assert(s.n == 0);
41+
42+
return 0;
43+
}

0 commit comments

Comments
 (0)