File indexing completed on 2026-05-10 08:36:29
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #ifndef LLVM_CLANG_AST_ATTRITERATOR_H
0014 #define LLVM_CLANG_AST_ATTRITERATOR_H
0015
0016 #include "clang/Basic/LLVM.h"
0017 #include "llvm/ADT/ADL.h"
0018 #include "llvm/ADT/SmallVector.h"
0019 #include "llvm/Support/Casting.h"
0020 #include <cassert>
0021 #include <cstddef>
0022 #include <iterator>
0023 #include <type_traits>
0024
0025 namespace clang {
0026
0027 class Attr;
0028
0029
0030 using AttrVec = SmallVector<Attr *, 4>;
0031
0032
0033
0034 template <typename SpecificAttr, typename Container = AttrVec>
0035 class specific_attr_iterator {
0036 using Iterator = typename Container::const_iterator;
0037
0038
0039
0040
0041
0042
0043
0044
0045 mutable Iterator Current;
0046
0047 void AdvanceToNext() const {
0048 while (!isa<SpecificAttr>(*Current))
0049 ++Current;
0050 }
0051
0052 void AdvanceToNext(Iterator I) const {
0053 while (Current != I && !isa<SpecificAttr>(*Current))
0054 ++Current;
0055 }
0056
0057 public:
0058 using value_type = SpecificAttr *;
0059 using reference = SpecificAttr *;
0060 using pointer = SpecificAttr *;
0061 using iterator_category = std::forward_iterator_tag;
0062 using difference_type = std::ptrdiff_t;
0063
0064 specific_attr_iterator() = default;
0065 explicit specific_attr_iterator(Iterator i) : Current(i) {}
0066
0067 reference operator*() const {
0068 AdvanceToNext();
0069 return cast<SpecificAttr>(*Current);
0070 }
0071 pointer operator->() const {
0072 AdvanceToNext();
0073 return cast<SpecificAttr>(*Current);
0074 }
0075
0076 specific_attr_iterator& operator++() {
0077 ++Current;
0078 return *this;
0079 }
0080 specific_attr_iterator operator++(int) {
0081 specific_attr_iterator Tmp(*this);
0082 ++(*this);
0083 return Tmp;
0084 }
0085
0086 friend bool operator==(specific_attr_iterator Left,
0087 specific_attr_iterator Right) {
0088 assert((Left.Current == nullptr) == (Right.Current == nullptr));
0089 if (Left.Current < Right.Current)
0090 Left.AdvanceToNext(Right.Current);
0091 else
0092 Right.AdvanceToNext(Left.Current);
0093 return Left.Current == Right.Current;
0094 }
0095 friend bool operator!=(specific_attr_iterator Left,
0096 specific_attr_iterator Right) {
0097 return !(Left == Right);
0098 }
0099 };
0100
0101 template <typename SpecificAttr, typename Container>
0102 inline specific_attr_iterator<SpecificAttr, Container>
0103 specific_attr_begin(const Container& container) {
0104 return specific_attr_iterator<SpecificAttr, Container>(container.begin());
0105 }
0106 template <typename SpecificAttr, typename Container>
0107 inline specific_attr_iterator<SpecificAttr, Container>
0108 specific_attr_end(const Container& container) {
0109 return specific_attr_iterator<SpecificAttr, Container>(container.end());
0110 }
0111
0112 template <typename SpecificAttr, typename Container>
0113 inline bool hasSpecificAttr(const Container& container) {
0114 return specific_attr_begin<SpecificAttr>(container) !=
0115 specific_attr_end<SpecificAttr>(container);
0116 }
0117 template <typename SpecificAttr, typename Container>
0118 inline auto *getSpecificAttr(const Container &container) {
0119 using ValueTy = llvm::detail::ValueOfRange<Container>;
0120 using ValuePointeeTy = std::remove_pointer_t<ValueTy>;
0121 using IterTy = std::conditional_t<std::is_const_v<ValuePointeeTy>,
0122 const SpecificAttr, SpecificAttr>;
0123 auto It = specific_attr_begin<IterTy>(container);
0124 return It != specific_attr_end<IterTy>(container) ? *It : nullptr;
0125 }
0126
0127 }
0128
0129 #endif