[clang] Make getAttr, getSpecificAttr, hasAttr, and hasSpecificAttr variadic (PR #78518)
Erich Keane via cfe-commits
cfe-commits at lists.llvm.org
Wed Jan 17 15:07:58 PST 2024
================
@@ -43,80 +55,102 @@ class specific_attr_iterator {
mutable Iterator Current;
void AdvanceToNext() const {
- while (!isa<SpecificAttr>(*Current))
+ while (!isa<SpecificAttrs...>(*Current))
++Current;
}
void AdvanceToNext(Iterator I) const {
- while (Current != I && !isa<SpecificAttr>(*Current))
+ while (Current != I && !isa<SpecificAttrs...>(*Current))
++Current;
}
public:
- using value_type = SpecificAttr *;
- using reference = SpecificAttr *;
- using pointer = SpecificAttr *;
+ using value_type = base_type *;
+ using reference = value_type;
+ using pointer = value_type;
using iterator_category = std::forward_iterator_tag;
using difference_type = std::ptrdiff_t;
- specific_attr_iterator() = default;
- explicit specific_attr_iterator(Iterator i) : Current(i) {}
+ specific_attr_iterator_impl() = default;
+ explicit specific_attr_iterator_impl(Iterator i) : Current(i) {}
reference operator*() const {
AdvanceToNext();
- return cast<SpecificAttr>(*Current);
+ return cast<base_type>(*Current);
}
pointer operator->() const {
AdvanceToNext();
- return cast<SpecificAttr>(*Current);
+ return cast<base_type>(*Current);
}
- specific_attr_iterator& operator++() {
+ specific_attr_iterator_impl &operator++() {
++Current;
return *this;
}
- specific_attr_iterator operator++(int) {
- specific_attr_iterator Tmp(*this);
+ specific_attr_iterator_impl operator++(int) {
+ specific_attr_iterator_impl Tmp(*this);
++(*this);
return Tmp;
}
- friend bool operator==(specific_attr_iterator Left,
- specific_attr_iterator Right) {
+ friend bool operator==(specific_attr_iterator_impl Left,
+ specific_attr_iterator_impl Right) {
assert((Left.Current == nullptr) == (Right.Current == nullptr));
if (Left.Current < Right.Current)
Left.AdvanceToNext(Right.Current);
else
Right.AdvanceToNext(Left.Current);
return Left.Current == Right.Current;
}
- friend bool operator!=(specific_attr_iterator Left,
- specific_attr_iterator Right) {
+ friend bool operator!=(specific_attr_iterator_impl Left,
+ specific_attr_iterator_impl Right) {
return !(Left == Right);
}
};
-template <typename SpecificAttr, typename Container>
-inline specific_attr_iterator<SpecificAttr, Container>
- specific_attr_begin(const Container& container) {
- return specific_attr_iterator<SpecificAttr, Container>(container.begin());
+/// Iterates over a subrange of a collection, only providing attributes that are
+/// of a specific type/s.
+template <typename Container, typename... SpecificAttrs>
+class specific_attr_iterator;
+
+template <typename SpecificAttr>
+class specific_attr_iterator<SpecificAttr>
+ : public specific_attr_iterator_impl<AttrVec, SpecificAttr> {
+ using specific_attr_iterator_impl<AttrVec,
+ SpecificAttr>::specific_attr_iterator_impl;
+};
+
+template <typename Container, typename... SpecificAttrs>
+class specific_attr_iterator
----------------
erichkeane wrote:
I have a version I played with where I put a conversion operator here, so that we can convert to the partial specialization, but it would only be useful in 1 place.
The downside we have here is you cannot do:
`specific_attr_iterator<MyAttr> Foo = Decl->specific_attr_iterator_begin<MyAttr>()`
since the two specializations are 'different' types. I was hoping @ldionne /someone else might have a clever way of combining the uses of these two.
https://github.com/llvm/llvm-project/pull/78518
More information about the cfe-commits
mailing list