Skip to content

Commit bfd6aa9

Browse files
committed
Fix C++1 generation of function pointers.
1 parent 5aa32ae commit bfd6aa9

File tree

5 files changed

+113
-5
lines changed

5 files changed

+113
-5
lines changed
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
g_inttemplate: std::optional<int> = std::nullopt;
2+
g_template: std::optional<*(_: int) -> void> = std::nullopt;
3+
g_signal_handlers: std::unordered_map<int, *(_: int) -> void> = ();
4+
5+
intfuncptr: type == *(_: int) -> void;
6+
7+
set_signal: (signum: int, handler: *(_: int) -> void) -> *(_: int) -> void = {
8+
default_handler := :(foo: int) -> void = {
9+
// Default handler does nothing
10+
_ = foo;
11+
};
12+
old_handler: intfuncptr = default_handler;
13+
if g_signal_handlers.find(signum) != g_signal_handlers.end() {
14+
old_handler = g_signal_handlers[signum];
15+
}
16+
g_signal_handlers[signum] = handler;
17+
return old_handler;
18+
}
19+
20+
g_signal: i64 = 0;
21+
inc_signal: (signum: int) -> void = {
22+
g_signal += signum;
23+
}
24+
dec_signal: (signum: int) -> void = {
25+
g_signal -= signum;
26+
}
27+
28+
main: () -> int = {
29+
_ = set_signal(1, inc_signal);
30+
cmpx := set_signal(1, dec_signal);
31+
return cmpx != inc_signal;
32+
}
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
2+
#define CPP2_IMPORT_STD Yes
3+
4+
//=== Cpp2 type declarations ====================================================
5+
6+
7+
#include "cpp2util.h"
8+
9+
#line 1 "pure2-bugfix-for-function-returning-funcptr.cpp2"
10+
11+
12+
//=== Cpp2 type definitions and function declarations ===========================
13+
14+
#line 1 "pure2-bugfix-for-function-returning-funcptr.cpp2"
15+
extern std::optional<int> g_inttemplate;
16+
#line 2 "pure2-bugfix-for-function-returning-funcptr.cpp2"
17+
extern std::optional<void(*)([[maybe_unused]] cpp2::impl::in<int> unnamed_param_1)> g_template;
18+
extern std::unordered_map<int,void(*)([[maybe_unused]] cpp2::impl::in<int> unnamed_param_1)> g_signal_handlers;
19+
20+
using intfuncptr = void(*)([[maybe_unused]] cpp2::impl::in<int> unnamed_param_1);
21+
22+
[[nodiscard]] auto set_signal(cpp2::impl::in<int> signum, void(*handler)([[maybe_unused]] cpp2::impl::in<int> unnamed_param_1)) -> void(*)([[maybe_unused]] cpp2::impl::in<int> unnamed_param_1);
23+
24+
#line 20 "pure2-bugfix-for-function-returning-funcptr.cpp2"
25+
extern cpp2::i64 g_signal;
26+
auto inc_signal(cpp2::impl::in<int> signum) -> void;
27+
28+
#line 24 "pure2-bugfix-for-function-returning-funcptr.cpp2"
29+
auto dec_signal(cpp2::impl::in<int> signum) -> void;
30+
31+
#line 28 "pure2-bugfix-for-function-returning-funcptr.cpp2"
32+
[[nodiscard]] auto main() -> int;
33+
34+
//=== Cpp2 function definitions =================================================
35+
36+
#line 1 "pure2-bugfix-for-function-returning-funcptr.cpp2"
37+
std::optional<int> g_inttemplate {std::nullopt};
38+
#line 2 "pure2-bugfix-for-function-returning-funcptr.cpp2"
39+
std::optional<void(*)([[maybe_unused]] cpp2::impl::in<int> unnamed_param_1)> g_template {std::nullopt};
40+
std::unordered_map<int,void(*)([[maybe_unused]] cpp2::impl::in<int> unnamed_param_1)> g_signal_handlers {};
41+
42+
#line 7 "pure2-bugfix-for-function-returning-funcptr.cpp2"
43+
[[nodiscard]] auto set_signal(cpp2::impl::in<int> signum, void(*handler)([[maybe_unused]] cpp2::impl::in<int> unnamed_param_1)) -> void(*)([[maybe_unused]] cpp2::impl::in<int> unnamed_param_1){
44+
auto default_handler {[](cpp2::impl::in<int> foo) -> void{
45+
// Default handler does nothing
46+
static_cast<void>(foo);
47+
}};
48+
intfuncptr old_handler {cpp2::move(default_handler)};
49+
if (CPP2_UFCS(find)(g_signal_handlers, signum) != CPP2_UFCS(end)(g_signal_handlers)) {
50+
old_handler = CPP2_ASSERT_IN_BOUNDS(g_signal_handlers, signum);
51+
}
52+
CPP2_ASSERT_IN_BOUNDS(g_signal_handlers, signum) = handler;
53+
return old_handler;
54+
}
55+
56+
cpp2::i64 g_signal {0};
57+
#line 21 "pure2-bugfix-for-function-returning-funcptr.cpp2"
58+
auto inc_signal(cpp2::impl::in<int> signum) -> void{
59+
g_signal += signum;
60+
}
61+
#line 24 "pure2-bugfix-for-function-returning-funcptr.cpp2"
62+
auto dec_signal(cpp2::impl::in<int> signum) -> void{
63+
g_signal -= signum;
64+
}
65+
66+
#line 28 "pure2-bugfix-for-function-returning-funcptr.cpp2"
67+
[[nodiscard]] auto main() -> int{
68+
static_cast<void>(set_signal(1, inc_signal));
69+
auto cmpx {set_signal(1, dec_signal)};
70+
return cpp2::move(cmpx) != inc_signal;
71+
}
72+
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
pure2-bugfix-for-function-returning-funcptr.cpp2... ok (all Cpp2, passes safety checks)
2+

source/parse.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7266,7 +7266,8 @@ class parser
72667266
auto type_id(
72677267
bool allow_omitting_type_name = false,
72687268
bool allow_constraint = false,
7269-
bool allow_function_type = false
7269+
bool allow_function_type = false,
7270+
bool allow_qualified_function_type = true
72707271
)
72717272
-> std::unique_ptr<type_id_node>
72727273
{
@@ -7339,7 +7340,9 @@ class parser
73397340
assert (n->id.index() == type_id_node::unqualified);
73407341
}
73417342
else if (std::unique_ptr<function_type_node> id = {};
7342-
allow_function_type
7343+
(allow_function_type ||
7344+
(allow_qualified_function_type &&
7345+
!n->pc_qualifiers.empty()))
73437346
&& (id = function_type({})) != nullptr
73447347
)
73457348
{

source/to_cpp1.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1978,9 +1978,8 @@ class cppfront
19781978

19791979
// Handle function types
19801980
if (n.is_function_typeid()) {
1981-
// If identifier is nonempty, we're doing a local variable with a (pointer to)
1982-
// function typeid, so stick in the pointers here for inside-out Cpp1 declarations
1983-
if (!identifier.empty()) {
1981+
// If there are qualifiers, stick in the pointers here for inside-out Cpp1 declarations
1982+
if (n.pc_qualifiers.size() > 0) {
19841983
for (auto q: n.pc_qualifiers) {
19851984
if (*q == "const") { identifier = " " + identifier; }
19861985
identifier = q->as_string_view() + identifier;

0 commit comments

Comments
 (0)