aboutsummaryrefslogtreecommitdiffstats
path: root/include/gmock
diff options
context:
space:
mode:
Diffstat (limited to 'include/gmock')
-rw-r--r--include/gmock/gmock-actions.h21
-rw-r--r--include/gmock/gmock-generated-matchers.h14
-rw-r--r--include/gmock/gmock-generated-matchers.h.pump15
-rw-r--r--include/gmock/gmock-matchers.h88
-rw-r--r--include/gmock/internal/gmock-internal-utils.h54
5 files changed, 125 insertions, 67 deletions
diff --git a/include/gmock/gmock-actions.h b/include/gmock/gmock-actions.h
index f7daf826..7f21a7d4 100644
--- a/include/gmock/gmock-actions.h
+++ b/include/gmock/gmock-actions.h
@@ -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
diff --git a/include/gmock/gmock-generated-matchers.h b/include/gmock/gmock-generated-matchers.h
index b2d55768..a59e457f 100644
--- a/include/gmock/gmock-generated-matchers.h
+++ b/include/gmock/gmock-generated-matchers.h
@@ -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:
diff --git a/include/gmock/gmock-generated-matchers.h.pump b/include/gmock/gmock-generated-matchers.h.pump
index 41294b7a..c43aa873 100644
--- a/include/gmock/gmock-generated-matchers.h.pump
+++ b/include/gmock/gmock-generated-matchers.h.pump
@@ -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:
diff --git a/include/gmock/gmock-matchers.h b/include/gmock/gmock-matchers.h
index e2beff4e..3d82279b 100644
--- a/include/gmock/gmock-matchers.h
+++ b/include/gmock/gmock-matchers.h
@@ -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.
diff --git a/include/gmock/internal/gmock-internal-utils.h b/include/gmock/internal/gmock-internal-utils.h
index 39e70b3f..7b173350 100644
--- a/include/gmock/internal/gmock-internal-utils.h
+++ b/include/gmock/internal/gmock-internal-utils.h
@@ -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
}
};