libcc1: add deleter objects
This adds deleter objects for various kinds of protocol pointers to libcc1. Existing specializations of argument_wrapper are then replaced with a single specialization that handles all pointer types via the appropriate deleter. The result here is a bit nicer because the argument_wrapper boilerplate code is completely shared, leaving just the memory-management detail to the particular specializations. libcc1 * rpc.hh (struct deleter): New template class and specializations. (argument_wrapper): Remove specializations. Add specialization for any pointer type.
This commit is contained in:
parent
e702c60e65
commit
0d5a0b9af5
204
libcc1/rpc.hh
204
libcc1/rpc.hh
@ -22,6 +22,7 @@ along with GCC; see the file COPYING3. If not see
|
|||||||
|
|
||||||
#include "status.hh"
|
#include "status.hh"
|
||||||
#include "connection.hh"
|
#include "connection.hh"
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
namespace cc1_plugin
|
namespace cc1_plugin
|
||||||
{
|
{
|
||||||
@ -54,183 +55,96 @@ namespace cc1_plugin
|
|||||||
T m_object;
|
T m_object;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Specialization for any kind of pointer. This is declared but not
|
// Any pointer type requires a deleter object that knows how to
|
||||||
// defined to avoid bugs if a new pointer type is introduced into
|
// clean up. These are used in multiple places.
|
||||||
// the API. Instead you will just get a compilation error.
|
template<typename T> struct deleter;
|
||||||
template<typename T>
|
|
||||||
class argument_wrapper<const T *>;
|
|
||||||
|
|
||||||
// Specialization for string types.
|
|
||||||
template<>
|
template<>
|
||||||
class argument_wrapper<const char *>
|
struct deleter<char>
|
||||||
{
|
{
|
||||||
public:
|
void operator() (char *s)
|
||||||
argument_wrapper () : m_object (NULL) { }
|
|
||||||
~argument_wrapper ()
|
|
||||||
{
|
{
|
||||||
delete[] m_object;
|
delete[] s;
|
||||||
}
|
}
|
||||||
|
|
||||||
argument_wrapper (const argument_wrapper &) = delete;
|
|
||||||
argument_wrapper &operator= (const argument_wrapper &) = delete;
|
|
||||||
|
|
||||||
operator const char * () const
|
|
||||||
{
|
|
||||||
return m_object;
|
|
||||||
}
|
|
||||||
|
|
||||||
status unmarshall (connection *conn)
|
|
||||||
{
|
|
||||||
return ::cc1_plugin::unmarshall (conn, &m_object);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
char *m_object;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Specialization for gcc_type_array.
|
|
||||||
template<>
|
template<>
|
||||||
class argument_wrapper<const gcc_type_array *>
|
struct deleter<gcc_type_array>
|
||||||
{
|
{
|
||||||
public:
|
void operator() (gcc_type_array *p)
|
||||||
argument_wrapper () : m_object (NULL) { }
|
|
||||||
~argument_wrapper ()
|
|
||||||
{
|
{
|
||||||
// It would be nicer if gcc_type_array could have a destructor.
|
delete[] p->elements;
|
||||||
// But, it is in code shared with gdb and cannot.
|
delete p;
|
||||||
if (m_object != NULL)
|
|
||||||
delete[] m_object->elements;
|
|
||||||
delete m_object;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
argument_wrapper (const argument_wrapper &) = delete;
|
|
||||||
argument_wrapper &operator= (const argument_wrapper &) = delete;
|
|
||||||
|
|
||||||
operator const gcc_type_array * () const
|
|
||||||
{
|
|
||||||
return m_object;
|
|
||||||
}
|
|
||||||
|
|
||||||
status unmarshall (connection *conn)
|
|
||||||
{
|
|
||||||
return ::cc1_plugin::unmarshall (conn, &m_object);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
gcc_type_array *m_object;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef GCC_CP_INTERFACE_H
|
#ifdef GCC_CP_INTERFACE_H
|
||||||
// Specialization for gcc_vbase_array.
|
|
||||||
template<>
|
template<>
|
||||||
class argument_wrapper<const gcc_vbase_array *>
|
struct deleter<gcc_vbase_array>
|
||||||
|
{
|
||||||
|
void operator() (gcc_vbase_array *p)
|
||||||
|
{
|
||||||
|
delete[] p->flags;
|
||||||
|
delete[] p->elements;
|
||||||
|
delete p;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct deleter<gcc_cp_template_args>
|
||||||
|
{
|
||||||
|
void operator() (gcc_cp_template_args *p)
|
||||||
|
{
|
||||||
|
delete[] p->elements;
|
||||||
|
delete[] p->kinds;
|
||||||
|
delete p;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct deleter<gcc_cp_function_args>
|
||||||
|
{
|
||||||
|
void operator() (gcc_cp_function_args *p)
|
||||||
|
{
|
||||||
|
delete[] p->elements;
|
||||||
|
delete p;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // GCC_CP_INTERFACE_H
|
||||||
|
|
||||||
|
// Specialization for any kind of pointer.
|
||||||
|
template<typename T>
|
||||||
|
class argument_wrapper<T *>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
argument_wrapper () : m_object (NULL) { }
|
argument_wrapper () = default;
|
||||||
~argument_wrapper ()
|
~argument_wrapper () = default;
|
||||||
{
|
|
||||||
// It would be nicer if gcc_type_array could have a destructor.
|
|
||||||
// But, it is in code shared with gdb and cannot.
|
|
||||||
if (m_object != NULL)
|
|
||||||
{
|
|
||||||
delete[] m_object->flags;
|
|
||||||
delete[] m_object->elements;
|
|
||||||
}
|
|
||||||
delete m_object;
|
|
||||||
}
|
|
||||||
|
|
||||||
argument_wrapper (const argument_wrapper &) = delete;
|
argument_wrapper (const argument_wrapper &) = delete;
|
||||||
argument_wrapper &operator= (const argument_wrapper &) = delete;
|
argument_wrapper &operator= (const argument_wrapper &) = delete;
|
||||||
|
|
||||||
operator const gcc_vbase_array * () const
|
typedef typename std::remove_const<T>::type type;
|
||||||
|
|
||||||
|
operator const type * () const
|
||||||
{
|
{
|
||||||
return m_object;
|
return m_object.get ();
|
||||||
}
|
}
|
||||||
|
|
||||||
status unmarshall (connection *conn)
|
status unmarshall (connection *conn)
|
||||||
{
|
{
|
||||||
return ::cc1_plugin::unmarshall (conn, &m_object);
|
type *ptr;
|
||||||
|
if (!::cc1_plugin::unmarshall (conn, &ptr))
|
||||||
|
return FAIL;
|
||||||
|
m_object.reset (ptr);
|
||||||
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
gcc_vbase_array *m_object;
|
std::unique_ptr<type, deleter<type>> m_object;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Specialization for gcc_cp_template_args.
|
|
||||||
template<>
|
|
||||||
class argument_wrapper<const gcc_cp_template_args *>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
argument_wrapper () : m_object (NULL) { }
|
|
||||||
~argument_wrapper ()
|
|
||||||
{
|
|
||||||
// It would be nicer if gcc_type_array could have a destructor.
|
|
||||||
// But, it is in code shared with gdb and cannot.
|
|
||||||
if (m_object != NULL)
|
|
||||||
{
|
|
||||||
delete[] m_object->elements;
|
|
||||||
delete[] m_object->kinds;
|
|
||||||
}
|
|
||||||
delete m_object;
|
|
||||||
}
|
|
||||||
|
|
||||||
argument_wrapper (const argument_wrapper &) = delete;
|
|
||||||
argument_wrapper &operator= (const argument_wrapper &) = delete;
|
|
||||||
|
|
||||||
operator const gcc_cp_template_args * () const
|
|
||||||
{
|
|
||||||
return m_object;
|
|
||||||
}
|
|
||||||
|
|
||||||
status unmarshall (connection *conn)
|
|
||||||
{
|
|
||||||
return ::cc1_plugin::unmarshall (conn, &m_object);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
gcc_cp_template_args *m_object;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Specialization for gcc_cp_function_args.
|
|
||||||
template<>
|
|
||||||
class argument_wrapper<const gcc_cp_function_args *>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
argument_wrapper () : m_object (NULL) { }
|
|
||||||
~argument_wrapper ()
|
|
||||||
{
|
|
||||||
// It would be nicer if gcc_type_array could have a destructor.
|
|
||||||
// But, it is in code shared with gdb and cannot.
|
|
||||||
if (m_object != NULL)
|
|
||||||
{
|
|
||||||
delete[] m_object->elements;
|
|
||||||
}
|
|
||||||
delete m_object;
|
|
||||||
}
|
|
||||||
|
|
||||||
argument_wrapper (const argument_wrapper &) = delete;
|
|
||||||
argument_wrapper &operator= (const argument_wrapper &) = delete;
|
|
||||||
|
|
||||||
operator const gcc_cp_function_args * () const
|
|
||||||
{
|
|
||||||
return m_object;
|
|
||||||
}
|
|
||||||
|
|
||||||
status unmarshall (connection *conn)
|
|
||||||
{
|
|
||||||
return ::cc1_plugin::unmarshall (conn, &m_object);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
gcc_cp_function_args *m_object;
|
|
||||||
};
|
|
||||||
#endif /* GCC_CP_INTERFACE_H */
|
|
||||||
|
|
||||||
// There are two kinds of template functions here: "call" and
|
// There are two kinds of template functions here: "call" and
|
||||||
// "callback". "call" is implemented with variadic templates, but
|
// "callback". "call" is implemented with variadic templates, but
|
||||||
// "callback" is repeated multiple times to handle different numbers
|
// "callback" is repeated multiple times to handle different numbers
|
||||||
|
Loading…
x
Reference in New Issue
Block a user