Skip to content

Commit 423c07f

Browse files
committed
New issue from Hewill: "simd::unchecked_load(I first, S last) construct span maybe ill-formed"
1 parent 0888f71 commit 423c07f

File tree

1 file changed

+91
-0
lines changed

1 file changed

+91
-0
lines changed

xml/issue4394.xml

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
<?xml version='1.0' encoding='utf-8' standalone='no'?>
2+
<!DOCTYPE issue SYSTEM "lwg-issue.dtd">
3+
4+
<issue num="4394" status="New">
5+
<title>`simd::unchecked_load(I first, S last)` construct `span` maybe ill-formed</title>
6+
<section><sref ref="[simd.loadstore]"/></section>
7+
<submitter>Hewill Kang</submitter>
8+
<date>30 Sep 2025</date>
9+
<priority>99</priority>
10+
11+
<discussion>
12+
<p>
13+
Currently, `simd::unchecked_load`/`partial_load`/`unchecked_store`/`partial_store`
14+
constructs a `span` via `span(first, last)` when taking an iterator-sentinel pair
15+
`first` and `last`.
16+
<p/>
17+
However, the construction may not be well-behaved or well-formed when the sentinel type
18+
can be implicitly converted to an integer type. Consider:
19+
</p>
20+
<blockquote><pre>
21+
struct I {
22+
using value_type = int;
23+
using difference_type = int;
24+
using iterator_category = std::contiguous_iterator_tag;
25+
// contiguous iterator operators
26+
// ...
27+
28+
operator int() const;
29+
};
30+
31+
int main() {
32+
std::simd::unchecked_load(I{}, I{});
33+
}
34+
</pre></blockquote>
35+
<p>
36+
Above, `unchecked_load` invokes `unchecked_load(I first, S last)` and we attempt to
37+
construct `span` through `span(first, last)`.
38+
However, this is invalid because the constructor requires that the sentinel type should not be convertible to
39+
`size_t`, so we fall back into `span(first, n)` via implicitly converting `I` to `size_t`. Such
40+
behavior is subtle and likely unintended.
41+
<p/>
42+
Now consider:
43+
</p>
44+
<blockquote><pre>
45+
struct I {
46+
using value_type = int;
47+
using difference_type = int;
48+
using iterator_category = std::contiguous_iterator_tag;
49+
// contiguous iterator operators
50+
// ...
51+
52+
operator int() &amp;&amp;;
53+
};
54+
55+
int main() {
56+
std::simd::unchecked_load(I{}, I{});
57+
}
58+
</pre></blockquote>
59+
<p>
60+
We still attempt to construct the `span` by calling `span(first, last)`, which is invalid,
61+
but because the lvalue sentinel cannot be converted to `size_t`, the call of `span(first, n)`
62+
is also invalid. This makes the construction of the `span` ill-formed and leads to a hard error in
63+
the function body.
64+
</p>
65+
</discussion>
66+
67+
<resolution>
68+
<p>
69+
This wording is relative to <paper num="N5014"/>.
70+
</p>
71+
72+
<ol>
73+
74+
75+
<li><p>In subclause <sref ref="[simd.loadstore]"/> replace all occurrences of
76+
</p>
77+
<blockquote><pre>
78+
R(first, last)
79+
</pre></blockquote>
80+
<p>
81+
by
82+
</p>
83+
<blockquote><pre>
84+
R(first, <ins>static_cast&lt;size_t&gt;(</ins>last<ins> - first)</ins>)
85+
</pre></blockquote>
86+
</li>
87+
</ol>
88+
89+
</resolution>
90+
91+
</issue>

0 commit comments

Comments
 (0)