Skip to content

Commit bbd104e

Browse files
committed
feat: recognize requires expressions
1 parent 387d352 commit bbd104e

29 files changed

+669
-18
lines changed

include/cpp2util.h

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@
113113
// in our -pure-cpp2 "import std;" simulation mode... if you need this,
114114
// use mixed mode (not -pure-cpp2) and #include all the headers you need
115115
// including this one
116-
//
116+
//
117117
// #include <execution>
118118
#ifdef __cpp_lib_expected
119119
#include <expected>
@@ -514,7 +514,7 @@ template<typename T>
514514
auto Typeid() -> decltype(auto) {
515515
#ifdef CPP2_NO_RTTI
516516
Type.expects(
517-
!"'any' dynamic casting is disabled with -fno-rtti", // more likely to appear on console
517+
!"'any' dynamic casting is disabled with -fno-rtti", // more likely to appear on console
518518
"'any' dynamic casting is disabled with -fno-rtti" // make message available to hooked handlers
519519
);
520520
#else
@@ -860,7 +860,7 @@ inline auto to_string(std::string const& s) -> std::string const&
860860

861861
template<typename T>
862862
inline auto to_string(T const& sv) -> std::string
863-
requires (std::is_convertible_v<T, std::string_view>
863+
requires (std::is_convertible_v<T, std::string_view>
864864
&& !std::is_convertible_v<T, const char*>)
865865
{
866866
return std::string{sv};
@@ -1000,17 +1000,17 @@ auto is( X const& ) -> bool {
10001000

10011001
template< typename C, typename X >
10021002
requires (
1003-
( std::is_base_of_v<X, C> ||
1004-
( std::is_polymorphic_v<C> && std::is_polymorphic_v<X>)
1003+
( std::is_base_of_v<X, C> ||
1004+
( std::is_polymorphic_v<C> && std::is_polymorphic_v<X>)
10051005
) && !std::is_same_v<C,X>)
10061006
auto is( X const& x ) -> bool {
10071007
return Dynamic_cast<C const*>(&x) != nullptr;
10081008
}
10091009

10101010
template< typename C, typename X >
10111011
requires (
1012-
( std::is_base_of_v<X, C> ||
1013-
( std::is_polymorphic_v<C> && std::is_polymorphic_v<X>)
1012+
( std::is_base_of_v<X, C> ||
1013+
( std::is_polymorphic_v<C> && std::is_polymorphic_v<X>)
10141014
) && !std::is_same_v<C,X>)
10151015
auto is( X const* x ) -> bool {
10161016
return Dynamic_cast<C const*>(x) != nullptr;
@@ -1641,7 +1641,7 @@ constexpr auto unsafe_narrow( X&& x ) noexcept -> decltype(auto)
16411641
// Returns a function object that takes a 'value' of the same type as
16421642
// 'flags', and evaluates to true if and only if 'value' has set all of
16431643
// the bits set in 'flags'
1644-
//
1644+
//
16451645
//-----------------------------------------------------------------------
16461646
//
16471647
template <typename T>
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// https://youtu.be/CXn02MPkn8Y?t=2337
2+
negatable: <T> concept = requires(t: T)
3+
{
4+
_ = -t is T; // Hopefully obviously wrong. Should be `{ -t } is T;`.
5+
};
6+
7+
main: () = static_assert(negatable<char>);
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// https://youtu.be/CXn02MPkn8Y?t=2418
2+
int_sized: <T> concept = requires(t: T)
3+
{
4+
_ = sizeof(T) == 4; // Hopefully obviously wrong. Should be `requires (sizeof(T) == 4);`.
5+
};
6+
// Could also be `int_sized: <T> concept = sizeof(T) == 4;`.
7+
8+
main: () = static_assert(int_sized<char>);
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// https://youtu.be/CXn02MPkn8Y?t=2455
2+
nothrow_incrementable: <T> concept = requires(inout t: T)
3+
{
4+
_ = noexcept(t++); // Hopefully obviously wrong. Should be `requires noexcept(t++);` or `{ t++ } !throws;`.
5+
};
6+
7+
main: () = { static_assert(nothrow_incrementable<char>); }
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// https://quuxplusone.github.io/blog/2021/06/09/another-concepts-chest-mimic/
2+
has_a_but_not_b: <T> concept = requires(t: T)
3+
{
4+
_ = a(t);
5+
!requires _ = b(t); // In Cpp2, this works and does the correct thing.
6+
};
7+
8+
s1: @struct type = { }
9+
s2: @struct type = { }
10+
a: (_: s2) = { }
11+
s3: @struct type = { }
12+
b: (_: s3) = { }
13+
s4: @struct type = { }
14+
a: (_: s4) = { }
15+
b: (_: s4) = { }
16+
17+
main: () = {
18+
static_assert(!has_a_but_not_b<s1>); // as expected
19+
static_assert(has_a_but_not_b<s2>); // as expected
20+
static_assert(!has_a_but_not_b<s3>); // as expected
21+
static_assert(!has_a_but_not_b<s4>); // pit of success!
22+
}
Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,26 @@
11
arithmetic: <T> concept = std::integral<T> || std::floating_point<T>;
2-
main: () = {
3-
[[assert Testing: arithmetic<i32>]]
4-
[[assert Testing: arithmetic<float>]]
2+
number_difference_t: <T> type == std::type_identity_t<decltype(T() - T())>;
3+
number: <T> concept = std::regular<T> && requires(c: T)
4+
{
5+
!requires std::iter_reference_t<T>; // Negative requirement.
6+
{c + c} is std::common_with<T>; // Compound requirement.
7+
number_difference_t<T>; // Type requirement.
8+
_ = c - c; // Expression requirement.
9+
requires std::common_with<number_difference_t<T>, T>; // Nested requirement.
10+
};
11+
test_nonthrowing_requirements: <T> concept = requires
12+
{ // clang-format off
13+
{ T() } !throws;
14+
{ -T() } !throws, is std::same_as<T>;
15+
}; // clang-format on
16+
main: () = {
17+
static_assert(arithmetic<i32>);
18+
static_assert(arithmetic<float>);
19+
static_assert(number<i32>);
20+
static_assert(number<float>);
21+
static_assert(number<std::chrono::seconds>);
22+
static_assert(!number<* i32>);
23+
static_assert(!number<std::reverse_iterator<* i32>>);
24+
static_assert(test_nonthrowing_requirements<i32>);
25+
static_assert(!test_nonthrowing_requirements<std::chrono::seconds>);
526
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
clang version 18.0.0 (https://github.com/llvm/llvm-project.git 3723ede3cf5324827f8fbbe7f484c2ee4d7a7204)
2+
Target: x86_64-pc-linux-gnu
3+
Thread model: posix
4+
InstalledDir: /home/johel/root/clang-main/bin

regression-tests/test-results/clang-18/pure2-bugfix-for-non-local-function-expression.cpp.execution

Whitespace-only changes.

regression-tests/test-results/clang-18/pure2-bugfix-for-non-local-function-expression.cpp.output

Whitespace-only changes.

regression-tests/test-results/clang-18/pure2-concept-definition-no-pitfall-1.cpp.execution

Whitespace-only changes.

0 commit comments

Comments
 (0)