Makes gmock work on Symbian (both 3rd & 5th editions), original patch contributed by Mika Raento.
This commit is contained in:
@@ -125,32 +125,13 @@ GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(unsigned char, '\0');
|
||||
GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(signed char, '\0');
|
||||
GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(char, '\0');
|
||||
|
||||
// signed wchar_t and unsigned wchar_t are NOT in the C++ standard.
|
||||
// Using them is a bad practice and not portable. So don't use them.
|
||||
//
|
||||
// Still, Google Mock is designed to work even if the user uses signed
|
||||
// wchar_t or unsigned wchar_t (obviously, assuming the compiler
|
||||
// supports them).
|
||||
//
|
||||
// To gcc,
|
||||
//
|
||||
// wchar_t == signed wchar_t != unsigned wchar_t == unsigned int
|
||||
//
|
||||
// MSVC does not recognize signed wchar_t or unsigned wchar_t. It
|
||||
// treats wchar_t as a native type usually, but treats it as the same
|
||||
// as unsigned short when the compiler option /Zc:wchar_t- is
|
||||
// specified.
|
||||
//
|
||||
// Therefore we provide a default action for wchar_t when compiled
|
||||
// with gcc or _NATIVE_WCHAR_T_DEFINED is defined.
|
||||
//
|
||||
// There's no need for a default action for signed wchar_t, as that
|
||||
// type is the same as wchar_t for gcc, and invalid for MSVC.
|
||||
//
|
||||
// There's also no need for a default action for unsigned wchar_t, as
|
||||
// that type is the same as unsigned int for gcc, and invalid for
|
||||
// MSVC.
|
||||
#if defined(__GNUC__) || defined(_NATIVE_WCHAR_T_DEFINED)
|
||||
#if GMOCK_WCHAR_T_IS_NATIVE_
|
||||
GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(wchar_t, 0U); // NOLINT
|
||||
#endif
|
||||
|
||||
|
||||
@@ -304,11 +304,15 @@ class ElementsAreMatcher1 {
|
||||
typedef typename internal::StlContainerView<RawContainer>::type::value_type
|
||||
Element;
|
||||
|
||||
const Matcher<const Element&> matchers[] = {
|
||||
MatcherCast<const Element&>(e1_),
|
||||
};
|
||||
|
||||
return MakeMatcher(new ElementsAreMatcherImpl<Container>(matchers, 1));
|
||||
// Nokia's Symbian Compiler has a nasty bug where the object put
|
||||
// in a one-element local array is not destructed when the array
|
||||
// goes out of scope. This leads to obvious badness as we've
|
||||
// added the linked_ptr in it to our other linked_ptrs list.
|
||||
// Hence we implement ElementsAreMatcher1 specially to avoid using
|
||||
// a local array.
|
||||
const Matcher<const Element&> matcher =
|
||||
MatcherCast<const Element&>(e1_);
|
||||
return MakeMatcher(new ElementsAreMatcherImpl<Container>(&matcher, 1));
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
@@ -192,6 +192,19 @@ class ElementsAreMatcher$i {
|
||||
typedef typename internal::StlContainerView<RawContainer>::type::value_type
|
||||
Element;
|
||||
|
||||
$if i==1 [[
|
||||
|
||||
// Nokia's Symbian Compiler has a nasty bug where the object put
|
||||
// in a one-element local array is not destructed when the array
|
||||
// goes out of scope. This leads to obvious badness as we've
|
||||
// added the linked_ptr in it to our other linked_ptrs list.
|
||||
// Hence we implement ElementsAreMatcher1 specially to avoid using
|
||||
// a local array.
|
||||
const Matcher<const Element&> matcher =
|
||||
MatcherCast<const Element&>(e1_);
|
||||
return MakeMatcher(new ElementsAreMatcherImpl<Container>(&matcher, 1));
|
||||
]] $else [[
|
||||
|
||||
const Matcher<const Element&> matchers[] = {
|
||||
|
||||
$for j [[
|
||||
@@ -201,6 +214,8 @@ $for j [[
|
||||
};
|
||||
|
||||
return MakeMatcher(new ElementsAreMatcherImpl<Container>(matchers, $i));
|
||||
]]
|
||||
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
@@ -320,47 +320,59 @@ inline PolymorphicMatcher<Impl> MakePolymorphicMatcher(const Impl& impl) {
|
||||
template <typename T, typename M>
|
||||
Matcher<T> MatcherCast(M m);
|
||||
|
||||
// TODO(vladl@google.com): Modify the implementation to reject casting
|
||||
// Matcher<int> to Matcher<double>.
|
||||
// Implements SafeMatcherCast().
|
||||
//
|
||||
// This overload handles polymorphic matchers only since monomorphic
|
||||
// matchers are handled by the next one.
|
||||
template <typename T, typename M>
|
||||
inline Matcher<T> SafeMatcherCast(M polymorphic_matcher) {
|
||||
return Matcher<T>(polymorphic_matcher);
|
||||
}
|
||||
// We use an intermediate class to do the actual safe casting as Nokia's
|
||||
// Symbian compiler cannot decide between
|
||||
// template <T, M> ... (M) and
|
||||
// template <T, U> ... (const Matcher<U>&)
|
||||
// for function templates but can for member function templates.
|
||||
template <typename T>
|
||||
class SafeMatcherCastImpl {
|
||||
public:
|
||||
// This overload handles polymorphic matchers only since monomorphic
|
||||
// matchers are handled by the next one.
|
||||
template <typename M>
|
||||
static inline Matcher<T> Cast(M polymorphic_matcher) {
|
||||
return Matcher<T>(polymorphic_matcher);
|
||||
}
|
||||
|
||||
// This overload handles monomorphic matchers.
|
||||
//
|
||||
// In general, if type T can be implicitly converted to type U, we can
|
||||
// safely convert a Matcher<U> to a Matcher<T> (i.e. Matcher is
|
||||
// contravariant): just keep a copy of the original Matcher<U>, convert the
|
||||
// argument from type T to U, and then pass it to the underlying Matcher<U>.
|
||||
// The only exception is when U is a reference and T is not, as the
|
||||
// underlying Matcher<U> may be interested in the argument's address, which
|
||||
// is not preserved in the conversion from T to U.
|
||||
template <typename T, typename U>
|
||||
Matcher<T> SafeMatcherCast(const Matcher<U>& matcher) {
|
||||
// Enforce that T can be implicitly converted to U.
|
||||
GMOCK_COMPILE_ASSERT_((internal::ImplicitlyConvertible<T, U>::value),
|
||||
T_must_be_implicitly_convertible_to_U);
|
||||
// Enforce that we are not converting a non-reference type T to a reference
|
||||
// type U.
|
||||
GMOCK_COMPILE_ASSERT_(
|
||||
internal::is_reference<T>::value || !internal::is_reference<U>::value,
|
||||
cannot_convert_non_referentce_arg_to_reference);
|
||||
// In case both T and U are arithmetic types, enforce that the
|
||||
// conversion is not lossy.
|
||||
typedef GMOCK_REMOVE_CONST_(GMOCK_REMOVE_REFERENCE_(T)) RawT;
|
||||
typedef GMOCK_REMOVE_CONST_(GMOCK_REMOVE_REFERENCE_(U)) RawU;
|
||||
const bool kTIsOther = GMOCK_KIND_OF_(RawT) == internal::kOther;
|
||||
const bool kUIsOther = GMOCK_KIND_OF_(RawU) == internal::kOther;
|
||||
GMOCK_COMPILE_ASSERT_(
|
||||
kTIsOther || kUIsOther ||
|
||||
(internal::LosslessArithmeticConvertible<RawT, RawU>::value),
|
||||
conversion_of_arithmetic_types_must_be_lossless);
|
||||
return MatcherCast<T>(matcher);
|
||||
// This overload handles monomorphic matchers.
|
||||
//
|
||||
// In general, if type T can be implicitly converted to type U, we can
|
||||
// safely convert a Matcher<U> to a Matcher<T> (i.e. Matcher is
|
||||
// contravariant): just keep a copy of the original Matcher<U>, convert the
|
||||
// argument from type T to U, and then pass it to the underlying Matcher<U>.
|
||||
// The only exception is when U is a reference and T is not, as the
|
||||
// underlying Matcher<U> may be interested in the argument's address, which
|
||||
// is not preserved in the conversion from T to U.
|
||||
template <typename U>
|
||||
static inline Matcher<T> Cast(const Matcher<U>& matcher) {
|
||||
// Enforce that T can be implicitly converted to U.
|
||||
GMOCK_COMPILE_ASSERT_((internal::ImplicitlyConvertible<T, U>::value),
|
||||
T_must_be_implicitly_convertible_to_U);
|
||||
// Enforce that we are not converting a non-reference type T to a reference
|
||||
// type U.
|
||||
GMOCK_COMPILE_ASSERT_(
|
||||
internal::is_reference<T>::value || !internal::is_reference<U>::value,
|
||||
cannot_convert_non_referentce_arg_to_reference);
|
||||
// In case both T and U are arithmetic types, enforce that the
|
||||
// conversion is not lossy.
|
||||
typedef GMOCK_REMOVE_CONST_(GMOCK_REMOVE_REFERENCE_(T)) RawT;
|
||||
typedef GMOCK_REMOVE_CONST_(GMOCK_REMOVE_REFERENCE_(U)) RawU;
|
||||
const bool kTIsOther = GMOCK_KIND_OF_(RawT) == internal::kOther;
|
||||
const bool kUIsOther = GMOCK_KIND_OF_(RawU) == internal::kOther;
|
||||
GMOCK_COMPILE_ASSERT_(
|
||||
kTIsOther || kUIsOther ||
|
||||
(internal::LosslessArithmeticConvertible<RawT, RawU>::value),
|
||||
conversion_of_arithmetic_types_must_be_lossless);
|
||||
return MatcherCast<T>(matcher);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, typename M>
|
||||
inline Matcher<T> SafeMatcherCast(const M& polymorphic_matcher) {
|
||||
return SafeMatcherCastImpl<T>::Cast(polymorphic_matcher);
|
||||
}
|
||||
|
||||
// A<T>() returns a matcher that matches any value of type T.
|
||||
|
||||
@@ -221,6 +221,34 @@ class ImplicitlyConvertible {
|
||||
template <typename From, typename To>
|
||||
const bool ImplicitlyConvertible<From, To>::value;
|
||||
|
||||
// Symbian compilation can be done with wchar_t being either a native
|
||||
// type or a typedef. Using Google Mock with OpenC without wchar_t
|
||||
// should require the definition of _STLP_NO_WCHAR_T.
|
||||
//
|
||||
// MSVC treats wchar_t as a native type usually, but treats it as the
|
||||
// same as unsigned short when the compiler option /Zc:wchar_t- is
|
||||
// specified. It defines _NATIVE_WCHAR_T_DEFINED symbol when wchar_t
|
||||
// is a native type.
|
||||
#if (GTEST_OS_SYMBIAN && defined(_STLP_NO_WCHAR_T)) || \
|
||||
(defined(_MSC_VER) && !defined(_NATIVE_WCHAR_T_DEFINED))
|
||||
// wchar_t is a typedef.
|
||||
#else
|
||||
#define GMOCK_WCHAR_T_IS_NATIVE_ 1
|
||||
#endif
|
||||
|
||||
// signed wchar_t and unsigned wchar_t are NOT in the C++ standard.
|
||||
// Using them is a bad practice and not portable. So DON'T use them.
|
||||
//
|
||||
// Still, Google Mock is designed to work even if the user uses signed
|
||||
// wchar_t or unsigned wchar_t (obviously, assuming the compiler
|
||||
// supports them).
|
||||
//
|
||||
// To gcc,
|
||||
// wchar_t == signed wchar_t != unsigned wchar_t == unsigned int
|
||||
#ifdef __GNUC__
|
||||
#define GMOCK_HAS_SIGNED_WCHAR_T_ 1 // signed/unsigned wchar_t are valid types.
|
||||
#endif
|
||||
|
||||
// In what follows, we use the term "kind" to indicate whether a type
|
||||
// is bool, an integer type (excluding bool), a floating-point type,
|
||||
// or none of them. This categorization is useful for determining
|
||||
@@ -252,10 +280,7 @@ GMOCK_DECLARE_KIND_(unsigned int, kInteger);
|
||||
GMOCK_DECLARE_KIND_(long, kInteger); // NOLINT
|
||||
GMOCK_DECLARE_KIND_(unsigned long, kInteger); // NOLINT
|
||||
|
||||
// MSVC can be configured to define wchar_t as a typedef of unsigned
|
||||
// short. It defines _NATIVE_WCHAR_T_DEFINED symbol when wchar_t is a
|
||||
// native type.
|
||||
#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED)
|
||||
#if GMOCK_WCHAR_T_IS_NATIVE_
|
||||
GMOCK_DECLARE_KIND_(wchar_t, kInteger);
|
||||
#endif
|
||||
|
||||
@@ -679,10 +704,31 @@ class StlContainerView<Element[N]> {
|
||||
static const_reference ConstReference(const Element (&array)[N]) {
|
||||
// Ensures that Element is not a const type.
|
||||
testing::StaticAssertTypeEq<Element, RawElement>();
|
||||
#if GTEST_OS_SYMBIAN
|
||||
// The Nokia Symbian compiler confuses itself in template instantiation
|
||||
// for this call without the cast to Element*:
|
||||
// function call '[testing::internal::NativeArray<char *>].NativeArray(
|
||||
// {lval} const char *[4], long, testing::internal::RelationToSource)'
|
||||
// does not match
|
||||
// 'testing::internal::NativeArray<char *>::NativeArray(
|
||||
// char *const *, unsigned int, testing::internal::RelationToSource)'
|
||||
// (instantiating: 'testing::internal::ContainsMatcherImpl
|
||||
// <const char * (&)[4]>::Matches(const char * (&)[4]) const')
|
||||
// (instantiating: 'testing::internal::StlContainerView<char *[4]>::
|
||||
// ConstReference(const char * (&)[4])')
|
||||
// (and though the N parameter type is mismatched in the above explicit
|
||||
// conversion of it doesn't help - only the conversion of the array).
|
||||
return type(const_cast<Element*>(&array[0]), N, kReference);
|
||||
#else
|
||||
return type(array, N, kReference);
|
||||
#endif // GTEST_OS_SYMBIAN
|
||||
}
|
||||
static type Copy(const Element (&array)[N]) {
|
||||
#if GTEST_OS_SYMBIAN
|
||||
return type(const_cast<Element*>(&array[0]), N, kCopy);
|
||||
#else
|
||||
return type(array, N, kCopy);
|
||||
#endif // GTEST_OS_SYMBIAN
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user