From ab330cc520525c69ba87c89346277f062cc3305b Mon Sep 17 00:00:00 2001 From: Danny Robson Date: Thu, 17 Mar 2016 18:05:28 +1100 Subject: [PATCH] add ref-qualifiers to avoid dangling refs/ptrs --- Makefile.am | 2 +- alloc/dynamic.hpp | 12 +++-- cmdopt.hpp | 9 ++-- cmdopt.ipp | 8 ++-- introspection.hpp | 16 ++++++- json/flat.cpp.rl | 2 + json/tree.cpp | 42 ++++++++--------- json/tree.hpp | 94 +++++++++++++++++++++----------------- memory/buffer/circular.cpp | 4 +- memory/buffer/circular.hpp | 12 ++--- memory/buffer/paged.cpp | 4 +- memory/buffer/paged.hpp | 12 ++--- pool.hpp | 4 +- strongdef.hpp | 6 +-- 14 files changed, 128 insertions(+), 99 deletions(-) diff --git a/Makefile.am b/Makefile.am index 51ea9d47..60962de8 100644 --- a/Makefile.am +++ b/Makefile.am @@ -345,7 +345,7 @@ LDADD = $(top_builddir)/libcruft-util.a $(BOOST_FILESYSTEM_LIB) $(BOOST_SYSTEM_L ## Tests AM_LDFLAGS += $(BOOST_LDFLAGS) $(BOOST_FILESYSTEM_LIB) $(BOOST_SYSTEM_LIB) -AM_CXXFLAGS += -I$(top_srcdir) +AM_CXXFLAGS += -I$(top_srcdir) -I$(top_builddir) TEST_BIN = \ test/alloc/arena \ diff --git a/alloc/dynamic.hpp b/alloc/dynamic.hpp index acb8877e..1715e2cd 100644 --- a/alloc/dynamic.hpp +++ b/alloc/dynamic.hpp @@ -49,15 +49,17 @@ namespace util { namespace alloc { } // allocation management - void* allocate (size_t bytes, - size_t alignment = DEFAULT_ALIGNMENT) + void* + allocate (size_t bytes, + size_t alignment = DEFAULT_ALIGNMENT) & { return m_child->allocate (bytes, alignment); } - void deallocate (void *ptr, - size_t bytes, - size_t alignment = DEFAULT_ALIGNMENT) + void + deallocate (void *ptr, + size_t bytes, + size_t alignment = DEFAULT_ALIGNMENT) { return m_child->deallocate (ptr, bytes, alignment); } diff --git a/cmdopt.hpp b/cmdopt.hpp index 31934175..ebfc0afd 100644 --- a/cmdopt.hpp +++ b/cmdopt.hpp @@ -68,6 +68,7 @@ namespace util { namespace cmdopt { class present : public base { public: explicit present (bool&); + explicit present (bool&&) = delete; using base::execute; virtual void execute (void) override; @@ -85,15 +86,16 @@ namespace util { namespace cmdopt { class value : public base { public: explicit value (T&); + explicit value (T&&) = delete; using base::execute; void execute (const char *restrict) override; const std::string& example (void) const override; - T data (void) const; - T& data (void); - T& data (T); + const T& data (void) const&; + T& data (void) &; + T& data (T) &; private: T& m_data; @@ -104,6 +106,7 @@ namespace util { namespace cmdopt { class count : public value { public: explicit count (T&); + explicit count (T&&) = delete; using value::execute; void execute (void) override; diff --git a/cmdopt.ipp b/cmdopt.ipp index ae0afaeb..c98593b0 100644 --- a/cmdopt.ipp +++ b/cmdopt.ipp @@ -96,8 +96,8 @@ namespace util { namespace cmdopt { //----------------------------------------------------------------------------- template - T - option::value::data (void) const + const T& + option::value::data (void) const& { return m_data; } @@ -106,7 +106,7 @@ namespace util { namespace cmdopt { //----------------------------------------------------------------------------- template T& - option::value::data (void) + option::value::data (void) & { return m_data; } @@ -115,7 +115,7 @@ namespace util { namespace cmdopt { //----------------------------------------------------------------------------- template T& - option::value::data (T _data) + option::value::data (T _data) & { return m_data = _data; } diff --git a/introspection.hpp b/introspection.hpp index b9d66a36..6b62b87f 100644 --- a/introspection.hpp +++ b/introspection.hpp @@ -273,8 +273,10 @@ namespace util { typedef R type; static const std::string name; + static const R& get (const K &k) { return k.*M; } - static R get (K &k) { return k.*M; } + static R& get ( K &k) { return k.*M; } + static R& get ( K &&) = delete; }; /////////////////////////////////////////////////////////////////////////// @@ -377,6 +379,8 @@ namespace util { std::tuple_element::fields>::type::get (k)... ); } + + static auto make (K&&) = delete; }; } @@ -389,6 +393,16 @@ namespace util { { return detail::_as_tuple::make (k); } + + template + auto as_tuple (K &_k) + { + const K &k = _k; + return as_tuple (k); + } + + template + auto as_tuple (K&&) = delete; } #endif diff --git a/json/flat.cpp.rl b/json/flat.cpp.rl index 4e467eb4..265a790e 100644 --- a/json/flat.cpp.rl +++ b/json/flat.cpp.rl @@ -20,7 +20,9 @@ #include "json/flat.hpp" #include "json/except.hpp" + #include "io.hpp" +#include "debug.hpp" #include diff --git a/json/tree.cpp b/json/tree.cpp index bd6a7ca0..36ec24ed 100644 --- a/json/tree.cpp +++ b/json/tree.cpp @@ -222,73 +222,73 @@ json::tree::from_path (const std::string &path) // Type conversion const json::tree::object& -json::tree::node::as_object (void) const +json::tree::node::as_object (void) const& { throw json::type_error ("node is not an object"); } //----------------------------------------------------------------------------- const json::tree::array& -json::tree::node::as_array (void) const +json::tree::node::as_array (void) const& { throw json::type_error ("node is not an array"); } //----------------------------------------------------------------------------- const json::tree::string& -json::tree::node::as_string (void) const +json::tree::node::as_string (void) const& { throw json::type_error ("node is not a string"); } //----------------------------------------------------------------------------- const json::tree::number& -json::tree::node::as_number (void) const +json::tree::node::as_number (void) const& { throw json::type_error ("node is not a number"); } //----------------------------------------------------------------------------- const json::tree::boolean& -json::tree::node::as_boolean (void) const +json::tree::node::as_boolean (void) const& { throw json::type_error ("node is not a boolean"); } //----------------------------------------------------------------------------- const json::tree::null& -json::tree::node::as_null (void) const +json::tree::node::as_null (void) const& { throw json::type_error ("node is not a null"); } /////////////////////////////////////////////////////////////////////////////// json::tree::object& -json::tree::node::as_object (void) +json::tree::node::as_object (void)& { throw json::type_error ("node is not an object"); } //----------------------------------------------------------------------------- json::tree::array& -json::tree::node::as_array (void) +json::tree::node::as_array (void)& { throw json::type_error ("node is not an array"); } //----------------------------------------------------------------------------- json::tree::string& -json::tree::node::as_string (void) +json::tree::node::as_string (void)& { throw json::type_error ("node is not a string"); } //----------------------------------------------------------------------------- json::tree::number& -json::tree::node::as_number (void) +json::tree::node::as_number (void)& { throw json::type_error ("node is not a number"); } //----------------------------------------------------------------------------- json::tree::boolean& -json::tree::node::as_boolean (void) +json::tree::node::as_boolean (void)& { throw json::type_error ("node is not a boolean"); } //----------------------------------------------------------------------------- json::tree::null& -json::tree::node::as_null (void) +json::tree::node::as_null (void)& { throw json::type_error ("node is not a null"); } @@ -331,7 +331,7 @@ json::tree::node::as_uint (void) const //----------------------------------------------------------------------------- const char* -json::tree::node::as_chars (void) const +json::tree::node::as_chars (void) const& { return as_string ().native ().c_str (); } @@ -405,25 +405,25 @@ bool json::tree::node::operator==(const char *rhs) const //----------------------------------------------------------------------------- json::tree::node& -json::tree::node::operator[] (const std::string &key) +json::tree::node::operator[] (const std::string &key)& { return as_object ()[key]; } //----------------------------------------------------------------------------- json::tree::node& -json::tree::node::operator[] (unsigned int idx) +json::tree::node::operator[] (unsigned int idx)& { return as_array()[idx]; } //----------------------------------------------------------------------------- const json::tree::node& -json::tree::node::operator[] (const std::string &key) const +json::tree::node::operator[] (const std::string &key) const& { return as_object ()[key]; } //----------------------------------------------------------------------------- const json::tree::node& -json::tree::node::operator[] (unsigned int idx) const +json::tree::node::operator[] (unsigned int idx) const& { return as_array()[idx]; } @@ -474,7 +474,7 @@ json::tree::object::insert (const std::string &_key, std::unique_ptr clone (void) const = 0; - virtual const object& as_object (void) const; - virtual const array& as_array (void) const; - virtual const string& as_string (void) const; - virtual const number& as_number (void) const; - virtual const boolean& as_boolean (void) const; - virtual const null& as_null (void) const; + virtual const object& as_object (void) const&; + virtual const array& as_array (void) const&; + virtual const string& as_string (void) const&; + virtual const number& as_number (void) const&; + virtual const boolean& as_boolean (void) const&; + virtual const null& as_null (void) const&; - virtual object& as_object (void); - virtual array& as_array (void); - virtual string& as_string (void); - virtual number& as_number (void); - virtual boolean& as_boolean (void); - virtual null& as_null (void); + virtual object& as_object (void)&; + virtual array& as_array (void)&; + virtual string& as_string (void)&; + virtual number& as_number (void)&; + virtual boolean& as_boolean (void)&; + virtual null& as_null (void)&; // we don't provide operators for conversion due to ambiguities // introduced when using indexing operators with pointer @@ -76,7 +76,7 @@ namespace json { namespace tree { virtual float as_float (void) const; virtual double as_double (void) const; virtual size_t as_uint (void) const; - virtual const char* as_chars (void) const; + virtual const char* as_chars (void) const&; template T as (void) const; @@ -102,10 +102,10 @@ namespace json { namespace tree { virtual bool operator==(const char *rhs) const; virtual bool operator!=(const char *rhs) const { return !(*this == rhs); } - virtual node& operator[] (const std::string&); - virtual node& operator[] (unsigned int); - virtual const node& operator[] (const std::string&) const; - virtual const node& operator[] (unsigned int) const; + virtual node& operator[] (const std::string&)&; + virtual node& operator[] (unsigned int)&; + virtual const node& operator[] (const std::string&) const&; + virtual const node& operator[] (unsigned int) const&; virtual std::ostream& write (std::ostream &os) const = 0; }; @@ -126,9 +126,9 @@ namespace json { namespace tree { virtual ~object (); virtual std::unique_ptr clone (void) const override; - virtual const object& as_object (void) const override { return *this; } - virtual object& as_object (void) override { return *this; } - virtual bool is_object (void) const override { return true; } + virtual const object& as_object (void) const& override { return *this; } + virtual object& as_object (void) & override { return *this; } + virtual bool is_object (void) const override { return true; } virtual type_t type (void) const override { return OBJECT; } virtual bool operator==(const object &rhs) const override; @@ -136,8 +136,8 @@ namespace json { namespace tree { { return rhs == *this; } virtual void insert (const std::string &key, std::unique_ptr&& value); - virtual const node& operator[](const std::string &key) const override; - virtual node& operator[](const std::string &key) override; + virtual const node& operator[](const std::string &key) const& override; + virtual node& operator[](const std::string &key)& override; virtual bool has (const std::string&) const; virtual const_iterator find (const std::string&) const; @@ -173,17 +173,17 @@ namespace json { namespace tree { virtual ~array(); virtual std::unique_ptr clone (void) const override; - virtual const array& as_array (void) const override { return *this; } - virtual array& as_array (void) override { return *this; } - virtual bool is_array (void) const override { return true; } + virtual const array& as_array (void) const& override { return *this; } + virtual array& as_array (void) & override { return *this; } + virtual bool is_array (void) const override { return true; } virtual type_t type (void) const override { return ARRAY; } virtual bool operator==(const array &rhs) const override; virtual bool operator==(const node &rhs) const override; virtual size_t size (void) const; - virtual node& operator [](unsigned int idx) override; - virtual const node& operator [](unsigned int idx) const override; + virtual node& operator [](unsigned int idx)& override; + virtual const node& operator [](unsigned int idx) const& override; virtual iterator begin (void); virtual iterator end (void); @@ -209,9 +209,9 @@ namespace json { namespace tree { string (const char *_first, const char *_last): m_value (_first, _last) { ; } virtual std::unique_ptr clone (void) const override; - virtual const string& as_string (void) const override { return *this; } - virtual string& as_string (void) override { return *this; } - virtual bool is_string (void) const override { return true; } + virtual const string& as_string (void) const& override { return *this; } + virtual string& as_string (void) & override { return *this; } + virtual bool is_string (void) const override { return true; } virtual type_t type (void) const override { return STRING; } @@ -243,9 +243,9 @@ namespace json { namespace tree { explicit number (size_t _value): m_value (_value) { ; } virtual std::unique_ptr clone (void) const override; - virtual const number& as_number (void) const override { return *this; } - virtual number& as_number (void) override { return *this; } - virtual bool is_number (void) const override { return true; } + virtual const number& as_number (void) const& override { return *this; } + virtual number& as_number (void) & override { return *this; } + virtual bool is_number (void) const override { return true; } virtual type_t type (void) const override { return NUMBER; } @@ -269,9 +269,9 @@ namespace json { namespace tree { explicit boolean (bool _value): m_value (_value) { ; } virtual std::unique_ptr clone (void) const override; - virtual const boolean& as_boolean (void) const override { return *this; } - virtual boolean& as_boolean (void) override { return *this; } - virtual bool is_boolean (void) const override { return true; } + virtual const boolean& as_boolean (void) const& override { return *this; } + virtual boolean& as_boolean (void) & override { return *this; } + virtual bool is_boolean (void) const override { return true; } virtual type_t type (void) const override { return BOOLEAN; } @@ -296,9 +296,9 @@ namespace json { namespace tree { virtual bool operator==(const node &rhs) const override { return rhs == *this; } - virtual bool is_null (void) const override { return true; } - virtual const null& as_null (void) const override { return *this; } - virtual null& as_null (void) override { return *this; } + virtual const null& as_null (void) const& override { return *this; } + virtual null& as_null (void) & override { return *this; } + virtual bool is_null (void) const override { return true; } virtual std::ostream& write (std::ostream &os) const override; }; @@ -319,13 +319,21 @@ namespace json { namespace tree { } } template -std::unique_ptr to_json (const T &t, Args&&... args) { - return json::tree::io::serialise (t, std::forward(args)...); +std::unique_ptr +to_json (const T &t, Args&&... args) +{ + return json::tree::io::serialise ( + t, std::forward(args)... + ); } template -T from_json (const json::tree::node &n, Args&&... args) { - return json::tree::io::deserialise (n, std::forward(args)...); +T +from_json (const json::tree::node &n, Args&&... args) +{ + return json::tree::io::deserialise ( + n, std::forward(args)... + ); } #endif diff --git a/memory/buffer/circular.cpp b/memory/buffer/circular.cpp index 1b48ddb4..20266dbc 100644 --- a/memory/buffer/circular.cpp +++ b/memory/buffer/circular.cpp @@ -124,7 +124,7 @@ circular::~circular () /////////////////////////////////////////////////////////////////////////////// char* -circular::begin (void) +circular::begin (void)& { return m_begin; } @@ -132,7 +132,7 @@ circular::begin (void) //----------------------------------------------------------------------------- char* -circular::end (void) +circular::end (void)& { return m_end; } diff --git a/memory/buffer/circular.hpp b/memory/buffer/circular.hpp index 32fe4891..f58f3fe9 100644 --- a/memory/buffer/circular.hpp +++ b/memory/buffer/circular.hpp @@ -35,14 +35,14 @@ namespace util { namespace memory { namespace buffer { circular& operator= (const circular&) = delete; circular& operator= (circular&&) = delete; - char& operator[] (size_t); - const char& operator[] (size_t) const; + char& operator[] (size_t)&; + const char& operator[] (size_t) const&; - char* begin (void); - char* end (void); + char* begin (void)&; + char* end (void)&; - const char* begin (void) const; - const char* end (void) const; + const char* begin (void) const&; + const char* end (void) const&; size_t size (void) const; diff --git a/memory/buffer/paged.cpp b/memory/buffer/paged.cpp index fbe78682..be6a0b63 100644 --- a/memory/buffer/paged.cpp +++ b/memory/buffer/paged.cpp @@ -64,7 +64,7 @@ paged::~paged () /////////////////////////////////////////////////////////////////////////////// char* -paged::begin (void) +paged::begin (void)& { return m_begin; } @@ -72,7 +72,7 @@ paged::begin (void) //----------------------------------------------------------------------------- char* -paged::end (void) +paged::end (void)& { return m_end; } diff --git a/memory/buffer/paged.hpp b/memory/buffer/paged.hpp index 0befbb38..6cba9bc7 100644 --- a/memory/buffer/paged.hpp +++ b/memory/buffer/paged.hpp @@ -32,14 +32,14 @@ namespace util { namespace memory { namespace buffer { paged& operator= (const paged&) = delete; paged& operator= (paged &&) = delete; - char* begin (void); - char* end (void); + char* begin (void)&; + char* end (void)&; - const char* cbegin (void); - const char* cend (void); + const char* cbegin (void)&; + const char* cend (void)&; - const char* begin (void) const; - const char* end (void) const; + const char* begin (void) const&; + const char* end (void) const&; void access (char*); diff --git a/pool.hpp b/pool.hpp index 1f3bf598..dbe3a460 100644 --- a/pool.hpp +++ b/pool.hpp @@ -57,8 +57,8 @@ namespace util { // Indexing size_t index (const T*) const; - T& operator[] (size_t idx); - const T& operator[] (size_t idx) const; + T& operator[] (size_t idx) &; + const T& operator[] (size_t idx) const&; }; } diff --git a/strongdef.hpp b/strongdef.hpp index c8046a60..5c9d50a8 100644 --- a/strongdef.hpp +++ b/strongdef.hpp @@ -52,13 +52,13 @@ namespace util { { data = rhs.data; return *this; } // simple value_type assignment. - strongdef& operator= (const T &rhs) + strongdef& operator= (const T &rhs)& { data = rhs; return *this; } // conversion operators must not be explicit or it defeats the point // of this class (ease of use, transparency). - operator const T& (void) const { return data; } - operator T& (void) { return data; } + operator const T& (void) const& { return data; } + operator T& (void) & { return data; } // explicitly disable equality with unequal types or tags. this // prevents the conversion operator getting invoked and falsely