Skip to content

Commit 549e4ce

Browse files
committed
fix(cpp1): handle known UFCS corner cases
Provide transparent SFINAE. Forward `noexcept`. Accept object with unparenthesized comma like `v<a, b>`. Disable UFCS in `f := t().f();`. Do not capture in signatures. Incidentially, merge the UFCS macros.
1 parent ecd3726 commit 549e4ce

File tree

73 files changed

+798
-417
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

73 files changed

+798
-417
lines changed

include/cpp2util.h

+48-85
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@
191191
// in our -pure-cpp2 "import std;" simulation mode... if you need this,
192192
// use mixed mode (not -pure-cpp2) and #include all the headers you need
193193
// including this one
194-
//
194+
//
195195
// #include <execution>
196196
#endif
197197

@@ -480,7 +480,7 @@ template<typename T>
480480
auto Typeid() -> decltype(auto) {
481481
#ifdef CPP2_NO_RTTI
482482
Type.expects(
483-
!"'any' dynamic casting is disabled with -fno-rtti", // more likely to appear on console
483+
!"'any' dynamic casting is disabled with -fno-rtti", // more likely to appear on console
484484
"'any' dynamic casting is disabled with -fno-rtti" // make message available to hooked handlers
485485
);
486486
#else
@@ -670,12 +670,19 @@ class out {
670670
//-----------------------------------------------------------------------
671671
//
672672
#if defined(_MSC_VER) && !defined(__clang_major__)
673-
#define CPP2_FORCE_INLINE __forceinline
674-
#define CPP2_FORCE_INLINE_LAMBDA [[msvc::forceinline]]
673+
#define CPP2_FORCE_INLINE __forceinline
674+
#define CPP2_FORCE_INLINE_LAMBDA [[msvc::forceinline]]
675+
#define CPP2_FORCE_INLINE_LAMBDA_CLANG /* empty */
675676
#define CPP2_LAMBDA_NO_DISCARD
676677
#else
677-
#define CPP2_FORCE_INLINE __attribute__((always_inline))
678-
#define CPP2_FORCE_INLINE_LAMBDA __attribute__((always_inline))
678+
#define CPP2_FORCE_INLINE __attribute__((always_inline))
679+
#if defined(__clang__)
680+
#define CPP2_FORCE_INLINE_LAMBDA /* empty */
681+
#define CPP2_FORCE_INLINE_LAMBDA_CLANG __attribute__((always_inline))
682+
#else
683+
#define CPP2_FORCE_INLINE_LAMBDA __attribute__((always_inline))
684+
#define CPP2_FORCE_INLINE_LAMBDA_CLANG /* empty */
685+
#endif
679686

680687
#if defined(__clang_major__)
681688
// Also check __cplusplus, only to satisfy Clang -pedantic-errors
@@ -701,84 +708,40 @@ class out {
701708
#endif
702709

703710

704-
// Note: [&] is because a nested UFCS might be viewed as trying to capture 'this'
705-
706-
#define CPP2_UFCS(FUNCNAME,PARAM1,...) \
707-
[&] CPP2_LAMBDA_NO_DISCARD (auto&& obj, auto&& ...params) CPP2_FORCE_INLINE_LAMBDA -> decltype(auto) { \
708-
if constexpr (requires{ CPP2_FORWARD(obj).FUNCNAME(CPP2_FORWARD(params)...); }) { \
709-
return CPP2_FORWARD(obj).FUNCNAME(CPP2_FORWARD(params)...); \
711+
#define CPP2_UFCS_(LAMBDADEFCAPT,TEMPKW,...) \
712+
[LAMBDADEFCAPT] CPP2_LAMBDA_NO_DISCARD (auto&& obj, auto&& ...params) CPP2_FORCE_INLINE_LAMBDA_CLANG \
713+
noexcept(requires { requires requires { CPP2_FORWARD(obj).TEMPKW __VA_ARGS__(CPP2_FORWARD(params)...); }; \
714+
requires noexcept(CPP2_FORWARD(obj).TEMPKW __VA_ARGS__(CPP2_FORWARD(params)...)); } \
715+
|| requires { requires !requires { CPP2_FORWARD(obj).TEMPKW __VA_ARGS__(CPP2_FORWARD(params)...); }; \
716+
requires noexcept(__VA_ARGS__(CPP2_FORWARD(obj), CPP2_FORWARD(params)...)); }) \
717+
CPP2_FORCE_INLINE_LAMBDA -> decltype(auto) \
718+
requires requires { CPP2_FORWARD(obj).TEMPKW __VA_ARGS__(CPP2_FORWARD(params)...); } \
719+
|| requires { __VA_ARGS__(CPP2_FORWARD(obj), CPP2_FORWARD(params)...); } { \
720+
if constexpr (requires{ CPP2_FORWARD(obj).TEMPKW __VA_ARGS__(CPP2_FORWARD(params)...); }) { \
721+
return CPP2_FORWARD(obj).TEMPKW __VA_ARGS__(CPP2_FORWARD(params)...); \
710722
} else { \
711-
return FUNCNAME(CPP2_FORWARD(obj), CPP2_FORWARD(params)...); \
723+
return __VA_ARGS__(CPP2_FORWARD(obj), CPP2_FORWARD(params)...); \
712724
} \
713-
}(PARAM1, __VA_ARGS__)
714-
715-
#define CPP2_UFCS_0(FUNCNAME,PARAM1) \
716-
[&] CPP2_LAMBDA_NO_DISCARD (auto&& obj) CPP2_FORCE_INLINE_LAMBDA -> decltype(auto) { \
717-
if constexpr (requires{ CPP2_FORWARD(obj).FUNCNAME(); }) { \
718-
return CPP2_FORWARD(obj).FUNCNAME(); \
719-
} else { \
720-
return FUNCNAME(CPP2_FORWARD(obj)); \
721-
} \
722-
}(PARAM1)
725+
}
723726

727+
#if 1 // When not rebasing, enable this branch.
728+
#define CPP2_UFCS(...) CPP2_UFCS_(&,,__VA_ARGS__)
729+
#define CPP2_UFCS_TEMPLATE(...) CPP2_UFCS_(&,template,__VA_ARGS__)
730+
#define CPP2_UFCS_NONLOCAL(...) CPP2_UFCS_(,,__VA_ARGS__)
731+
#define CPP2_UFCS_TEMPLATE_NONLOCAL(...) CPP2_UFCS_(,template,__VA_ARGS__)
732+
#else // When rebasing, enable this branch.
733+
// `git restore --staged` and `git restore` conflicting sources.
734+
// Compile `cppfront`. Regenerate conflicting sources. Disable this branch. Complete rebase.
724735
#define CPP2_UFCS_REMPARENS(...) __VA_ARGS__
725-
726-
#define CPP2_UFCS_TEMPLATE(FUNCNAME,TEMPARGS,PARAM1,...) \
727-
[&] CPP2_LAMBDA_NO_DISCARD (auto&& obj, auto&& ...params) CPP2_FORCE_INLINE_LAMBDA -> decltype(auto) { \
728-
if constexpr (requires{ CPP2_FORWARD(obj).template FUNCNAME CPP2_UFCS_REMPARENS TEMPARGS (CPP2_FORWARD(params)...); }) { \
729-
return CPP2_FORWARD(obj).template FUNCNAME CPP2_UFCS_REMPARENS TEMPARGS (CPP2_FORWARD(params)...); \
730-
} else { \
731-
return FUNCNAME CPP2_UFCS_REMPARENS TEMPARGS (CPP2_FORWARD(obj), CPP2_FORWARD(params)...); \
732-
} \
733-
}(PARAM1, __VA_ARGS__)
734-
735-
#define CPP2_UFCS_TEMPLATE_0(FUNCNAME,TEMPARGS,PARAM1) \
736-
[&] CPP2_LAMBDA_NO_DISCARD (auto&& obj) CPP2_FORCE_INLINE_LAMBDA -> decltype(auto) { \
737-
if constexpr (requires{ CPP2_FORWARD(obj).template FUNCNAME CPP2_UFCS_REMPARENS TEMPARGS (); }) { \
738-
return CPP2_FORWARD(obj).template FUNCNAME CPP2_UFCS_REMPARENS TEMPARGS (); \
739-
} else { \
740-
return FUNCNAME CPP2_UFCS_REMPARENS TEMPARGS (CPP2_FORWARD(obj)); \
741-
} \
742-
}(PARAM1)
743-
744-
745-
// But for non-local lambdas [&] is not allowed
746-
747-
#define CPP2_UFCS_NONLOCAL(FUNCNAME,PARAM1,...) \
748-
[] CPP2_LAMBDA_NO_DISCARD (auto&& obj, auto&& ...params) CPP2_FORCE_INLINE_LAMBDA -> decltype(auto) { \
749-
if constexpr (requires{ CPP2_FORWARD(obj).FUNCNAME(CPP2_FORWARD(params)...); }) { \
750-
return CPP2_FORWARD(obj).FUNCNAME(CPP2_FORWARD(params)...); \
751-
} else { \
752-
return FUNCNAME(CPP2_FORWARD(obj), CPP2_FORWARD(params)...); \
753-
} \
754-
}(PARAM1, __VA_ARGS__)
755-
756-
#define CPP2_UFCS_0_NONLOCAL(FUNCNAME,PARAM1) \
757-
[] CPP2_LAMBDA_NO_DISCARD (auto&& obj) CPP2_FORCE_INLINE_LAMBDA -> decltype(auto) { \
758-
if constexpr (requires{ CPP2_FORWARD(obj).FUNCNAME(); }) { \
759-
return CPP2_FORWARD(obj).FUNCNAME(); \
760-
} else { \
761-
return FUNCNAME(CPP2_FORWARD(obj)); \
762-
} \
763-
}(PARAM1)
764-
765-
#define CPP2_UFCS_TEMPLATE_NONLOCAL(FUNCNAME,TEMPARGS,PARAM1,...) \
766-
[] CPP2_LAMBDA_NO_DISCARD (auto&& obj, auto&& ...params) CPP2_FORCE_INLINE_LAMBDA -> decltype(auto) { \
767-
if constexpr (requires{ CPP2_FORWARD(obj).template FUNCNAME CPP2_UFCS_REMPARENS TEMPARGS (CPP2_FORWARD(params)...); }) { \
768-
return CPP2_FORWARD(obj).template FUNCNAME CPP2_UFCS_REMPARENS TEMPARGS (CPP2_FORWARD(params)...); \
769-
} else { \
770-
return FUNCNAME CPP2_UFCS_REMPARENS TEMPARGS (CPP2_FORWARD(obj), CPP2_FORWARD(params)...); \
771-
} \
772-
}(PARAM1, __VA_ARGS__)
773-
774-
#define CPP2_UFCS_TEMPLATE_0_NONLOCAL(FUNCNAME,TEMPARGS,PARAM1) \
775-
[] CPP2_LAMBDA_NO_DISCARD (auto&& obj) CPP2_FORCE_INLINE_LAMBDA -> decltype(auto) { \
776-
if constexpr (requires{ CPP2_FORWARD(obj).template FUNCNAME CPP2_UFCS_REMPARENS TEMPARGS (); }) { \
777-
return CPP2_FORWARD(obj).template FUNCNAME CPP2_UFCS_REMPARENS TEMPARGS (); \
778-
} else { \
779-
return FUNCNAME CPP2_UFCS_REMPARENS TEMPARGS (CPP2_FORWARD(obj)); \
780-
} \
781-
}(PARAM1)
736+
#define CPP2_UFCS(FUNCNAME,PARAM1,...) CPP2_UFCS_(&,,FUNCNAME)(PARAM1,__VA_ARGS__)
737+
#define CPP2_UFCS_0(FUNCNAME,PARAM1) CPP2_UFCS_(&,,FUNCNAME)(PARAM1)
738+
#define CPP2_UFCS_TEMPLATE(FUNCNAME,TEMPARGS,PARAM1,...) CPP2_UFCS_(&,template,FUNCNAME CPP2_UFCS_REMPARENS TEMPARGS)(PARAM1,__VA_ARGS__)
739+
#define CPP2_UFCS_TEMPLATE_0(FUNCNAME,TEMPARGS,PARAM1) CPP2_UFCS_(&,template,FUNCNAME CPP2_UFCS_REMPARENS TEMPARGS)(PARAM1)
740+
#define CPP2_UFCS_NONLOCAL(FUNCNAME,PARAM1,...) CPP2_UFCS_(,,FUNCNAME)(PARAM1,__VA_ARGS__)
741+
#define CPP2_UFCS_0_NONLOCAL(FUNCNAME,PARAM1) CPP2_UFCS_(,,FUNCNAME)(PARAM1)
742+
#define CPP2_UFCS_TEMPLATE_NONLOCAL(FUNCNAME,TEMPARGS,PARAM1,...) CPP2_UFCS_(,template,FUNCNAME CPP2_UFCS_REMPARENS TEMPARGS)(PARAM1,__VA_ARGS__)
743+
#define CPP2_UFCS_TEMPLATE_0_NONLOCAL(FUNCNAME,TEMPARGS,PARAM1) CPP2_UFCS_(,template,FUNCNAME CPP2_UFCS_REMPARENS TEMPARGS)(PARAM1)
744+
#endif
782745

783746

784747
//-----------------------------------------------------------------------
@@ -847,17 +810,17 @@ auto is( X const& ) -> bool {
847810

848811
template< typename C, typename X >
849812
requires (
850-
( std::is_base_of_v<X, C> ||
851-
( std::is_polymorphic_v<C> && std::is_polymorphic_v<X>)
813+
( std::is_base_of_v<X, C> ||
814+
( std::is_polymorphic_v<C> && std::is_polymorphic_v<X>)
852815
) && !std::is_same_v<C,X>)
853816
auto is( X const& x ) -> bool {
854817
return Dynamic_cast<C const*>(&x) != nullptr;
855818
}
856819

857820
template< typename C, typename X >
858821
requires (
859-
( std::is_base_of_v<X, C> ||
860-
( std::is_polymorphic_v<C> && std::is_polymorphic_v<X>)
822+
( std::is_base_of_v<X, C> ||
823+
( std::is_polymorphic_v<C> && std::is_polymorphic_v<X>)
861824
) && !std::is_same_v<C,X>)
862825
auto is( X const* x ) -> bool {
863826
return Dynamic_cast<C const*>(x) != nullptr;
@@ -1462,7 +1425,7 @@ inline auto to_string(std::string const& s) -> std::string const&
14621425

14631426
template<typename T>
14641427
inline auto to_string(T const& sv) -> std::string
1465-
requires (std::is_convertible_v<T, std::string_view>
1428+
requires (std::is_convertible_v<T, std::string_view>
14661429
&& !std::is_convertible_v<T, const char*>)
14671430
{
14681431
return std::string{sv};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
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()> = (); // Blocked on Clang 12 (lambda in unevaluated context).
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()>) = { } // Blocked on Clang 12 (lambda in unevaluated context).
18+
19+
g: () [[pre: o.f()]] = { }
20+
21+
// h: () -> t<o.f()> = o; // Blocked on Clang 12 (lambda in unevaluated context).
22+
23+
// Aliases.
24+
25+
// a: <V: t<o.f()>> type == bool; // Blocked on [GCC109781][].
26+
27+
// b: <V: t<o.f()>> _ == false; // Blocked on [GCC109781][].
28+
29+
// c: type == t<o.f()>; // Blocked on Clang 12 (lambda in unevaluated context).
30+
31+
// d: _ == t<o.f()>(); // Blocked on Clang 12 (lambda in unevaluated context).
32+
33+
main: () = { }
34+
35+
// [GCC109781]: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109781
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
print_res: (x: i32) -> i32 = {
2+
std::cout << x;
3+
if (x == 9) { std::cout << '\n'; }
4+
return x;
5+
}
6+
t: @struct type = {
7+
f: (inout this) -> i32 = print_res(0);
8+
f: (inout this, x) -> i32 = print_res(1);
9+
f: <T> (inout this) -> i32 = print_res(2);
10+
f: <T> (inout this, x) -> i32 = print_res(3);
11+
f: <T, U> (inout this, x, y) -> i32 = print_res(4);
12+
}
13+
f: (o: t) -> i32 = print_res(5);
14+
f: (o: t, x) -> i32 = print_res(6);
15+
f: <T> (o: t) -> i32 = print_res(7);
16+
f: <T> (o: t, x) -> i32 = print_res(8);
17+
f: <T, U> (o: t, x, y) -> i32 = print_res(9);
18+
m: t = ();
19+
n: const t = ();
20+
a: <T, U> _ == n;
21+
_: i32 = m.f();
22+
_: i32 = m.f(0);
23+
_: i32 = m.f<t>();
24+
_: i32 = m.f<t>(0);
25+
_: i32 = m.f<t, t>(0, 0);
26+
_: i32 = n.f();
27+
_: i32 = n.f(0);
28+
_: i32 = n.f<t>();
29+
_: i32 = n.f<t>(0);
30+
_: i32 = n.f<t, t>(0, 0);
31+
_: i32 = a<t, t>.f<t, t>(0, 0);
32+
main: () = {
33+
_: i32 = m.f();
34+
_: i32 = m.f(0);
35+
_: i32 = m.f<t>();
36+
_: i32 = m.f<t>(0);
37+
_: i32 = m.f<t, t>(0, 0);
38+
_: i32 = n.f();
39+
_: i32 = n.f(0);
40+
_: i32 = n.f<t>();
41+
_: i32 = n.f<t>(0);
42+
_: i32 = n.f<t, t>(0, 0);
43+
_: i32 = a<t, t>.f<t, t>(0, 0);
44+
45+
_ = :(a, f) = { _ = a.f(a).f(); };
46+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
t: type = {
2+
f: (this) -> i32 = 0;
3+
}
4+
main: () = {
5+
f := t().f();
6+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
t: type = {
2+
// swap: (inout this, that) = { } // Blocked on #508.
3+
}
4+
main: () = {
5+
// static_assert(noexcept(t().swap(t()))); // Blocked on Clang 12 (lambda in unevaluated context).
6+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
// f: <T> () -> std::type_identity_t<decltype(T().a())> = { } // Blocked on Clang 12 (lambda in unevaluated context).
2+
B: type = { }
3+
main: () = {
4+
// static_assert(!std::invocable<decltype(:<T> (x: T) -> std::void_t<decltype(f<T>())> = {}), B>); // Blocked on Clang 12 (lambda in unevaluated context).
5+
}
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
clang version 18.0.0 (https://git.uplinklabs.net/mirrors/llvm-project.git c0abd3814564a568dfc607c216e6407eaa314f46)
1+
clang version 18.0.0 (https://github.com/llvm/llvm-project.git 3723ede3cf5324827f8fbbe7f484c2ee4d7a7204)
22
Target: x86_64-pc-linux-gnu
33
Thread model: posix
44
InstalledDir: /home/johel/root/clang-main/bin

regression-tests/test-results/clang-18/mixed-bugfix-for-ufcs-non-local.cpp.execution

Whitespace-only changes.

regression-tests/test-results/clang-18/mixed-bugfix-for-ufcs-non-local.cpp.output

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
0123456789
2+
9
3+
0123456789
4+
9

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

Whitespace-only changes.

regression-tests/test-results/clang-18/pure2-bugfix-for-ufcs-name-lookup.cpp.execution

Whitespace-only changes.

regression-tests/test-results/clang-18/pure2-bugfix-for-ufcs-name-lookup.cpp.output

Whitespace-only changes.

regression-tests/test-results/clang-18/pure2-bugfix-for-ufcs-noexcept.cpp.execution

Whitespace-only changes.

regression-tests/test-results/clang-18/pure2-bugfix-for-ufcs-noexcept.cpp.output

Whitespace-only changes.

regression-tests/test-results/clang-18/pure2-bugfix-for-ufcs-sfinae.cpp.execution

Whitespace-only changes.

regression-tests/test-results/clang-18/pure2-bugfix-for-ufcs-sfinae.cpp.output

Whitespace-only changes.

regression-tests/test-results/gcc-13/mixed-bugfix-for-ufcs-non-local.cpp.execution

Whitespace-only changes.

regression-tests/test-results/gcc-13/mixed-bugfix-for-ufcs-non-local.cpp.output

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
0123456789
2+
9
3+
0123456789
4+
9

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

Whitespace-only changes.

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

Whitespace-only changes.

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

Whitespace-only changes.

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.

regression-tests/test-results/mixed-bounds-check.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
std::set_terminate(std::abort);
2525

2626
std::vector v {1, 2, 3, 4, 5, -999};
27-
CPP2_UFCS_0(pop_back, v);
27+
CPP2_UFCS(pop_back)(v);
2828
std::cout << cpp2::assert_in_bounds(std::move(v), 5) << "\n";
2929
}
3030

regression-tests/test-results/mixed-bounds-safety-with-assert-2.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ auto add_42_to_subrange(auto& rng, cpp2::in<int> start, cpp2::in<int> end) -> vo
3838
auto add_42_to_subrange(auto& rng, cpp2::in<int> start, cpp2::in<int> end) -> void
3939
{
4040
cpp2::Bounds.expects(cpp2::cmp_less_eq(0,start), "");
41-
cpp2::Bounds.expects(cpp2::cmp_less_eq(end,CPP2_UFCS_0(ssize, rng)), "");
41+
cpp2::Bounds.expects(cpp2::cmp_less_eq(end,CPP2_UFCS(ssize)(rng)), "");
4242

4343
auto count {0};
4444
for (

regression-tests/test-results/mixed-bounds-safety-with-assert.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ auto print_subrange(auto const& rng, cpp2::in<int> start, cpp2::in<int> end) ->
3737

3838
auto print_subrange(auto const& rng, cpp2::in<int> start, cpp2::in<int> end) -> void{
3939
cpp2::Bounds.expects(cpp2::cmp_less_eq(0,start), "");
40-
cpp2::Bounds.expects(cpp2::cmp_less_eq(end,CPP2_UFCS_0(ssize, rng)), "");
40+
cpp2::Bounds.expects(cpp2::cmp_less_eq(end,CPP2_UFCS(ssize)(rng)), "");
4141

4242
auto count {0};
4343
for (
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
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+
// _: t<o.f()> = (); // Blocked on Clang 12 (lambda in unevaluated context).
21+
22+
#line 11 "mixed-bugfix-for-ufcs-non-local.cpp2"
23+
extern bool auto_11_1;
24+
25+
// Functions.
26+
27+
// g: <V: t<o.f()>> () = { } // Blocked on [GCC109781][].
28+
29+
// g: (x: t<o.f()>) = { } // Blocked on Clang 12 (lambda in unevaluated context).
30+
31+
auto g() -> void;
32+
33+
// h: () -> t<o.f()> = o; // Blocked on Clang 12 (lambda in unevaluated context).
34+
35+
// Aliases.
36+
37+
// a: <V: t<o.f()>> type == bool; // Blocked on [GCC109781][].
38+
39+
// b: <V: t<o.f()>> _ == false; // Blocked on [GCC109781][].
40+
41+
// c: type == t<o.f()>; // Blocked on Clang 12 (lambda in unevaluated context).
42+
43+
// d: _ == t<o.f()>(); // Blocked on Clang 12 (lambda in unevaluated context).
44+
45+
auto main() -> int;
46+
47+
// [GCC109781]: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109781
48+
49+
50+
//=== Cpp2 function definitions =================================================
51+
52+
53+
#line 11 "mixed-bugfix-for-ufcs-non-local.cpp2"
54+
bool auto_11_1 {CPP2_UFCS_NONLOCAL(f)(o)};
55+
56+
#line 19 "mixed-bugfix-for-ufcs-non-local.cpp2"
57+
auto g() -> void{
58+
cpp2::Default.expects(CPP2_UFCS(f)(o), "");
59+
#line 19 "mixed-bugfix-for-ufcs-non-local.cpp2"
60+
}
61+
62+
#line 33 "mixed-bugfix-for-ufcs-non-local.cpp2"
63+
auto main() -> int{}
64+

0 commit comments

Comments
 (0)