diff options
author | Lancelot SIX <lsix@lancelotsix.com> | 2021-10-19 21:51:40 +0000 |
---|---|---|
committer | Lancelot SIX <lsix@lancelotsix.com> | 2021-11-08 21:55:36 +0000 |
commit | e92f2b5eef008a8617bcd6d878b09848adf6ea7f (patch) | |
tree | ca1ddafb398545629ba0974847d2624b7545322c /gdbsupport | |
parent | 8b4195d8d1d1a7c328f9b0dc48cdbf3d8abb6fe6 (diff) | |
download | binutils-gdb-e92f2b5eef008a8617bcd6d878b09848adf6ea7f.tar.gz |
Improve gdb::array_view ctor from contiguous containers
While reading the interface of gdb::array_view, I realized that the
constructor that builds an array_view on top of a contiguous container
(such as std::vector, std::array or even gdb::array_view) can be
missused.
Lets consider the following code sample:
struct Parent
{
Parent (int a): a { a } {}
int a;
};
std::ostream &operator<< (std::ostream& os, const Parent & p)
{ os << "Parent {a=" << p.a << "}"; return os; }
struct Child : public Parent
{
Child (int a, int b): Parent { a }, b { b } {}
int b;
};
std::ostream &operator<< (std::ostream& os, const Child & p)
{ os << "Child {a=" << p.a << ", b=" << p.b << "}"; return os; }
template <typename T>
void print (const gdb::array_view<const T> &p)
{
std::for_each (p.begin (), p.end (), [](const T &p) { std::cout << p << '\n'; });
}
Then with the current interface nothinng prevents this usage of
array_view to be done:
const std::array<Child, 3> elts = {
Child {1, 2},
Child {3, 4},
Child {5, 6}
};
print_all<Parent> (elts);
This compiles fine and produces the following output:
Parent {a=1}
Parent {a=2}
Parent {a=3}
which is obviously wrong. There is nowhere in memory a Parent-like
object for which the A member is 2 and this call to print_all<Parent>
shold not compile at all (calling print_all<Child> is however fine).
This comes down to the fact that a Child* is convertible into a Parent*,
and that an array view is constructed to a pointer to the first element
and a size. The valid type pointed to that can be used with this
constructor are restricted using SFINAE, which requires that a
pointer to a member into the underlying container can be converted into a
pointer the array_view's data type.
This patch proposes to change the constraints on the gdb::array_view
ctor which accepts a container now requires that the (decayed) type of
the elements in the container match the (decayed) type of the array_view
being constructed.
Applying this change required minimum adjustment in GDB codebase, which
are also included in this patch.
Tested by rebuilding.
Diffstat (limited to 'gdbsupport')
-rw-r--r-- | gdbsupport/array-view.h | 7 |
1 files changed, 4 insertions, 3 deletions
diff --git a/gdbsupport/array-view.h b/gdbsupport/array-view.h index ab1d032c60e..6f7e45a979c 100644 --- a/gdbsupport/array-view.h +++ b/gdbsupport/array-view.h @@ -139,9 +139,10 @@ public: template<typename Container, typename = Requires<gdb::Not<IsDecayedT<Container>>>, typename - = Requires<std::is_convertible - <decltype (std::declval<Container> ().data ()), - T *>>, + = Requires<DecayedConvertible + <typename std::remove_pointer + <decltype (std::declval<Container> ().data ()) + >::type>>, typename = Requires<std::is_convertible <decltype (std::declval<Container> ().size ()), |