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

Sam McCall via llvm-commits llvm-commits at lists.llvm.org
Tue Feb 13 05:00:56 PST 2018


Hi Galina,

I dug into this a bunch more.
There is an existing workaround in that test: #pragma GCC diagnostic
ignored "-Wunused-function".
This works around the GCC bug, which is
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80916

Unfortunately, GCC's warning suppression pragmas are fragile, and don't
work for this case.
This is GCC bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53431

I can't find a reasonable workaround for this combination of errors, so I'd
suggest adding -Wno-unused-function to the buildbot. Thoughts?


On Mon, Feb 12, 2018 at 11:06 PM Sam McCall <sam.mccall at gmail.com> wrote:

> 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/20180213/0fda936d/attachment.html>


More information about the llvm-commits mailing list