Skip to content

Commit 0c8fa21

Browse files
committed
fix(to_cpp1): emit qualified UFCS template call correctly
1 parent 295a886 commit 0c8fa21

File tree

4 files changed

+49
-24
lines changed

4 files changed

+49
-24
lines changed

include/cpp2util.h

Lines changed: 23 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -791,18 +791,18 @@ class out {
791791
// we instead make it a template parameter of the UFCS lambda.
792792
// But using a template parameter, Clang also ICEs on an application.
793793
// So we use these `NOTHROW` macros to fall back to the ideal for when not using GCC.
794-
#define CPP2_UFCS_IS_NOTHROW(TEMPKW,...) \
795-
requires { requires requires { std::declval<Obj>().TEMPKW __VA_ARGS__(std::declval<Params>()...); }; \
796-
requires noexcept(std::declval<Obj>().TEMPKW __VA_ARGS__(std::declval<Params>()...)); } \
797-
|| requires { requires !requires { std::declval<Obj>().TEMPKW __VA_ARGS__(std::declval<Params>()...); }; \
798-
requires noexcept(__VA_ARGS__(std::declval<Obj>(), std::declval<Params>()...)); }
799-
#define CPP2_UFCS_IS_NOTHROW_PARAM(TEMPKW,...) /*empty*/
800-
#define CPP2_UFCS_IS_NOTHROW_ARG(TEMPKW,...) CPP2_UFCS_IS_NOTHROW(TEMPKW,__VA_ARGS__)
794+
#define CPP2_UFCS_IS_NOTHROW(QUALID,TEMPKW,...) \
795+
requires { requires requires { std::declval<Obj>().QUALID TEMPKW __VA_ARGS__(std::declval<Params>()...); }; \
796+
requires noexcept(std::declval<Obj>().QUALID TEMPKW __VA_ARGS__(std::declval<Params>()...)); } \
797+
|| requires { requires !requires { std::declval<Obj>().QUALID TEMPKW __VA_ARGS__(std::declval<Params>()...); }; \
798+
requires noexcept(QUALID __VA_ARGS__(std::declval<Obj>(), std::declval<Params>()...)); }
799+
#define CPP2_UFCS_IS_NOTHROW_PARAM(QUALID,TEMPKW,...) /*empty*/
800+
#define CPP2_UFCS_IS_NOTHROW_ARG(QUALID,TEMPKW,...) CPP2_UFCS_IS_NOTHROW(QUALID,TEMPKW,__VA_ARGS__)
801801
#if defined(__GNUC__) && !defined(__clang__)
802802
#undef CPP2_UFCS_IS_NOTHROW_PARAM
803803
#undef CPP2_UFCS_IS_NOTHROW_ARG
804-
#define CPP2_UFCS_IS_NOTHROW_PARAM(TEMPKW,...) , bool IsNothrow = CPP2_UFCS_IS_NOTHROW(TEMPKW,__VA_ARGS__)
805-
#define CPP2_UFCS_IS_NOTHROW_ARG(TEMPKW,...) IsNothrow
804+
#define CPP2_UFCS_IS_NOTHROW_PARAM(QUALID,TEMPKW,...) , bool IsNothrow = CPP2_UFCS_IS_NOTHROW(QUALID,TEMPKW,__VA_ARGS__)
805+
#define CPP2_UFCS_IS_NOTHROW_ARG(QUALID,TEMPKW,...) IsNothrow
806806
#if __GNUC__ < 11
807807
#undef CPP2_UFCS_IS_NOTHROW_PARAM
808808
#undef CPP2_UFCS_IS_NOTHROW_ARG
@@ -811,23 +811,25 @@ class out {
811811
#endif
812812
#endif
813813

814-
#define CPP2_UFCS_(LAMBDADEFCAPT,TEMPKW,...) \
815-
[LAMBDADEFCAPT]<typename Obj, typename... Params CPP2_UFCS_IS_NOTHROW_PARAM(TEMPKW,__VA_ARGS__)> \
814+
#define CPP2_UFCS_(LAMBDADEFCAPT,QUALID,TEMPKW,...) \
815+
[LAMBDADEFCAPT]<typename Obj, typename... Params CPP2_UFCS_IS_NOTHROW_PARAM(QUALID,TEMPKW,__VA_ARGS__)> \
816816
CPP2_LAMBDA_NO_DISCARD (Obj&& obj, Params&& ...params) CPP2_FORCE_INLINE_LAMBDA_CLANG \
817-
noexcept(CPP2_UFCS_IS_NOTHROW_ARG(TEMPKW,__VA_ARGS__)) CPP2_FORCE_INLINE_LAMBDA -> decltype(auto) \
818-
requires requires { CPP2_FORWARD(obj).TEMPKW __VA_ARGS__(CPP2_FORWARD(params)...); } \
819-
|| requires { __VA_ARGS__(CPP2_FORWARD(obj), CPP2_FORWARD(params)...); } { \
820-
if constexpr (requires{ CPP2_FORWARD(obj).TEMPKW __VA_ARGS__(CPP2_FORWARD(params)...); }) { \
821-
return CPP2_FORWARD(obj).TEMPKW __VA_ARGS__(CPP2_FORWARD(params)...); \
817+
noexcept(CPP2_UFCS_IS_NOTHROW_ARG(QUALID,TEMPKW,__VA_ARGS__)) CPP2_FORCE_INLINE_LAMBDA -> decltype(auto) \
818+
requires requires { CPP2_FORWARD(obj).QUALID TEMPKW __VA_ARGS__(CPP2_FORWARD(params)...); } \
819+
|| requires { QUALID __VA_ARGS__(CPP2_FORWARD(obj), CPP2_FORWARD(params)...); } { \
820+
if constexpr (requires{ CPP2_FORWARD(obj).QUALID TEMPKW __VA_ARGS__(CPP2_FORWARD(params)...); }) { \
821+
return CPP2_FORWARD(obj).QUALID TEMPKW __VA_ARGS__(CPP2_FORWARD(params)...); \
822822
} else { \
823-
return __VA_ARGS__(CPP2_FORWARD(obj), CPP2_FORWARD(params)...); \
823+
return QUALID __VA_ARGS__(CPP2_FORWARD(obj), CPP2_FORWARD(params)...); \
824824
} \
825825
}
826826

827-
#define CPP2_UFCS(...) CPP2_UFCS_(&,,__VA_ARGS__)
828-
#define CPP2_UFCS_TEMPLATE(...) CPP2_UFCS_(&,template,__VA_ARGS__)
829-
#define CPP2_UFCS_NONLOCAL(...) CPP2_UFCS_(,,__VA_ARGS__)
830-
#define CPP2_UFCS_TEMPLATE_NONLOCAL(...) CPP2_UFCS_(,template,__VA_ARGS__)
827+
#define CPP2_UFCS(...) CPP2_UFCS_(&,,,__VA_ARGS__)
828+
#define CPP2_UFCS_TEMPLATE(...) CPP2_UFCS_(&,,template,__VA_ARGS__)
829+
#define CPP2_UFCS_QUALIFIED_TEMPLATE(QUALID,...) CPP2_UFCS_(&,QUALID,template,__VA_ARGS__)
830+
#define CPP2_UFCS_NONLOCAL(...) CPP2_UFCS_(,,,__VA_ARGS__)
831+
#define CPP2_UFCS_TEMPLATE_NONLOCAL(...) CPP2_UFCS_(,,template,__VA_ARGS__)
832+
#define CPP2_UFCS_QUALIFIED_TEMPLATE_NONLOCAL(QUALID,...) CPP2_UFCS_(,QUALID,template,__VA_ARGS__)
831833

832834

833835
//-----------------------------------------------------------------------

regression-tests/pure2-bugfix-for-ufcs-arguments.cpp2

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,4 +48,7 @@ main: () = {
4848
_ = a<t, t>.f<t, t>(0, 0);
4949

5050
_ = :(a, f) = { _ = a.f(a).f(); };
51+
_ = 0.std::min<int>(0);
5152
}
53+
54+
_: i32 = 0.std::min<int>(0);

regression-tests/test-results/pure2-bugfix-for-ufcs-arguments.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,9 @@ extern cpp2::i32 auto_35_1;
5050

5151
auto main() -> int;
5252

53+
#line 54 "pure2-bugfix-for-ufcs-arguments.cpp2"
54+
extern cpp2::i32 auto_54_1;
55+
5356
//=== Cpp2 function definitions =================================================
5457

5558
#line 1 "pure2-bugfix-for-ufcs-arguments.cpp2"
@@ -104,5 +107,8 @@ auto main() -> int{
104107
static_cast<void>(CPP2_UFCS_TEMPLATE(f<t,t>)(a<t,t>, 0, 0));
105108

106109
static_cast<void>([](auto const& a, auto const& f) -> void{static_cast<void>(CPP2_UFCS(f)(CPP2_UFCS(f)(a, a))); });
110+
static_cast<void>(CPP2_UFCS_QUALIFIED_TEMPLATE(std::,min<int>)(0, 0));
107111
}
108112

113+
cpp2::i32 auto_54_1 {CPP2_UFCS_QUALIFIED_TEMPLATE_NONLOCAL(std::,min<int>)(0, 0)};
114+

source/to_cpp1.h

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1810,7 +1810,10 @@ class cppfront
18101810

18111811
//-----------------------------------------------------------------------
18121812
//
1813-
auto emit(qualified_id_node const& n)
1813+
auto emit(
1814+
qualified_id_node const& n,
1815+
bool include_unqualified_id = true
1816+
)
18141817
-> void
18151818
{
18161819
if (!sema.check(n)) {
@@ -1834,7 +1837,7 @@ class cppfront
18341837
auto ident = std::string{};
18351838
printer.emit_to_string(&ident);
18361839

1837-
for (auto const& id : n.ids)
1840+
for (auto const& id : std::span{n.ids}.first(n.ids.size() - !include_unqualified_id))
18381841
{
18391842
if (id.scope_op) {
18401843
emit(*id.scope_op);
@@ -1879,7 +1882,7 @@ class cppfront
18791882
//
18801883
auto emit(
18811884
id_expression_node const& n,
1882-
bool is_local_name = true
1885+
bool is_local_name = true
18831886
)
18841887
-> void
18851888
{
@@ -3139,6 +3142,7 @@ class cppfront
31393142
&& !lookup_finds_variable_with_placeholder_type_under_initialization(*i->id_expr)
31403143
)
31413144
{
3145+
// The function name is the argument to the macro
31423146
auto funcname = print_to_string(*i->id_expr);
31433147

31443148
// First, build the UFCS macro name
@@ -3147,6 +3151,16 @@ class cppfront
31473151

31483152
// If there are template arguments, use the _TEMPLATE version
31493153
if (std::ssize(i->id_expr->template_arguments()) > 0) {
3154+
// If it is qualified, use the _QUALIFIED version
3155+
if (i->id_expr->is_qualified()) {
3156+
ufcs_string += "_QUALIFIED";
3157+
// And split the unqualified id in the function name as two macro arguments
3158+
auto& id = *get<id_expression_node::qualified>(i->id_expr->id);
3159+
funcname =
3160+
print_to_string(id, false)
3161+
+ "::,"
3162+
+ print_to_string(*cpp2::assert_not_null(id.ids.back().id), false, true, true);
3163+
}
31503164
ufcs_string += "_TEMPLATE";
31513165
}
31523166

0 commit comments

Comments
 (0)