-
Alessandro Di Federico authored
This commit enforces on the whole project the usage of our own assertion system. This means all calls to `abort`, `assert` and `llvm_unreachable` have been replaced with calls to `revng_abort`, `revng_assert` and `revng_unreachable`, respectively. The error messages, usually expressed as `assert(Condition && "Message")` have now been replaced using the second (optional) argument of `revng_assert`. Additionally, all the `assert(false)` statements have been replaced with calls to `revng_abort`. Apart from readibility, this ensures the compilers is aware of the fact that call will never return. This change will enable us to drop many statements whose sole purpose was marking a variable employed in an assertion as used in release mode. In fact, with the new assertion system this is no longer necessary.
Alessandro Di Federico authoredThis commit enforces on the whole project the usage of our own assertion system. This means all calls to `abort`, `assert` and `llvm_unreachable` have been replaced with calls to `revng_abort`, `revng_assert` and `revng_unreachable`, respectively. The error messages, usually expressed as `assert(Condition && "Message")` have now been replaced using the second (optional) argument of `revng_assert`. Additionally, all the `assert(false)` statements have been replaced with calls to `revng_abort`. Apart from readibility, this ensures the compilers is aware of the fact that call will never return. This change will enable us to drop many statements whose sole purpose was marking a variable employed in an assertion as used in release mode. In fact, with the new assertion system this is no longer necessary.
datastructures.h 1.93 KiB
#ifndef DATASTRUCTURES_H
#define DATASTRUCTURES_H
//
// This file is distributed under the MIT License. See LICENSE.md for details.
//
// Standard includes
#include "revng-assert.h"
#include <algorithm>
#include <queue>
#include <set>
#include <stack>
/// \brief Queue where an element cannot be re-inserted if it's already in the
/// queue
template<typename T, bool Once>
class QueueImpl {
public:
void insert(T Element) {
if (Set.count(Element) == 0) {
Set.insert(Element);
Queue.push(Element);
}
}
bool empty() const { return Queue.empty(); }
T head() const { return Queue.front(); }
T pop() {
T Result = head();
Queue.pop();
if (!Once)
Set.erase(Result);
return Result;
}
size_t size() const { return Queue.size(); }
std::set<T> visited() {
revng_assert(Once);
return std::move(Set);
}
void clear() {
std::set<T>().swap(Set);
std::queue<T>().swap(Queue);
}
private:
std::set<T> Set;
std::queue<T> Queue;
};
template<typename T>
using UniquedQueue = QueueImpl<T, false>;
template<typename T>
using OnceQueue = QueueImpl<T, true>;
/// \brief Stack where an element cannot be re-inserted in it's already in the
/// stack
template<typename T>
class UniquedStack {
public:
void insert(T Element) {
if (Set.count(Element) == 0) {
revng_assert(Element->getParent() != nullptr);
Set.insert(Element);
Queue.push_back(Element);
}
}
bool empty() const { return Queue.empty(); }
T pop() {
T Result = Queue.back();
Queue.pop_back();
Set.erase(Result);
return Result;
}
/// \brief Reverses the stack in its current status
void reverse() { std::reverse(Queue.begin(), Queue.end()); }
size_t size() const { return Queue.size(); }
private:
std::set<T> Set;
std::vector<T> Queue;
};
template<class T>
inline void freeContainer(T &Container) {
T Empty;
Empty.swap(Container);
}
#endif // DATASTRUCTURES_H