-
Notifications
You must be signed in to change notification settings - Fork 260
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix(util): handle known UFCS corner cases (#506)
* fix(util): 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. * refactor: regenerate `reflect.h` * refactor(util): use new UFCS macros * test: add unit tests for fixed UFCS corner cases * test: regenerate regression tests * refactor(util): remove old UFCS branch * refactor(util): comment the need for `CPP2_UFCS_IS_NOTHROW` * refactor(to_cpp1): split name lookup from `ufcs_possible` * refactor(to_cpp1): clarify name of `ufcs_possible` * refactor(to_cpp1): rename `stack` variables to `guard` * refactor(to_cpp1): add comment on added `stack` functions * refactor(to_cpp1): invert meaning of result to match rename * fix(to_cpp1): a using declaration doesn't name a variable * fix(to_cpp1): do not capture in UFCS of type scope alias * fix(to_cpp1): do not capture in UFCS of type scope alias * refactor(to_cpp1): regroup conditions more naturally * test: regenerate test-results * fix(to_cpp1): do capture in UFCS of contract * test: regenerate test-results * fix(to_cpp1): emit qualified UFCS template call correctly * fix(to_cpp1): emit qualified UFCS template call correctly * fix(util): workaround MSVC bug for UFCS of 'F' in member 'F' * test: disable the simpler test case due to the GCC bug * test: disable test cases now failing on MSVC * Results of testing the PR incl. with MSVC 2022 And minor code tweaks * refactor(to_cpp1): apply review comment and rename name lookup * test: regenerate test-results * test: add case for the happy path * test: regenerate UFCS tests --------- Co-authored-by: Herb Sutter <[email protected]>
- Loading branch information
Showing
102 changed files
with
1,698 additions
and
526 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
namespace ns { | ||
|
||
template<bool> struct t { }; | ||
constexpr bool f(const t<true>&) { return true; } | ||
constexpr t<true> o{}; | ||
|
||
} // namespace ns | ||
|
||
ns: namespace = { | ||
|
||
// Variables. | ||
|
||
v0: <_: t<o.f()>> bool == false; // Fails on GCC ([GCC109781][]) and Clang 12 (a lambda expression cannot appear in this context) | ||
|
||
v1: t<o.f()> == t<true>(); // Fails on Clang 12 (lambda in unevaluated context). | ||
|
||
v2: bool == o.f(); | ||
|
||
// Functions. | ||
|
||
g: <_: t<o.f()>> () = { } // Fails on GCC ([GCC109781][]) and Clang 12 (a lambda expression cannot appear in this context) | ||
|
||
g: (_: t<o.f()>) = { } // Fails on Clang 12 (lambda in unevaluated context). | ||
|
||
g: () pre(o.f()) = { } | ||
|
||
h: () -> t<o.f()> = o; // Fails on Clang 12 (lambda in unevaluated context). | ||
|
||
// Aliases. | ||
|
||
a: <_: t<o.f()>> type == bool; // Fails on GCC ([GCC109781][]) and Clang 12 (a lambda expression cannot appear in this context) | ||
|
||
b: <_: t<o.f()>> _ == false; // Fails on GCC ([GCC109781][]). | ||
|
||
c: type == t<o.f()>; // Fails on Clang 12 (lambda in unevaluated context) and Clang 12 (a lambda expression cannot appear in this context) | ||
|
||
d: _ == t<o.f()>(); // Fails on Clang 12 (lambda in unevaluated context). | ||
|
||
u: @struct type = { | ||
b: bool == o.f(); | ||
c: bool == :(x: std::type_identity_t<decltype(o.f())>) x;(true); // Fails on Clang 12 (lambda in unevaluated context). | ||
g: (s, sz) pre(s.sz() != 0) = { } | ||
} | ||
|
||
} // namespace ns | ||
|
||
main: () = { } | ||
|
||
// [GCC109781]: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109781 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
print_res: (x: i32) -> i32 = { | ||
std::cout << x; | ||
if x == 9 { std::cout << '\n'; } | ||
return x; | ||
} | ||
|
||
t: @struct type = { | ||
f: (inout this) -> i32 = print_res(0); | ||
f: (inout this, _) -> i32 = print_res(1); | ||
f: <_> (inout this) -> i32 = print_res(2); | ||
f: <_> (inout this, _) -> i32 = print_res(3); | ||
f: <_, U> (inout this, _, _) -> i32 = print_res(4); | ||
} | ||
|
||
f: (_: t) -> i32 = print_res(5); | ||
f: (_: t, _) -> i32 = print_res(6); | ||
f: <_> (_: t) -> i32 = print_res(7); | ||
f: <_> (_: t, _) -> i32 = print_res(8); | ||
f: <_, U> (_: t, _, _) -> i32 = print_res(9); | ||
|
||
m: t = (); | ||
n: const t = (); | ||
a: <_, U> _ == n; | ||
|
||
_: i32 = m.f(); | ||
_: i32 = m.f(0); | ||
_: i32 = m.f<t>(); | ||
_: i32 = m.f<t>(0); | ||
_: i32 = m.f<t, t>(0, 0); | ||
_: i32 = n.f(); | ||
_: i32 = n.f(0); | ||
_: i32 = n.f<t>(); | ||
_: i32 = n.f<t>(0); | ||
_: i32 = n.f<t, t>(0, 0); | ||
_: i32 = a<t, t>.f<t, t>(0, 0); | ||
|
||
main: () = { | ||
_ = m.f(); | ||
_ = m.f(0); | ||
_ = m.f<t>(); | ||
_ = m.f<t>(0); | ||
_ = m.f<t, t>(0, 0); | ||
_ = n.f(); | ||
_ = n.f(0); | ||
_ = n.f<t>(); | ||
_ = n.f<t>(0); | ||
_ = n.f<t, t>(0, 0); | ||
_ = a<t, t>.f<t, t>(0, 0); | ||
|
||
_ = :(a, f) = { _ = a.f(a).f(); }; | ||
// _ = 0.std::min<int>(0); | ||
_ = 0.ns::t<0, 0>::f<0>(); | ||
} | ||
|
||
// _: i32 = 0.std::min<int>(0); | ||
_: i32 = 0.ns::t<0, 0>::f<0>(); | ||
|
||
ns: namespace = { | ||
t: @struct <T: int, U: int> type = { | ||
f: <V: int> (_: int) -> i32 = 0; | ||
} | ||
} // namespace ns | ||
|
||
A: @struct type = { | ||
f: (this) = { } | ||
} | ||
|
||
B: @struct type = { | ||
m: A; | ||
f: (this) = m.f(); | ||
} |
Oops, something went wrong.