Skip to content

Commit 4490a7d

Browse files
committed
Remove double evaluation of container in subscript checks
Better addresses #799 See comment thread #799 (comment)
1 parent 776110d commit 4490a7d

26 files changed

+189
-100
lines changed

include/cpp2util.h

Lines changed: 35 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -467,31 +467,47 @@ auto assert_not_null(auto&& p CPP2_SOURCE_LOCATION_PARAM_WITH_DEFAULT) -> declty
467467

468468
// Subscript bounds checking
469469
//
470-
auto assert_in_bounds_impl(auto&& x, auto&& arg CPP2_SOURCE_LOCATION_PARAM_WITH_DEFAULT) -> void
471-
requires (std::is_integral_v<CPP2_TYPEOF(arg)> &&
472-
requires { std::size(x); std::ssize(x); x[arg]; std::begin(x) + 2; })
470+
#define CPP2_ASSERT_IN_BOUNDS_IMPL \
471+
requires (std::is_integral_v<CPP2_TYPEOF(arg)> && \
472+
requires { std::size(x); std::ssize(x); x[arg]; std::begin(x) + 2; }) \
473+
{ \
474+
auto max = [&]() -> auto { \
475+
if constexpr (std::is_signed_v<CPP2_TYPEOF(arg)>) { return std::ssize(x); } \
476+
else { return std::size(x); } \
477+
}; \
478+
auto msg = "out of bounds access attempt detected - attempted access at index " + std::to_string(arg) + ", "; \
479+
if (max() > 0 ) { \
480+
msg += "[min,max] range is [0," + std::to_string(max()-1) + "]"; \
481+
} \
482+
else { \
483+
msg += "but container is empty"; \
484+
} \
485+
if (!(0 <= arg && arg < max())) { \
486+
Bounds.report_violation(msg.c_str() CPP2_SOURCE_LOCATION_ARG); \
487+
} \
488+
return CPP2_FORWARD(x) [ arg ]; \
489+
}
490+
491+
template<auto arg>
492+
auto assert_in_bounds(auto&& x CPP2_SOURCE_LOCATION_PARAM_WITH_DEFAULT) -> decltype(auto)
493+
CPP2_ASSERT_IN_BOUNDS_IMPL
494+
495+
auto assert_in_bounds(auto&& x, auto&& arg CPP2_SOURCE_LOCATION_PARAM_WITH_DEFAULT) -> decltype(auto)
496+
CPP2_ASSERT_IN_BOUNDS_IMPL
497+
498+
template<auto arg>
499+
auto assert_in_bounds(auto&& x CPP2_SOURCE_LOCATION_PARAM_WITH_DEFAULT) -> decltype(auto)
473500
{
474-
auto max = [&]() -> auto {
475-
if constexpr (std::is_signed_v<CPP2_TYPEOF(arg)>) { return std::ssize(x); }
476-
else { return std::size(x); }
477-
};
478-
auto msg = "out of bounds access attempt detected - attempted access at index " + std::to_string(arg) + ", ";
479-
if (max() > 0 ) {
480-
msg += "[min,max] range is [0," + std::to_string(max()-1) + "]";
481-
}
482-
else {
483-
msg += "but container is empty";
484-
}
485-
if (!(0 <= arg && arg < max())) {
486-
Bounds.report_violation(msg.c_str() CPP2_SOURCE_LOCATION_ARG);
487-
}
501+
return CPP2_FORWARD(x) [ arg ];
488502
}
489503

490-
auto assert_in_bounds_impl(auto&&, auto&& CPP2_SOURCE_LOCATION_PARAM_WITH_DEFAULT) -> void
504+
auto assert_in_bounds(auto&& x, auto&& arg CPP2_SOURCE_LOCATION_PARAM_WITH_DEFAULT) -> decltype(auto)
491505
{
506+
return CPP2_FORWARD(x) [ CPP2_FORWARD(arg) ];
492507
}
493508

494-
#define CPP2_ASSERT_IN_BOUNDS(x, arg) (cpp2::assert_in_bounds_impl((x),(arg)), (x)[(arg)])
509+
#define CPP2_ASSERT_IN_BOUNDS(x,arg) (cpp2::assert_in_bounds((x),(arg)))
510+
#define CPP2_ASSERT_IN_BOUNDS_LITERAL(x,arg) (cpp2::assert_in_bounds<(arg)>(x))
495511

