summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog9
-rw-r--r--NEWS7
-rw-r--r--configure.ac2
-rw-r--r--sigc++/macros/object_slot.h.m42
-rw-r--r--sigc++/macros/signal.h.m439
-rw-r--r--tests/test_accumulated.cc4
-rw-r--r--tests/test_signal.cc6
7 files changed, 53 insertions, 16 deletions
diff --git a/ChangeLog b/ChangeLog
index c7f54ee..a633df7 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2004-05-30 Martin Schulze <mschulze@cvs.gnome.org>
+
+ * configure.ac: Bump version number to 2.0.3.
+ * NEWS: Add ChangeLog summary for version 2.0.3.
+ * sigc++/macros/signal.h.m4: Fix segfault on emission of unconnected signal.
+ * tests/test_signal.cc, tests/test_accumulated.cc: Emit unconnected signal.
+ * sigc++/macros/object_slot.h.m4: Suppress compiler warning at
+ dynamic_cast<>-test (tested by Christof Petig/Timothy M. Shead).
+
2004-05-22 Martin Schulze <mschulze@cvs.gnome.org>
* configure.ac: Bump version number to 2.0.2.
diff --git a/NEWS b/NEWS
index 46bae73..26e3681 100644
--- a/NEWS
+++ b/NEWS
@@ -17,6 +17,13 @@ This version of libsigc++ needs GNU g++ 3.2 or higher to compile.
*** ChangeLog summary:
+2.0.3:
+
+* Fix segfault on emission of unconnected signal.
+* Test emission of unconnected signals in the test case.
+* Suppress compiler warning at dynamic_cast<>-test for good.
+ (Help from Christof Petig and Timothy M. Shead.)
+
2.0.2:
* Suppress compiler warning in compatibility module at
diff --git a/configure.ac b/configure.ac
index 99b2897..727abbd 100644
--- a/configure.ac
+++ b/configure.ac
@@ -11,7 +11,7 @@ dnl This version stuff is just for the packaging section of the tool.
dnl thus make format_package-0.0.1.tar.gz
FP_MAJOR_VERSION=2
FP_MINOR_VERSION=0
-FP_MICRO_VERSION=2
+FP_MICRO_VERSION=3
FP_VERSION=$FP_MAJOR_VERSION.$FP_MINOR_VERSION.$FP_MICRO_VERSION
dnl For automake.
diff --git a/sigc++/macros/object_slot.h.m4 b/sigc++/macros/object_slot.h.m4
index a1bf73f..435444c 100644
--- a/sigc++/macros/object_slot.h.m4
+++ b/sigc++/macros/object_slot.h.m4
@@ -32,7 +32,7 @@ define([SLOT_MEM_FUN],[dnl
template <LIST(class T_return, LOOP(class T_arg%1, $1), class T_obj1, class T_obj2)>
inline Slot$1<LIST(T_return, LOOP(T_arg%1, $1))>
slot($3 T_obj1& _A_obj, T_return (T_obj2::*_A_func)(LOOP(T_arg%1,$1)) $4)
-{ dynamic_cast<$3 Object&>(_A_obj);
+{ (void)dynamic_cast<$3 Object&>(_A_obj); // trigger compiler error if T_obj1 does not derive from SigC::Object
return ::sigc::bound_mem_functor$1<LIST(T_return, T_obj2, LOOP(T_arg%1, $1))>(_A_obj, _A_func); }
])
diff --git a/sigc++/macros/signal.h.m4 b/sigc++/macros/signal.h.m4
index d44f249..7146f42 100644
--- a/sigc++/macros/signal.h.m4
+++ b/sigc++/macros/signal.h.m4
@@ -65,12 +65,16 @@ FOR(1, $1,[
*/
static result_type emit(LIST(signal_impl* impl, LOOP(typename type_trait<T_arg%1>::take _A_a%1, $1)))
{
+ T_accumulator accumulator;
+
+ if (!impl)
+ return accumulator(slot_iterator_buf_type(), slot_iterator_buf_type());
+
signal_exec exec(impl);
self_type self ifelse($1,0,,[(LOOP(_A_a%1, $1))]);
- T_accumulator accumulator;
- return accumulator(slot_iterator_buf_type(impl->slots_.begin(), self),
- slot_iterator_buf_type(impl->slots_.end(), self));
+ return accumulator(slot_iterator_buf_type(impl->slots_.begin(), &self),
+ slot_iterator_buf_type(impl->slots_.end(), &self));
}
dnl
FOR(1, $1,[
@@ -102,7 +106,7 @@ FOR(1, $1,[
*/
static result_type emit(LIST(signal_impl* impl, LOOP(typename type_trait<T_arg%1>::take _A_a%1, $1)))
{
- if (impl->slots_.empty()) return T_return();
+ if (!impl || impl->slots_.empty()) return T_return();
iterator_type it = impl->slots_.begin();
for (; it != impl->slots_.end(); ++it)
if (!it->empty() && !it->blocked()) break;
@@ -145,7 +149,7 @@ FOR(1, $1,[
*/
static result_type emit(LIST(signal_impl* impl, LOOP(typename type_trait<T_arg%1>::take _A_a%1, $1)))
{
- if (impl->slots_.empty()) return;
+ if (!impl || impl->slots_.empty()) return;
signal_exec exec(impl);
for (iterator_type it = impl->slots_.begin(); it != impl->slots_.end(); ++it)
@@ -702,14 +706,17 @@ struct slot_iterator_buf
typedef signal_impl::const_iterator_type iterator_type;
- slot_iterator_buf(const iterator_type& i, const emitter_type& c)
+ slot_iterator_buf()
+ : c_(0), invoked_(false) {}
+
+ slot_iterator_buf(const iterator_type& i, const emitter_type* c)
: i_(i), c_(c), invoked_(false) {}
result_type operator*() const
{
if (!i_->empty() && !i_->blocked() && !invoked_)
{
- r_ = c_(static_cast<const slot_type&>(*i_));
+ r_ = (*c_)(static_cast<const slot_type&>(*i_));
invoked_ = true;
}
return r_;
@@ -746,14 +753,17 @@ struct slot_iterator_buf
}
bool operator == (const slot_iterator_buf& other) const
- { return i_ == other.i_; }
+ { return (!c_ || (i_ == other.i_)); } /* If '!c_' the iterators are empty.
+ * Unfortunately, empty stl iterators are not equal.
+ * We are forcing equality so that 'first==last'
+ * in the accumulator's emit function yields true. */
bool operator != (const slot_iterator_buf& other) const
- { return i_ != other.i_; }
+ { return (c_ && (i_ != other.i_)); }
private:
iterator_type i_;
- const emitter_type& c_;
+ const emitter_type* c_;
mutable result_type r_;
mutable bool invoked_;
};
@@ -773,14 +783,17 @@ struct slot_iterator_buf<T_emitter, void>
typedef signal_impl::const_iterator_type iterator_type;
- slot_iterator_buf(const iterator_type& i, const emitter_type& c)
+ slot_iterator_buf()
+ : c_(0), invoked_(false) {}
+
+ slot_iterator_buf(const iterator_type& i, const emitter_type* c)
: i_(i), c_(c), invoked_(false) {}
void operator*() const
{
if (!i_->empty() && !i_->blocked() && !invoked_)
{
- c_(static_cast<const slot_type&>(*i_));
+ (*c_)(static_cast<const slot_type&>(*i_));
invoked_ = true;
}
}
@@ -823,7 +836,7 @@ struct slot_iterator_buf<T_emitter, void>
private:
iterator_type i_;
- const emitter_type& c_;
+ const emitter_type* c_;
mutable bool invoked_;
};
diff --git a/tests/test_accumulated.cc b/tests/test_accumulated.cc
index 38716c7..ecf96e5 100644
--- a/tests/test_accumulated.cc
+++ b/tests/test_accumulated.cc
@@ -19,7 +19,7 @@ struct arithmetic_mean_accumulator
int n_ = 0;
for (; first != last; ++first, ++n_)
value_ += *first;
- return value_ / n_;
+ return (n_ ? value_ / n_ : -1); // empty slot list <=> n_==0
}
};
@@ -35,6 +35,8 @@ int main()
{
sigc::signal<int,int>::accumulated<arithmetic_mean_accumulator> sig;
+ std::cout << "Result (empty slot list): " << sig(0) << std::endl;
+
A a;
sig.connect(sigc::ptr_fun1(&foo));
sig.connect(sigc::mem_fun1(&a, &A::foo));
diff --git a/tests/test_signal.cc b/tests/test_signal.cc
index b78bfea..f8e7446 100644
--- a/tests/test_signal.cc
+++ b/tests/test_signal.cc
@@ -21,7 +21,13 @@ struct A : public sigc::trackable
int main()
{
+ // signal
sigc::signal<int,int> sig;
+
+ // emit empty signal
+ sig(0);
+
+ // connect some slots before emitting & test auto-disconnection
{
A a;
sig.connect(sigc::ptr_fun1(&foo));