On Thu, 5 Mar 2026 at 16:51, Jonathan Wakely <[email protected]> wrote:
>
> On Thu, 5 Mar 2026 at 15:59, Nathan Myers wrote:
> >
> > Changes in v2:
> > - Rejigger testing, test on c++98 et al.
> > - Add tests for regular bitset<>::op[].
> >
> > Perform __glibcxx_assert bounds check on indices to bitset<>::op[]
> > for const and non-const overloads.
> >
> > Also, add previously neglected regular tests for bitset<>::op[].
>
> OK for trunk, thanks.
>
>
> >
> > libstdc++-v3/ChangeLog
> > PR libstdc++/118341
> > * include/std/bitset (operator[] (2x)): Add assertion.
> > * testsuite/20_util/bitset/access/118341_neg1.cc: New test.
> > * testsuite/20_util/bitset/access/118341_neg2.cc: Same.
> > * testsuite/20_util/bitset/access/118341_smoke.cc: Same.
> > * testsuite/20_util/bitset/access/subscript.cc: Same.
> > * testsuite/20_util/bitset/access/subscript_const_neg.cc: Same.
> > ---
> > libstdc++-v3/include/std/bitset | 10 ++++--
> > .../20_util/bitset/access/118341_neg1.cc | 14 +++++++++
> > .../20_util/bitset/access/118341_neg2.cc | 14 +++++++++
> > .../20_util/bitset/access/118341_smoke.cc | 31 +++++++++++++++++++
> > .../20_util/bitset/access/subscript.cc | 28 +++++++++++++++++
> > .../bitset/access/subscript_const_neg.cc | 15 +++++++++
> > 6 files changed, 110 insertions(+), 2 deletions(-)
> > create mode 100644
> > libstdc++-v3/testsuite/20_util/bitset/access/118341_neg1.cc
> > create mode 100644
> > libstdc++-v3/testsuite/20_util/bitset/access/118341_neg2.cc
> > create mode 100644
> > libstdc++-v3/testsuite/20_util/bitset/access/118341_smoke.cc
> > create mode 100644
> > libstdc++-v3/testsuite/20_util/bitset/access/subscript.cc
> > create mode 100644
> > libstdc++-v3/testsuite/20_util/bitset/access/subscript_const_neg.cc
> >
> > diff --git a/libstdc++-v3/include/std/bitset
> > b/libstdc++-v3/include/std/bitset
> > index 331d0894342..eb200ab9246 100644
> > --- a/libstdc++-v3/include/std/bitset
> > +++ b/libstdc++-v3/include/std/bitset
> > @@ -1290,11 +1290,17 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
> > _GLIBCXX23_CONSTEXPR
> > reference
> > operator[](size_t __position)
> > - { return reference(*this, __position); }
> > + {
> > + __glibcxx_assert(__position < _Nb);
> > + return reference(*this, __position);
> > + }
> >
> > _GLIBCXX_CONSTEXPR bool
> > operator[](size_t __position) const
> > - { return _Unchecked_test(__position); }
> > + {
> > + __glibcxx_assert(__position < _Nb);
> > + return _Unchecked_test(__position);
> > + }
> > ///@}
> >
> > /**
> > diff --git a/libstdc++-v3/testsuite/20_util/bitset/access/118341_neg1.cc
> > b/libstdc++-v3/testsuite/20_util/bitset/access/118341_neg1.cc
> > new file mode 100644
> > index 00000000000..22991ffac91
> > --- /dev/null
> > +++ b/libstdc++-v3/testsuite/20_util/bitset/access/118341_neg1.cc
> > @@ -0,0 +1,14 @@
> > +// { dg-do run { xfail *-*-* } }
> > +// { dg-options "-D_GLIBCXX_ASSERTIONS" }
> > +
> > +#include <bitset>
> > +#include <testsuite_hooks.h>
> > +
> > +// Check bitset<>::op[] hardening, non-const.
> > +
> > +int main()
> > +{
> > + std::bitset<13> bs(0x1555ull);
> > + bs[12]; // OK
> > + bs[13]; // aborts, 13 > 12, non-const
> > +}
> > diff --git a/libstdc++-v3/testsuite/20_util/bitset/access/118341_neg2.cc
> > b/libstdc++-v3/testsuite/20_util/bitset/access/118341_neg2.cc
> > new file mode 100644
> > index 00000000000..fa8942ec510
> > --- /dev/null
> > +++ b/libstdc++-v3/testsuite/20_util/bitset/access/118341_neg2.cc
> > @@ -0,0 +1,14 @@
> > +// { dg-do run { xfail *-*-* } }
> > +// { dg-options "-D_GLIBCXX_ASSERTIONS" }
> > +
> > +#include <bitset>
> > +#include <testsuite_hooks.h>
> > +
> > +// Check bitset<>::op[] hardening, const.
> > +
> > +int main()
> > +{
> > + const std::bitset<13> bs(0x1555ull);
> > + bs[12]; // OK
> > + bs[13]; // aborts, 13 > 12, const
> > +}
> > diff --git a/libstdc++-v3/testsuite/20_util/bitset/access/118341_smoke.cc
> > b/libstdc++-v3/testsuite/20_util/bitset/access/118341_smoke.cc
> > new file mode 100644
> > index 00000000000..0a525c1b3fa
> > --- /dev/null
> > +++ b/libstdc++-v3/testsuite/20_util/bitset/access/118341_smoke.cc
> > @@ -0,0 +1,31 @@
> > +// { dg-do run }
> > +// { dg-options "-D_GLIBCXX_ASSERTIONS" }
> > +
> > +// Smoke test, op[] hardening.
> > +
> > +#include <bitset>
> > +#include <testsuite_hooks.h>
> > +
> > +void test_non_const_subscript()
> > +{
> > + std::bitset<13> bs(0x1555ull);
> > + for (int i = 0; i < 13; ++i)
> > + {
> > + VERIFY(bs[i] != (i & 1)); // Check op[] proxy result rvalue.
> > + bs[i] = not bs[i]; // Assign via op[] proxy result lvalue.
> > + VERIFY(bs[i] == (i & 1)); // Check modified.
> > + }
> > +}
> > +
> > +void test_const_subscript()
> > +{
> > + const std::bitset<13> cbs(0x1555ull);
> > + for (int i = 0; i < 13; ++i)
> > + VERIFY(cbs[i] != (i & 1)); // Check op[] proxy result const rvalue.
> > +}
> > +
> > +int main()
> > +{
> > + test_non_const_subscript();
> > + test_const_subscript();
> > +}
> > diff --git a/libstdc++-v3/testsuite/20_util/bitset/access/subscript.cc
> > b/libstdc++-v3/testsuite/20_util/bitset/access/subscript.cc
> > new file mode 100644
> > index 00000000000..4bcf6e3d530
> > --- /dev/null
> > +++ b/libstdc++-v3/testsuite/20_util/bitset/access/subscript.cc
> > @@ -0,0 +1,28 @@
> > +// { dg-do run }
> > +
> > +#include <bitset>
> > +#include <testsuite_hooks.h>
> > +
> > +void test_non_const_subscript()
> > +{
> > + std::bitset<13> bs(0x1555ull);
> > + for (int i = 0; i < 13; ++i)
> > + {
> > + VERIFY(bs[i] != (i & 1)); // Check op[] proxy result rvalue.
> > + bs[i] = not bs[i]; // Assign via op[] proxy result lvalue.
> > + VERIFY(bs[i] == (i & 1)); // Check modified.
> > + }
> > +}
> > +
> > +void test_const_subscript()
> > +{
> > + const std::bitset<13> cbs(0x1555ull);
> > + for (int i = 0; i < 13; ++i)
> > + VERIFY(cbs[i] != (i & 1)); // Check op[] proxy result const rvalue.
> > +}
> > +
> > +int main()
> > +{
> > + test_non_const_subscript();
> > + test_const_subscript();
> > +}
> > diff --git
> > a/libstdc++-v3/testsuite/20_util/bitset/access/subscript_const_neg.cc
> > b/libstdc++-v3/testsuite/20_util/bitset/access/subscript_const_neg.cc
> > new file mode 100644
> > index 00000000000..00ed36196f8
> > --- /dev/null
> > +++ b/libstdc++-v3/testsuite/20_util/bitset/access/subscript_const_neg.cc
> > @@ -0,0 +1,15 @@
> > +// { dg-do compile
Oh hang on, this line looks mangled.
Since it doesn't end with a } I think dejagnu ignores it, so this will
be a dg-do run test instead, which is probably what was intended
anyway?
> > +
> > +#include <bitset>
> > +
> > +void test_const_subscript_assignment()
> > +{
> > + const std::bitset<13> bs(0x1555ull);
> > + for (int i = 0; i < 13; ++i)
> > + bs[i] = not bs[i]; // { dg-error "lvalue required" }
> > +}
> > +
> > +int main()
> > +{
> > + test_const_subscript_assignment();
> > +}
> > --
> > 2.52.0
> >