-
Notifications
You must be signed in to change notification settings - Fork 14.2k
[ADT] Fix llvm::concat_iterator for ValueT == common_base_class *
#144744
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
[ADT] Fix llvm::concat_iterator for ValueT == common_base_class *
#144744
Conversation
@llvm/pr-subscribers-llvm-adt Author: Javier Lopez-Gomez (jalopezg-git) ChangesFix In particular, the case below was not working before this patch, but I see no particular reason why it shouldn't be supported.
Full diff: https://github.com/llvm/llvm-project/pull/144744.diff 2 Files Affected:
diff --git a/llvm/include/llvm/ADT/STLExtras.h b/llvm/include/llvm/ADT/STLExtras.h
index eea06cfb99ba2..951da522a8aa2 100644
--- a/llvm/include/llvm/ADT/STLExtras.h
+++ b/llvm/include/llvm/ADT/STLExtras.h
@@ -1030,14 +1030,15 @@ class concat_iterator
std::forward_iterator_tag, ValueT> {
using BaseT = typename concat_iterator::iterator_facade_base;
- static constexpr bool ReturnsByValue =
- !(std::is_reference_v<decltype(*std::declval<IterTs>())> && ...);
+ static constexpr bool ReturnsValueOrPointer =
+ !(std::is_reference_v<decltype(*std::declval<IterTs>())> && ...)
+ || (std::is_pointer_v<IterTs> && ...);
using reference_type =
- typename std::conditional_t<ReturnsByValue, ValueT, ValueT &>;
+ typename std::conditional_t<ReturnsValueOrPointer, ValueT, ValueT &>;
using handle_type =
- typename std::conditional_t<ReturnsByValue, std::optional<ValueT>,
+ typename std::conditional_t<ReturnsValueOrPointer, std::optional<ValueT>,
ValueT *>;
/// We store both the current and end iterators for each concatenated
@@ -1088,7 +1089,7 @@ class concat_iterator
if (Begin == End)
return {};
- if constexpr (ReturnsByValue)
+ if constexpr (ReturnsValueOrPointer)
return *Begin;
else
return &*Begin;
diff --git a/llvm/unittests/ADT/STLExtrasTest.cpp b/llvm/unittests/ADT/STLExtrasTest.cpp
index 286cfa745fd14..0e6b040a08f4a 100644
--- a/llvm/unittests/ADT/STLExtrasTest.cpp
+++ b/llvm/unittests/ADT/STLExtrasTest.cpp
@@ -398,6 +398,9 @@ struct some_struct {
std::string swap_val;
};
+struct derives_from_some_struct : some_struct {
+};
+
std::vector<int>::const_iterator begin(const some_struct &s) {
return s.data.begin();
}
@@ -532,6 +535,19 @@ TEST(STLExtrasTest, ConcatRangeADL) {
EXPECT_THAT(concat<const int>(S0, S1), ElementsAre(1, 2, 3, 4));
}
+TEST(STLExtrasTest, ConcatRangePtrToDerivedClass) {
+ auto S0 = std::make_unique<some_namespace::some_struct>();
+ auto S1 = std::make_unique<some_namespace::derives_from_some_struct>();
+ SmallVector<some_namespace::some_struct *> V0{S0.get()};
+ SmallVector<some_namespace::derives_from_some_struct *> V1{S1.get(), S1.get()};
+
+ // Use concat over ranges of pointers to different (but related) types.
+ EXPECT_THAT(concat<some_namespace::some_struct *>(V0, V1),
+ ElementsAre(S0.get(),
+ static_cast<some_namespace::some_struct *>(S1.get()),
+ static_cast<some_namespace::some_struct *>(S1.get())));
+}
+
TEST(STLExtrasTest, MakeFirstSecondRangeADL) {
// Make sure that we use the `begin`/`end` functions from `some_namespace`,
// using ADL.
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
ebdc2a3
to
560fccc
Compare
llvm/unittests/ADT/STLExtrasTest.cpp
Outdated
auto S0 = std::make_unique<some_namespace::some_struct>(); | ||
auto S1 = std::make_unique<some_namespace::derives_from_some_struct>(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we necessarily need unique_ptr to test this, stack allocated values would work too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed 👍; thanks for pointing out!
llvm/include/llvm/ADT/STLExtras.h
Outdated
if constexpr (ReturnsValueOrPointer) | ||
return *Begin; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So this wraps pointers with std::optional
? Why can't we return pointers here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, let me give it another round of work - this week is WG21 meeting; I was in a hurry but still wanted to open a draft PR.
3d31e30
to
74331ed
Compare
Fix llvm::concat_iterator for the case of `ValueT` being a pointer to a common base class to which the result of dereferencing any iterator in `ItersT` can be casted to.
74331ed
to
ca4ae15
Compare
Fix
llvm::concat_iterator
for the case ofValueT
being a pointer to a common base class to which the result of dereferencing any iterator inItersT
can be casted to.In particular, the case below was not working before this patch, but I see no particular reason why it shouldn't be supported.