+2017-04-25 Pedro Alves <palves@redhat.com>
+
+ * common/common-defs.h: Include "common/poison.h".
+ * common/function-view.h: (Not, Or, Requires): Move to traits.h
+ and adjust.
+ * common/poison.h: New file.
+ * common/traits.h: Include <type_traits>.
+ (Not, Or, Requires): New, moved from common/function-view.h.
+
2017-04-25 Pedro Alves <palves@redhat.com>
* breakpoint.h (struct breakpoint): In-class initialize all
#include "common-debug.h"
#include "cleanups.h"
#include "common-exceptions.h"
+#include "common/poison.h"
#define EXTERN_C extern "C"
#define EXTERN_C_PUSH extern "C" {
namespace gdb {
-namespace traits {
- /* A few trait helpers. */
- template<typename Predicate>
- struct Not : public std::integral_constant<bool, !Predicate::value>
- {};
-
- template<typename...>
- struct Or;
-
- template<>
- struct Or<> : public std::false_type
- {};
-
- template<typename B1>
- struct Or<B1> : public B1
- {};
-
- template<typename B1, typename B2>
- struct Or<B1, B2>
- : public std::conditional<B1::value, B1, B2>::type
- {};
-
- template<typename B1,typename B2,typename B3, typename... Bn>
- struct Or<B1, B2, B3, Bn...>
- : public std::conditional<B1::value, B1, Or<B2, B3, Bn...>>::type
- {};
-} /* namespace traits */
-
namespace fv_detail {
/* Bits shared by all function_view instantiations that do not depend
on the template parameters. */
{
template<typename From, typename To>
using CompatibleReturnType
- = traits::Or<std::is_void<To>,
- std::is_same<From, To>,
- std::is_convertible<From, To>>;
+ = Or<std::is_void<To>,
+ std::is_same<From, To>,
+ std::is_convertible<From, To>>;
/* True if Func can be called with Args, and either the result is
Res, convertible to Res or Res is void. */
: std::is_same<function_view, typename std::decay<Callable>::type>
{};
- /* Helper to make SFINAE logic easier to read. */
- template<typename Condition>
- using Requires = typename std::enable_if<Condition::value, void>::type;
-
public:
/* NULL by default. */
compatible. */
template
<typename Callable,
- typename = Requires<traits::Not<IsFunctionView<Callable>>>,
+ typename = Requires<Not<IsFunctionView<Callable>>>,
typename = Requires<IsCompatibleCallable<Callable>>>
function_view (Callable &&callable) noexcept
{
--- /dev/null
+/* Poison symbols at compile time.
+
+ Copyright (C) 2017 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef COMMON_POISON_H
+#define COMMON_POISON_H
+
+#include "traits.h"
+
+/* Poison memset of non-POD types. The idea is catching invalid
+ initialization of non-POD structs that is easy to be introduced as
+ side effect of refactoring. For example, say this:
+
+ struct S { VEC(foo_s) *m_data; };
+
+is converted to this at some point:
+
+ struct S {
+ S() { m_data.reserve (10); }
+ std::vector<foo> m_data;
+ };
+
+and old code was initializing S objects like this:
+
+ struct S s;
+ memset (&s, 0, sizeof (S)); // whoops, now wipes vector.
+
+Declaring memset as deleted for non-POD types makes the memset above
+be a compile-time error. */
+
+/* Helper for SFINAE. True if "T *" is memsettable. I.e., if T is
+ either void, or POD. */
+template<typename T>
+struct IsMemsettable
+ : gdb::Or<std::is_void<T>,
+ std::is_pod<T>>
+{};
+
+template <typename T,
+ typename = gdb::Requires<gdb::Not<IsMemsettable<T>>>>
+void *memset (T *s, int c, size_t n) = delete;
+
+/* Similarly, poison memcpy and memmove of non trivially-copyable
+ types, which is undefined. */
+
+/* True if "T *" is relocatable. I.e., copyable with memcpy/memmove.
+ I.e., T is either trivially copyable, or void. */
+template<typename T>
+struct IsRelocatable
+ : gdb::Or<std::is_void<T>,
+ std::is_trivially_copyable<T>>
+{};
+
+/* True if both source and destination are relocatable. */
+
+template <typename D, typename S>
+using BothAreRelocatable
+ = gdb::And<IsRelocatable<D>, IsRelocatable<S>>;
+
+template <typename D, typename S,
+ typename = gdb::Requires<gdb::Not<BothAreRelocatable<D, S>>>>
+void *memcpy (D *dest, const S *src, size_t n) = delete;
+
+template <typename D, typename S,
+ typename = gdb::Requires<gdb::Not<BothAreRelocatable<D, S>>>>
+void *memmove (D *dest, const S *src, size_t n) = delete;
+
+#endif /* COMMON_POISON_H */
using void_t = typename make_void<Ts...>::type;
/* A few trait helpers, mainly stolen from libstdc++. Uppercase
- because "and" is a keyword. */
+ because "and/or", etc. are reserved keywords. */
+
+template<typename Predicate>
+struct Not : public std::integral_constant<bool, !Predicate::value>
+{};
+
+template<typename...>
+struct Or;
+
+template<>
+struct Or<> : public std::false_type
+{};
+
+template<typename B1>
+struct Or<B1> : public B1
+{};
+
+template<typename B1, typename B2>
+struct Or<B1, B2>
+ : public std::conditional<B1::value, B1, B2>::type
+{};
+
+template<typename B1,typename B2,typename B3, typename... Bn>
+struct Or<B1, B2, B3, Bn...>
+ : public std::conditional<B1::value, B1, Or<B2, B3, Bn...>>::type
+{};
template<typename...>
struct And;
: public std::conditional<B1::value, And<B2, B3, Bn...>, B1>::type
{};
+/* Concepts-light-like helper to make SFINAE logic easier to read. */
+template<typename Condition>
+using Requires = typename std::enable_if<Condition::value, void>::type;
}
#endif /* COMMON_TRAITS_H */