aboutsummaryrefslogtreecommitdiffhomepage
path: root/include
diff options
context:
space:
mode:
authorDan Liew <daniel.liew@imperial.ac.uk>2016-11-28 09:48:07 +0000
committerDan Liew <daniel.liew@imperial.ac.uk>2016-11-28 15:08:08 +0000
commit3946c3232512e436891d299243c9986a5f6e1e4c (patch)
tree63ddb553c3754899a3a52039b5d73ed2a598a1ad /include
parent48d20142488fbd644b1be53f42d30517adc59f6f (diff)
downloadklee-3946c3232512e436891d299243c9986a5f6e1e4c.tar.gz
Remove default implementation of `Expr::compareContents(const Expr&)`
and make it a pure virtual method. Also make it protected rather than public because it is an implementation detail of `Expr::compare()`. This means that sub classes must implement it so this commit also provides implementations. The comparision behaves as before except for `ConcatExpr` where its `width` attribute is now used (previously it wasn't). This commit also documents the semantics of `Expr::compareContents(const Expr&)` which was clearly needed because it has been incorrectly implemented in the past and has gone unnoticed for several years. This partially addresses #515 .
Diffstat (limited to 'include')
-rw-r--r--include/klee/Expr.h169
1 files changed, 114 insertions, 55 deletions
diff --git a/include/klee/Expr.h b/include/klee/Expr.h
index 500d7d46..26c91ae3 100644
--- a/include/klee/Expr.h
+++ b/include/klee/Expr.h
@@ -176,7 +176,31 @@ public:
protected:
unsigned hashValue;
-
+
+ /// Compares `b` to `this` Expr and determines how they are ordered
+ /// (ignoring their kid expressions - i.e. those returned by `getKid()`).
+ ///
+ /// Typically this requires comparing internal attributes of the Expr.
+ ///
+ /// Implementations can assume that `b` and `this` are of the same kind.
+ ///
+ /// This method effectively defines a partial order over Expr of the same
+ /// kind (partial because kid Expr are not compared).
+ ///
+ /// This method should not be called directly. Instead `compare()` should
+ /// be used.
+ ///
+ /// \param [in] b Expr to compare `this` to.
+ ///
+ /// \return One of the following values:
+ ///
+ /// * -1 if `this` is `<` `b` ignoring kid expressions.
+ /// * 1 if `this` is `>` `b` ignoring kid expressions.
+ /// * 0 if `this` and `b` are not ordered.
+ ///
+ /// `<` and `>` are binary relations that express the partial order.
+ virtual int compareContents(const Expr &b) const = 0;
+
public:
Expr() : refCount(0) { Expr::count++; }
virtual ~Expr() { Expr::count--; }
@@ -208,7 +232,6 @@ public:
equivs.clear();
return r;
}
- virtual int compareContents(const Expr &b) const { return 0; }
// Given an array of new kids return a copy of the expression
// but using those children.
@@ -404,6 +427,12 @@ public:
private:
NotOptimizedExpr(const ref<Expr> &_src) : src(_src) {}
+protected:
+ virtual int compareContents(const Expr &b) const {
+ // No attributes to compare.
+ return 0;
+ }
+
public:
static bool classof(const Expr *E) {
return E->getKind() == Expr::NotOptimized;
@@ -625,6 +654,12 @@ public:
return E->getKind() == Expr::Select;
}
static bool classof(const SelectExpr *) { return true; }
+
+protected:
+ virtual int compareContents(const Expr &b) const {
+ // No attributes to compare.
+ return 0;
+ }
};
@@ -682,6 +717,14 @@ public:
return E->getKind() == Expr::Concat;
}
static bool classof(const ConcatExpr *) { return true; }
+
+protected:
+ virtual int compareContents(const Expr &b) const {
+ const ConcatExpr &eb = static_cast<const ConcatExpr &>(b);
+ if (width != eb.width)
+ return width < eb.width ? -1 : 1;
+ return 0;
+ }
};
@@ -779,6 +822,12 @@ public:
private:
NotExpr(const ref<Expr> &e) : expr(e) {}
+
+protected:
+ virtual int compareContents(const Expr &b) const {
+ // No attributes to compare.
+ return 0;
+ }
};
@@ -846,33 +895,38 @@ CAST_EXPR_CLASS(ZExt)
// Arithmetic/Bit Exprs
-#define ARITHMETIC_EXPR_CLASS(_class_kind) \
-class _class_kind ## Expr : public BinaryExpr { \
-public: \
- static const Kind kind = _class_kind; \
- static const unsigned numKids = 2; \
-public: \
- _class_kind ## Expr(const ref<Expr> &l, \
- const ref<Expr> &r) : BinaryExpr(l,r) {} \
- static ref<Expr> alloc(const ref<Expr> &l, const ref<Expr> &r) { \
- ref<Expr> res(new _class_kind ## Expr (l, r)); \
- res->computeHash(); \
- return res; \
- } \
- static ref<Expr> create(const ref<Expr> &l, const ref<Expr> &r); \
- Width getWidth() const { return left->getWidth(); } \
- Kind getKind() const { return _class_kind; } \
- virtual ref<Expr> rebuild(ref<Expr> kids[]) const { \
- return create(kids[0], kids[1]); \
- } \
- \
- static bool classof(const Expr *E) { \
- return E->getKind() == Expr::_class_kind; \
- } \
- static bool classof(const _class_kind ## Expr *) { \
- return true; \
- } \
-}; \
+#define ARITHMETIC_EXPR_CLASS(_class_kind) \
+ class _class_kind##Expr : public BinaryExpr { \
+ public: \
+ static const Kind kind = _class_kind; \
+ static const unsigned numKids = 2; \
+ \
+ public: \
+ _class_kind##Expr(const ref<Expr> &l, const ref<Expr> &r) \
+ : BinaryExpr(l, r) {} \
+ static ref<Expr> alloc(const ref<Expr> &l, const ref<Expr> &r) { \
+ ref<Expr> res(new _class_kind##Expr(l, r)); \
+ res->computeHash(); \
+ return res; \
+ } \
+ static ref<Expr> create(const ref<Expr> &l, const ref<Expr> &r); \
+ Width getWidth() const { return left->getWidth(); } \
+ Kind getKind() const { return _class_kind; } \
+ virtual ref<Expr> rebuild(ref<Expr> kids[]) const { \
+ return create(kids[0], kids[1]); \
+ } \
+ \
+ static bool classof(const Expr *E) { \
+ return E->getKind() == Expr::_class_kind; \
+ } \
+ static bool classof(const _class_kind##Expr *) { return true; } \
+ \
+ protected: \
+ virtual int compareContents(const Expr &b) const { \
+ /* No attributes to compare.*/ \
+ return 0; \
+ } \
+ };
ARITHMETIC_EXPR_CLASS(Add)
ARITHMETIC_EXPR_CLASS(Sub)
@@ -890,32 +944,37 @@ ARITHMETIC_EXPR_CLASS(AShr)
// Comparison Exprs
-#define COMPARISON_EXPR_CLASS(_class_kind) \
-class _class_kind ## Expr : public CmpExpr { \
-public: \
- static const Kind kind = _class_kind; \
- static const unsigned numKids = 2; \
-public: \
- _class_kind ## Expr(const ref<Expr> &l, \
- const ref<Expr> &r) : CmpExpr(l,r) {} \
- static ref<Expr> alloc(const ref<Expr> &l, const ref<Expr> &r) { \
- ref<Expr> res(new _class_kind ## Expr (l, r)); \
- res->computeHash(); \
- return res; \
- } \
- static ref<Expr> create(const ref<Expr> &l, const ref<Expr> &r); \
- Kind getKind() const { return _class_kind; } \
- virtual ref<Expr> rebuild(ref<Expr> kids[]) const { \
- return create(kids[0], kids[1]); \
- } \
- \
- static bool classof(const Expr *E) { \
- return E->getKind() == Expr::_class_kind; \
- } \
- static bool classof(const _class_kind ## Expr *) { \
- return true; \
- } \
-}; \
+#define COMPARISON_EXPR_CLASS(_class_kind) \
+ class _class_kind##Expr : public CmpExpr { \
+ public: \
+ static const Kind kind = _class_kind; \
+ static const unsigned numKids = 2; \
+ \
+ public: \
+ _class_kind##Expr(const ref<Expr> &l, const ref<Expr> &r) \
+ : CmpExpr(l, r) {} \
+ static ref<Expr> alloc(const ref<Expr> &l, const ref<Expr> &r) { \
+ ref<Expr> res(new _class_kind##Expr(l, r)); \
+ res->computeHash(); \
+ return res; \
+ } \
+ static ref<Expr> create(const ref<Expr> &l, const ref<Expr> &r); \
+ Kind getKind() const { return _class_kind; } \
+ virtual ref<Expr> rebuild(ref<Expr> kids[]) const { \
+ return create(kids[0], kids[1]); \
+ } \
+ \
+ static bool classof(const Expr *E) { \
+ return E->getKind() == Expr::_class_kind; \
+ } \
+ static bool classof(const _class_kind##Expr *) { return true; } \
+ \
+ protected: \
+ virtual int compareContents(const Expr &b) const { \
+ /* No attributes to compare. */ \
+ return 0; \
+ } \
+ };
COMPARISON_EXPR_CLASS(Eq)
COMPARISON_EXPR_CLASS(Ne)