include/PatriciaTreeSetAbstractDomain.h (91 lines of code) (raw):

/* * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ #pragma once #include <cstddef> #include <initializer_list> #include <unordered_set> #include "PatriciaTreeSet.h" #include "PowersetAbstractDomain.h" namespace sparta { template <typename Element> class PatriciaTreeSetAbstractDomain; namespace ptsad_impl { /* * An abstract value from a powerset is implemented as a Patricia tree. */ template <typename Element> class SetValue final : public PowersetImplementation<Element, const PatriciaTreeSet<Element>&, SetValue<Element>> { public: SetValue() = default; SetValue(const Element& e) { m_set.insert(e); } SetValue(std::initializer_list<Element> l) : m_set(l.begin(), l.end()) {} SetValue(const PatriciaTreeSet<Element>& set) : m_set(set) {} const PatriciaTreeSet<Element>& elements() const override { return m_set; } size_t size() const override { return m_set.size(); } bool contains(const Element& e) const override { return m_set.contains(e); } void add(const Element& e) override { m_set.insert(e); } void remove(const Element& e) override { m_set.remove(e); } void clear() override { m_set.clear(); } AbstractValueKind kind() const override { return AbstractValueKind::Value; } bool leq(const SetValue& other) const override { return m_set.is_subset_of(other.m_set); } bool equals(const SetValue& other) const override { return m_set.equals(other.m_set); } AbstractValueKind join_with(const SetValue& other) override { m_set.union_with(other.m_set); return AbstractValueKind::Value; } AbstractValueKind meet_with(const SetValue& other) override { m_set.intersection_with(other.m_set); return AbstractValueKind::Value; } AbstractValueKind difference_with(const SetValue& other) override { m_set.difference_with(other.m_set); return AbstractValueKind::Value; } friend std::ostream& operator<<(std::ostream& o, const SetValue& value) { o << "[#" << value.size() << "]"; o << value.m_set; return o; } private: PatriciaTreeSet<Element> m_set; template <typename T> friend class sparta::PatriciaTreeSetAbstractDomain; }; } // namespace ptsad_impl /* * An implementation of powerset abstract domains using Patricia trees. This * implementation should be used for analyses that create large numbers of * identical or nearly identical sets (like a pointer analysis, for example). * This powerset domain can only handle elements that are either unsigned * integers or pointers to objects. * * Sample usage: * * using Powerset = PatriciaTreeSetAbstractDomain<std::string*>; * * std::string a = "a"; * ... * Powerset s; * * s.add(&a); * ... * for(std::string* p : s) { * if (*p == "a") { * ... * } * } * */ template <typename Element> class PatriciaTreeSetAbstractDomain final : public PowersetAbstractDomain<Element, ptsad_impl::SetValue<Element>, const PatriciaTreeSet<Element>&, PatriciaTreeSetAbstractDomain<Element>> { public: using Value = ptsad_impl::SetValue<Element>; PatriciaTreeSetAbstractDomain() : PowersetAbstractDomain<Element, Value, const PatriciaTreeSet<Element>&, PatriciaTreeSetAbstractDomain>() {} PatriciaTreeSetAbstractDomain(AbstractValueKind kind) : PowersetAbstractDomain<Element, Value, const PatriciaTreeSet<Element>&, PatriciaTreeSetAbstractDomain>(kind) {} explicit PatriciaTreeSetAbstractDomain(const Element& e) { this->set_to_value(Value(e)); } explicit PatriciaTreeSetAbstractDomain(std::initializer_list<Element> l) { this->set_to_value(Value(l)); } explicit PatriciaTreeSetAbstractDomain(const PatriciaTreeSet<Element>& set) { this->set_to_value(Value(set)); } static PatriciaTreeSetAbstractDomain bottom() { return PatriciaTreeSetAbstractDomain(AbstractValueKind::Bottom); } static PatriciaTreeSetAbstractDomain top() { return PatriciaTreeSetAbstractDomain(AbstractValueKind::Top); } }; } // namespace sparta