namespace llvm {
+class raw_ostream;
+
namespace optional_detail {
/// Storage for any type.
template <typename T, bool = isPodLike<T>::value> struct OptionalStorage {
return !(X < Y);
}
+raw_ostream &operator<<(raw_ostream &OS, NoneType);
+
+template <typename T, typename = decltype(std::declval<raw_ostream &>()
+ << std::declval<const T &>())>
+raw_ostream &operator<<(raw_ostream &OS, const Optional<T> &O) {
+ if (O)
+ OS << *O;
+ else
+ OS << None;
+ return OS;
+}
+
} // end namespace llvm
#endif // LLVM_ADT_OPTIONAL_H
--- /dev/null
+//===- Optional.cpp - Optional values ---------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/Optional.h"
+#include "llvm/Support/raw_ostream.h"
+
+llvm::raw_ostream &llvm::operator<<(raw_ostream &OS, NoneType) {
+ return OS << "None";
+}
//===----------------------------------------------------------------------===//
#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/Support/raw_ostream.h"
+#include "gtest/gtest-spi.h"
#include "gtest/gtest.h"
using namespace llvm;
CheckRelation<GreaterEqual>(InequalityLhs, InequalityRhs, !IsLess);
}
-} // end anonymous namespace
+struct ComparableAndStreamable {
+ friend bool operator==(ComparableAndStreamable,
+ ComparableAndStreamable) LLVM_ATTRIBUTE_USED {
+ return true;
+ }
+
+ friend raw_ostream &operator<<(raw_ostream &OS, ComparableAndStreamable) {
+ return OS << "ComparableAndStreamable";
+ }
+ static Optional<ComparableAndStreamable> get() {
+ return ComparableAndStreamable();
+ }
+};
+
+TEST_F(OptionalTest, StreamOperator) {
+ auto to_string = [](Optional<ComparableAndStreamable> O) {
+ SmallString<16> S;
+ raw_svector_ostream OS(S);
+ OS << O;
+ return S;
+ };
+ EXPECT_EQ("ComparableAndStreamable",
+ to_string(ComparableAndStreamable::get()));
+ EXPECT_EQ("None", to_string(None));
+}
+
+struct Comparable {
+ friend bool operator==(Comparable, Comparable) LLVM_ATTRIBUTE_USED {
+ return true;
+ }
+ static Optional<Comparable> get() { return Comparable(); }
+};
+
+TEST_F(OptionalTest, UseInUnitTests) {
+ // Test that we invoke the streaming operators when pretty-printing values in
+ // EXPECT macros.
+ EXPECT_NONFATAL_FAILURE(EXPECT_EQ(llvm::None, ComparableAndStreamable::get()),
+ R"(Expected: llvm::None
+ Which is: None
+To be equal to: ComparableAndStreamable::get()
+ Which is: ComparableAndStreamable)");
+
+ // Test that it is still possible to compare objects which do not have a
+ // custom streaming operator.
+ EXPECT_NONFATAL_FAILURE(EXPECT_EQ(llvm::None, Comparable::get()), "object");
+}
+
+} // end anonymous namespace
// If raw_ostream support is enabled, we specialize for types with operator<<
// that takes a raw_ostream.
#if !GTEST_NO_LLVM_RAW_OSTREAM
-#include "llvm/Support/raw_ostream.h"
+#include "llvm/ADT/Optional.h"
#include "llvm/Support/raw_os_ostream.h"
+#include "llvm/Support/raw_ostream.h"
#include <ostream>
namespace llvm_gtest {
<< ConvertibleTo<const T &>()))> {
static const RawStreamProxy<T> printable(const T &V) { return {V}; }
};
+
+// llvm::Optional has a template operator<<, which means it will not accept any
+// implicit conversions, so we need to special-case it here.
+template <typename T>
+struct StreamSwitch<llvm::Optional<T>,
+ decltype((void)(std::declval<llvm::raw_ostream &>()
+ << std::declval<llvm::Optional<T>>()))> {
+ static const RawStreamProxy<llvm::Optional<T>>
+ printable(const llvm::Optional<T> &V) {
+ return {V};
+ }
+};
} // namespace llvm_gtest
#endif // !GTEST_NO_LLVM_RAW_OSTREAM