496512

497513
//-----------------------------------------------------------------------
Lines changed: 26 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,118 +1,118 @@
11
mixed-bugfix-for-ufcs-non-local.cpp2:13:12: error: a lambda expression cannot appear in this context
22
template<t<CPP2_UFCS_NONLOCAL(f)(o)> _> bool inline constexpr v0 = false;// Fails on GCC ([GCC109781][]) and Clang 12 (a lambda expression cannot appear in this context)
33
^
4-
../../../include/cpp2util.h:868:59: note: expanded from macro 'CPP2_UFCS_NONLOCAL'
4+
../../../include/cpp2util.h:884:59: note: expanded from macro 'CPP2_UFCS_NONLOCAL'
55
#define CPP2_UFCS_NONLOCAL(...) CPP2_UFCS_(,(),,__VA_ARGS__)
66
^
7-
../../../include/cpp2util.h:849:53: note: expanded from macro 'CPP2_UFCS_'
7+
../../../include/cpp2util.h:865:53: note: expanded from macro 'CPP2_UFCS_'
88
#define CPP2_UFCS_(LAMBDADEFCAPT,QUALID,TEMPKW,...) \
99
^
1010
mixed-bugfix-for-ufcs-non-local.cpp2:15:3: error: a lambda expression cannot appear in this context
1111
t<CPP2_UFCS_NONLOCAL(f)(o)> inline constexpr v1 = t<true>();// Fails on Clang 12 (lambda in unevaluated context).
1212
^
13-
../../../include/cpp2util.h:868:59: note: expanded from macro 'CPP2_UFCS_NONLOCAL'
13+
../../../include/cpp2util.h:884:59: note: expanded from macro 'CPP2_UFCS_NONLOCAL'
1414
#define CPP2_UFCS_NONLOCAL(...) CPP2_UFCS_(,(),,__VA_ARGS__)
1515
^
16-
../../../include/cpp2util.h:849:53: note: expanded from macro 'CPP2_UFCS_'
16+
../../../include/cpp2util.h:865:53: note: expanded from macro 'CPP2_UFCS_'
1717
#define CPP2_UFCS_(LAMBDADEFCAPT,QUALID,TEMPKW,...) \
1818
^
1919
mixed-bugfix-for-ufcs-non-local.cpp2:21:12: error: a lambda expression cannot appear in this context
2020
template<t<CPP2_UFCS_NONLOCAL(f)(o)> _> auto g() -> void;
2121
^
22-
../../../include/cpp2util.h:868:59: note: expanded from macro 'CPP2_UFCS_NONLOCAL'
22+
../../../include/cpp2util.h:884:59: note: expanded from macro 'CPP2_UFCS_NONLOCAL'
2323
#define CPP2_UFCS_NONLOCAL(...) CPP2_UFCS_(,(),,__VA_ARGS__)
2424
^
25-
../../../include/cpp2util.h:849:53: note: expanded from macro 'CPP2_UFCS_'
25+
../../../include/cpp2util.h:865:53: note: expanded from macro 'CPP2_UFCS_'
2626
#define CPP2_UFCS_(LAMBDADEFCAPT,QUALID,TEMPKW,...) \
2727
^
2828
mixed-bugfix-for-ufcs-non-local.cpp2:23:36: error: a lambda expression cannot appear in this context
2929
auto g([[maybe_unused]] cpp2::in<t<CPP2_UFCS_NONLOCAL(f)(o)>> unnamed_param_1) -> void;
3030
^
31-
../../../include/cpp2util.h:868:59: note: expanded from macro 'CPP2_UFCS_NONLOCAL'
31+
../../../include/cpp2util.h:884:59: note: expanded from macro 'CPP2_UFCS_NONLOCAL'
3232
#define CPP2_UFCS_NONLOCAL(...) CPP2_UFCS_(,(),,__VA_ARGS__)
3333
^
34-
../../../include/cpp2util.h:849:53: note: expanded from macro 'CPP2_UFCS_'
34+
../../../include/cpp2util.h:865:53: note: expanded from macro 'CPP2_UFCS_'
3535
#define CPP2_UFCS_(LAMBDADEFCAPT,QUALID,TEMPKW,...) \
3636
^
3737
mixed-bugfix-for-ufcs-non-local.cpp2:27:29: error: a lambda expression cannot appear in this context
3838
[[nodiscard]] auto h() -> t<CPP2_UFCS_NONLOCAL(f)(o)>;
3939
^
40-
../../../include/cpp2util.h:868:59: note: expanded from macro 'CPP2_UFCS_NONLOCAL'
40+
../../../include/cpp2util.h:884:59: note: expanded from macro 'CPP2_UFCS_NONLOCAL'
4141
#define CPP2_UFCS_NONLOCAL(...) CPP2_UFCS_(,(),,__VA_ARGS__)
4242
^
43-
../../../include/cpp2util.h:849:53: note: expanded from macro 'CPP2_UFCS_'
43+
../../../include/cpp2util.h:865:53: note: expanded from macro 'CPP2_UFCS_'
4444
#define CPP2_UFCS_(LAMBDADEFCAPT,QUALID,TEMPKW,...) \
4545
^
4646
mixed-bugfix-for-ufcs-non-local.cpp2:31:12: error: a lambda expression cannot appear in this context
4747
template<t<CPP2_UFCS_NONLOCAL(f)(o)> _> using a = bool;// Fails on GCC ([GCC109781][]) and Clang 12 (a lambda expression cannot appear in this context)
4848
^
49-
../../../include/cpp2util.h:868:59: note: expanded from macro 'CPP2_UFCS_NONLOCAL'
49+
../../../include/cpp2util.h:884:59: note: expanded from macro 'CPP2_UFCS_NONLOCAL'
5050
#define CPP2_UFCS_NONLOCAL(...) CPP2_UFCS_(,(),,__VA_ARGS__)
5151
^
52-
../../../include/cpp2util.h:849:53: note: expanded from macro 'CPP2_UFCS_'
52+
../../../include/cpp2util.h:865:53: note: expanded from macro 'CPP2_UFCS_'
5353
#define CPP2_UFCS_(LAMBDADEFCAPT,QUALID,TEMPKW,...) \
5454
^
5555
mixed-bugfix-for-ufcs-non-local.cpp2:33:12: error: a lambda expression cannot appear in this context
5656
template<t<CPP2_UFCS_NONLOCAL(f)(o)> _> auto inline constexpr b = false;// Fails on GCC ([GCC109781][]).
5757
^
58-
../../../include/cpp2util.h:868:59: note: expanded from macro 'CPP2_UFCS_NONLOCAL'
58+
../../../include/cpp2util.h:884:59: note: expanded from macro 'CPP2_UFCS_NONLOCAL'
5959
#define CPP2_UFCS_NONLOCAL(...) CPP2_UFCS_(,(),,__VA_ARGS__)
6060
^
61-
../../../include/cpp2util.h:849:53: note: expanded from macro 'CPP2_UFCS_'
61+
../../../include/cpp2util.h:865:53: note: expanded from macro 'CPP2_UFCS_'
6262
#define CPP2_UFCS_(LAMBDADEFCAPT,QUALID,TEMPKW,...) \
6363
^
6464
mixed-bugfix-for-ufcs-non-local.cpp2:35:13: error: a lambda expression cannot appear in this context
6565
using c = t<CPP2_UFCS_NONLOCAL(f)(o)>;// Fails on Clang 12 (lambda in unevaluated context) and Clang 12 (a lambda expression cannot appear in this context)
6666
^
67-
../../../include/cpp2util.h:868:59: note: expanded from macro 'CPP2_UFCS_NONLOCAL'
67+
../../../include/cpp2util.h:884:59: note: expanded from macro 'CPP2_UFCS_NONLOCAL'
6868
#define CPP2_UFCS_NONLOCAL(...) CPP2_UFCS_(,(),,__VA_ARGS__)
6969
^
70-
../../../include/cpp2util.h:849:53: note: expanded from macro 'CPP2_UFCS_'
70+
../../../include/cpp2util.h:865:53: note: expanded from macro 'CPP2_UFCS_'
7171
#define CPP2_UFCS_(LAMBDADEFCAPT,QUALID,TEMPKW,...) \
7272
^
7373
mixed-bugfix-for-ufcs-non-local.cpp2:37:29: error: a lambda expression cannot appear in this context
7474
auto inline constexpr d = t<CPP2_UFCS_NONLOCAL(f)(o)>();// Fails on Clang 12 (lambda in unevaluated context).
7575
^
76-
../../../include/cpp2util.h:868:59: note: expanded from macro 'CPP2_UFCS_NONLOCAL'
76+
../../../include/cpp2util.h:884:59: note: expanded from macro 'CPP2_UFCS_NONLOCAL'
7777
#define CPP2_UFCS_NONLOCAL(...) CPP2_UFCS_(,(),,__VA_ARGS__)
7878
^
79-
../../../include/cpp2util.h:849:53: note: expanded from macro 'CPP2_UFCS_'
79+
../../../include/cpp2util.h:865:53: note: expanded from macro 'CPP2_UFCS_'
8080
#define CPP2_UFCS_(LAMBDADEFCAPT,QUALID,TEMPKW,...) \
8181
^
8282
mixed-bugfix-for-ufcs-non-local.cpp2:21:12: error: a lambda expression cannot appear in this context
8383
template<t<CPP2_UFCS_NONLOCAL(f)(o)> _> auto g() -> void{}// Fails on GCC ([GCC109781][]) and Clang 12 (a lambda expression cannot appear in this context)
8484
^
85-
../../../include/cpp2util.h:868:59: note: expanded from macro 'CPP2_UFCS_NONLOCAL'
85+
../../../include/cpp2util.h:884:59: note: expanded from macro 'CPP2_UFCS_NONLOCAL'
8686
#define CPP2_UFCS_NONLOCAL(...) CPP2_UFCS_(,(),,__VA_ARGS__)
8787
^
88-
../../../include/cpp2util.h:849:53: note: expanded from macro 'CPP2_UFCS_'
88+
../../../include/cpp2util.h:865:53: note: expanded from macro 'CPP2_UFCS_'
8989
#define CPP2_UFCS_(LAMBDADEFCAPT,QUALID,TEMPKW,...) \
9090
^
9191
mixed-bugfix-for-ufcs-non-local.cpp2:23:36: error: a lambda expression cannot appear in this context
9292
auto g([[maybe_unused]] cpp2::in<t<CPP2_UFCS_NONLOCAL(f)(o)>> unnamed_param_1) -> void{}// Fails on Clang 12 (lambda in unevaluated context).
9393
^
94-
../../../include/cpp2util.h:868:59: note: expanded from macro 'CPP2_UFCS_NONLOCAL'
94+
../../../include/cpp2util.h:884:59: note: expanded from macro 'CPP2_UFCS_NONLOCAL'
9595
#define CPP2_UFCS_NONLOCAL(...) CPP2_UFCS_(,(),,__VA_ARGS__)
9696
^
97-
../../../include/cpp2util.h:849:53: note: expanded from macro 'CPP2_UFCS_'
97+
../../../include/cpp2util.h:865:53: note: expanded from macro 'CPP2_UFCS_'
9898
#define CPP2_UFCS_(LAMBDADEFCAPT,QUALID,TEMPKW,...) \
9999
^
100100
mixed-bugfix-for-ufcs-non-local.cpp2:27:29: error: a lambda expression cannot appear in this context
101101
[[nodiscard]] auto h() -> t<CPP2_UFCS_NONLOCAL(f)(o)> { return o; }// Fails on Clang 12 (lambda in unevaluated context).
102102
^
103-
../../../include/cpp2util.h:868:59: note: expanded from macro 'CPP2_UFCS_NONLOCAL'
103+
../../../include/cpp2util.h:884:59: note: expanded from macro 'CPP2_UFCS_NONLOCAL'
104104
#define CPP2_UFCS_NONLOCAL(...) CPP2_UFCS_(,(),,__VA_ARGS__)
105105
^
106-
../../../include/cpp2util.h:849:53: note: expanded from macro 'CPP2_UFCS_'
106+
../../../include/cpp2util.h:865:53: note: expanded from macro 'CPP2_UFCS_'
107107
#define CPP2_UFCS_(LAMBDADEFCAPT,QUALID,TEMPKW,...) \
108108
^
109109
mixed-bugfix-for-ufcs-non-local.cpp2:41:79: error: lambda expression in an unevaluated operand
110110
inline CPP2_CONSTEXPR bool u::c = [](cpp2::in<std::type_identity_t<decltype(CPP2_UFCS_NONLOCAL(f)(o))>> x) mutable -> auto { return x; }(true);// Fails on Clang 12 (lambda in unevaluated context).
111111
^
112-
../../../include/cpp2util.h:868:59: note: expanded from macro 'CPP2_UFCS_NONLOCAL'
112+
../../../include/cpp2util.h:884:59: note: expanded from macro 'CPP2_UFCS_NONLOCAL'
113113
#define CPP2_UFCS_NONLOCAL(...) CPP2_UFCS_(,(),,__VA_ARGS__)
114114
^
115-
../../../include/cpp2util.h:849:53: note: expanded from macro 'CPP2_UFCS_'
115+
../../../include/cpp2util.h:865:53: note: expanded from macro 'CPP2_UFCS_'
116116
#define CPP2_UFCS_(LAMBDADEFCAPT,QUALID,TEMPKW,...) \
117117
^
118118
13 errors generated.

