Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. //===- AttrIterator.h - Classes for attribute iteration ---------*- C++ -*-===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. //  This file defines the Attr vector and specific_attr_iterator interfaces.
  10. //
  11. //===----------------------------------------------------------------------===//
  12.  
  13. #ifndef LLVM_CLANG_AST_ATTRITERATOR_H
  14. #define LLVM_CLANG_AST_ATTRITERATOR_H
  15.  
  16. #include "clang/Basic/LLVM.h"
  17. #include "llvm/ADT/SmallVector.h"
  18. #include "llvm/Support/Casting.h"
  19. #include <cassert>
  20. #include <cstddef>
  21. #include <iterator>
  22.  
  23. namespace clang {
  24.  
  25. class Attr;
  26.  
  27. /// AttrVec - A vector of Attr, which is how they are stored on the AST.
  28. using AttrVec = SmallVector<Attr *, 4>;
  29.  
  30. /// specific_attr_iterator - Iterates over a subrange of an AttrVec, only
  31. /// providing attributes that are of a specific type.
  32. template <typename SpecificAttr, typename Container = AttrVec>
  33. class specific_attr_iterator {
  34.   using Iterator = typename Container::const_iterator;
  35.  
  36.   /// Current - The current, underlying iterator.
  37.   /// In order to ensure we don't dereference an invalid iterator unless
  38.   /// specifically requested, we don't necessarily advance this all the
  39.   /// way. Instead, we advance it when an operation is requested; if the
  40.   /// operation is acting on what should be a past-the-end iterator,
  41.   /// then we offer no guarantees, but this way we do not dereference a
  42.   /// past-the-end iterator when we move to a past-the-end position.
  43.   mutable Iterator Current;
  44.  
  45.   void AdvanceToNext() const {
  46.     while (!isa<SpecificAttr>(*Current))
  47.       ++Current;
  48.   }
  49.  
  50.   void AdvanceToNext(Iterator I) const {
  51.     while (Current != I && !isa<SpecificAttr>(*Current))
  52.       ++Current;
  53.   }
  54.  
  55. public:
  56.   using value_type = SpecificAttr *;
  57.   using reference = SpecificAttr *;
  58.   using pointer = SpecificAttr *;
  59.   using iterator_category = std::forward_iterator_tag;
  60.   using difference_type = std::ptrdiff_t;
  61.  
  62.   specific_attr_iterator() = default;
  63.   explicit specific_attr_iterator(Iterator i) : Current(i) {}
  64.  
  65.   reference operator*() const {
  66.     AdvanceToNext();
  67.     return cast<SpecificAttr>(*Current);
  68.   }
  69.   pointer operator->() const {
  70.     AdvanceToNext();
  71.     return cast<SpecificAttr>(*Current);
  72.   }
  73.  
  74.   specific_attr_iterator& operator++() {
  75.     ++Current;
  76.     return *this;
  77.   }
  78.   specific_attr_iterator operator++(int) {
  79.     specific_attr_iterator Tmp(*this);
  80.     ++(*this);
  81.     return Tmp;
  82.   }
  83.  
  84.   friend bool operator==(specific_attr_iterator Left,
  85.                          specific_attr_iterator Right) {
  86.     assert((Left.Current == nullptr) == (Right.Current == nullptr));
  87.     if (Left.Current < Right.Current)
  88.       Left.AdvanceToNext(Right.Current);
  89.     else
  90.       Right.AdvanceToNext(Left.Current);
  91.     return Left.Current == Right.Current;
  92.   }
  93.   friend bool operator!=(specific_attr_iterator Left,
  94.                          specific_attr_iterator Right) {
  95.     return !(Left == Right);
  96.   }
  97. };
  98.  
  99. template <typename SpecificAttr, typename Container>
  100. inline specific_attr_iterator<SpecificAttr, Container>
  101.           specific_attr_begin(const Container& container) {
  102.   return specific_attr_iterator<SpecificAttr, Container>(container.begin());
  103. }
  104. template <typename SpecificAttr, typename Container>
  105. inline specific_attr_iterator<SpecificAttr, Container>
  106.           specific_attr_end(const Container& container) {
  107.   return specific_attr_iterator<SpecificAttr, Container>(container.end());
  108. }
  109.  
  110. template <typename SpecificAttr, typename Container>
  111. inline bool hasSpecificAttr(const Container& container) {
  112.   return specific_attr_begin<SpecificAttr>(container) !=
  113.           specific_attr_end<SpecificAttr>(container);
  114. }
  115. template <typename SpecificAttr, typename Container>
  116. inline SpecificAttr *getSpecificAttr(const Container& container) {
  117.   specific_attr_iterator<SpecificAttr, Container> i =
  118.       specific_attr_begin<SpecificAttr>(container);
  119.   if (i != specific_attr_end<SpecificAttr>(container))
  120.     return *i;
  121.   else
  122.     return nullptr;
  123. }
  124.  
  125. } // namespace clang
  126.  
  127. #endif // LLVM_CLANG_AST_ATTRITERATOR_H
  128.