[llvm] r324876 - [gtest] Support raw_ostream printing functions more comprehensively.

Sam McCall via llvm-commits llvm-commits at lists.llvm.org
Mon Feb 12 14:06:26 PST 2018


Hi Galina,

Thanks for the pointer.

I had a quick look already:
- this is definitely a GCC bug, and not one I recognize
- the trigger is unmodified third-party code (my patch just tickled it)

I'll get a GCC 7.1 set up in the CET morning and hunt for a workaround. If
I can't find one I'll revert.

On Mon, Feb 12, 2018, 22:53 Galina Kistanova <gkistanova at gmail.com> wrote:

> Hello Sam,
>
> This commit  broke the one of our builders:
> http://lab.llvm.org:8011/builders/ubuntu-gcc7.1-werror/builds/5290
>
> Please have a look?
>
> Thanks
>
> Galina
>
> On Mon, Feb 12, 2018 at 2:20 AM, Sam McCall via llvm-commits <
> llvm-commits at lists.llvm.org> wrote:
>
>> Author: sammccall
>> Date: Mon Feb 12 02:20:09 2018
>> New Revision: 324876
>>
>> URL: http://llvm.org/viewvc/llvm-project?rev=324876&view=rev
>> Log:
>> [gtest] Support raw_ostream printing functions more comprehensively.
>>
>> Summary:
>> These are functions like operator<<(raw_ostream&, Foo).
>>
>> Previously these were only supported for messages. In the assertion
>>   EXPECT_EQ(A, B) << C;
>> the local modifications would explicitly try to use raw_ostream printing
>> for C.
>> However A and B would look for a std::ostream printing function, and
>> often fall
>> back to gtest's default "168 byte object <00 01 FE 42 ...>".
>>
>> This patch pulls out the raw_ostream support into a new header under
>> `custom/`.
>>
>> I changed the mechanism: instead of a convertible stream, we wrap the
>> printed
>> value in a proxy object to allow it to be sent to a std::ostream.
>> I think the new way is clearer.
>>
>> I also changed the policy: we prefer raw_ostream printers over
>> std::ostream
>> ones. This is because the fallback printers are defined using
>> std::ostream,
>> while all the raw_ostream printers should be "good".
>>
>> Reviewers: ilya-biryukov, chandlerc
>>
>> Subscribers: llvm-commits
>>
>> Differential Revision: https://reviews.llvm.org/D43091
>>
>> Added:
>>
>> llvm/trunk/utils/unittest/googletest/include/gtest/internal/custom/raw-ostream.h
>> Modified:
>>     llvm/trunk/utils/unittest/googletest/include/gtest/gtest-message.h
>>     llvm/trunk/utils/unittest/googletest/include/gtest/gtest-printers.h
>>
>> Modified:
>> llvm/trunk/utils/unittest/googletest/include/gtest/gtest-message.h
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/unittest/googletest/include/gtest/gtest-message.h?rev=324876&r1=324875&r2=324876&view=diff
>>
>> ==============================================================================
>> --- llvm/trunk/utils/unittest/googletest/include/gtest/gtest-message.h
>> (original)
>> +++ llvm/trunk/utils/unittest/googletest/include/gtest/gtest-message.h
>> Mon Feb 12 02:20:09 2018
>> @@ -49,36 +49,7 @@
>>  #include <limits>
>>
>>  #include "gtest/internal/gtest-port.h"
>> -
>> -#if !GTEST_NO_LLVM_RAW_OSTREAM
>> -#include "llvm/Support/raw_os_ostream.h"
>> -
>> -// LLVM INTERNAL CHANGE: To allow operator<< to work with both
>> -// std::ostreams and LLVM's raw_ostreams, we define a special
>> -// std::ostream with an implicit conversion to raw_ostream& and stream
>> -// to that.  This causes the compiler to prefer std::ostream overloads
>> -// but still find raw_ostream& overloads.
>> -namespace llvm {
>> -class convertible_fwd_ostream : public std::ostream {
>> -  raw_os_ostream ros_;
>> -
>> -public:
>> -  convertible_fwd_ostream(std::ostream& os)
>> -    : std::ostream(os.rdbuf()), ros_(*this) {}
>> -  operator raw_ostream&() { return ros_; }
>> -};
>> -}
>> -template <typename T>
>> -inline void GTestStreamToHelper(std::ostream& os, const T& val) {
>> -  llvm::convertible_fwd_ostream cos(os);
>> -  cos << val;
>> -}
>> -#else
>> -template <typename T>
>> -inline void GTestStreamToHelper(std::ostream& os, const T& val) {
>> -  os << val;
>> -}
>> -#endif
>> +#include "gtest/internal/custom/raw-ostream.h"
>>
>>  // Ensures that there is at least one operator<< in the global namespace.
>>  // See Message& operator<<(...) below for why.
>> @@ -157,12 +128,8 @@ class GTEST_API_ Message {
>>      // 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.
>> -#if GTEST_NO_LLVM_RAW_OSTREAM
>>      using ::operator <<;
>> -    *ss_ << val;
>> -#else
>> -    ::GTestStreamToHelper(*ss_, val);
>> -#endif
>> +    *ss_ << llvm_gtest::printable(val);
>>      return *this;
>>    }
>>
>> @@ -184,11 +151,7 @@ class GTEST_API_ Message {
>>      if (pointer == NULL) {
>>        *ss_ << "(null)";
>>      } else {
>> -#if GTEST_NO_LLVM_RAW_OSTREAM
>> -      *ss_ << pointer;
>> -#else
>> -      ::GTestStreamToHelper(*ss_, pointer);
>> -#endif
>> +      *ss_ << llvm_gtest::printable(pointer);
>>      }
>>      return *this;
>>    }
>>
>> Modified:
>> llvm/trunk/utils/unittest/googletest/include/gtest/gtest-printers.h
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/unittest/googletest/include/gtest/gtest-printers.h?rev=324876&r1=324875&r2=324876&view=diff
>>
>> ==============================================================================
>> --- llvm/trunk/utils/unittest/googletest/include/gtest/gtest-printers.h
>> (original)
>> +++ llvm/trunk/utils/unittest/googletest/include/gtest/gtest-printers.h
>> Mon Feb 12 02:20:09 2018
>> @@ -102,6 +102,7 @@
>>  #include <vector>
>>  #include "gtest/internal/gtest-port.h"
>>  #include "gtest/internal/gtest-internal.h"
>> +#include "gtest/internal/custom/raw-ostream.h"
>>
>>  #if GTEST_HAS_STD_TUPLE_
>>  # include <tuple>
>> @@ -246,7 +247,7 @@ void DefaultPrintNonContainerTo(const T&
>>    // impossible to define #1 (e.g. when foo is ::std, defining
>>    // anything in it is undefined behavior unless you are a compiler
>>    // vendor.).
>> -  *os << value;
>> +  *os << ::llvm_gtest::printable(value);
>>  }
>>
>>  }  // namespace testing_internal
>>
>> Added:
>> llvm/trunk/utils/unittest/googletest/include/gtest/internal/custom/raw-ostream.h
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/unittest/googletest/include/gtest/internal/custom/raw-ostream.h?rev=324876&view=auto
>>
>> ==============================================================================
>> ---
>> llvm/trunk/utils/unittest/googletest/include/gtest/internal/custom/raw-ostream.h
>> (added)
>> +++
>> llvm/trunk/utils/unittest/googletest/include/gtest/internal/custom/raw-ostream.h
>> Mon Feb 12 02:20:09 2018
>> @@ -0,0 +1,74 @@
>> +//===-- raw-ostream.h - Support for printing using raw_ostream --*- C++
>> -*-===//
>> +//
>> +//                     The LLVM Compiler Infrastructure
>> +//
>> +// This file is distributed under the University of Illinois Open Source
>> +// License. See LICENSE.TXT for details.
>> +//
>>
>> +//===----------------------------------------------------------------------===//
>> +// This file is not part of gtest, but extends it to support LLVM
>> libraries.
>> +// This is not a public API for testing - it's a detail of LLVM's gtest.
>> +//
>> +// gtest allows providing printers for custom types by defining
>> operator<<.
>> +// In LLVM, operator<< usually takes llvm:raw_ostream& instead of
>> std::ostream&.
>> +//
>> +// This file defines a template printable(V), which returns a version of
>> V that
>> +// can be streamed into a std::ostream.
>> +//
>> +// This interface is chosen so that in the default case (printable(V) is
>> V),
>> +// the main gtest code calls operator<<(OS, V) itself. gtest-printers
>> carefully
>> +// controls the lookup to enable fallback printing (see
>> testing::internal2).
>>
>> +//===----------------------------------------------------------------------===//
>> +
>> +#ifndef GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_RAW_OSTREAM_H_
>> +#define GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_RAW_OSTREAM_H_
>> +
>> +namespace llvm_gtest {
>> +// StreamSwitch is a trait that tells us how to stream a T into a
>> std::ostream.
>> +// By default, we just stream the T directly. We'll specialize this
>> later.
>> +template <typename T, typename Enable = void> struct StreamSwitch {
>> +  static const T& printable(const T& V) { return V; }
>> +};
>> +
>> +// printable() returns a version of its argument that can be streamed
>> into a
>> +// std::ostream. This may be the argument itself, or some other
>> representation.
>> +template <typename T>
>> +auto printable(const T &V) -> decltype(StreamSwitch<T>::printable(V)) {
>> +  // We delegate to the trait, to allow partial specialization.
>> +  return StreamSwitch<T>::printable(V);
>> +}
>> +} // namespace llvm_gtest
>> +
>> +// 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/Support/raw_os_ostream.h"
>> +#include <ostream>
>> +namespace llvm_gtest {
>> +
>> +// The printable() of a raw_ostream-enabled type T is a
>> RawStreamProxy<T>.
>> +// It uses raw_os_ostream to write the wrapped value to a std::ostream.
>> +template <typename T>
>> +struct RawStreamProxy {
>> +  const T& V;
>> +  friend std::ostream &operator<<(std::ostream &S, const
>> RawStreamProxy<T> &V) {
>> +    llvm::raw_os_ostream OS(S);
>> +    OS << V.V;
>> +    return S;
>> +  }
>> +};
>> +
>> +// We enable raw_ostream treatment if `(raw_ostream&) << (const T&)` is
>> valid.
>> +// We don't want implicit conversions on the RHS (e.g. to bool!), so
>> "consume"
>> +// the possible conversion by passing something convertible to const T&
>> instead.
>> +template <typename T> struct ConvertibleTo { operator T(); };
>> +template <typename T>
>> +struct StreamSwitch<T, decltype((void)(std::declval<llvm::raw_ostream
>> &>()
>> +                                       << ConvertibleTo<const T &>()))> {
>> +  static const RawStreamProxy<T> printable(const T &V) { return {V}; }
>> +};
>> +} // namespace llvm_gtest
>> +#endif  // !GTEST_NO_LLVM_RAW_OSTREAM
>> +
>> +#endif // GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_RAW_OSTREAM_H_
>>
>>
>> _______________________________________________
>> llvm-commits mailing list
>> llvm-commits at lists.llvm.org
>> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
>>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20180212/df98f760/attachment.html>


More information about the llvm-commits mailing list