summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzhanyong.wan <zhanyong.wan@861a406c-534a-0410-8894-cb66d6ee9925>2013-02-28 23:46:07 +0000
committerzhanyong.wan <zhanyong.wan@861a406c-534a-0410-8894-cb66d6ee9925>2013-02-28 23:46:07 +0000
commit2733a36231e9e59dfe0648562ac021ccea0e27d8 (patch)
tree6758198925bed7d581f7f9d81580a726592236e8
parent99788d751da80001db223de2cd6178046ff5bad0 (diff)
downloadgtest-2733a36231e9e59dfe0648562ac021ccea0e27d8.tar.gz
gtest-2733a36231e9e59dfe0648562ac021ccea0e27d8.tar.bz2
gtest-2733a36231e9e59dfe0648562ac021ccea0e27d8.tar.xz
Fixes a nasty issue in gtest's template instantiation.
git-svn-id: http://googletest.googlecode.com/svn/trunk@642 861a406c-534a-0410-8894-cb66d6ee9925
-rw-r--r--include/gtest/gtest-message.h72
-rw-r--r--include/gtest/gtest.h12
-rw-r--r--include/gtest/internal/gtest-internal.h46
-rw-r--r--include/gtest/internal/gtest-port.h9
-rw-r--r--include/gtest/internal/gtest-string.h11
-rw-r--r--include/gtest/internal/gtest-type-util.h1
-rw-r--r--include/gtest/internal/gtest-type-util.h.pump1
-rw-r--r--src/gtest-filepath.cc1
-rw-r--r--src/gtest.cc28
9 files changed, 85 insertions, 96 deletions
diff --git a/include/gtest/gtest-message.h b/include/gtest/gtest-message.h
index 6336b4a..fe879bc 100644
--- a/include/gtest/gtest-message.h
+++ b/include/gtest/gtest-message.h
@@ -48,8 +48,11 @@
#include <limits>
-#include "gtest/internal/gtest-string.h"
-#include "gtest/internal/gtest-internal.h"
+#include "gtest/internal/gtest-port.h"
+
+// Ensures that there is at least one operator<< in the global namespace.
+// See Message& operator<<(...) below for why.
+void operator<<(const testing::internal::Secret&, int);
namespace testing {
@@ -87,15 +90,7 @@ class GTEST_API_ Message {
public:
// Constructs an empty Message.
- // We allocate the stringstream separately because otherwise each use of
- // ASSERT/EXPECT in a procedure adds over 200 bytes to the procedure's
- // stack frame leading to huge stack frames in some cases; gcc does not reuse
- // the stack space.
- Message() : ss_(new ::std::stringstream) {
- // By default, we want there to be enough precision when printing
- // a double to a Message.
- *ss_ << std::setprecision(std::numeric_limits<double>::digits10 + 2);
- }
+ Message();
// Copy constructor.
Message(const Message& msg) : ss_(new ::std::stringstream) { // NOLINT
@@ -118,7 +113,22 @@ class GTEST_API_ Message {
// Streams a non-pointer value to this object.
template <typename T>
inline Message& operator <<(const T& val) {
- ::GTestStreamToHelper(ss_.get(), val);
+ // Some libraries overload << for STL containers. These
+ // overloads are defined in the global namespace instead of ::std.
+ //
+ // C++'s symbol lookup rule (i.e. Koenig lookup) says that these
+ // overloads are visible in either the std namespace or the global
+ // namespace, but not other namespaces, including the testing
+ // namespace which Google Test's Message class is in.
+ //
+ // To allow STL containers (and other types that has a << operator
+ // defined in the global namespace) to be used in Google Test
+ // assertions, testing::Message must access the custom << operator
+ // from the global namespace. With this using declaration,
+ // overloads of << defined in the global namespace and those
+ // visible via Koenig lookup are both exposed in this function.
+ using ::operator <<;
+ *ss_ << val;
return *this;
}
@@ -140,7 +150,7 @@ class GTEST_API_ Message {
if (pointer == NULL) {
*ss_ << "(null)";
} else {
- ::GTestStreamToHelper(ss_.get(), pointer);
+ *ss_ << pointer;
}
return *this;
}
@@ -164,12 +174,8 @@ class GTEST_API_ Message {
// These two overloads allow streaming a wide C string to a Message
// using the UTF-8 encoding.
- Message& operator <<(const wchar_t* wide_c_str) {
- return *this << internal::String::ShowWideCString(wide_c_str);
- }
- Message& operator <<(wchar_t* wide_c_str) {
- return *this << internal::String::ShowWideCString(wide_c_str);
- }
+ Message& operator <<(const wchar_t* wide_c_str);
+ Message& operator <<(wchar_t* wide_c_str);
#if GTEST_HAS_STD_WSTRING
// Converts the given wide string to a narrow string using the UTF-8
@@ -187,9 +193,7 @@ class GTEST_API_ Message {
// Each '\0' character in the buffer is replaced with "\\0".
//
// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
- std::string GetString() const {
- return internal::StringStreamToString(ss_.get());
- }
+ std::string GetString() const;
private:
@@ -199,16 +203,20 @@ class GTEST_API_ Message {
// decide between class template specializations for T and T*, so a
// tr1::type_traits-like is_pointer works, and we can overload on that.
template <typename T>
- inline void StreamHelper(internal::true_type /*dummy*/, T* pointer) {
+ inline void StreamHelper(internal::true_type /*is_pointer*/, T* pointer) {
if (pointer == NULL) {
*ss_ << "(null)";
} else {
- ::GTestStreamToHelper(ss_.get(), pointer);
+ *ss_ << pointer;
}
}
template <typename T>
- inline void StreamHelper(internal::false_type /*dummy*/, const T& value) {
- ::GTestStreamToHelper(ss_.get(), value);
+ inline void StreamHelper(internal::false_type /*is_pointer*/,
+ const T& value) {
+ // See the comments in Message& operator <<(const T&) above for why
+ // we need this using statement.
+ using ::operator <<;
+ *ss_ << value;
}
#endif // GTEST_OS_SYMBIAN
@@ -225,6 +233,18 @@ inline std::ostream& operator <<(std::ostream& os, const Message& sb) {
return os << sb.GetString();
}
+namespace internal {
+
+// Converts a streamable value to an std::string. A NULL pointer is
+// converted to "(null)". When the input value is a ::string,
+// ::std::string, ::wstring, or ::std::wstring object, each NUL
+// character in it is replaced with "\\0".
+template <typename T>
+std::string StreamableToString(const T& streamable) {
+ return (Message() << streamable).GetString();
+}
+
+} // namespace internal
} // namespace testing
#endif // GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_
diff --git a/include/gtest/gtest.h b/include/gtest/gtest.h
index e06082c..6d13ff6 100644
--- a/include/gtest/gtest.h
+++ b/include/gtest/gtest.h
@@ -163,18 +163,6 @@ class UnitTestImpl* GetUnitTestImpl();
void ReportFailureInUnknownLocation(TestPartResult::Type result_type,
const std::string& message);
-// Converts a streamable value to an std::string. A NULL pointer is
-// converted to "(null)". When the input value is a ::string,
-// ::std::string, ::wstring, or ::std::wstring object, each NUL
-// character in it is replaced with "\\0".
-// Declared in gtest-internal.h but defined here, so that it has access
-// to the definition of the Message class, required by the ARM
-// compiler.
-template <typename T>
-std::string StreamableToString(const T& streamable) {
- return (Message() << streamable).GetString();
-}
-
} // namespace internal
// The friend relationship of some of these classes is cyclic.
diff --git a/include/gtest/internal/gtest-internal.h b/include/gtest/internal/gtest-internal.h
index 892ddec..1604725 100644
--- a/include/gtest/internal/gtest-internal.h
+++ b/include/gtest/internal/gtest-internal.h
@@ -56,6 +56,7 @@
#include <limits>
#include <set>
+#include "gtest/gtest-message.h"
#include "gtest/internal/gtest-string.h"
#include "gtest/internal/gtest-filepath.h"
#include "gtest/internal/gtest-type-util.h"
@@ -71,36 +72,6 @@
#define GTEST_CONCAT_TOKEN_(foo, bar) GTEST_CONCAT_TOKEN_IMPL_(foo, bar)
#define GTEST_CONCAT_TOKEN_IMPL_(foo, bar) foo ## bar
-// Google Test defines the testing::Message class to allow construction of
-// test messages via the << operator. The idea is that anything
-// streamable to std::ostream can be streamed to a testing::Message.
-// This allows a user to use his own types in Google Test assertions by
-// overloading the << operator.
-//
-// util/gtl/stl_logging.h overloads << for STL containers. These
-// overloads cannot be defined in the std namespace, as that will be
-// undefined behavior. Therefore, they are defined in the global
-// namespace instead.
-//
-// C++'s symbol lookup rule (i.e. Koenig lookup) says that these
-// overloads are visible in either the std namespace or the global
-// namespace, but not other namespaces, including the testing
-// namespace which Google Test's Message class is in.
-//
-// To allow STL containers (and other types that has a << operator
-// defined in the global namespace) to be used in Google Test assertions,
-// testing::Message must access the custom << operator from the global
-// namespace. Hence this helper function.
-//
-// Note: Jeffrey Yasskin suggested an alternative fix by "using
-// ::operator<<;" in the definition of Message's operator<<. That fix
-// doesn't require a helper function, but unfortunately doesn't
-// compile with MSVC.
-template <typename T>
-inline void GTestStreamToHelper(std::ostream* os, const T& val) {
- *os << val;
-}
-
class ProtocolMessage;
namespace proto2 { class Message; }
@@ -132,11 +103,6 @@ GTEST_API_ extern int g_init_gtest_count;
// stack trace.
GTEST_API_ extern const char kStackTraceMarker[];
-// A secret type that Google Test users don't know about. It has no
-// definition on purpose. Therefore it's impossible to create a
-// Secret object, which is what we want.
-class Secret;
-
// Two overloaded helpers for checking at compile time whether an
// expression is a null pointer literal (i.e. NULL or any 0-valued
// compile-time integral constant). Their return values have
@@ -204,16 +170,6 @@ class GTEST_API_ ScopedTrace {
// c'tor and d'tor. Therefore it doesn't
// need to be used otherwise.
-// Converts a streamable value to an std::string. A NULL pointer is
-// converted to "(null)". When the input value is a ::string,
-// ::std::string, ::wstring, or ::std::wstring object, each NUL
-// character in it is replaced with "\\0".
-// Declared here but defined in gtest.h, so that it has access
-// to the definition of the Message class, required by the ARM
-// compiler.
-template <typename T>
-std::string StreamableToString(const T& streamable);
-
// Constructs and returns the message for an equality assertion
// (e.g. ASSERT_EQ, EXPECT_STREQ, etc) failure.
//
diff --git a/include/gtest/internal/gtest-port.h b/include/gtest/internal/gtest-port.h
index c79f12a..f78994a 100644
--- a/include/gtest/internal/gtest-port.h
+++ b/include/gtest/internal/gtest-port.h
@@ -32,6 +32,10 @@
// Low-level types and utilities for porting Google Test to various
// platforms. They are subject to change without notice. DO NOT USE
// THEM IN USER CODE.
+//
+// This file is fundamental to Google Test. All other Google Test source
+// files are expected to #include this. Therefore, it cannot #include
+// any other Google Test header.
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_H_
#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_H_
@@ -784,6 +788,11 @@ class Message;
namespace internal {
+// A secret type that Google Test users don't know about. It has no
+// definition on purpose. Therefore it's impossible to create a
+// Secret object, which is what we want.
+class Secret;
+
// The GTEST_COMPILE_ASSERT_ macro can be used to verify that a compile time
// expression is true. For example, you could use it to verify the
// size of a static array:
diff --git a/include/gtest/internal/gtest-string.h b/include/gtest/internal/gtest-string.h
index 7b74085..97f1a7f 100644
--- a/include/gtest/internal/gtest-string.h
+++ b/include/gtest/internal/gtest-string.h
@@ -161,17 +161,6 @@ class GTEST_API_ String {
// character in the buffer is replaced with "\\0".
GTEST_API_ std::string StringStreamToString(::std::stringstream* stream);
-// Converts a streamable value to an std::string. A NULL pointer is
-// converted to "(null)". When the input value is a ::string,
-// ::std::string, ::wstring, or ::std::wstring object, each NUL
-// character in it is replaced with "\\0".
-
-// Declared here but defined in gtest.h, so that it has access
-// to the definition of the Message class, required by the ARM
-// compiler.
-template <typename T>
-std::string StreamableToString(const T& streamable);
-
} // namespace internal
} // namespace testing
diff --git a/include/gtest/internal/gtest-type-util.h b/include/gtest/internal/gtest-type-util.h
index 4a7d946..e46f7cf 100644
--- a/include/gtest/internal/gtest-type-util.h
+++ b/include/gtest/internal/gtest-type-util.h
@@ -45,7 +45,6 @@
#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_
#include "gtest/internal/gtest-port.h"
-#include "gtest/internal/gtest-string.h"
// #ifdef __GNUC__ is too general here. It is possible to use gcc without using
// libstdc++ (which is where cxxabi.h comes from).
diff --git a/include/gtest/internal/gtest-type-util.h.pump b/include/gtest/internal/gtest-type-util.h.pump
index 3638d51..251fdf0 100644
--- a/include/gtest/internal/gtest-type-util.h.pump
+++ b/include/gtest/internal/gtest-type-util.h.pump
@@ -43,7 +43,6 @@ $var n = 50 $$ Maximum length of type lists we want to support.
#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_
#include "gtest/internal/gtest-port.h"
-#include "gtest/internal/gtest-string.h"
// #ifdef __GNUC__ is too general here. It is possible to use gcc without using
// libstdc++ (which is where cxxabi.h comes from).
diff --git a/src/gtest-filepath.cc b/src/gtest-filepath.cc
index 708389d..6be58b6 100644
--- a/src/gtest-filepath.cc
+++ b/src/gtest-filepath.cc
@@ -29,6 +29,7 @@
//
// Authors: keith.ray@gmail.com (Keith Ray)
+#include "gtest/gtest-message.h"
#include "gtest/internal/gtest-filepath.h"
#include "gtest/internal/gtest-port.h"
diff --git a/src/gtest.cc b/src/gtest.cc
index 1ade269..8e6db0c 100644
--- a/src/gtest.cc
+++ b/src/gtest.cc
@@ -44,6 +44,8 @@
#include <wctype.h>
#include <algorithm>
+#include <iomanip>
+#include <limits>
#include <ostream> // NOLINT
#include <sstream>
#include <vector>
@@ -886,6 +888,26 @@ static void StreamWideCharsToMessage(const wchar_t* wstr, size_t length,
} // namespace internal
+// Constructs an empty Message.
+// We allocate the stringstream separately because otherwise each use of
+// ASSERT/EXPECT in a procedure adds over 200 bytes to the procedure's
+// stack frame leading to huge stack frames in some cases; gcc does not reuse
+// the stack space.
+Message::Message() : ss_(new ::std::stringstream) {
+ // By default, we want there to be enough precision when printing
+ // a double to a Message.
+ *ss_ << std::setprecision(std::numeric_limits<double>::digits10 + 2);
+}
+
+// These two overloads allow streaming a wide C string to a Message
+// using the UTF-8 encoding.
+Message& Message::operator <<(const wchar_t* wide_c_str) {
+ return *this << internal::String::ShowWideCString(wide_c_str);
+}
+Message& Message::operator <<(wchar_t* wide_c_str) {
+ return *this << internal::String::ShowWideCString(wide_c_str);
+}
+
#if GTEST_HAS_STD_WSTRING
// Converts the given wide string to a narrow string using the UTF-8
// encoding, and streams the result to this Message object.
@@ -904,6 +926,12 @@ Message& Message::operator <<(const ::wstring& wstr) {
}
#endif // GTEST_HAS_GLOBAL_WSTRING
+// Gets the text streamed to this object so far as an std::string.
+// Each '\0' character in the buffer is replaced with "\\0".
+std::string Message::GetString() const {
+ return internal::StringStreamToString(ss_.get());
+}
+
// AssertionResult constructors.
// Used in EXPECT_TRUE/FALSE(assertion_result).
AssertionResult::AssertionResult(const AssertionResult& other)