diff options
-rw-r--r-- | include/klee/util/Ref.h | 29 | ||||
-rwxr-xr-x | unittests/Makefile | 2 | ||||
-rw-r--r-- | unittests/Ref/Makefile | 19 | ||||
-rw-r--r-- | unittests/Ref/RefTest.cpp | 31 |
4 files changed, 65 insertions, 16 deletions
diff --git a/include/klee/util/Ref.h b/include/klee/util/Ref.h index 1b823f56..d14de471 100644 --- a/include/klee/util/Ref.h +++ b/include/klee/util/Ref.h @@ -32,15 +32,15 @@ public: ~ref () { dec (); } private: - void inc() { + void inc() const { if (ptr) ++ptr->refCount; } - - void dec() { + + void dec() const { if (ptr && --ptr->refCount == 0) delete ptr; - } + } public: template<class U> friend class ref; @@ -49,19 +49,18 @@ public: ref(T *p) : ptr(p) { inc(); } - + // normal copy constructor ref(const ref<T> &r) : ptr(r.ptr) { inc(); } - + // conversion constructor template<class U> - ref (const ref<U> &r) { - ptr = r.ptr; + ref (const ref<U> &r) : ptr(r.ptr) { inc(); } - + // pointer operations T *get () const { return ptr; @@ -70,18 +69,18 @@ public: /* The copy assignment operator must also explicitly be defined, * despite a redundant template. */ ref<T> &operator= (const ref<T> &r) { + r.inc(); dec(); ptr = r.ptr; - inc(); - + return *this; } - + template<class U> ref<T> &operator= (const ref<U> &r) { + r.inc(); dec(); ptr = r.ptr; - inc(); - + return *this; } @@ -130,7 +129,7 @@ struct simplify_type<const ::klee::ref<T> > { } }; -template<typename T> +template<typename T> struct simplify_type< ::klee::ref<T> > : public simplify_type<const ::klee::ref<T> > {}; } diff --git a/unittests/Makefile b/unittests/Makefile index 545d7fa7..761987d6 100755 --- a/unittests/Makefile +++ b/unittests/Makefile @@ -10,7 +10,7 @@ CPP.Flags += -I$(LLVM_SRC_ROOT)/utils/unittest/googletest/include/ CPP.Flags += -Wno-variadic-macros # FIXME: Parallel dirs is broken? -DIRS = Expr Solver +DIRS = Expr Solver Ref include $(LEVEL)/Makefile.common diff --git a/unittests/Ref/Makefile b/unittests/Ref/Makefile new file mode 100644 index 00000000..3117a5fd --- /dev/null +++ b/unittests/Ref/Makefile @@ -0,0 +1,19 @@ +##===- unittests/Expr/Makefile -----------------------------*- Makefile -*-===## + +LEVEL := ../.. +include $(LEVEL)/Makefile.config + +TESTNAME := RefTest +STP_LIBS := stp_c_interface.a stp_AST.a stp_bitvec.a \ + stp_constantbv.a stp_sat.a stp_simplifier.a +USEDLIBS := kleaverExpr.a kleeBasic.a +ifeq ($(ENABLE_EXT_STP),0) + USEDLIBS += $(STP_LIBS) +endif +LINK_COMPONENTS := support + +include $(LLVM_SRC_ROOT)/unittests/Makefile.unittest + +ifeq ($(ENABLE_EXT_STP),1) + LIBS += -lstp +endif diff --git a/unittests/Ref/RefTest.cpp b/unittests/Ref/RefTest.cpp new file mode 100644 index 00000000..229fd9a8 --- /dev/null +++ b/unittests/Ref/RefTest.cpp @@ -0,0 +1,31 @@ +/* Regression test for a bug caused by assigning a ref to itself. + More details at http://keeda.stanford.edu/pipermail/klee-commits/2012-February/000904.html */ + +#include "gtest/gtest.h" +#include <iostream> +#include "klee/util/Ref.h" +using klee::ref; + +int finished = 0; + +struct Expr +{ + int refCount; + Expr() : refCount(0) { + //std::cout << "Expr(" << this << ") created\n"; + } + ~Expr() { + //std::cout << "Expr(" << this << ") destroyed\n"; + EXPECT_EQ(finished, 1); + } +}; + +TEST(RefTest, SelfAssign) +{ + struct Expr *r_e = new Expr(); + ref<Expr> r(r_e); + EXPECT_EQ(r_e->refCount, 1); + r = r; + EXPECT_EQ(r_e->refCount, 1); + finished = 1; +} |