regression-tests/test-results/clang-12/pure2-bugfix-for-indexed-call.cpp.execution

Whitespace-only changes.

regression-tests/test-results/clang-12/pure2-bugfix-for-indexed-call.cpp.output

Whitespace-only changes.
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
pure2-bugfix-for-ufcs-noexcept.cpp2:5:26: error: lambda expression in an unevaluated operand
22
static_assert(noexcept(CPP2_UFCS(swap)(t(), t())));// Fails on Clang 12 (lambda in unevaluated context) and GCC 10 (static assertion failed)
33
^
4-
../../../include/cpp2util.h:865:59: note: expanded from macro 'CPP2_UFCS'
4+
../../../include/cpp2util.h:881:59: note: expanded from macro 'CPP2_UFCS'
55
#define CPP2_UFCS(...) CPP2_UFCS_(&,(),,__VA_ARGS__)
66
^
7-
../../../include/cpp2util.h:849:53: note: expanded from macro 'CPP2_UFCS_'
7+
../../../include/cpp2util.h:865:53: note: expanded from macro 'CPP2_UFCS_'
88
#define CPP2_UFCS_(LAMBDADEFCAPT,QUALID,TEMPKW,...) \
99
^
1010
1 error generated.
Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
11
pure2-bugfix-for-ufcs-sfinae.cpp2:1:78: error: lambda expression in an unevaluated operand
22
template<typename T> [[nodiscard]] auto f() -> std::type_identity_t<decltype(CPP2_UFCS_NONLOCAL(a)(T()))>;
33
^
4-
../../../include/cpp2util.h:868:59: note: expanded from macro 'CPP2_UFCS_NONLOCAL'
4+
../../../include/cpp2util.h:884:59: note: expanded from macro 'CPP2_UFCS_NONLOCAL'
55
#define CPP2_UFCS_NONLOCAL(...) CPP2_UFCS_(,(),,__VA_ARGS__)
66
^
7-
../../../include/cpp2util.h:849:53: note: expanded from macro 'CPP2_UFCS_'
7+
../../../include/cpp2util.h:865:53: note: expanded from macro 'CPP2_UFCS_'
88
#define CPP2_UFCS_(LAMBDADEFCAPT,QUALID,TEMPKW,...) \
99
^
1010
pure2-bugfix-for-ufcs-sfinae.cpp2:1:78: error: lambda expression in an unevaluated operand
1111
template<typename T> [[nodiscard]] auto f() -> std::type_identity_t<decltype(CPP2_UFCS_NONLOCAL(a)(T()))>{}// Fails on Clang 12 (lambda in unevaluated context).
1212
^
13-
../../../include/cpp2util.h:868:59: note: expanded from macro 'CPP2_UFCS_NONLOCAL'
13+
../../../include/cpp2util.h:884:59: note: expanded from macro 'CPP2_UFCS_NONLOCAL'
1414
#define CPP2_UFCS_NONLOCAL(...) CPP2_UFCS_(,(),,__VA_ARGS__)
1515
^
16-
../../../include/cpp2util.h:849:53: note: expanded from macro 'CPP2_UFCS_'
16+
../../../include/cpp2util.h:865:53: note: expanded from macro 'CPP2_UFCS_'
1717
#define CPP2_UFCS_(LAMBDADEFCAPT,QUALID,TEMPKW,...) \
1818
^
1919
2 errors generated.

