diff options
Diffstat (limited to 'include/clang/StaticAnalyzer/Core')
-rw-r--r-- | include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h | 93 |
1 files changed, 86 insertions, 7 deletions
diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h b/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h index 7b5b1c2e2a..bd4f7c19b8 100644 --- a/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h +++ b/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h @@ -20,6 +20,8 @@ #include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/PointerUnion.h" +#include "llvm/ADT/ilist.h" +#include "llvm/ADT/ilist_node.h" #include <deque> #include <iterator> #include <string> @@ -386,12 +388,32 @@ public: virtual void Profile(llvm::FoldingSetNodeID &ID) const; }; - - -class PathPieces : public std::deque<IntrusiveRefCntPtr<PathDiagnosticPiece> > { + +/// \brief An ordered collection of PathDiagnosticPieces. +/// +/// Multiple PathPieces are allowed to reference the same PathDiagnosticPieces. +/// This sharing is needed for some clients that want "flattened" copies +/// of the same pieces. +class PathPieces { + /// A simple wrapper for PathDiagnosticPiece, allowing sharing of + /// the same pieces between different PathPieces. + struct Node : public llvm::ilist_node<Node> { + IntrusiveRefCntPtr<PathDiagnosticPiece> Data; + explicit Node(PathDiagnosticPiece *P) : Data(P) {} + explicit Node() {} + }; + llvm::ilist<Node> L; + void flattenTo(PathPieces &Primary, PathPieces &Current, bool ShouldFlattenMacros) const; + public: + PathPieces() {} + PathPieces &operator=(const PathPieces & X); + PathPieces(const PathPieces &X) { + *this = X; + } + ~PathPieces(); PathPieces flatten(bool ShouldFlattenMacros) const { @@ -399,6 +421,63 @@ public: flattenTo(Result, Result, ShouldFlattenMacros); return Result; } + + class iterator { + typedef llvm::ilist<Node>::iterator impl_iterator; + friend class PathPieces; + impl_iterator Impl; + iterator(const impl_iterator &Impl) : Impl(Impl) {} + public: + typedef PathDiagnosticPiece value_type; + typedef value_type* pointer; + typedef value_type& reference; + typedef ptrdiff_t difference_type; + typedef std::bidirectional_iterator_tag iterator_category; + + bool operator==(const iterator &X) const { + return Impl == X.Impl; + } + + bool operator!=(const iterator &X) const { + return Impl != X.Impl; + } + + reference operator*() const { return *Impl->Data; } + pointer operator->() const { return Impl->Data.getPtr(); } + + iterator &operator++() { + ++Impl; + return *this; + } + + iterator &operator--() { + --Impl; + return *this; + } + }; + + typedef std::reverse_iterator<iterator> reverse_iterator; + + iterator begin() const { return iterator(const_cast<PathPieces*>(this)->L.begin()); } + iterator end() const { return iterator(const_cast<PathPieces*>(this)->L.end()); } + reverse_iterator rbegin() { return reverse_iterator(end()); } + reverse_iterator rend() { return reverse_iterator(begin()); } + + void push_front(PathDiagnosticPiece *P) { + L.push_front(new Node(P)); + } + void pop_front() { L.pop_front(); } + + void push_back(PathDiagnosticPiece *P) { L.push_back(new Node(P)); } + void push_back(const IntrusiveRefCntPtr<PathDiagnosticPiece> &P) { + push_back(P.getPtr()); + } + + PathDiagnosticPiece *front() const { return L.front().Data.getPtr(); } + PathDiagnosticPiece *back() const { return L.back().Data.getPtr(); } + void clear() { L.clear(); } + bool empty() const { return L.empty(); } + unsigned size() const { return L.size(); } }; class PathDiagnosticSpotPiece : public PathDiagnosticPiece { @@ -568,7 +647,7 @@ public: callEnter.flatten(); callReturn.flatten(); for (PathPieces::iterator I = path.begin(), - E = path.end(); I != E; ++I) (*I)->flattenLocations(); + E = path.end(); I != E; ++I) I->flattenLocations(); } static PathDiagnosticCallPiece *construct(const ExplodedNode *N, @@ -655,7 +734,7 @@ public: virtual void flattenLocations() { PathDiagnosticSpotPiece::flattenLocations(); for (PathPieces::iterator I = subPieces.begin(), - E = subPieces.end(); I != E; ++I) (*I)->flattenLocations(); + E = subPieces.end(); I != E; ++I) I->flattenLocations(); } static inline bool classof(const PathDiagnosticPiece *P) { @@ -693,7 +772,7 @@ public: ~PathDiagnostic(); - const PathPieces &path; + PathPieces &path; /// Return the path currently used by builders for constructing the /// PathDiagnostic. @@ -764,7 +843,7 @@ public: void flattenLocations() { Loc.flatten(); for (PathPieces::iterator I = pathImpl.begin(), E = pathImpl.end(); - I != E; ++I) (*I)->flattenLocations(); + I != E; ++I) I->flattenLocations(); } /// Profiles the diagnostic, independent of the path it references. |