Skip to content

Commit 11d06ba

Browse files
committed
fix(cpp1): emit correct UFCS in function signature
1 parent cde47ea commit 11d06ba

14 files changed

+148
-32
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
template<bool> struct t { };
2+
constexpr bool f(const t<true>&) { return true; }
3+
constexpr t<true> o{};
4+
5+
// Variables.
6+
7+
// _: <V: t<o.f()>> bool = (); // Blocked on #389, [GCC109781][].
8+
9+
_: t<o.f()> = ();
10+
11+
_: bool = o.f();
12+
13+
// Functions.
14+
15+
// g: <V: t<o.f()>> () = { } // Blocked on [GCC109781][].
16+
17+
g: (x: t<o.f()>) = { }
18+
19+
g: () [[pre: o.f()]] = { }
20+
21+
h: () -> t<o.f()> = o;
22+
23+
main: () = { }
24+
25+
// [GCC109781]: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109781

regression-tests/mixed-bugfix-for-ufcs-sfinae.cpp2

-4
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
f: <T> () -> std::type_identity_t<decltype(T().a())> = { }
2+
B: type = { }
3+
main: () = {
4+
static_assert(!std::invocable<decltype(:<T> (x: T) -> std::void_t<decltype(f<T>())> = {}), B>);
5+
}

regression-tests/test-results/gcc-13/pure2-bugfix-for-ufcs-sfinae.cpp.execution

Whitespace-only changes.

regression-tests/test-results/gcc-13/pure2-bugfix-for-ufcs-sfinae.cpp.output

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
2+
3+
//=== Cpp2 type declarations ====================================================
4+
5+
6+
#include "cpp2util.h"
7+
8+
9+
10+
//=== Cpp2 type definitions and function declarations ===========================
11+
12+
template<bool> struct t { };
13+
constexpr bool f(const t<true>&) { return true; }
14+
constexpr t<true> o{};
15+
16+
// Variables.
17+
18+
// _: <V: t<o.f()>> bool = (); // Blocked on #389, [GCC109781][].
19+
20+
#line 9 "mixed-bugfix-for-ufcs-non-local.cpp2"
21+
extern t<CPP2_UFCS(,,(f),(o),())> auto_9_1;
22+
23+
extern bool auto_11_1;
24+
25+
// Functions.
26+
27+
// g: <V: t<o.f()>> () = { } // Blocked on [GCC109781][].
28+
29+
auto g(cpp2::in<t<CPP2_UFCS(,,(f),(o),())>> x) -> void;
30+
31+
auto g() -> void;
32+
33+
[[nodiscard]] auto h() -> t<CPP2_UFCS(,,(f),(o),())>;
34+
35+
auto main() -> int;
36+
37+
// [GCC109781]: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109781
38+
39+
40+
//=== Cpp2 function definitions =================================================
41+
42+
43+
#line 9 "mixed-bugfix-for-ufcs-non-local.cpp2"
44+
t<CPP2_UFCS(,,(f),(o),())> auto_9_1 {};
45+
46+
bool auto_11_1 {CPP2_UFCS(,,(f),(o),())};
47+
48+
#line 17 "mixed-bugfix-for-ufcs-non-local.cpp2"
49+
auto g(cpp2::in<t<CPP2_UFCS(,,(f),(o),())>> x) -> void{}
50+
51+
auto g() -> void{
52+
cpp2::Default.expects(CPP2_UFCS(&,,(f),(o),()), "");
53+
#line 19 "mixed-bugfix-for-ufcs-non-local.cpp2"
54+
}
55+
56+
[[nodiscard]] auto h() -> t<CPP2_UFCS(,,(f),(o),())> { return o; }
57+
58+
auto main() -> int{}
59+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
mixed-bugfix-for-ufcs-non-local.cpp2... ok (mixed Cpp1/Cpp2, Cpp2 code passes safety checks)
2+

regression-tests/test-results/mixed-bugfix-for-ufcs-sfinae.cpp