regression-tests/test-results/gcc-10/pure2-bugfix-for-indexed-call.cpp.execution

Whitespace-only changes.

regression-tests/test-results/gcc-10/pure2-bugfix-for-indexed-call.cpp.output

Whitespace-only changes.

regression-tests/test-results/gcc-10/pure2-bugfix-for-requires-clause-in-forward-declaration.cpp.output

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,12 @@ pure2-bugfix-for-requires-clause-in-forward-declaration.cpp2:3:46: error: expect
66
In file included from pure2-bugfix-for-requires-clause-in-forward-declaration.cpp:7:
77
../../../include/cpp2util.h:10005:47: error: static assertion failed: GCC 11 or higher is required to support variables and type-scope functions that have a 'requires' clause. This includes a type-scope 'forward' parameter of non-wildcard type, such as 'func: (this, forward s: std::string)', which relies on being able to add a 'requires' clause - in that case, use 'forward s: _' instead if you need the result to compile with GCC 10.
88
pure2-bugfix-for-requires-clause-in-forward-declaration.cpp2:4:1: note: in expansion of macro ‘CPP2_REQUIRES_’
9-
pure2-bugfix-for-requires-clause-in-forward-declaration.cpp2:3:3: error: no declaration matches ‘element::element(auto:92&&) requires is_same_v<typename std::remove_cv<typename std::remove_reference<decltype(element::__ct ::n)>::type>::type, std::__cxx11::string>’
9+
pure2-bugfix-for-requires-clause-in-forward-declaration.cpp2:3:3: error: no declaration matches ‘element::element(auto:94&&) requires is_same_v<typename std::remove_cv<typename std::remove_reference<decltype(element::__ct ::n)>::type>::type, std::__cxx11::string>’
1010
pure2-bugfix-for-requires-clause-in-forward-declaration.cpp2:5:11: note: candidates are: ‘element::element(const element&)’
11-
pure2-bugfix-for-requires-clause-in-forward-declaration.cpp2:3:20: note: ‘template<class auto:90> element::element(auto:90&&)’
11+
pure2-bugfix-for-requires-clause-in-forward-declaration.cpp2:3:20: note: ‘template<class auto:92> element::element(auto:92&&)’
1212
pure2-bugfix-for-requires-clause-in-forward-declaration.cpp2:1:7: note: ‘class element’ defined here
1313
pure2-bugfix-for-requires-clause-in-forward-declaration.cpp2:5:78: error: expected unqualified-id before ‘{’ token
14-
pure2-bugfix-for-requires-clause-in-forward-declaration.cpp2:3:8: error: no declaration matches ‘element& element::operator=(auto:93&&) requires is_same_v<typename std::remove_cv<typename std::remove_reference<decltype(element::operator=::n)>::type>::type, std::__cxx11::string>’
14+
pure2-bugfix-for-requires-clause-in-forward-declaration.cpp2:3:8: error: no declaration matches ‘element& element::operator=(auto:95&&) requires is_same_v<typename std::remove_cv<typename std::remove_reference<decltype(element::operator=::n)>::type>::type, std::__cxx11::string>’
1515
pure2-bugfix-for-requires-clause-in-forward-declaration.cpp2:6:16: note: candidates are: ‘void element::operator=(const element&)’
16-
pure2-bugfix-for-requires-clause-in-forward-declaration.cpp2:3:16: note: ‘template<class auto:91> element& element::operator=(auto:91&&)’
16+
pure2-bugfix-for-requires-clause-in-forward-declaration.cpp2:3:16: note: ‘template<class auto:93> element& element::operator=(auto:93&&)’
1717
pure2-bugfix-for-requires-clause-in-forward-declaration.cpp2:1:7: note: ‘class element’ defined here

0 commit comments

Comments
 (0)