Skip to content

Commit c6ed828

Browse files
authored
[ADT] Fix incorrect const parent ptr type in ilist (#96059)
Fixes issue reported in: #94224 The recent commit above added an ilist_parent<ParentTy> option, which added a parent pointer to the ilist_node_base type for the list. The const methods for returning that parent pointer however were incorrectly implemented, returning `const ParentPtrTy`, which is equivalent to `ParentTy * const` rather than `const ParentTy *`. This patch fixes this by passing around `ParentTy` in ilist's internal logic rather than `ParentPtrTy`, removing the ability to have a `void*` parent pointer but cleanly fixing this error.
1 parent 02af67c commit c6ed828

8 files changed

+68
-49
lines changed

llvm/include/llvm/ADT/ilist_base.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@
1515
namespace llvm {
1616

1717
/// Implementations of list algorithms using ilist_node_base.
18-
template <bool EnableSentinelTracking, class ParentPtrTy> class ilist_base {
18+
template <bool EnableSentinelTracking, class ParentTy> class ilist_base {
1919
public:
20-
using node_base_type = ilist_node_base<EnableSentinelTracking, ParentPtrTy>;
20+
using node_base_type = ilist_node_base<EnableSentinelTracking, ParentTy>;
2121

2222
static void insertBeforeImpl(node_base_type &Next, node_base_type &N) {
2323
node_base_type &Prev = *Next.getPrev();

llvm/include/llvm/ADT/ilist_iterator.h

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -53,19 +53,19 @@ template <> struct IteratorHelper<true> : ilist_detail::NodeAccess {
5353
/// Mixin class used to add a \a getNodeParent() function to iterators iff the
5454
/// list uses \a ilist_parent, calling through to the node's \a getParent(). For
5555
/// more details see \a ilist_node.
56-
template <class IteratorTy, class ParentPtrTy, bool IsConst>
56+
template <class IteratorTy, class ParentTy, bool IsConst>
5757
class iterator_parent_access;
58-
template <class IteratorTy, class ParentPtrTy>
59-
class iterator_parent_access<IteratorTy, ParentPtrTy, true> {
58+
template <class IteratorTy, class ParentTy>
59+
class iterator_parent_access<IteratorTy, ParentTy, true> {
6060
public:
61-
inline const ParentPtrTy getNodeParent() const {
61+
inline const ParentTy *getNodeParent() const {
6262
return static_cast<IteratorTy *>(this)->NodePtr->getParent();
6363
}
6464
};
65-
template <class IteratorTy, class ParentPtrTy>
66-
class iterator_parent_access<IteratorTy, ParentPtrTy, false> {
65+
template <class IteratorTy, class ParentTy>
66+
class iterator_parent_access<IteratorTy, ParentTy, false> {
6767
public:
68-
inline ParentPtrTy getNodeParent() {
68+
inline ParentTy *getNodeParent() {
6969
return static_cast<IteratorTy *>(this)->NodePtr->getParent();
7070
}
7171
};
@@ -81,13 +81,13 @@ template <class OptionsT, bool IsReverse, bool IsConst>
8181
class ilist_iterator : ilist_detail::SpecificNodeAccess<OptionsT>,
8282
public ilist_detail::iterator_parent_access<
8383
ilist_iterator<OptionsT, IsReverse, IsConst>,
84-
typename OptionsT::parent_ptr_ty, IsConst> {
84+
typename OptionsT::parent_ty, IsConst> {
8585
friend ilist_iterator<OptionsT, IsReverse, !IsConst>;
8686
friend ilist_iterator<OptionsT, !IsReverse, IsConst>;
8787
friend ilist_iterator<OptionsT, !IsReverse, !IsConst>;
8888
friend ilist_detail::iterator_parent_access<
89-
ilist_iterator<OptionsT, IsReverse, IsConst>,
90-
typename OptionsT::parent_ptr_ty, IsConst>;
89+
ilist_iterator<OptionsT, IsReverse, IsConst>,
90+
typename OptionsT::parent_ty, IsConst>;
9191

9292
using Traits = ilist_detail::IteratorTraits<OptionsT, IsConst>;
9393
using Access = ilist_detail::SpecificNodeAccess<OptionsT>;
@@ -215,13 +215,13 @@ class ilist_iterator_w_bits
215215
: ilist_detail::SpecificNodeAccess<OptionsT>,
216216
public ilist_detail::iterator_parent_access<
217217
ilist_iterator_w_bits<OptionsT, IsReverse, IsConst>,
218-
typename OptionsT::parent_ptr_ty, IsConst> {
218+
typename OptionsT::parent_ty, IsConst> {
219219
friend ilist_iterator_w_bits<OptionsT, IsReverse, !IsConst>;
220220
friend ilist_iterator_w_bits<OptionsT, !IsReverse, IsConst>;
221221
friend ilist_iterator<OptionsT, !IsReverse, !IsConst>;
222222
friend ilist_detail::iterator_parent_access<
223-
ilist_iterator_w_bits<OptionsT, IsReverse, IsConst>,
224-
typename OptionsT::parent_ptr_ty, IsConst>;
223+
ilist_iterator_w_bits<OptionsT, IsReverse, IsConst>,
224+
typename OptionsT::parent_ty, IsConst>;
225225

226226
using Traits = ilist_detail::IteratorTraits<OptionsT, IsConst>;
227227
using Access = ilist_detail::SpecificNodeAccess<OptionsT>;

llvm/include/llvm/ADT/ilist_node.h

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,17 +25,17 @@ namespace ilist_detail {
2525
struct NodeAccess;
2626

2727
/// Mixin base class that is used to add \a getParent() and
28-
/// \a setParent(ParentPtrTy) methods to \a ilist_node_impl iff \a ilist_parent
28+
/// \a setParent(ParentTy*) methods to \a ilist_node_impl iff \a ilist_parent
2929
/// has been set in the list options.
30-
template <class NodeTy, class ParentPtrTy> class node_parent_access {
30+
template <class NodeTy, class ParentTy> class node_parent_access {
3131
public:
32-
inline const ParentPtrTy getParent() const {
32+
inline const ParentTy *getParent() const {
3333
return static_cast<const NodeTy *>(this)->getNodeBaseParent();
3434
}
35-
inline ParentPtrTy getParent() {
35+
inline ParentTy *getParent() {
3636
return static_cast<NodeTy *>(this)->getNodeBaseParent();
3737
}
38-
void setParent(ParentPtrTy Parent) {
38+
void setParent(ParentTy *Parent) {
3939
return static_cast<NodeTy *>(this)->setNodeBaseParent(Parent);
4040
}
4141
};
@@ -71,8 +71,8 @@ class ilist_select_iterator_type<true, Opts, arg1, arg2> {
7171
template <class OptionsT>
7272
class ilist_node_impl
7373
: OptionsT::node_base_type,
74-
public ilist_detail::node_parent_access<
75-
ilist_node_impl<OptionsT>, typename OptionsT::parent_ptr_ty> {
74+
public ilist_detail::node_parent_access<ilist_node_impl<OptionsT>,
75+
typename OptionsT::parent_ty> {
7676
using value_type = typename OptionsT::value_type;
7777
using node_base_type = typename OptionsT::node_base_type;
7878
using list_base_type = typename OptionsT::list_base_type;
@@ -81,8 +81,8 @@ class ilist_node_impl
8181
friend struct ilist_detail::NodeAccess;
8282
friend class ilist_sentinel<OptionsT>;
8383

84-
friend class ilist_detail::node_parent_access<
85-
ilist_node_impl<OptionsT>, typename OptionsT::parent_ptr_ty>;
84+
friend class ilist_detail::node_parent_access<ilist_node_impl<OptionsT>,
85+
typename OptionsT::parent_ty>;
8686
friend class ilist_iterator<OptionsT, false, false>;
8787
friend class ilist_iterator<OptionsT, false, true>;
8888
friend class ilist_iterator<OptionsT, true, false>;

llvm/include/llvm/ADT/ilist_node_base.h

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -46,13 +46,13 @@ template <class NodeBase> class node_base_prevnext<NodeBase, true> {
4646
void initializeSentinel() { PrevAndSentinel.setInt(true); }
4747
};
4848

49-
template <class ParentPtrTy> class node_base_parent {
50-
ParentPtrTy Parent = nullptr;
49+
template <class ParentTy> class node_base_parent {
50+
ParentTy *Parent = nullptr;
5151

5252
public:
53-
void setNodeBaseParent(ParentPtrTy Parent) { this->Parent = Parent; }
54-
inline const ParentPtrTy getNodeBaseParent() const { return Parent; }
55-
inline ParentPtrTy getNodeBaseParent() { return Parent; }
53+
void setNodeBaseParent(ParentTy *Parent) { this->Parent = Parent; }
54+
inline const ParentTy *getNodeBaseParent() const { return Parent; }
55+
inline ParentTy *getNodeBaseParent() { return Parent; }
5656
};
5757
template <> class node_base_parent<void> {};
5858

@@ -61,12 +61,11 @@ template <> class node_base_parent<void> {};
6161
/// Base class for ilist nodes.
6262
///
6363
/// Optionally tracks whether this node is the sentinel.
64-
template <bool EnableSentinelTracking, class ParentPtrTy>
65-
class ilist_node_base
66-
: public ilist_detail::node_base_prevnext<
67-
ilist_node_base<EnableSentinelTracking, ParentPtrTy>,
68-
EnableSentinelTracking>,
69-
public ilist_detail::node_base_parent<ParentPtrTy> {};
64+
template <bool EnableSentinelTracking, class ParentTy>
65+
class ilist_node_base : public ilist_detail::node_base_prevnext<
66+
ilist_node_base<EnableSentinelTracking, ParentTy>,
67+
EnableSentinelTracking>,
68+
public ilist_detail::node_base_parent<ParentTy> {};
7069

7170
} // end namespace llvm
7271

llvm/include/llvm/ADT/ilist_node_options.h

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@
1515

1616
namespace llvm {
1717

18-
template <bool EnableSentinelTracking, class ParentPtrTy> class ilist_node_base;
19-
template <bool EnableSentinelTracking, class ParentPtrTy> class ilist_base;
18+
template <bool EnableSentinelTracking, class ParentTy> class ilist_node_base;
19+
template <bool EnableSentinelTracking, class ParentTy> class ilist_base;
2020

2121
/// Option to choose whether to track sentinels.
2222
///
@@ -134,7 +134,7 @@ struct is_valid_option<ilist_iterator_bits<IteratorBits>> : std::true_type {};
134134
template <class... Options> struct extract_parent;
135135
template <class ParentTy, class... Options>
136136
struct extract_parent<ilist_parent<ParentTy>, Options...> {
137-
typedef ParentTy *type;
137+
typedef ParentTy type;
138138
};
139139
template <class Option1, class... Options>
140140
struct extract_parent<Option1, Options...> : extract_parent<Options...> {};
@@ -156,7 +156,7 @@ struct check_options<Option1, Options...>
156156
///
157157
/// This is usually computed via \a compute_node_options.
158158
template <class T, bool EnableSentinelTracking, bool IsSentinelTrackingExplicit,
159-
class TagT, bool HasIteratorBits, class ParentPtrTy>
159+
class TagT, bool HasIteratorBits, class ParentTy>
160160
struct node_options {
161161
typedef T value_type;
162162
typedef T *pointer;
@@ -168,10 +168,9 @@ struct node_options {
168168
static const bool is_sentinel_tracking_explicit = IsSentinelTrackingExplicit;
169169
static const bool has_iterator_bits = HasIteratorBits;
170170
typedef TagT tag;
171-
typedef ParentPtrTy parent_ptr_ty;
172-
typedef ilist_node_base<enable_sentinel_tracking, parent_ptr_ty>
173-
node_base_type;
174-
typedef ilist_base<enable_sentinel_tracking, parent_ptr_ty> list_base_type;
171+
typedef ParentTy parent_ty;
172+
typedef ilist_node_base<enable_sentinel_tracking, parent_ty> node_base_type;
173+
typedef ilist_base<enable_sentinel_tracking, parent_ty> list_base_type;
175174
};
176175

177176
template <class T, class... Options> struct compute_node_options {

llvm/unittests/ADT/IListIteratorTest.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,7 @@ TEST(IListIteratorTest, GetParent) {
175175
simple_ilist<ParentNode, ilist_parent<Parent>> L;
176176
Parent P;
177177
ParentNode A;
178+
const simple_ilist<ParentNode, ilist_parent<Parent>> &CL = L;
178179

179180
// Parents are not set automatically.
180181
A.setParent(&P);
@@ -187,6 +188,15 @@ TEST(IListIteratorTest, GetParent) {
187188
EXPECT_EQ(&P, L.end().getNodeParent());
188189
EXPECT_EQ(&P, L.rbegin().getNodeParent());
189190
EXPECT_EQ(&P, L.rend().getNodeParent());
191+
192+
using VarParentTy =
193+
std::remove_pointer_t<decltype(L.begin().getNodeParent())>;
194+
using ConstParentTy =
195+
std::remove_pointer_t<decltype(CL.begin().getNodeParent())>;
196+
static_assert(
197+
std::is_const_v<ConstParentTy> &&
198+
std::is_same_v<VarParentTy, std::remove_const_t<ConstParentTy>>,
199+
"`getNodeParent() const` adds const to parent type");
190200
}
191201

192202
} // end namespace

llvm/unittests/ADT/IListNodeBaseTest.cpp

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
#include "llvm/ADT/ilist_node_base.h"
1010
#include "gtest/gtest.h"
1111

12+
#include <type_traits>
13+
1214
using namespace llvm;
1315

1416
namespace {
@@ -17,8 +19,8 @@ class Parent {};
1719

1820
typedef ilist_node_base<false, void> RawNode;
1921
typedef ilist_node_base<true, void> TrackingNode;
20-
typedef ilist_node_base<false, Parent*> ParentNode;
21-
typedef ilist_node_base<true, Parent*> ParentTrackingNode;
22+
typedef ilist_node_base<false, Parent> ParentNode;
23+
typedef ilist_node_base<true, Parent> ParentTrackingNode;
2224

2325
TEST(IListNodeBaseTest, DefaultConstructor) {
2426
RawNode A;
@@ -177,9 +179,10 @@ TEST(IListNodeBaseTest, isKnownSentinel) {
177179
EXPECT_EQ(&PTB, PTA.getNext());
178180
}
179181

180-
TEST(IListNodeBaseTest, setNodeBaseParent) {
182+
TEST(IListNodeBaseTest, nodeBaseParent) {
181183
Parent Par;
182184
ParentNode PA;
185+
const ParentNode CPA;
183186
EXPECT_EQ(nullptr, PA.getNodeBaseParent());
184187
PA.setNodeBaseParent(&Par);
185188
EXPECT_EQ(&Par, PA.getNodeBaseParent());
@@ -188,6 +191,14 @@ TEST(IListNodeBaseTest, setNodeBaseParent) {
188191
EXPECT_EQ(nullptr, PTA.getNodeBaseParent());
189192
PTA.setNodeBaseParent(&Par);
190193
EXPECT_EQ(&Par, PTA.getNodeBaseParent());
194+
195+
using VarParentTy = std::remove_pointer_t<decltype(PA.getNodeBaseParent())>;
196+
using ConstParentTy =
197+
std::remove_pointer_t<decltype(CPA.getNodeBaseParent())>;
198+
static_assert(
199+
std::is_const_v<ConstParentTy> &&
200+
std::is_same_v<VarParentTy, std::remove_const_t<ConstParentTy>>,
201+
"`getNodeBaseParent() const` adds const to parent type");
191202
}
192203

193204
} // end namespace

llvm/unittests/ADT/IListNodeTest.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,9 @@ TEST(IListNodeTest, Options) {
6666
ilist_sentinel_tracking<true>>::type>,
6767
"order shouldn't matter with real tags");
6868
static_assert(
69-
!std::is_same_v<compute_node_options<Node>::type,
70-
compute_node_options<Node, ilist_parent<void>>::type>,
71-
"void parent is different to no parent");
69+
std::is_same_v<compute_node_options<Node>::type,
70+
compute_node_options<Node, ilist_parent<void>>::type>,
71+
"default parent is void");
7272
static_assert(
7373
!std::is_same_v<compute_node_options<Node, ilist_parent<ParentA>>::type,
7474
compute_node_options<Node, ilist_parent<void>>::type>,

0 commit comments

Comments
 (0)