-24
This file was deleted.

regression-tests/test-results/mixed-bugfix-for-ufcs-sfinae.cpp2.output

-2
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
2+
#define CPP2_USE_MODULES Yes
3+
4+
//=== Cpp2 type declarations ====================================================
5+
6+
7+
#include "cpp2util.h"
8+
9+
10+
#line 2 "pure2-bugfix-for-ufcs-sfinae.cpp2"
11+
class B;
12+
13+
14+
//=== Cpp2 type definitions and function declarations ===========================
15+
16+
#line 1 "pure2-bugfix-for-ufcs-sfinae.cpp2"
17+
template<typename T> [[nodiscard]] auto f() -> std::type_identity_t<decltype(CPP2_UFCS(,,(a),(T()),()))>;
18+
class B {
19+
public: B() = default;
20+
public: B(B const&) = delete; /* No 'that' constructor, suppress copy */
21+
public: auto operator=(B const&) -> void = delete;
22+
23+
#line 2 "pure2-bugfix-for-ufcs-sfinae.cpp2"
24+
};
25+
auto main() -> int;
26+
27+
28+
//=== Cpp2 function definitions =================================================
29+
30+
#line 1 "pure2-bugfix-for-ufcs-sfinae.cpp2"
31+
template<typename T> [[nodiscard]] auto f() -> std::type_identity_t<decltype(CPP2_UFCS(,,(a),(T()),()))>{}
32+
33+
auto main() -> int {
34+
static_assert(!(std::invocable<decltype([]<typename T>(T const& x) -> std::void_t<decltype(f<T>())>{}),B>));
35+
}
36+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
pure2-bugfix-for-ufcs-sfinae.cpp2... ok (all Cpp2, passes safety checks)
2+

source/cppfront.cpp

+19-2
Original file line numberDiff line numberDiff line change
@@ -1004,6 +1004,8 @@ class cppfront
10041004
bool violates_initialization_safety = false;
10051005
bool suppress_move_from_last_use = false;
10061006

1007+
declaration_node const* having_signature_emitted = {};
1008+
10071009
declaration_node const* generating_assignment_from = {};
10081010
declaration_node const* generating_move_from = {};
10091011
bool emitting_that_function = false;
@@ -2946,7 +2948,13 @@ class cppfront
29462948
if (
29472949
current_declarations.back()->is_namespace()
29482950
|| (
2949-
current_declarations.back()->is_object()
2951+
(
2952+
current_declarations.back()->is_object()
2953+
|| (
2954+
current_declarations.back()->is_function()
2955+
&& current_declarations.back() == having_signature_emitted
2956+
)
2957+
)
29502958
&& current_declarations.back()->parent_is_namespace()
29512959
)
29522960
)
@@ -4807,6 +4815,13 @@ class cppfront
48074815
printer.print_extra("\n");
48084816
}
48094817

4818+
auto stack_value = []<typename T>(T& var, std::type_identity_t<T> const& value) {
4819+
return finally([&var, old = std::exchange(var, value)]() {
4820+
var = old;
4821+
});
4822+
};
4823+
auto stack = stack_value(having_signature_emitted, &n);
4824+
48104825
// Handle aliases
48114826

48124827
if (n.is_alias())
@@ -5551,7 +5566,8 @@ class cppfront
55515566
function_returns.emplace_back(nullptr); // no return type at all
55525567
}
55535568

5554-
for (auto&& c : func->contracts)
5569+
for (auto stack = stack_value(having_signature_emitted, nullptr);
5570+
auto&& c : func->contracts)
55555571
{
55565572
auto print = std::string();
55575573
printer.emit_to_string(&print);
@@ -5665,6 +5681,7 @@ class cppfront
56655681
}
56665682
// *** END NOTE =================================================
56675683

5684+
having_signature_emitted = nullptr;
56685685
emit(
56695686
*n.initializer,
56705687
true, func->position(), func->returns.index() == function_type_node::empty,

0 commit comments

Comments
 (0)